summaryrefslogtreecommitdiff
path: root/ReferenceCode/Haswell/CpuInit/Dxe/MpCommon.h
blob: 7677e8010875b5a2107d2d6b49c4bf6cd591ef9e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
/** @file
  Some definitions for MP and HT driver.

@copyright
  Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
  This software and associated documentation (if any) is furnished
  under a license and may only be used or copied in accordance
  with the terms of the license. Except as permitted by such
  license, no part of this software or documentation may be
  reproduced, stored in a retrieval system, or transmitted in any
  form or by any means without the express written consent of
  Intel Corporation.

  This file contains an 'Intel Peripheral Driver' and is
  licensed for Intel CPUs and chipsets under the terms of your
  license agreement with Intel or your vendor.  This file may
  be modified by the user, subject to additional terms of the
  license agreement

**/
#ifndef _MP_COMMON_
#define _MP_COMMON_

#include "ProcessorData.h"
#include "CacheData.h"
#include "Exception.h"
#include "ProcessorDef.h"

//
// Protocol produced by this driver
//
#include EFI_PROTOCOL_PRODUCER (MpService)

//
// Protocol consumed by this driver
//
#include EFI_PROTOCOL_DEFINITION (CpuPlatformPolicy)

//
// GUID definitions
//
#include EFI_GUID_DEFINITION (HtBistHOB)
#include EFI_GUID_DEFINITION (SmramCpuDataVariable)
#include EFI_GUID_DEFINITION (SmramCpuDataHeader)

#define VacantFlag          0x00
#define NotVacantFlag       0xff
#define MICROSECOND         10
#define MAXIMUM_CPU_NUMBER  0x40
#define STACK_SIZE_PER_PROC 0x8000

#define IO_APIC_INDEX_REGISTER        0xFEC00000
#define IO_APIC_DATA_REGISTER         0xFEC00010

///
/// Data structure used in MP/HT driver
///
#define MP_CPU_EXCHANGE_INFO_OFFSET     (0x1000 - 0x400)
#define MP_CPU_LEGACY_RESET_INFO_OFFSET (0x100 - 0x20)

#define SMM_FROM_CPU_DRIVER_SAVE_INFO   0x81

#pragma pack(1)
#define SIZE_OF_MCE_HANDLER 16

typedef struct {
  UINT16 LimitLow;
  UINT16 BaseLow;
  UINT8  BaseMiddle;
  UINT16 Attributes;
  UINT8  BaseHigh;
} SEGMENT_DESCRIPTOR;

#pragma pack()

#define BREAK_TO_RUN_AP_SIGNAL  0x6E755200
#define MONITOR_FILTER_SIZE     0x40

typedef enum {
  WakeUpApCounterInit   = 0,
  WakeUpApPerHltLoop    = 1,
  WakeUpApPerMwaitLoop  = 2,
  WakeUpApPerRunLoop    = 3,
  WakeUpApPerMwaitLoop32= 4,
  WakeUpApPerRunLoop32  = 5
} WAKEUP_AP_MANNER;

typedef struct {
  UINTN BreakToRunApSignal;
  UINTN HltLoopBreakCounter;
  UINTN MwaitLoopBreakCounter;
  UINTN RunLoopBreakCounter;
  UINTN MwaitLoopBreakCounter32;
  UINTN RunLoopBreakCounter32;
  UINTN WakeUpApVectorChangeFlag;
  UINTN MwaitTargetCstate;
} MONITOR_MWAIT_DATA;

typedef struct {
  UINT32 Number;
  UINT32 BIST;
} BIST_INFO;

typedef struct {
  UINTN             Lock;
  VOID              *StackStart;
  UINTN             StackSize;
  VOID              *ApFunction;
  PSEUDO_DESCRIPTOR GdtrProfile;
  PSEUDO_DESCRIPTOR IdtrProfile;
  UINT32            BufferStart;
  UINT32            Cr3;
  UINT32            InitFlag;
  WAKEUP_AP_MANNER  WakeUpApManner;
  BIST_INFO         BistBuffer[MAXIMUM_CPU_NUMBER];
} MP_CPU_EXCHANGE_INFO;

