1 | /** @file
|
---|
2 | The CPU specific programming for PiSmmCpuDxeSmm module.
|
---|
3 |
|
---|
4 | Copyright (c) 2010 - 2023, Intel Corporation. All rights reserved.<BR>
|
---|
5 |
|
---|
6 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
7 | **/
|
---|
8 |
|
---|
9 | #include <IndustryStandard/Q35MchIch9.h>
|
---|
10 | #include <Library/BaseLib.h>
|
---|
11 | #include <Library/BaseMemoryLib.h>
|
---|
12 | #include <Library/DebugLib.h>
|
---|
13 | #include <Library/MemEncryptSevLib.h>
|
---|
14 | #include <Library/MemoryAllocationLib.h>
|
---|
15 | #include <Library/PcdLib.h>
|
---|
16 | #include <Library/SafeIntLib.h>
|
---|
17 | #include <Library/SmmCpuFeaturesLib.h>
|
---|
18 | #include <Library/SmmServicesTableLib.h>
|
---|
19 | #include <Library/UefiBootServicesTableLib.h>
|
---|
20 | #include <Library/HobLib.h>
|
---|
21 | #include <Pcd/CpuHotEjectData.h>
|
---|
22 | #include <PiSmm.h>
|
---|
23 | #include <Register/Amd/SmramSaveStateMap.h>
|
---|
24 | #include <Guid/SmmBaseHob.h>
|
---|
25 |
|
---|
26 | //
|
---|
27 | // EFER register LMA bit
|
---|
28 | //
|
---|
29 | #define LMA BIT10
|
---|
30 |
|
---|
31 | //
|
---|
32 | // Indicate SmBase for each Processors has been relocated or not. If TRUE,
|
---|
33 | // means no need to do the relocation in SmmCpuFeaturesInitializeProcessor().
|
---|
34 | //
|
---|
35 | BOOLEAN mSmmCpuFeaturesSmmRelocated;
|
---|
36 |
|
---|
37 | /**
|
---|
38 | The constructor function
|
---|
39 |
|
---|
40 | @param[in] ImageHandle The firmware allocated handle for the EFI image.
|
---|
41 | @param[in] SystemTable A pointer to the EFI System Table.
|
---|
42 |
|
---|
43 | @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
|
---|
44 |
|
---|
45 | **/
|
---|
46 | EFI_STATUS
|
---|
47 | EFIAPI
|
---|
48 | SmmCpuFeaturesLibConstructor (
|
---|
49 | IN EFI_HANDLE ImageHandle,
|
---|
50 | IN EFI_SYSTEM_TABLE *SystemTable
|
---|
51 | )
|
---|
52 | {
|
---|
53 | //
|
---|
54 | // If gSmmBaseHobGuid found, means SmBase info has been relocated and recorded
|
---|
55 | // in the SmBase array.
|
---|
56 | //
|
---|
57 | mSmmCpuFeaturesSmmRelocated = (BOOLEAN)(GetFirstGuidHob (&gSmmBaseHobGuid) != NULL);
|
---|
58 |
|
---|
59 | //
|
---|
60 | // No need to program SMRRs on our virtual platform.
|
---|
61 | //
|
---|
62 | return EFI_SUCCESS;
|
---|
63 | }
|
---|
64 |
|
---|
65 | /**
|
---|
66 | Called during the very first SMI into System Management Mode to initialize
|
---|
67 | CPU features, including SMBASE, for the currently executing CPU. Since this
|
---|
68 | is the first SMI, the SMRAM Save State Map is at the default address of
|
---|
69 | SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET. The currently executing
|
---|
70 | CPU is specified by CpuIndex and CpuIndex can be used to access information
|
---|
71 | about the currently executing CPU in the ProcessorInfo array and the
|
---|
72 | HotPlugCpuData data structure.
|
---|
73 |
|
---|
74 | @param[in] CpuIndex The index of the CPU to initialize. The value
|
---|
75 | must be between 0 and the NumberOfCpus field in
|
---|
76 | the System Management System Table (SMST).
|
---|
77 | @param[in] IsMonarch TRUE if the CpuIndex is the index of the CPU that
|
---|
78 | was elected as monarch during System Management
|
---|
79 | Mode initialization.
|
---|
80 | FALSE if the CpuIndex is not the index of the CPU
|
---|
81 | that was elected as monarch during System
|
---|
82 | Management Mode initialization.
|
---|
83 | @param[in] ProcessorInfo Pointer to an array of EFI_PROCESSOR_INFORMATION
|
---|
84 | structures. ProcessorInfo[CpuIndex] contains the
|
---|
85 | information for the currently executing CPU.
|
---|
86 | @param[in] CpuHotPlugData Pointer to the CPU_HOT_PLUG_DATA structure that
|
---|
87 | contains the ApidId and SmBase arrays.
|
---|
88 | **/
|
---|
89 | VOID
|
---|
90 | EFIAPI
|
---|
91 | SmmCpuFeaturesInitializeProcessor (
|
---|
92 | IN UINTN CpuIndex,
|
---|
93 | IN BOOLEAN IsMonarch,
|
---|
94 | IN EFI_PROCESSOR_INFORMATION *ProcessorInfo,
|
---|
95 | IN CPU_HOT_PLUG_DATA *CpuHotPlugData
|
---|
96 | )
|
---|
97 | {
|
---|
98 | AMD_SMRAM_SAVE_STATE_MAP *CpuState;
|
---|
99 |
|
---|
100 | //
|
---|
101 | // No need to configure SMBASE if SmBase relocation has been done.
|
---|
102 | //
|
---|
103 | if (!mSmmCpuFeaturesSmmRelocated) {
|
---|
104 | //
|
---|
105 | // Configure SMBASE.
|
---|
106 | //
|
---|
107 | CpuState = (AMD_SMRAM_SAVE_STATE_MAP *)(UINTN)(
|
---|
108 | SMM_DEFAULT_SMBASE +
|
---|
109 | SMRAM_SAVE_STATE_MAP_OFFSET
|
---|
110 | );
|
---|
111 | if ((CpuState->x86.SMMRevId & 0xFFFF) == 0) {
|
---|
112 | CpuState->x86.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex];
|
---|
113 | } else {
|
---|
114 | CpuState->x64.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex];
|
---|
115 | }
|
---|
116 | }
|
---|
117 |
|
---|
118 | //
|
---|
119 | // No need to program SMRRs on our virtual platform.
|
---|
120 | //
|
---|
121 | }
|
---|
122 |
|
---|
123 | /**
|
---|
124 | This function updates the SMRAM save state on the currently executing CPU
|
---|
125 | to resume execution at a specific address after an RSM instruction. This
|
---|
126 | function must evaluate the SMRAM save state to determine the execution mode
|
---|
127 | the RSM instruction resumes and update the resume execution address with
|
---|
128 | either NewInstructionPointer32 or NewInstructionPoint. The auto HALT restart
|
---|
129 | flag in the SMRAM save state must always be cleared. This function returns
|
---|
130 | the value of the instruction pointer from the SMRAM save state that was
|
---|
131 | replaced. If this function returns 0, then the SMRAM save state was not
|
---|
132 | modified.
|
---|
133 |
|
---|
134 | This function is called during the very first SMI on each CPU after
|
---|
135 | SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode
|
---|
136 | to signal that the SMBASE of each CPU has been updated before the default
|
---|
137 | SMBASE address is used for the first SMI to the next CPU.
|
---|
138 |
|
---|
139 | @param[in] CpuIndex The index of the CPU to hook. The value
|
---|
140 | must be between 0 and the NumberOfCpus
|
---|
141 | field in the System Management System
|
---|
142 | Table (SMST).
|
---|
143 | @param[in] CpuState Pointer to SMRAM Save State Map for the
|
---|
144 | currently executing CPU.
|
---|
145 | @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to
|
---|
146 | 32-bit execution mode from 64-bit SMM.
|
---|
147 | @param[in] NewInstructionPointer Instruction pointer to use if resuming to
|
---|
148 | same execution mode as SMM.
|
---|
149 |
|
---|
150 | @retval 0 This function did modify the SMRAM save state.
|
---|
151 | @retval > 0 The original instruction pointer value from the SMRAM save state
|
---|
152 | before it was replaced.
|
---|
153 | **/
|
---|
154 | UINT64
|
---|
155 | EFIAPI
|
---|
156 | SmmCpuFeaturesHookReturnFromSmm (
|
---|
157 | IN UINTN CpuIndex,
|
---|
158 | IN SMRAM_SAVE_STATE_MAP *CpuState,
|
---|
159 | IN UINT64 NewInstructionPointer32,
|
---|
160 | IN UINT64 NewInstructionPointer
|
---|
161 | )
|
---|
162 | {
|
---|
163 | UINT64 OriginalInstructionPointer;
|
---|
164 | AMD_SMRAM_SAVE_STATE_MAP *CpuSaveState;
|
---|
165 |
|
---|
166 | CpuSaveState = (AMD_SMRAM_SAVE_STATE_MAP *)CpuState;
|
---|
167 | if ((CpuSaveState->x86.SMMRevId & 0xFFFF) == 0) {
|
---|
168 | OriginalInstructionPointer = (UINT64)CpuSaveState->x86._EIP;
|
---|
169 | CpuSaveState->x86._EIP = (UINT32)NewInstructionPointer;
|
---|
170 | //
|
---|
171 | // Clear the auto HALT restart flag so the RSM instruction returns
|
---|
172 | // program control to the instruction following the HLT instruction.
|
---|
173 | //
|
---|
174 | if ((CpuSaveState->x86.AutoHALTRestart & BIT0) != 0) {
|
---|
175 | CpuSaveState->x86.AutoHALTRestart &= ~BIT0;
|
---|
176 | }
|
---|
177 | } else {
|
---|
178 | OriginalInstructionPointer = CpuSaveState->x64._RIP;
|
---|
179 | if ((CpuSaveState->x64.EFER & LMA) == 0) {
|
---|
180 | CpuSaveState->x64._RIP = (UINT32)NewInstructionPointer32;
|
---|
181 | } else {
|
---|
182 | CpuSaveState->x64._RIP = (UINT32)NewInstructionPointer;
|
---|
183 | }
|
---|
184 |
|
---|
185 | //
|
---|
186 | // Clear the auto HALT restart flag so the RSM instruction returns
|
---|
187 | // program control to the instruction following the HLT instruction.
|
---|
188 | //
|
---|
189 | if ((CpuSaveState->x64.AutoHALTRestart & BIT0) != 0) {
|
---|
190 | CpuSaveState->x64.AutoHALTRestart &= ~BIT0;
|
---|
191 | }
|
---|
192 | }
|
---|
193 |
|
---|
194 | return OriginalInstructionPointer;
|
---|
195 | }
|
---|
196 |
|
---|
197 | STATIC CPU_HOT_EJECT_DATA *mCpuHotEjectData = NULL;
|
---|
198 |
|
---|
199 | /**
|
---|
200 | Initialize mCpuHotEjectData if PcdCpuMaxLogicalProcessorNumber > 1.
|
---|
201 |
|
---|
202 | Also setup the corresponding PcdCpuHotEjectDataAddress.
|
---|
203 | **/
|
---|
204 | STATIC
|
---|
205 | VOID
|
---|
206 | InitCpuHotEjectData (
|
---|
207 | VOID
|
---|
208 | )
|
---|
209 | {
|
---|
210 | UINTN Size;
|
---|
211 | UINT32 Idx;
|
---|
212 | UINT32 MaxNumberOfCpus;
|
---|
213 | RETURN_STATUS PcdStatus;
|
---|
214 |
|
---|
215 | MaxNumberOfCpus = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
|
---|
216 | if (MaxNumberOfCpus == 1) {
|
---|
217 | return;
|
---|
218 | }
|
---|
219 |
|
---|
220 | //
|
---|
221 | // We allocate CPU_HOT_EJECT_DATA and CPU_HOT_EJECT_DATA->QemuSelectorMap[]
|
---|
222 | // in a single allocation, and explicitly align the QemuSelectorMap[] (which
|
---|
223 | // is a UINT64 array) at its natural boundary.
|
---|
224 | // Accordingly, allocate:
|
---|
225 | // sizeof(*mCpuHotEjectData) + (MaxNumberOfCpus * sizeof(UINT64))
|
---|
226 | // and, add sizeof(UINT64) - 1 to use as padding if needed.
|
---|
227 | //
|
---|
228 |
|
---|
229 | if (RETURN_ERROR (SafeUintnMult (MaxNumberOfCpus, sizeof (UINT64), &Size)) ||
|
---|
230 | RETURN_ERROR (SafeUintnAdd (Size, sizeof (*mCpuHotEjectData), &Size)) ||
|
---|
231 | RETURN_ERROR (SafeUintnAdd (Size, sizeof (UINT64) - 1, &Size)))
|
---|
232 | {
|
---|
233 | DEBUG ((DEBUG_ERROR, "%a: invalid CPU_HOT_EJECT_DATA\n", __func__));
|
---|
234 | goto Fatal;
|
---|
235 | }
|
---|
236 |
|
---|
237 | mCpuHotEjectData = AllocatePool (Size);
|
---|
238 | if (mCpuHotEjectData == NULL) {
|
---|
239 | ASSERT (mCpuHotEjectData != NULL);
|
---|
240 | goto Fatal;
|
---|
241 | }
|
---|
242 |
|
---|
243 | mCpuHotEjectData->Handler = NULL;
|
---|
244 | mCpuHotEjectData->ArrayLength = MaxNumberOfCpus;
|
---|
245 |
|
---|
246 | mCpuHotEjectData->QemuSelectorMap = ALIGN_POINTER (
|
---|
247 | mCpuHotEjectData + 1,
|
---|
248 | sizeof (UINT64)
|
---|
249 | );
|
---|
250 | //
|
---|
251 | // We use mCpuHotEjectData->QemuSelectorMap to map
|
---|
252 | // ProcessorNum -> QemuSelector. Initialize to invalid values.
|
---|
253 | //
|
---|
254 | for (Idx = 0; Idx < mCpuHotEjectData->ArrayLength; Idx++) {
|
---|
255 | mCpuHotEjectData->QemuSelectorMap[Idx] = CPU_EJECT_QEMU_SELECTOR_INVALID;
|
---|
256 | }
|
---|
257 |
|
---|
258 | //
|
---|
259 | // Expose address of CPU Hot eject Data structure
|
---|
260 | //
|
---|
261 | PcdStatus = PcdSet64S (
|
---|
262 | PcdCpuHotEjectDataAddress,
|
---|
263 | (UINTN)(VOID *)mCpuHotEjectData
|
---|
264 | );
|
---|
265 | ASSERT_RETURN_ERROR (PcdStatus);
|
---|
266 |
|
---|
267 | return;
|
---|
268 |
|
---|
269 | Fatal:
|
---|
270 | CpuDeadLoop ();
|
---|
271 | }
|
---|
272 |
|
---|
273 | /**
|
---|
274 | Hook point in normal execution mode that allows the one CPU that was elected
|
---|
275 | as monarch during System Management Mode initialization to perform additional
|
---|
276 | initialization actions immediately after all of the CPUs have processed their
|
---|
277 | first SMI and called SmmCpuFeaturesInitializeProcessor() relocating SMBASE
|
---|
278 | into a buffer in SMRAM and called SmmCpuFeaturesHookReturnFromSmm().
|
---|
279 | **/
|
---|
280 | VOID
|
---|
281 | EFIAPI
|
---|
282 | SmmCpuFeaturesSmmRelocationComplete (
|
---|
283 | VOID
|
---|
284 | )
|
---|
285 | {
|
---|
286 | EFI_STATUS Status;
|
---|
287 | UINTN MapPagesBase;
|
---|
288 | UINTN MapPagesCount;
|
---|
289 |
|
---|
290 | InitCpuHotEjectData ();
|
---|
291 |
|
---|
292 | if (!MemEncryptSevIsEnabled ()) {
|
---|
293 | return;
|
---|
294 | }
|
---|
295 |
|
---|
296 | //
|
---|
297 | // Now that SMBASE relocation is complete, re-encrypt the original SMRAM save
|
---|
298 | // state map's container pages, and release the pages to DXE. (The pages were
|
---|
299 | // allocated in PlatformPei.)
|
---|
300 | //
|
---|
301 | Status = MemEncryptSevLocateInitialSmramSaveStateMapPages (
|
---|
302 | &MapPagesBase,
|
---|
303 | &MapPagesCount
|
---|
304 | );
|
---|
305 | ASSERT_EFI_ERROR (Status);
|
---|
306 |
|
---|
307 | Status = MemEncryptSevSetPageEncMask (
|
---|
308 | 0, // Cr3BaseAddress -- use current CR3
|
---|
309 | MapPagesBase, // BaseAddress
|
---|
310 | MapPagesCount // NumPages
|
---|
311 | );
|
---|
312 | if (EFI_ERROR (Status)) {
|
---|
313 | DEBUG ((
|
---|
314 | DEBUG_ERROR,
|
---|
315 | "%a: MemEncryptSevSetPageEncMask(): %r\n",
|
---|
316 | __func__,
|
---|
317 | Status
|
---|
318 | ));
|
---|
319 | ASSERT (FALSE);
|
---|
320 | CpuDeadLoop ();
|
---|
321 | }
|
---|
322 |
|
---|
323 | ZeroMem ((VOID *)MapPagesBase, EFI_PAGES_TO_SIZE (MapPagesCount));
|
---|
324 |
|
---|
325 | if (PcdGetBool (PcdQ35SmramAtDefaultSmbase)) {
|
---|
326 | //
|
---|
327 | // The initial SMRAM Save State Map has been covered as part of a larger
|
---|
328 | // reserved memory allocation in PlatformPei's InitializeRamRegions(). That
|
---|
329 | // allocation is supposed to survive into OS runtime; we must not release
|
---|
330 | // any part of it. Only re-assert the containment here.
|
---|
331 | //
|
---|
332 | ASSERT (SMM_DEFAULT_SMBASE <= MapPagesBase);
|
---|
333 | ASSERT (
|
---|
334 | (MapPagesBase + EFI_PAGES_TO_SIZE (MapPagesCount) <=
|
---|
335 | SMM_DEFAULT_SMBASE + MCH_DEFAULT_SMBASE_SIZE)
|
---|
336 | );
|
---|
337 | } else {
|
---|
338 | Status = gBS->FreePages (MapPagesBase, MapPagesCount);
|
---|
339 | ASSERT_EFI_ERROR (Status);
|
---|
340 | }
|
---|
341 | }
|
---|
342 |
|
---|
343 | /**
|
---|
344 | Return the size, in bytes, of a custom SMI Handler in bytes. If 0 is
|
---|
345 | returned, then a custom SMI handler is not provided by this library,
|
---|
346 | and the default SMI handler must be used.
|
---|
347 |
|
---|
348 | @retval 0 Use the default SMI handler.
|
---|
349 | @retval > 0 Use the SMI handler installed by
|
---|
350 | SmmCpuFeaturesInstallSmiHandler(). The caller is required to
|
---|
351 | allocate enough SMRAM for each CPU to support the size of the
|
---|
352 | custom SMI handler.
|
---|
353 | **/
|
---|
354 | UINTN
|
---|
355 | EFIAPI
|
---|
356 | SmmCpuFeaturesGetSmiHandlerSize (
|
---|
357 | VOID
|
---|
358 | )
|
---|
359 | {
|
---|
360 | return 0;
|
---|
361 | }
|
---|
362 |
|
---|
363 | /**
|
---|
364 | Install a custom SMI handler for the CPU specified by CpuIndex. This
|
---|
365 | function is only called if SmmCpuFeaturesGetSmiHandlerSize() returns a size
|
---|
366 | is greater than zero and is called by the CPU that was elected as monarch
|
---|
367 | during System Management Mode initialization.
|
---|
368 |
|
---|
369 | @param[in] CpuIndex The index of the CPU to install the custom SMI handler.
|
---|
370 | The value must be between 0 and the NumberOfCpus field
|
---|
371 | in the System Management System Table (SMST).
|
---|
372 | @param[in] SmBase The SMBASE address for the CPU specified by CpuIndex.
|
---|
373 | @param[in] SmiStack The stack to use when an SMI is processed by the
|
---|
374 | the CPU specified by CpuIndex.
|
---|
375 | @param[in] StackSize The size, in bytes, if the stack used when an SMI is
|
---|
376 | processed by the CPU specified by CpuIndex.
|
---|
377 | @param[in] GdtBase The base address of the GDT to use when an SMI is
|
---|
378 | processed by the CPU specified by CpuIndex.
|
---|
379 | @param[in] GdtSize The size, in bytes, of the GDT used when an SMI is
|
---|
380 | processed by the CPU specified by CpuIndex.
|
---|
381 | @param[in] IdtBase The base address of the IDT to use when an SMI is
|
---|
382 | processed by the CPU specified by CpuIndex.
|
---|
383 | @param[in] IdtSize The size, in bytes, of the IDT used when an SMI is
|
---|
384 | processed by the CPU specified by CpuIndex.
|
---|
385 | @param[in] Cr3 The base address of the page tables to use when an SMI
|
---|
386 | is processed by the CPU specified by CpuIndex.
|
---|
387 | **/
|
---|
388 | VOID
|
---|
389 | EFIAPI
|
---|
390 | SmmCpuFeaturesInstallSmiHandler (
|
---|
391 | IN UINTN CpuIndex,
|
---|
392 | IN UINT32 SmBase,
|
---|
393 | IN VOID *SmiStack,
|
---|
394 | IN UINTN StackSize,
|
---|
395 | IN UINTN GdtBase,
|
---|
396 | IN UINTN GdtSize,
|
---|
397 | IN UINTN IdtBase,
|
---|
398 | IN UINTN IdtSize,
|
---|
399 | IN UINT32 Cr3
|
---|
400 | )
|
---|
401 | {
|
---|
402 | }
|
---|
403 |
|
---|
404 | /**
|
---|
405 | Determines if MTRR registers must be configured to set SMRAM cache-ability
|
---|
406 | when executing in System Management Mode.
|
---|
407 |
|
---|
408 | @retval TRUE MTRR registers must be configured to set SMRAM cache-ability.
|
---|
409 | @retval FALSE MTRR registers do not need to be configured to set SMRAM
|
---|
410 | cache-ability.
|
---|
411 | **/
|
---|
412 | BOOLEAN
|
---|
413 | EFIAPI
|
---|
414 | SmmCpuFeaturesNeedConfigureMtrrs (
|
---|
415 | VOID
|
---|
416 | )
|
---|
417 | {
|
---|
418 | return FALSE;
|
---|
419 | }
|
---|
420 |
|
---|
421 | /**
|
---|
422 | Disable SMRR register if SMRR is supported and
|
---|
423 | SmmCpuFeaturesNeedConfigureMtrrs() returns TRUE.
|
---|
424 | **/
|
---|
425 | VOID
|
---|
426 | EFIAPI
|
---|
427 | SmmCpuFeaturesDisableSmrr (
|
---|
428 | VOID
|
---|
429 | )
|
---|
430 | {
|
---|
431 | //
|
---|
432 | // No SMRR support, nothing to do
|
---|
433 | //
|
---|
434 | }
|
---|
435 |
|
---|
436 | /**
|
---|
437 | Enable SMRR register if SMRR is supported and
|
---|
438 | SmmCpuFeaturesNeedConfigureMtrrs() returns TRUE.
|
---|
439 | **/
|
---|
440 | VOID
|
---|
441 | EFIAPI
|
---|
442 | SmmCpuFeaturesReenableSmrr (
|
---|
443 | VOID
|
---|
444 | )
|
---|
445 | {
|
---|
446 | //
|
---|
447 | // No SMRR support, nothing to do
|
---|
448 | //
|
---|
449 | }
|
---|
450 |
|
---|
451 | /**
|
---|
452 | Processor specific hook point each time a CPU enters System Management Mode.
|
---|
453 |
|
---|
454 | @param[in] CpuIndex The index of the CPU that has entered SMM. The value
|
---|
455 | must be between 0 and the NumberOfCpus field in the
|
---|
456 | System Management System Table (SMST).
|
---|
457 | **/
|
---|
458 | VOID
|
---|
459 | EFIAPI
|
---|
460 | SmmCpuFeaturesRendezvousEntry (
|
---|
461 | IN UINTN CpuIndex
|
---|
462 | )
|
---|
463 | {
|
---|
464 | //
|
---|
465 | // No SMRR support, nothing to do
|
---|
466 | //
|
---|
467 | }
|
---|
468 |
|
---|
469 | /**
|
---|
470 | Processor specific hook point each time a CPU exits System Management Mode.
|
---|
471 |
|
---|
472 | @param[in] CpuIndex The index of the CPU that is exiting SMM. The value
|
---|
473 | must be between 0 and the NumberOfCpus field in the
|
---|
474 | System Management System Table (SMST).
|
---|
475 | **/
|
---|
476 | VOID
|
---|
477 | EFIAPI
|
---|
478 | SmmCpuFeaturesRendezvousExit (
|
---|
479 | IN UINTN CpuIndex
|
---|
480 | )
|
---|
481 | {
|
---|
482 | //
|
---|
483 | // We only call the Handler if CPU hot-eject is enabled
|
---|
484 | // (PcdCpuMaxLogicalProcessorNumber > 1), and hot-eject is needed
|
---|
485 | // in this SMI exit (otherwise mCpuHotEjectData->Handler is not armed.)
|
---|
486 | //
|
---|
487 |
|
---|
488 | if (mCpuHotEjectData != NULL) {
|
---|
489 | CPU_HOT_EJECT_HANDLER Handler;
|
---|
490 |
|
---|
491 | //
|
---|
492 | // As the comment above mentions, mCpuHotEjectData->Handler might be
|
---|
493 | // written to on the BSP as part of handling of the CPU-ejection.
|
---|
494 | //
|
---|
495 | // We know that any initial assignment to mCpuHotEjectData->Handler
|
---|
496 | // (on the BSP, in the CpuHotplugMmi() context) is ordered-before the
|
---|
497 | // load below, since it is guaranteed to happen before the
|
---|
498 | // control-dependency of the BSP's SMI exit signal -- by way of a store
|
---|
499 | // to AllCpusInSync (on the BSP, in BspHandler()) and the corresponding
|
---|
500 | // AllCpusInSync loop (on the APs, in SmiRendezvous()) which depends on
|
---|
501 | // that store.
|
---|
502 | //
|
---|
503 | // This guarantees that these pieces of code can never execute
|
---|
504 | // simultaneously. In addition, we ensure that the following load is
|
---|
505 | // ordered-after the AllCpusInSync loop by using a MemoryFence() with
|
---|
506 | // acquire semantics.
|
---|
507 | //
|
---|
508 | MemoryFence ();
|
---|
509 |
|
---|
510 | Handler = mCpuHotEjectData->Handler;
|
---|
511 |
|
---|
512 | if (Handler != NULL) {
|
---|
513 | Handler (CpuIndex);
|
---|
514 | }
|
---|
515 | }
|
---|
516 | }
|
---|
517 |
|
---|
518 | /**
|
---|
519 | Check to see if an SMM register is supported by a specified CPU.
|
---|
520 |
|
---|
521 | @param[in] CpuIndex The index of the CPU to check for SMM register support.
|
---|
522 | The value must be between 0 and the NumberOfCpus field
|
---|
523 | in the System Management System Table (SMST).
|
---|
524 | @param[in] RegName Identifies the SMM register to check for support.
|
---|
525 |
|
---|
526 | @retval TRUE The SMM register specified by RegName is supported by the CPU
|
---|
527 | specified by CpuIndex.
|
---|
528 | @retval FALSE The SMM register specified by RegName is not supported by the
|
---|
529 | CPU specified by CpuIndex.
|
---|
530 | **/
|
---|
531 | BOOLEAN
|
---|
532 | EFIAPI
|
---|
533 | SmmCpuFeaturesIsSmmRegisterSupported (
|
---|
534 | IN UINTN CpuIndex,
|
---|
535 | IN SMM_REG_NAME RegName
|
---|
536 | )
|
---|
537 | {
|
---|
538 | ASSERT (RegName == SmmRegFeatureControl);
|
---|
539 | return FALSE;
|
---|
540 | }
|
---|
541 |
|
---|
542 | /**
|
---|
543 | Returns the current value of the SMM register for the specified CPU.
|
---|
544 | If the SMM register is not supported, then 0 is returned.
|
---|
545 |
|
---|
546 | @param[in] CpuIndex The index of the CPU to read the SMM register. The
|
---|
547 | value must be between 0 and the NumberOfCpus field in
|
---|
548 | the System Management System Table (SMST).
|
---|
549 | @param[in] RegName Identifies the SMM register to read.
|
---|
550 |
|
---|
551 | @return The value of the SMM register specified by RegName from the CPU
|
---|
552 | specified by CpuIndex.
|
---|
553 | **/
|
---|
554 | UINT64
|
---|
555 | EFIAPI
|
---|
556 | SmmCpuFeaturesGetSmmRegister (
|
---|
557 | IN UINTN CpuIndex,
|
---|
558 | IN SMM_REG_NAME RegName
|
---|
559 | )
|
---|
560 | {
|
---|
561 | //
|
---|
562 | // This is called for SmmRegSmmDelayed, SmmRegSmmBlocked, SmmRegSmmEnable.
|
---|
563 | // The last of these should actually be SmmRegSmmDisable, so we can just
|
---|
564 | // return FALSE.
|
---|
565 | //
|
---|
566 | return 0;
|
---|
567 | }
|
---|
568 |
|
---|
569 | /**
|
---|
570 | Sets the value of an SMM register on a specified CPU.
|
---|
571 | If the SMM register is not supported, then no action is performed.
|
---|
572 |
|
---|
573 | @param[in] CpuIndex The index of the CPU to write the SMM register. The
|
---|
574 | value must be between 0 and the NumberOfCpus field in
|
---|
575 | the System Management System Table (SMST).
|
---|
576 | @param[in] RegName Identifies the SMM register to write.
|
---|
577 | registers are read-only.
|
---|
578 | @param[in] Value The value to write to the SMM register.
|
---|
579 | **/
|
---|
580 | VOID
|
---|
581 | EFIAPI
|
---|
582 | SmmCpuFeaturesSetSmmRegister (
|
---|
583 | IN UINTN CpuIndex,
|
---|
584 | IN SMM_REG_NAME RegName,
|
---|
585 | IN UINT64 Value
|
---|
586 | )
|
---|
587 | {
|
---|
588 | ASSERT (FALSE);
|
---|
589 | }
|
---|
590 |
|
---|
591 | /**
|
---|
592 | This function is hook point called after the gEfiSmmReadyToLockProtocolGuid
|
---|
593 | notification is completely processed.
|
---|
594 | **/
|
---|
595 | VOID
|
---|
596 | EFIAPI
|
---|
597 | SmmCpuFeaturesCompleteSmmReadyToLock (
|
---|
598 | VOID
|
---|
599 | )
|
---|
600 | {
|
---|
601 | }
|
---|