1 | /** @file
|
---|
2 | Common header file for MP Initialize Library.
|
---|
3 |
|
---|
4 | Copyright (c) 2016 - 2024, Intel Corporation. All rights reserved.<BR>
|
---|
5 | Copyright (c) 2020 - 2024, AMD Inc. All rights reserved.<BR>
|
---|
6 |
|
---|
7 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
8 |
|
---|
9 | **/
|
---|
10 |
|
---|
11 | #ifndef _MP_LIB_H_
|
---|
12 | #define _MP_LIB_H_
|
---|
13 |
|
---|
14 | #include <PiPei.h>
|
---|
15 |
|
---|
16 | #include <Register/Intel/Cpuid.h>
|
---|
17 | #include <Register/Amd/Cpuid.h>
|
---|
18 | #include <Register/Amd/Ghcb.h>
|
---|
19 | #include <Register/Intel/Msr.h>
|
---|
20 | #include <Register/Intel/LocalApic.h>
|
---|
21 | #include <Register/Intel/Microcode.h>
|
---|
22 |
|
---|
23 | #include <Library/MpInitLib.h>
|
---|
24 | #include <Library/BaseLib.h>
|
---|
25 | #include <Library/BaseMemoryLib.h>
|
---|
26 | #include <Library/MemoryAllocationLib.h>
|
---|
27 | #include <Library/DebugLib.h>
|
---|
28 | #include <Library/LocalApicLib.h>
|
---|
29 | #include <Library/CpuLib.h>
|
---|
30 | #include <Library/TimerLib.h>
|
---|
31 | #include <Library/SynchronizationLib.h>
|
---|
32 | #include <Library/MtrrLib.h>
|
---|
33 | #include <Library/HobLib.h>
|
---|
34 | #include <Library/PcdLib.h>
|
---|
35 | #include <Library/MicrocodeLib.h>
|
---|
36 | #include <Library/CpuPageTableLib.h>
|
---|
37 | #include <Library/SafeIntLib.h>
|
---|
38 | #include <ConfidentialComputingGuestAttr.h>
|
---|
39 |
|
---|
40 | #include <Register/Amd/SevSnpMsr.h>
|
---|
41 | #include <Register/Amd/Ghcb.h>
|
---|
42 |
|
---|
43 | #include <Guid/MicrocodePatchHob.h>
|
---|
44 | #include "MpHandOff.h"
|
---|
45 |
|
---|
46 | #define WAKEUP_AP_SIGNAL SIGNATURE_32 ('S', 'T', 'A', 'P')
|
---|
47 | //
|
---|
48 | // To trigger the start-up signal, BSP writes the specified
|
---|
49 | // StartupSignalValue to the StartupSignalAddress of each processor.
|
---|
50 | // This address is monitored by the APs, and as soon as they receive
|
---|
51 | // the value that matches the MP_HAND_OFF_SIGNAL, they will wake up
|
---|
52 | // and switch the context from PEI to DXE phase.
|
---|
53 | //
|
---|
54 | #define MP_HAND_OFF_SIGNAL SIGNATURE_32 ('M', 'P', 'H', 'O')
|
---|
55 |
|
---|
56 | #define CPU_INIT_MP_LIB_HOB_GUID \
|
---|
57 | { \
|
---|
58 | 0x58eb6a19, 0x3699, 0x4c68, { 0xa8, 0x36, 0xda, 0xcd, 0x8e, 0xdc, 0xad, 0x4a } \
|
---|
59 | }
|
---|
60 |
|
---|
61 | //
|
---|
62 | // The MP data for switch BSP
|
---|
63 | //
|
---|
64 | #define CPU_SWITCH_STATE_IDLE 0
|
---|
65 | #define CPU_SWITCH_STATE_STORED 1
|
---|
66 | #define CPU_SWITCH_STATE_LOADED 2
|
---|
67 |
|
---|
68 | //
|
---|
69 | // Default maximum number of entries to store the microcode patches information
|
---|
70 | //
|
---|
71 | #define DEFAULT_MAX_MICROCODE_PATCH_NUM 8
|
---|
72 |
|
---|
73 | #define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
|
---|
74 |
|
---|
75 | //
|
---|
76 | // Data structure for microcode patch information
|
---|
77 | //
|
---|
78 | typedef struct {
|
---|
79 | UINTN Address;
|
---|
80 | UINTN Size;
|
---|
81 | } MICROCODE_PATCH_INFO;
|
---|
82 |
|
---|
83 | //
|
---|
84 | // CPU volatile registers around INIT-SIPI-SIPI
|
---|
85 | //
|
---|
86 | typedef struct {
|
---|
87 | UINTN Cr0;
|
---|
88 | UINTN Cr3;
|
---|
89 | UINTN Cr4;
|
---|
90 | UINTN Dr0;
|
---|
91 | UINTN Dr1;
|
---|
92 | UINTN Dr2;
|
---|
93 | UINTN Dr3;
|
---|
94 | UINTN Dr6;
|
---|
95 | UINTN Dr7;
|
---|
96 | IA32_DESCRIPTOR Gdtr;
|
---|
97 | IA32_DESCRIPTOR Idtr;
|
---|
98 | UINT16 Tr;
|
---|
99 | } CPU_VOLATILE_REGISTERS;
|
---|
100 |
|
---|
101 | //
|
---|
102 | // CPU exchange information for switch BSP
|
---|
103 | //
|
---|
104 | typedef struct {
|
---|
105 | UINT8 State; // offset 0
|
---|
106 | UINTN StackPointer; // offset 4 / 8
|
---|
107 | CPU_VOLATILE_REGISTERS VolatileRegisters; // offset 8 / 16
|
---|
108 | } CPU_EXCHANGE_ROLE_INFO;
|
---|
109 |
|
---|
110 | //
|
---|
111 | // AP loop state when APs are in idle state
|
---|
112 | // It's value is the same with PcdCpuApLoopMode
|
---|
113 | //
|
---|
114 | typedef enum {
|
---|
115 | ApInHltLoop = 1,
|
---|
116 | ApInMwaitLoop = 2,
|
---|
117 | ApInRunLoop = 3
|
---|
118 | } AP_LOOP_MODE;
|
---|
119 |
|
---|
120 | //
|
---|
121 | // AP initialization state during APs wakeup
|
---|
122 | //
|
---|
123 | typedef enum {
|
---|
124 | ApInitConfig = 1,
|
---|
125 | ApInitDone = 2
|
---|
126 | } AP_INIT_STATE;
|
---|
127 |
|
---|
128 | //
|
---|
129 | // AP state
|
---|
130 | //
|
---|
131 | // The state transitions for an AP when it process a procedure are:
|
---|
132 | // Idle ----> Ready ----> Busy ----> Idle
|
---|
133 | // [BSP] [AP] [AP]
|
---|
134 | //
|
---|
135 | typedef enum {
|
---|
136 | CpuStateIdle,
|
---|
137 | CpuStateReady,
|
---|
138 | CpuStateBusy,
|
---|
139 | CpuStateFinished,
|
---|
140 | CpuStateDisabled
|
---|
141 | } CPU_STATE;
|
---|
142 |
|
---|
143 | //
|
---|
144 | // AP related data
|
---|
145 | //
|
---|
146 | typedef struct {
|
---|
147 | SPIN_LOCK ApLock;
|
---|
148 | volatile UINT32 *StartupApSignal;
|
---|
149 | volatile UINTN ApFunction;
|
---|
150 | volatile UINTN ApFunctionArgument;
|
---|
151 | BOOLEAN CpuHealthy;
|
---|
152 | volatile CPU_STATE State;
|
---|
153 | CPU_VOLATILE_REGISTERS VolatileRegisters;
|
---|
154 | BOOLEAN Waiting;
|
---|
155 | BOOLEAN *Finished;
|
---|
156 | UINT64 ExpectedTime;
|
---|
157 | UINT64 CurrentTime;
|
---|
158 | UINT64 TotalTime;
|
---|
159 | EFI_EVENT WaitEvent;
|
---|
160 | UINT32 ProcessorSignature;
|
---|
161 | UINT8 PlatformId;
|
---|
162 | UINT64 MicrocodeEntryAddr;
|
---|
163 | UINT32 MicrocodeRevision;
|
---|
164 | SEV_ES_SAVE_AREA *SevEsSaveArea;
|
---|
165 | } CPU_AP_DATA;
|
---|
166 |
|
---|
167 | //
|
---|
168 | // Basic CPU information saved in Guided HOB.
|
---|
169 | // Because the contents will be shard between PEI and DXE,
|
---|
170 | // we need to make sure the each fields offset same in different
|
---|
171 | // architecture.
|
---|
172 | //
|
---|
173 | #pragma pack (1)
|
---|
174 | typedef struct {
|
---|
175 | UINT32 InitialApicId;
|
---|
176 | UINT32 ApicId;
|
---|
177 | UINT32 Health;
|
---|
178 | UINT64 ApTopOfStack;
|
---|
179 | } CPU_INFO_IN_HOB;
|
---|
180 | #pragma pack ()
|
---|
181 |
|
---|
182 | //
|
---|
183 | // AP reset code information including code address and size,
|
---|
184 | // this structure will be shared be C code and assembly code.
|
---|
185 | // It is natural aligned by design.
|
---|
186 | //
|
---|
187 | typedef struct {
|
---|
188 | UINT8 *RendezvousFunnelAddress;
|
---|
189 | UINTN ModeEntryOffset;
|
---|
190 | UINTN RendezvousFunnelSize;
|
---|
191 | UINT8 *RelocateApLoopFuncAddressGeneric;
|
---|
192 | UINTN RelocateApLoopFuncSizeGeneric;
|
---|
193 | UINT8 *RelocateApLoopFuncAddressAmdSev;
|
---|
194 | UINTN RelocateApLoopFuncSizeAmdSev;
|
---|
195 | UINTN ModeTransitionOffset;
|
---|
196 | UINTN SwitchToRealNoNxOffset;
|
---|
197 | UINTN SwitchToRealPM16ModeOffset;
|
---|
198 | UINTN SwitchToRealPM16ModeSize;
|
---|
199 | } MP_ASSEMBLY_ADDRESS_MAP;
|
---|
200 |
|
---|
201 | typedef struct _CPU_MP_DATA CPU_MP_DATA;
|
---|
202 |
|
---|
203 | #pragma pack(1)
|
---|
204 |
|
---|
205 | //
|
---|
206 | // MP CPU exchange information for AP reset code
|
---|
207 | // This structure is required to be packed because fixed field offsets
|
---|
208 | // into this structure are used in assembly code in this module
|
---|
209 | // Assembly routines should refrain from directly interacting with
|
---|
210 | // the internal details of CPU_MP_DATA.
|
---|
211 | //
|
---|
212 | typedef struct {
|
---|
213 | UINTN StackStart;
|
---|
214 | UINTN StackSize;
|
---|
215 | UINTN CFunction;
|
---|
216 | IA32_DESCRIPTOR GdtrProfile;
|
---|
217 | IA32_DESCRIPTOR IdtrProfile;
|
---|
218 | UINTN BufferStart;
|
---|
219 | UINTN ModeOffset;
|
---|
220 | UINTN ApIndex;
|
---|
221 | UINTN CodeSegment;
|
---|
222 | UINTN DataSegment;
|
---|
223 | UINTN EnableExecuteDisable;
|
---|
224 | UINTN Cr3;
|
---|
225 | UINTN InitFlag;
|
---|
226 | CPU_INFO_IN_HOB *CpuInfo;
|
---|
227 | UINTN NumApsExecuting;
|
---|
228 | CPU_MP_DATA *CpuMpData;
|
---|
229 | UINTN InitializeFloatingPointUnitsAddress;
|
---|
230 | UINT32 ModeTransitionMemory;
|
---|
231 | UINT16 ModeTransitionSegment;
|
---|
232 | UINT32 ModeHighMemory;
|
---|
233 | UINT16 ModeHighSegment;
|
---|
234 | //
|
---|
235 | // Enable5LevelPaging indicates whether 5-level paging is enabled in long mode.
|
---|
236 | //
|
---|
237 | BOOLEAN Enable5LevelPaging;
|
---|
238 | BOOLEAN SevEsIsEnabled;
|
---|
239 | BOOLEAN SevSnpIsEnabled;
|
---|
240 | UINTN GhcbBase;
|
---|
241 | BOOLEAN ExtTopoAvail;
|
---|
242 | } MP_CPU_EXCHANGE_INFO;
|
---|
243 |
|
---|
244 | #pragma pack()
|
---|
245 |
|
---|
246 | //
|
---|
247 | // CPU MP Data save in memory, and intended for use in C code.
|
---|
248 | // There are some duplicated fields, such as XD status, between
|
---|
249 | // CpuMpData and ExchangeInfo. These duplications in CpuMpData
|
---|
250 | // are present to avoid to be direct accessed and comprehended
|
---|
251 | // in assembly code.
|
---|
252 | //
|
---|
253 | struct _CPU_MP_DATA {
|
---|
254 | UINT64 CpuInfoInHob;
|
---|
255 | UINT32 CpuCount;
|
---|
256 | UINT32 BspNumber;
|
---|
257 | SPIN_LOCK MpLock;
|
---|
258 | UINTN Buffer;
|
---|
259 |
|
---|
260 | //
|
---|
261 | // InitialBspApicMode stores the initial BSP APIC mode.
|
---|
262 | // It is used to synchronize the BSP APIC mode with APs
|
---|
263 | // in the first time APs wake up.
|
---|
264 | // Its value doesn't reflect the current APIC mode since there are
|
---|
265 | // two cases the APIC mode is changed:
|
---|
266 | // 1. MpLib explicitly switches to X2 APIC mode because number of threads is greater than 255,
|
---|
267 | // or there are any logical processors reporting an initial APIC ID of 255 or greater.
|
---|
268 | // 2. Some code switches to X2 APIC mode in all threads through MP services PPI/Protocol.
|
---|
269 | //
|
---|
270 | UINTN InitialBspApicMode;
|
---|
271 | UINTN CpuApStackSize;
|
---|
272 | MP_ASSEMBLY_ADDRESS_MAP AddressMap;
|
---|
273 | UINTN WakeupBuffer;
|
---|
274 | UINTN WakeupBufferHigh;
|
---|
275 | UINTN BackupBuffer;
|
---|
276 | UINTN BackupBufferSize;
|
---|
277 |
|
---|
278 | volatile UINT32 FinishedCount;
|
---|
279 | UINT32 RunningCount;
|
---|
280 | BOOLEAN SingleThread;
|
---|
281 | EFI_AP_PROCEDURE Procedure;
|
---|
282 | VOID *ProcArguments;
|
---|
283 | BOOLEAN *Finished;
|
---|
284 | UINT64 ExpectedTime;
|
---|
285 | UINT64 CurrentTime;
|
---|
286 | UINT64 TotalTime;
|
---|
287 | EFI_EVENT WaitEvent;
|
---|
288 | UINTN **FailedCpuList;
|
---|
289 | BOOLEAN EnableExecuteDisableForSwitchContext;
|
---|
290 |
|
---|
291 | AP_INIT_STATE InitFlag;
|
---|
292 | BOOLEAN SwitchBspFlag;
|
---|
293 | UINTN NewBspNumber;
|
---|
294 | CPU_EXCHANGE_ROLE_INFO BSPInfo;
|
---|
295 | CPU_EXCHANGE_ROLE_INFO APInfo;
|
---|
296 | MTRR_SETTINGS MtrrTable;
|
---|
297 | UINT8 ApLoopMode;
|
---|
298 | UINT8 ApTargetCState;
|
---|
299 | UINT16 PmCodeSegment;
|
---|
300 | UINT16 Pm16CodeSegment;
|
---|
301 | CPU_AP_DATA *CpuData;
|
---|
302 | volatile MP_CPU_EXCHANGE_INFO *MpCpuExchangeInfo;
|
---|
303 |
|
---|
304 | UINT32 InitTimerCount;
|
---|
305 | UINTN DivideValue;
|
---|
306 | UINT8 Vector;
|
---|
307 | BOOLEAN PeriodicMode;
|
---|
308 | BOOLEAN TimerInterruptState;
|
---|
309 | UINT64 MicrocodePatchAddress;
|
---|
310 | UINT64 MicrocodePatchRegionSize;
|
---|
311 |
|
---|
312 | //
|
---|
313 | // Whether need to use Init-Sipi-Sipi to wake up the APs.
|
---|
314 | // Two cases need to set this value to TRUE. One is in HLT
|
---|
315 | // loop mode, the other is resume from S3 which loop mode
|
---|
316 | // will be hardcode change to HLT mode by PiSmmCpuDxeSmm
|
---|
317 | // driver.
|
---|
318 | //
|
---|
319 | BOOLEAN WakeUpByInitSipiSipi;
|
---|
320 |
|
---|
321 | BOOLEAN SevEsIsEnabled;
|
---|
322 | BOOLEAN SevSnpIsEnabled;
|
---|
323 | BOOLEAN UseSevEsAPMethod;
|
---|
324 | UINTN SevEsAPBuffer;
|
---|
325 | UINTN SevEsAPResetStackStart;
|
---|
326 | CPU_MP_DATA *NewCpuMpData;
|
---|
327 |
|
---|
328 | UINT64 GhcbBase;
|
---|
329 | };
|
---|
330 |
|
---|
331 | //
|
---|
332 | // AP_STACK_DATA is stored at the top of each AP stack.
|
---|
333 | //
|
---|
334 | typedef struct {
|
---|
335 | UINTN Bist;
|
---|
336 | CPU_MP_DATA *MpData;
|
---|
337 | } AP_STACK_DATA;
|
---|
338 |
|
---|
339 | #define AP_SAFE_STACK_SIZE 128
|
---|
340 | #define AP_RESET_STACK_SIZE AP_SAFE_STACK_SIZE
|
---|
341 | STATIC_ASSERT ((AP_SAFE_STACK_SIZE & (CPU_STACK_ALIGNMENT - 1)) == 0, "AP_SAFE_STACK_SIZE is not aligned with CPU_STACK_ALIGNMENT");
|
---|
342 |
|
---|
343 | #pragma pack(1)
|
---|
344 |
|
---|
345 | typedef struct {
|
---|
346 | UINT8 InsnBuffer[8];
|
---|
347 | UINT16 Rip;
|
---|
348 | UINT16 Segment;
|
---|
349 | } SEV_ES_AP_JMP_FAR;
|
---|
350 |
|
---|
351 | #pragma pack()
|
---|
352 |
|
---|
353 | /**
|
---|
354 | Assembly code to move an AP from long mode to real mode.
|
---|
355 |
|
---|
356 | Move an AP from long mode to real mode in preparation to invoking
|
---|
357 | the reset vector. This is used for SEV-ES guests where a hypervisor
|
---|
358 | is not allowed to set the CS and RIP to point to the reset vector.
|
---|
359 |
|
---|
360 | @param[in] BufferStart The reset vector target.
|
---|
361 | @param[in] Code16 16-bit protected mode code segment value.
|
---|
362 | @param[in] Code32 32-bit protected mode code segment value.
|
---|
363 | @param[in] StackStart The start of a stack to be used for transitioning
|
---|
364 | from long mode to real mode.
|
---|
365 | **/
|
---|
366 | typedef
|
---|
367 | VOID
|
---|
368 | (EFIAPI AP_RESET)(
|
---|
369 | IN UINTN BufferStart,
|
---|
370 | IN UINT16 Code16,
|
---|
371 | IN UINT16 Code32,
|
---|
372 | IN UINTN StackStart
|
---|
373 | );
|
---|
374 |
|
---|
375 | extern EFI_GUID mCpuInitMpLibHobGuid;
|
---|
376 | extern volatile UINT32 mNumberToFinish;
|
---|
377 |
|
---|
378 | /**
|
---|
379 | Assembly code to place AP into safe loop mode.
|
---|
380 |
|
---|
381 | Place AP into targeted C-State if MONITOR is supported, otherwise
|
---|
382 | place AP into hlt state.
|
---|
383 | Place AP in protected mode if the current is long mode. Due to AP maybe
|
---|
384 | wakeup by some hardware event. It could avoid accessing page table that
|
---|
385 | may not available during booting to OS.
|
---|
386 |
|
---|
387 | @param[in] MwaitSupport TRUE indicates MONITOR is supported.
|
---|
388 | FALSE indicates MONITOR is not supported.
|
---|
389 | @param[in] ApTargetCState Target C-State value.
|
---|
390 | @param[in] PmCodeSegment Protected mode code segment value.
|
---|
391 | **/
|
---|
392 | typedef
|
---|
393 | VOID
|
---|
394 | (EFIAPI *ASM_RELOCATE_AP_LOOP_GENERIC)(
|
---|
395 | IN BOOLEAN MwaitSupport,
|
---|
396 | IN UINTN ApTargetCState,
|
---|
397 | IN UINTN TopOfApStack,
|
---|
398 | IN UINTN NumberToFinish,
|
---|
399 | IN UINTN Cr3
|
---|
400 | );
|
---|
401 |
|
---|
402 | /**
|
---|
403 | Assembly code to place AP into safe loop mode for Amd processors
|
---|
404 | with Sev enabled.
|
---|
405 | Place AP into targeted C-State if MONITOR is supported, otherwise
|
---|
406 | place AP into hlt state.
|
---|
407 | Place AP in protected mode if the current is long mode. Due to AP maybe
|
---|
408 | wakeup by some hardware event. It could avoid accessing page table that
|
---|
409 | may not available during booting to OS.
|
---|
410 | @param[in] MwaitSupport TRUE indicates MONITOR is supported.
|
---|
411 | FALSE indicates MONITOR is not supported.
|
---|
412 | @param[in] ApTargetCState Target C-State value.
|
---|
413 | @param[in] PmCodeSegment Protected mode code segment value.
|
---|
414 | **/
|
---|
415 | typedef
|
---|
416 | VOID
|
---|
417 | (EFIAPI *ASM_RELOCATE_AP_LOOP_AMDSEV)(
|
---|
418 | IN BOOLEAN MwaitSupport,
|
---|
419 | IN UINTN ApTargetCState,
|
---|
420 | IN UINTN PmCodeSegment,
|
---|
421 | IN UINTN TopOfApStack,
|
---|
422 | IN UINTN NumberToFinish,
|
---|
423 | IN UINTN Pm16CodeSegment,
|
---|
424 | IN UINTN SevEsAPJumpTable,
|
---|
425 | IN UINTN WakeupBuffer
|
---|
426 | );
|
---|
427 |
|
---|
428 | /**
|
---|
429 | Assembly code to get starting address and size of the rendezvous entry for APs.
|
---|
430 | Information for fixing a jump instruction in the code is also returned.
|
---|
431 |
|
---|
432 | @param[out] AddressMap Output buffer for address map information.
|
---|
433 | **/
|
---|
434 | VOID
|
---|
435 | EFIAPI
|
---|
436 | AsmGetAddressMap (
|
---|
437 | OUT MP_ASSEMBLY_ADDRESS_MAP *AddressMap
|
---|
438 | );
|
---|
439 |
|
---|
440 | /**
|
---|
441 | This function is called by both the BSP and the AP which is to become the BSP to
|
---|
442 | Exchange execution context including stack between them. After return from this
|
---|
443 | function, the BSP becomes AP and the AP becomes the BSP.
|
---|
444 |
|
---|
445 | @param[in] MyInfo Pointer to buffer holding the exchanging information for the executing processor.
|
---|
446 | @param[in] OthersInfo Pointer to buffer holding the exchanging information for the peer.
|
---|
447 |
|
---|
448 | **/
|
---|
449 | VOID
|
---|
450 | EFIAPI
|
---|
451 | AsmExchangeRole (
|
---|
452 | IN CPU_EXCHANGE_ROLE_INFO *MyInfo,
|
---|
453 | IN CPU_EXCHANGE_ROLE_INFO *OthersInfo
|
---|
454 | );
|
---|
455 |
|
---|
456 | typedef union {
|
---|
457 | VOID *Data;
|
---|
458 | ASM_RELOCATE_AP_LOOP_AMDSEV AmdSevEntry; // 64-bit AMD Sev processors
|
---|
459 | ASM_RELOCATE_AP_LOOP_GENERIC GenericEntry; // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or AMD non-Sev processors
|
---|
460 | } RELOCATE_AP_LOOP_ENTRY;
|
---|
461 |
|
---|
462 | /**
|
---|
463 | Get the pointer to CPU MP Data structure.
|
---|
464 |
|
---|
465 | @return The pointer to CPU MP Data structure.
|
---|
466 | **/
|
---|
467 | CPU_MP_DATA *
|
---|
468 | GetCpuMpData (
|
---|
469 | VOID
|
---|
470 | );
|
---|
471 |
|
---|
472 | /**
|
---|
473 | Save the pointer to CPU MP Data structure.
|
---|
474 |
|
---|
475 | @param[in] CpuMpData The pointer to CPU MP Data structure will be saved.
|
---|
476 | **/
|
---|
477 | VOID
|
---|
478 | SaveCpuMpData (
|
---|
479 | IN CPU_MP_DATA *CpuMpData
|
---|
480 | );
|
---|
481 |
|
---|
482 | /**
|
---|
483 | Get available system memory below 1MB by specified size.
|
---|
484 |
|
---|
485 | @param[in] WakeupBufferSize Wakeup buffer size required
|
---|
486 |
|
---|
487 | @retval other Return wakeup buffer address below 1MB.
|
---|
488 | @retval -1 Cannot find free memory below 1MB.
|
---|
489 | **/
|
---|
490 | UINTN
|
---|
491 | GetWakeupBuffer (
|
---|
492 | IN UINTN WakeupBufferSize
|
---|
493 | );
|
---|
494 |
|
---|
495 | /**
|
---|
496 | Switch Context for each AP.
|
---|
497 |
|
---|
498 | **/
|
---|
499 | VOID
|
---|
500 | SwitchApContext (
|
---|
501 | IN CONST MP_HAND_OFF_CONFIG *MpHandOffConfig,
|
---|
502 | IN CONST MP_HAND_OFF *FirstMpHandOff
|
---|
503 | );
|
---|
504 |
|
---|
505 | /**
|
---|
506 | Get pointer to next MP_HAND_OFF GUIDed HOB body.
|
---|
507 |
|
---|
508 | @param[in] MpHandOff Previous HOB body. Pass NULL to get the first HOB.
|
---|
509 |
|
---|
510 | @return The pointer to MP_HAND_OFF structure.
|
---|
511 | **/
|
---|
512 | MP_HAND_OFF *
|
---|
513 | GetNextMpHandOffHob (
|
---|
514 | IN CONST MP_HAND_OFF *MpHandOff
|
---|
515 | );
|
---|
516 |
|
---|
517 | /**
|
---|
518 | Get available EfiBootServicesCode memory below 4GB by specified size.
|
---|
519 |
|
---|
520 | This buffer is required to safely transfer AP from real address mode to
|
---|
521 | protected mode or long mode, due to the fact that the buffer returned by
|
---|
522 | GetWakeupBuffer() may be marked as non-executable.
|
---|
523 |
|
---|
524 | @param[in] BufferSize Wakeup transition buffer size.
|
---|
525 |
|
---|
526 | @retval other Return wakeup transition buffer address below 4GB.
|
---|
527 | @retval 0 Cannot find free memory below 4GB.
|
---|
528 | **/
|
---|
529 | UINTN
|
---|
530 | AllocateCodeBuffer (
|
---|
531 | IN UINTN BufferSize
|
---|
532 | );
|
---|
533 |
|
---|
534 | /**
|
---|
535 | Return the address of the SEV-ES AP jump table.
|
---|
536 |
|
---|
537 | This buffer is required in order for an SEV-ES guest to transition from
|
---|
538 | UEFI into an OS.
|
---|
539 |
|
---|
540 | @return Return SEV-ES AP jump table buffer
|
---|
541 | **/
|
---|
542 | UINTN
|
---|
543 | GetSevEsAPMemory (
|
---|
544 | VOID
|
---|
545 | );
|
---|
546 |
|
---|
547 | /**
|
---|
548 | Create 1:1 mapping page table in reserved memory to map the specified address range.
|
---|
549 | @param[in] LinearAddress The start of the linear address range.
|
---|
550 | @param[in] Length The length of the linear address range.
|
---|
551 | @return The page table to be created.
|
---|
552 | **/
|
---|
553 | UINTN
|
---|
554 | CreatePageTable (
|
---|
555 | IN UINTN Address,
|
---|
556 | IN UINTN Length
|
---|
557 | );
|
---|
558 |
|
---|
559 | /**
|
---|
560 | This function will be called by BSP to wakeup AP.
|
---|
561 |
|
---|
562 | @param[in] CpuMpData Pointer to CPU MP Data
|
---|
563 | @param[in] Broadcast TRUE: Send broadcast IPI to all APs
|
---|
564 | FALSE: Send IPI to AP by ApicId
|
---|
565 | @param[in] ProcessorNumber The handle number of specified processor
|
---|
566 | @param[in] Procedure The function to be invoked by AP
|
---|
567 | @param[in] ProcedureArgument The argument to be passed into AP function
|
---|
568 | @param[in] WakeUpDisabledAps Whether need to wake up disabled APs in broadcast mode.
|
---|
569 | **/
|
---|
570 | VOID
|
---|
571 | WakeUpAP (
|
---|
572 | IN CPU_MP_DATA *CpuMpData,
|
---|
573 | IN BOOLEAN Broadcast,
|
---|
574 | IN UINTN ProcessorNumber,
|
---|
575 | IN EFI_AP_PROCEDURE Procedure OPTIONAL,
|
---|
576 | IN VOID *ProcedureArgument OPTIONAL,
|
---|
577 | IN BOOLEAN WakeUpDisabledAps
|
---|
578 | );
|
---|
579 |
|
---|
580 | /**
|
---|
581 | Initialize global data for MP support.
|
---|
582 |
|
---|
583 | @param[in] CpuMpData The pointer to CPU MP Data structure.
|
---|
584 | **/
|
---|
585 | VOID
|
---|
586 | InitMpGlobalData (
|
---|
587 | IN CPU_MP_DATA *CpuMpData
|
---|
588 | );
|
---|
589 |
|
---|
590 | /**
|
---|
591 | Worker function to execute a caller provided function on all enabled APs.
|
---|
592 |
|
---|
593 | @param[in] Procedure A pointer to the function to be run on
|
---|
594 | enabled APs of the system.
|
---|
595 | @param[in] SingleThread If TRUE, then all the enabled APs execute
|
---|
596 | the function specified by Procedure one by
|
---|
597 | one, in ascending order of processor handle
|
---|
598 | number. If FALSE, then all the enabled APs
|
---|
599 | execute the function specified by Procedure
|
---|
600 | simultaneously.
|
---|
601 | @param[in] ExcludeBsp Whether let BSP also trig this task.
|
---|
602 | @param[in] WaitEvent The event created by the caller with CreateEvent()
|
---|
603 | service.
|
---|
604 | @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
|
---|
605 | APs to return from Procedure, either for
|
---|
606 | blocking or non-blocking mode.
|
---|
607 | @param[in] ProcedureArgument The parameter passed into Procedure for
|
---|
608 | all APs.
|
---|
609 | @param[out] FailedCpuList If all APs finish successfully, then its
|
---|
610 | content is set to NULL. If not all APs
|
---|
611 | finish before timeout expires, then its
|
---|
612 | content is set to address of the buffer
|
---|
613 | holding handle numbers of the failed APs.
|
---|
614 |
|
---|
615 | @retval EFI_SUCCESS In blocking mode, all APs have finished before
|
---|
616 | the timeout expired.
|
---|
617 | @retval EFI_SUCCESS In non-blocking mode, function has been dispatched
|
---|
618 | to all enabled APs.
|
---|
619 | @retval others Failed to Startup all APs.
|
---|
620 |
|
---|
621 | **/
|
---|
622 | EFI_STATUS
|
---|
623 | StartupAllCPUsWorker (
|
---|
624 | IN EFI_AP_PROCEDURE Procedure,
|
---|
625 | IN BOOLEAN SingleThread,
|
---|
626 | IN BOOLEAN ExcludeBsp,
|
---|
627 | IN EFI_EVENT WaitEvent OPTIONAL,
|
---|
628 | IN UINTN TimeoutInMicroseconds,
|
---|
629 | IN VOID *ProcedureArgument OPTIONAL,
|
---|
630 | OUT UINTN **FailedCpuList OPTIONAL
|
---|
631 | );
|
---|
632 |
|
---|
633 | /**
|
---|
634 | Worker function to let the caller get one enabled AP to execute a caller-provided
|
---|
635 | function.
|
---|
636 |
|
---|
637 | @param[in] Procedure A pointer to the function to be run on
|
---|
638 | enabled APs of the system.
|
---|
639 | @param[in] ProcessorNumber The handle number of the AP.
|
---|
640 | @param[in] WaitEvent The event created by the caller with CreateEvent()
|
---|
641 | service.
|
---|
642 | @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
|
---|
643 | APs to return from Procedure, either for
|
---|
644 | blocking or non-blocking mode.
|
---|
645 | @param[in] ProcedureArgument The parameter passed into Procedure for
|
---|
646 | all APs.
|
---|
647 | @param[out] Finished If AP returns from Procedure before the
|
---|
648 | timeout expires, its content is set to TRUE.
|
---|
649 | Otherwise, the value is set to FALSE.
|
---|
650 |
|
---|
651 | @retval EFI_SUCCESS In blocking mode, specified AP finished before
|
---|
652 | the timeout expires.
|
---|
653 | @retval others Failed to Startup AP.
|
---|
654 |
|
---|
655 | **/
|
---|
656 | EFI_STATUS
|
---|
657 | StartupThisAPWorker (
|
---|
658 | IN EFI_AP_PROCEDURE Procedure,
|
---|
659 | IN UINTN ProcessorNumber,
|
---|
660 | IN EFI_EVENT WaitEvent OPTIONAL,
|
---|
661 | IN UINTN TimeoutInMicroseconds,
|
---|
662 | IN VOID *ProcedureArgument OPTIONAL,
|
---|
663 | OUT BOOLEAN *Finished OPTIONAL
|
---|
664 | );
|
---|
665 |
|
---|
666 | /**
|
---|
667 | Worker function to switch the requested AP to be the BSP from that point onward.
|
---|
668 |
|
---|
669 | @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
|
---|
670 | @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
|
---|
671 | enabled AP. Otherwise, it will be disabled.
|
---|
672 |
|
---|
673 | @retval EFI_SUCCESS BSP successfully switched.
|
---|
674 | @retval others Failed to switch BSP.
|
---|
675 |
|
---|
676 | **/
|
---|
677 | EFI_STATUS
|
---|
678 | SwitchBSPWorker (
|
---|
679 | IN UINTN ProcessorNumber,
|
---|
680 | IN BOOLEAN EnableOldBSP
|
---|
681 | );
|
---|
682 |
|
---|
683 | /**
|
---|
684 | Worker function to let the caller enable or disable an AP from this point onward.
|
---|
685 | This service may only be called from the BSP.
|
---|
686 |
|
---|
687 | @param[in] ProcessorNumber The handle number of AP.
|
---|
688 | @param[in] EnableAP Specifies the new state for the processor for
|
---|
689 | enabled, FALSE for disabled.
|
---|
690 | @param[in] HealthFlag If not NULL, a pointer to a value that specifies
|
---|
691 | the new health status of the AP.
|
---|
692 |
|
---|
693 | @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
|
---|
694 | @retval others Failed to Enable/Disable AP.
|
---|
695 |
|
---|
696 | **/
|
---|
697 | EFI_STATUS
|
---|
698 | EnableDisableApWorker (
|
---|
699 | IN UINTN ProcessorNumber,
|
---|
700 | IN BOOLEAN EnableAP,
|
---|
701 | IN UINT32 *HealthFlag OPTIONAL
|
---|
702 | );
|
---|
703 |
|
---|
704 | /**
|
---|
705 | Get pointer to CPU MP Data structure from GUIDed HOB.
|
---|
706 |
|
---|
707 | @return The pointer to CPU MP Data structure.
|
---|
708 | **/
|
---|
709 | CPU_MP_DATA *
|
---|
710 | GetCpuMpDataFromGuidedHob (
|
---|
711 | VOID
|
---|
712 | );
|
---|
713 |
|
---|
714 | /** Checks status of specified AP.
|
---|
715 |
|
---|
716 | This function checks whether the specified AP has finished the task assigned
|
---|
717 | by StartupThisAP(), and whether timeout expires.
|
---|
718 |
|
---|
719 | @param[in] ProcessorNumber The handle number of processor.
|
---|
720 |
|
---|
721 | @retval EFI_SUCCESS Specified AP has finished task assigned by StartupThisAPs().
|
---|
722 | @retval EFI_TIMEOUT The timeout expires.
|
---|
723 | @retval EFI_NOT_READY Specified AP has not finished task and timeout has not expired.
|
---|
724 | **/
|
---|
725 | EFI_STATUS
|
---|
726 | CheckThisAP (
|
---|
727 | IN UINTN ProcessorNumber
|
---|
728 | );
|
---|
729 |
|
---|
730 | /**
|
---|
731 | Checks status of all APs.
|
---|
732 |
|
---|
733 | This function checks whether all APs have finished task assigned by StartupAllAPs(),
|
---|
734 | and whether timeout expires.
|
---|
735 |
|
---|
736 | @retval EFI_SUCCESS All APs have finished task assigned by StartupAllAPs().
|
---|
737 | @retval EFI_TIMEOUT The timeout expires.
|
---|
738 | @retval EFI_NOT_READY APs have not finished task and timeout has not expired.
|
---|
739 | **/
|
---|
740 | EFI_STATUS
|
---|
741 | CheckAllAPs (
|
---|
742 | VOID
|
---|
743 | );
|
---|
744 |
|
---|
745 | /**
|
---|
746 | Checks APs status and updates APs status if needed.
|
---|
747 |
|
---|
748 | **/
|
---|
749 | VOID
|
---|
750 | CheckAndUpdateApsStatus (
|
---|
751 | VOID
|
---|
752 | );
|
---|
753 |
|
---|
754 | /**
|
---|
755 | Detect whether specified processor can find matching microcode patch and load it.
|
---|
756 |
|
---|
757 | @param[in] CpuMpData The pointer to CPU MP Data structure.
|
---|
758 | @param[in] ProcessorNumber The handle number of the processor. The range is
|
---|
759 | from 0 to the total number of logical processors
|
---|
760 | minus 1.
|
---|
761 | **/
|
---|
762 | VOID
|
---|
763 | MicrocodeDetect (
|
---|
764 | IN CPU_MP_DATA *CpuMpData,
|
---|
765 | IN UINTN ProcessorNumber
|
---|
766 | );
|
---|
767 |
|
---|
768 | /**
|
---|
769 | Shadow the required microcode patches data into memory.
|
---|
770 |
|
---|
771 | @param[in, out] CpuMpData The pointer to CPU MP Data structure.
|
---|
772 | **/
|
---|
773 | VOID
|
---|
774 | ShadowMicrocodeUpdatePatch (
|
---|
775 | IN OUT CPU_MP_DATA *CpuMpData
|
---|
776 | );
|
---|
777 |
|
---|
778 | /**
|
---|
779 | Get the cached microcode patch base address and size from the microcode patch
|
---|
780 | information cache HOB.
|
---|
781 |
|
---|
782 | @param[out] Address Base address of the microcode patches data.
|
---|
783 | It will be updated if the microcode patch
|
---|
784 | information cache HOB is found.
|
---|
785 | @param[out] RegionSize Size of the microcode patches data.
|
---|
786 | It will be updated if the microcode patch
|
---|
787 | information cache HOB is found.
|
---|
788 |
|
---|
789 | @retval TRUE The microcode patch information cache HOB is found.
|
---|
790 | @retval FALSE The microcode patch information cache HOB is not found.
|
---|
791 |
|
---|
792 | **/
|
---|
793 | BOOLEAN
|
---|
794 | GetMicrocodePatchInfoFromHob (
|
---|
795 | UINT64 *Address,
|
---|
796 | UINT64 *RegionSize
|
---|
797 | );
|
---|
798 |
|
---|
799 | /**
|
---|
800 | Detect whether Mwait-monitor feature is supported.
|
---|
801 |
|
---|
802 | @retval TRUE Mwait-monitor feature is supported.
|
---|
803 | @retval FALSE Mwait-monitor feature is not supported.
|
---|
804 | **/
|
---|
805 | BOOLEAN
|
---|
806 | IsMwaitSupport (
|
---|
807 | VOID
|
---|
808 | );
|
---|
809 |
|
---|
810 | /**
|
---|
811 | Enable Debug Agent to support source debugging on AP function.
|
---|
812 |
|
---|
813 | **/
|
---|
814 | VOID
|
---|
815 | EnableDebugAgent (
|
---|
816 | VOID
|
---|
817 | );
|
---|
818 |
|
---|
819 | /**
|
---|
820 | Find the current Processor number by APIC ID.
|
---|
821 |
|
---|
822 | @param[in] CpuMpData Pointer to PEI CPU MP Data
|
---|
823 | @param[out] ProcessorNumber Return the pocessor number found
|
---|
824 |
|
---|
825 | @retval EFI_SUCCESS ProcessorNumber is found and returned.
|
---|
826 | @retval EFI_NOT_FOUND ProcessorNumber is not found.
|
---|
827 | **/
|
---|
828 | EFI_STATUS
|
---|
829 | GetProcessorNumber (
|
---|
830 | IN CPU_MP_DATA *CpuMpData,
|
---|
831 | OUT UINTN *ProcessorNumber
|
---|
832 | );
|
---|
833 |
|
---|
834 | /**
|
---|
835 | This funtion will try to invoke platform specific microcode shadow logic to
|
---|
836 | relocate microcode update patches into memory.
|
---|
837 |
|
---|
838 | @param[in, out] CpuMpData The pointer to CPU MP Data structure.
|
---|
839 |
|
---|
840 | @retval EFI_SUCCESS Shadow microcode success.
|
---|
841 | @retval EFI_OUT_OF_RESOURCES No enough resource to complete the operation.
|
---|
842 | @retval EFI_UNSUPPORTED Can't find platform specific microcode shadow
|
---|
843 | PPI/Protocol.
|
---|
844 | **/
|
---|
845 | EFI_STATUS
|
---|
846 | PlatformShadowMicrocode (
|
---|
847 | IN OUT CPU_MP_DATA *CpuMpData
|
---|
848 | );
|
---|
849 |
|
---|
850 | /**
|
---|
851 | Allocate the SEV-ES AP jump table buffer.
|
---|
852 |
|
---|
853 | @param[in, out] CpuMpData The pointer to CPU MP Data structure.
|
---|
854 | **/
|
---|
855 | VOID
|
---|
856 | AllocateSevEsAPMemory (
|
---|
857 | IN OUT CPU_MP_DATA *CpuMpData
|
---|
858 | );
|
---|
859 |
|
---|
860 | /**
|
---|
861 | Program the SEV-ES AP jump table buffer.
|
---|
862 |
|
---|
863 | @param[in] SipiVector The SIPI vector used for the AP Reset
|
---|
864 | **/
|
---|
865 | VOID
|
---|
866 | SetSevEsJumpTable (
|
---|
867 | IN UINTN SipiVector
|
---|
868 | );
|
---|
869 |
|
---|
870 | /**
|
---|
871 | The function puts the AP in halt loop.
|
---|
872 |
|
---|
873 | @param[in] CpuMpData The pointer to CPU MP Data structure.
|
---|
874 | **/
|
---|
875 | VOID
|
---|
876 | SevEsPlaceApHlt (
|
---|
877 | CPU_MP_DATA *CpuMpData
|
---|
878 | );
|
---|
879 |
|
---|
880 | /**
|
---|
881 | Check if the specified confidential computing attribute is active.
|
---|
882 |
|
---|
883 | @retval TRUE The specified Attr is active.
|
---|
884 | @retval FALSE The specified Attr is not active.
|
---|
885 | **/
|
---|
886 | BOOLEAN
|
---|
887 | EFIAPI
|
---|
888 | ConfidentialComputingGuestHas (
|
---|
889 | CONFIDENTIAL_COMPUTING_GUEST_ATTR Attr
|
---|
890 | );
|
---|
891 |
|
---|
892 | /**
|
---|
893 | The function fills the exchange data for the AP.
|
---|
894 |
|
---|
895 | @param[in] ExchangeInfo The pointer to CPU Exchange Data structure
|
---|
896 | **/
|
---|
897 | VOID
|
---|
898 | FillExchangeInfoDataSevEs (
|
---|
899 | IN volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo
|
---|
900 | );
|
---|
901 |
|
---|
902 | /**
|
---|
903 | Create an SEV-SNP AP save area (VMSA) for use in running the vCPU.
|
---|
904 |
|
---|
905 | @param[in] CpuMpData Pointer to CPU MP Data
|
---|
906 | @param[in] CpuData Pointer to CPU AP Data
|
---|
907 | @param[in] ApicId APIC ID of the vCPU
|
---|
908 | **/
|
---|
909 | VOID
|
---|
910 | SevSnpCreateSaveArea (
|
---|
911 | IN CPU_MP_DATA *CpuMpData,
|
---|
912 | IN CPU_AP_DATA *CpuData,
|
---|
913 | UINT32 ApicId
|
---|
914 | );
|
---|
915 |
|
---|
916 | /**
|
---|
917 | Create SEV-SNP APs.
|
---|
918 |
|
---|
919 | @param[in] CpuMpData Pointer to CPU MP Data
|
---|
920 | @param[in] ProcessorNumber The handle number of specified processor
|
---|
921 | (-1 for all APs)
|
---|
922 | **/
|
---|
923 | VOID
|
---|
924 | SevSnpCreateAP (
|
---|
925 | IN CPU_MP_DATA *CpuMpData,
|
---|
926 | IN INTN ProcessorNumber
|
---|
927 | );
|
---|
928 |
|
---|
929 | /**
|
---|
930 | Determine if the SEV-SNP AP Create protocol should be used.
|
---|
931 |
|
---|
932 | @param[in] CpuMpData Pointer to CPU MP Data
|
---|
933 |
|
---|
934 | @retval TRUE Use SEV-SNP AP Create protocol
|
---|
935 | @retval FALSE Do not use SEV-SNP AP Create protocol
|
---|
936 | **/
|
---|
937 | BOOLEAN
|
---|
938 | CanUseSevSnpCreateAP (
|
---|
939 | IN CPU_MP_DATA *CpuMpData
|
---|
940 | );
|
---|
941 |
|
---|
942 | /**
|
---|
943 | Get pointer to CPU MP Data structure from GUIDed HOB.
|
---|
944 |
|
---|
945 | @param[in] CpuMpData The pointer to CPU MP Data structure.
|
---|
946 | **/
|
---|
947 | VOID
|
---|
948 | AmdSevUpdateCpuMpData (
|
---|
949 | IN CPU_MP_DATA *CpuMpData
|
---|
950 | );
|
---|
951 |
|
---|
952 | /**
|
---|
953 | Prepare ApLoopCode.
|
---|
954 |
|
---|
955 | @param[in] CpuMpData Pointer to CpuMpData.
|
---|
956 | **/
|
---|
957 | VOID
|
---|
958 | PrepareApLoopCode (
|
---|
959 | IN CPU_MP_DATA *CpuMpData
|
---|
960 | );
|
---|
961 |
|
---|
962 | /**
|
---|
963 | Do sync on APs.
|
---|
964 |
|
---|
965 | @param[in, out] Buffer Pointer to private data buffer.
|
---|
966 | **/
|
---|
967 | VOID
|
---|
968 | EFIAPI
|
---|
969 | RelocateApLoop (
|
---|
970 | IN OUT VOID *Buffer
|
---|
971 | );
|
---|
972 |
|
---|
973 | /**
|
---|
974 | Allocate buffer for ApLoopCode.
|
---|
975 |
|
---|
976 | @param[in] Pages Number of pages to allocate.
|
---|
977 | @param[in, out] Address Pointer to the allocated buffer.
|
---|
978 | **/
|
---|
979 | VOID
|
---|
980 | AllocateApLoopCodeBuffer (
|
---|
981 | IN UINTN Pages,
|
---|
982 | IN OUT EFI_PHYSICAL_ADDRESS *Address
|
---|
983 | );
|
---|
984 |
|
---|
985 | /**
|
---|
986 | Remove Nx protection for the range specific by BaseAddress and Length.
|
---|
987 |
|
---|
988 | The PEI implementation uses CpuPageTableLib to change the attribute.
|
---|
989 | The DXE implementation uses gDS to change the attribute.
|
---|
990 |
|
---|
991 | @param[in] BaseAddress BaseAddress of the range.
|
---|
992 | @param[in] Length Length of the range.
|
---|
993 | **/
|
---|
994 | VOID
|
---|
995 | RemoveNxprotection (
|
---|
996 | IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
---|
997 | IN UINTN Length
|
---|
998 | );
|
---|
999 |
|
---|
1000 | #endif
|
---|