extern ACPI_CPU_DATA *mAcpiCpuData;

//
// Protocol interface functions
//
/**
  Get general MP information

  @param[in] This                  - EFI_MP_SERVICE_PROTOCOL
  @param[in] NumberOfCPUs          - Number of processors
  @param[in] MaxiumNumberOfCPUs    - Max supported number of processors
  @param[in] NumberOfEnabledCPUs   - Number of processors enabled
  @param[in] RendezvousIntNumber   - number of Rendezvous procedure
  @param[in] RendezvousProcLength  - length of Rendezvous procedure

  @retval EFI_SUCCESS - always return success
**/
EFI_STATUS
EFIAPI
GetGeneralMPInfo (
  IN EFI_MP_SERVICES_PROTOCOL *This,
  OUT UINTN                   *NumberOfCPUs,
  OUT UINTN                   *MaxiumNumberOfCPUs,
  OUT UINTN                   *NumberOfEnabledCPUs,
  OUT UINTN                   *RendezvousIntNumber,
  OUT UINTN                   *RendezvousProcLength
  );

/**
  Get processor context

  @param[in] This                    - EFI_MP_SERVICE_PROTOCOL
  @param[in] ProcessorNumber         - Cpu number
  @param[in] BufferLength            - buffer length
  @param[in] ProcessorContextBuffer  - pointer to the buffer that will be updated

  @retval EFI_INVALID_PARAMETER - buffer is NULL or CpuNumber our of range
  @retval EFI_BUFFER_TOO_SMALL - buffer too small
  @retval EFI_SUCCESS - got processor context successfully
**/
EFI_STATUS
EFIAPI
GetProcessorContext (
  IN EFI_MP_SERVICES_PROTOCOL *This,
  IN UINTN                    ProcessorNumber,
  IN OUT UINTN                *BufferLength,
  IN OUT EFI_MP_PROC_CONTEXT  *ProcessorContextBuffer
  );

/**
  MP Service to get specified application processor (AP)
  to execute a caller-provided code stream.

  @param[in] This                - Pointer to MP Service Protocol
  @param[in] Procedure           - The procedure to be assigned to AP.
  @param[in] ProcessorNumber     - Cpu number
  @param[in] WaitEvent           - If timeout, the event to be triggered after this AP finishes.
  @param[in] TimeoutInMicroSecs  - The timeout value in microsecond. Zero means infinity.
  @param[in] ProcArguments       - Argument for Procedure.

  @retval EFI_INVALID_PARAMETER - Procudure is NULL.
  @retval EFI_INVALID_PARAMETER - Number of CPU out of range, or it belongs to BSP.
  @retval EFI_INVALID_PARAMETER - Specified CPU is not idle.
  @retval EFI_SUCCESS           - The AP has finished.
  @retval EFI_TIMEOUT           - Time goes out before the AP has finished.
**/
EFI_STATUS
EFIAPI
StartupThisAP (
  IN EFI_MP_SERVICES_PROTOCOL *This,
  IN EFI_AP_PROCEDURE         Procedure,
  IN UINTN                    ProcessorNumber,
  IN EFI_EVENT WaitEvent      OPTIONAL,
  IN UINTN TimeoutInMicroSecs OPTIONAL,
  IN OUT VOID *ProcArguments  OPTIONAL
  );

/**
  MP Service to get all the available application processors (APs)
  to execute a caller-provided code stream.

  @param[in] This                - Pointer to MP Service Protocol
  @param[in] Procedure           - The procedure to be assigned to APs.
  @param[in] SingleThread        - If true, all APs execute in block mode.
                        Otherwise, all APs exceute in non-block mode.
  @param[in] WaitEvent           - If timeout, the event to be triggered after all APs finish.
  @param[in] TimeoutInMicroSecs  - The timeout value in microsecond. Zero means infinity.
  @param[in] ProcArguments       - Argument for Procedure.
  @param[in] FailedCPUList       - If not NULL, all APs that fail to start will be recorded in the list.

  @retval EFI_INVALID_PARAMETER - Procudure is NULL.
  @retval EFI_SUCCESS           - Only 1 logical processor exists.
  @retval EFI_SUCCESS           - All APs have finished.
  @retval EFI_TIMEOUT           - Time goes out before all APs have finished.
**/
EFI_STATUS
EFIAPI
StartupAllAPs (
  IN EFI_MP_SERVICES_PROTOCOL *This,
  IN EFI_AP_PROCEDURE         Procedure,
  IN BOOLEAN                  SingleThread,
  IN EFI_EVENT WaitEvent      OPTIONAL,
  IN UINTN TimeoutInMicroSecs OPTIONAL,
  IN OUT VOID *ProcArguments  OPTIONAL,
  OUT UINTN *FailedCPUList    OPTIONAL
  );

/**
    MP Service to makes the current BSP into an AP and then switches the
    designated AP into the AP. This procedure is usually called after a CPU
    test that has found that BSP is not healthy to continue it's responsbilities.

    @param[in] This            - Pointer to MP Service Protocol.
    @param[in] ProcessorNumber - The handle number of processor.
    @param[in] OldBSPState     - Whether to enable or disable the original BSP.

    @retval EFI_INVALID_PARAMETER - Number for Specified AP out of range.
    @retval EFI_INVALID_PARAMETER - Number of specified CPU belongs to BSP.
    @retval EFI_NOT_READY         - Specified AP is not idle.
    @retval EFI_SUCCESS           - BSP successfully switched.
**/
EFI_STATUS
EFIAPI
SwitchBSP (
  IN EFI_MP_SERVICES_PROTOCOL *This,
  IN UINTN                    ProcessorNumber,
  IN BOOLEAN                  OldBSPState
  );

/**
  This procedure sends an IPI to the designated processor in
  the requested delivery mode with the requested vector.

  @param[in] This         - Pointer to MP Service Protocol.
  @param[in] ProcessorNumber - The handle number of processor.
  @param[in] VectorNumber - Vector number.
  @param[in] DeliveryMode - I/O APIC Interrupt Deliver Modes

  @retval EFI_INVALID_PARAMETER - Input paramters were not correct.
  @retval Other status          - Status returned by SendInterrupt ()
**/
EFI_STATUS
EFIAPI
SendIPI (
  IN EFI_MP_SERVICES_PROTOCOL *This,
  IN UINTN                    ProcessorNumber,
  IN UINTN                    VectorNumber,
  IN UINTN                    DeliveryMode
  );

/**
  This procedure enables or disables APs.

  @param[in] This            - Pointer to MP Service Protocol.
  @param[in] ProcessorNumber - The handle number of processor.
  @param[in] NewAPState      - Indicate new desired AP state
  @param[in] HealthState     - If not NULL, it points to the value that specifies the new health status of the AP.
                               If it is NULL, this parameter is ignored.

  @retval EFI_INVALID_PARAMETER - Input paramters were not correct.
  @retval EFI_SUCCESS           - Function completed successfully
**/
EFI_STATUS
EFIAPI
EnableDisableAP (
  IN EFI_MP_SERVICES_PROTOCOL   *This,
  IN UINTN                      ProcessorNumber,
  IN BOOLEAN                    NewAPState,
  IN EFI_MP_HEALTH *HealthState OPTIONAL
  );

/**
  Implementation of WhoAmI() service of MP Services Protocol.

  This service lets the caller processor get its handle number.
  This service may be called from the BSP and APs.

  @param[in] This                 - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
  @param[in] ProcessorNumber      - Pointer to the handle number of AP.

  @retval EFI_SUCCESS           - Processor number successfully returned.
  @retval EFI_INVALID_PARAMETER - ProcessorNumber is NULL
**/
EFI_STATUS
EFIAPI
WhoAmI (
  IN EFI_MP_SERVICES_PROTOCOL *This,
  OUT UINTN                   *ProcessorNumber
  );

///
/// Functions shared in MP/HT drivers
///
/**
  Send interrupt to CPU

  @param[in] BroadcastMode - interrupt broadcast mode
  @param[in] ApicID        - APIC ID for sending interrupt
  @param[in] VectorNumber  - Vector number
  @param[in] DeliveryMode  - Interrupt delivery mode
  @param[in] TriggerMode   - Interrupt trigger mode
  @param[in] Assert        - Interrupt pin polarity

  @retval EFI_INVALID_PARAMETER - input parameter not correct
  @retval EFI_NOT_READY         - there was a pending interrupt
  @retval EFI_SUCCESS           - interrupt sent successfully
**/
EFI_STATUS
SendInterrupt (
  IN UINT32  BroadcastMode,
  IN UINT32  ApicID,
  IN UINT32  VectorNumber,
  IN UINT32  DeliveryMode,
  IN UINT32  TriggerMode,
  IN BOOLEAN Assert
  );

/**
  Get APIC ID of processor

  @param[in] ApicBase          - APIC base
  @param[in] ApicVersionNumber - APIC version

  @retval APIC ID of processor
**/
UINT32
GetApicID (
  OUT EFI_PHYSICAL_ADDRESS *ApicBase OPTIONAL,
  OUT UINT32 *ApicVersionNumber      OPTIONAL
  );

/**
  Programs XAPIC registers.

  @param[in] BSP             - Is this BSP
**/
VOID
ProgramXApic (
  IN BOOLEAN BSP
  );

/**
  Allocate a temporary memory under 1MB for MP Init to perform INIT-SIPI.
  This buffer also provides memory for stack/data for MP running.

  @param[in] WakeUpBuffer  - Return buffer location

  @retval EFI_SUCCESS if ok to get a memory under 1MB for MP running.
**/
EFI_STATUS
AllocateWakeUpBuffer (
  OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer
  );

///
/// Assembly functions implemented in MP/HT drivers
///
/**
  Lock APs

  @param[in] Lock  - Lock state
**/
VOID
AsmAcquireMPLock (
  IN UINT8 *Lock
  );

/**
  Release APs

  @param[in] Lock  - Lock state
**/
VOID
AsmReleaseMPLock (
  IN UINT8 *Lock
  );

/**
  Get GDTR and IDTR

  @param[in] Gdt - will be stored GDTR
  @param[in] Idt - will be stored IDTR
**/
VOID
AsmGetGdtrIdtr (
  OUT PSEUDO_DESCRIPTOR **Gdt,
  OUT PSEUDO_DESCRIPTOR **Idt
  );

/**
  Prepare GDTR and IDTR for AP

  @param[in] GDTR  - The GDTR profile
  @param[in] IDTR  - The IDTR profile

  @retval EFI_STATUS  - status returned by each sub-routine
  @retval EFI_SUCCESS - GDTR and IDTR has been prepared for AP
**/
EFI_STATUS
PrepareGdtIdtForAP (
  OUT PSEUDO_DESCRIPTOR *GDTR,
  OUT PSEUDO_DESCRIPTOR *IDTR
  );

/**
  Allocate Reserved Memory

  @param[in] Size      - Memory Size
  @param[in] Alignment - Alignment size
  @param[in] Pointer   - return memory location

  @retval EFI_SUCCESS - Allocate a reserved memory successfully
**/
EFI_STATUS
AllocateAlignedReservedMemory (
  IN UINTN Size,
  IN UINTN Alignment,
  OUT VOID **Pointer
  );

/**
  Fill in CPU relevant information into data hub

  @param[in] CpuNumber         - CPU number
  @param[in] CpuDataForDatahub - pointer to data hub that will be updated

  @retval EFI_SUCCESS - always return success
**/
EFI_STATUS
FillinDataforDataHub (
  IN UINTN                 CpuNumber,
  OUT CPU_DATA_FOR_DATAHUB *CpuDataForDatahub
  );

/**
  This function is invoked when LegacyBios protocol is installed, we must
  allocate reserved memory under 1M for AP.

  @param[in] Event   - The triggered event.
  @param[in] Context - Context for this event.
**/
VOID
EFIAPI
ReAllocateEbdaMemoryForAP (
  IN EFI_EVENT Event,
  IN VOID      *Context
  );

/**
  This function is invoked when LegacyBios protocol is installed, we must
  allocate reserved memory under 1M for AP.

  @param[in] Event   - The triggered event.
  @param[in] Context - Context for this event.
**/
VOID
EFIAPI
ReAllocateMemoryForAP (
  IN EFI_EVENT Event,
  IN VOID      *Context
  );

/**
  This function is invoked by EFI_EVENT_SIGNAL_LEGACY_BOOT.
  Before booting to legacy OS, reset it with memory allocated
  by ReAllocateMemoryForAp() and set local APIC correctly.

  @param[in] Event   - The triggered event.
  @param[in] Context - Context for this event.
**/
VOID
ResetAPs (
  IN EFI_EVENT Event,
  IN VOID      *Context
  );

/**
  Prepare Wakeup Buffer and stack for APs.

  @param[in] WakeUpBuffer             - Pointer to the address of wakeup buffer for output.
  @param[in] StackAddressStart        - Pointer to the stack address of APs for output.
  @param[in] MaximumCPUsForThisSystem - Maximum CPUs in this system.

  @retval EFI_SUCCESS              - Memory successfully prepared for APs.
  @retval Other                    - Error occurred while allocating memory.
**/
EFI_STATUS
PrepareMemoryForAPs (
  OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer,
  OUT VOID                 **StackAddressStart,
  IN UINTN                 MaximumCPUsForThisSystem
  );

/**
  Prepare exchange information for APs.

  @param[in] ExchangeInfo      - Pointer to the exchange info buffer for output.
  @param[in] StackAddressStart - Start address of APs' stacks.
  @param[in] ApFunction        - Address of function assigned to AP.
  @param[in] WakeUpBuffer      - Pointer to the address of wakeup buffer.

  @retval EFI_SUCCESS       - Exchange Info successfully prepared for APs.
  @retval Other             - Error occurred while allocating memory.
**/
EFI_STATUS
PrepareExchangeInfo (
  OUT MP_CPU_EXCHANGE_INFO *ExchangeInfo,
  IN VOID                  *StackAddressStart,
  IN VOID                  *ApFunction,
  IN EFI_PHYSICAL_ADDRESS  WakeUpBuffer
  );

/**
  Prepare Wakeup Buffer and stack for APs during S3.

  @param[in] WakeUpBuffer      - Pointer to the address of wakeup buffer for output.
  @param[in] StackAddressStart - Pointer to the stack address of APs for output.

  @retval EFI_SUCCESS       - Memory successfully prepared for APs.
**/
EFI_STATUS
S3PrepareMemoryForAPs (
  OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer,
  OUT VOID                 **StackAddressStart
  );

/**
  Prepare exchange information for APs during S3.

  @param[in] ExchangeInfo      - Pointer to the exchange info for output.
  @param[in] StackAddressStart - Start address of APs' stacks.
  @param[in] ApFunction        - Address of function assigned to AP.
  @param[in] WakeUpBuffer      - Pointer to the address of wakeup buffer.

  @retval EFI_SUCCESS       - Exchange Info successfully prepared for APs.
**/
EFI_STATUS
S3PrepareExchangeInfo (
  OUT MP_CPU_EXCHANGE_INFO *ExchangeInfo,
  IN VOID                  *StackAddressStart,
  IN VOID                  *ApFunction,
  IN EFI_PHYSICAL_ADDRESS  WakeUpBuffer
  );

/**
  Check whether any AP is running for assigned task.

  @retval TRUE  - Some APs are running.
  @retval FALSE - No AP is running.
**/
BOOLEAN
ApRunning (
  VOID
  );

/**
  Wrapper function for all procedures assigned to AP via MP service protocol.
  It controls states of AP and invokes assigned precedure.
**/
VOID
ApProcWrapper (
  VOID
  );

/**
  Allocate EfiReservedMemoryType below 4G memory address.

  @param[in] Size   - Size of memory to allocate.
  @param[in] Buffer - Allocated address for output.

  @retval EFI_SUCCESS - Memory successfully allocated.
  @retval Other       - Other errors occur.
**/
EFI_STATUS
AllocateReservedMemoryBelow4G (
  IN UINTN Size,
  OUT VOID **Buffer
  );

/**
  Dynamically write the far jump destination in APs' wakeup buffer,
  in order to refresh APs' CS registers for mode switching.
**/
VOID
RedirectFarJump (
  VOID
  );

#endif