mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-30 10:43:45 +01:00 
			
		
		
		
	OvmfPkg/CpuHotplugSmm: introduce First SMI Handler for hot-added CPUs
Implement the First SMI Handler for hot-added CPUs, in NASM. Add the interfacing C-language function that the SMM Monarch calls. This function launches and coordinates SMBASE relocation for a hot-added CPU. Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Igor Mammedov <imammedo@redhat.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Michael Kinney <michael.d.kinney@intel.com> Cc: Philippe Mathieu-Daudé <philmd@redhat.com> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1512 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Message-Id: <20200226221156.29589-13-lersek@redhat.com> Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Tested-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
This commit is contained in:
		
							parent
							
								
									63c89da242
								
							
						
					
					
						commit
						51a6fb4118
					
				| @ -24,6 +24,8 @@ | |||||||
| [Sources] | [Sources] | ||||||
|   ApicId.h |   ApicId.h | ||||||
|   CpuHotplug.c |   CpuHotplug.c | ||||||
|  |   FirstSmiHandler.nasm | ||||||
|  |   FirstSmiHandlerContext.h | ||||||
|   PostSmmPen.nasm |   PostSmmPen.nasm | ||||||
|   QemuCpuhp.c |   QemuCpuhp.c | ||||||
|   QemuCpuhp.h |   QemuCpuhp.h | ||||||
| @ -39,9 +41,11 @@ | |||||||
|   BaseLib |   BaseLib | ||||||
|   BaseMemoryLib |   BaseMemoryLib | ||||||
|   DebugLib |   DebugLib | ||||||
|  |   LocalApicLib | ||||||
|   MmServicesTableLib |   MmServicesTableLib | ||||||
|   PcdLib |   PcdLib | ||||||
|   SafeIntLib |   SafeIntLib | ||||||
|  |   SynchronizationLib | ||||||
|   UefiDriverEntryPoint |   UefiDriverEntryPoint | ||||||
| 
 | 
 | ||||||
| [Protocols] | [Protocols] | ||||||
|  | |||||||
							
								
								
									
										154
									
								
								OvmfPkg/CpuHotplugSmm/FirstSmiHandler.nasm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								OvmfPkg/CpuHotplugSmm/FirstSmiHandler.nasm
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,154 @@ | |||||||
|  | ;------------------------------------------------------------------------------ | ||||||
|  | ; @file | ||||||
|  | ; Relocate the SMBASE on a hot-added CPU when it services its first SMI. | ||||||
|  | ; | ||||||
|  | ; Copyright (c) 2020, Red Hat, Inc. | ||||||
|  | ; | ||||||
|  | ; SPDX-License-Identifier: BSD-2-Clause-Patent | ||||||
|  | ; | ||||||
|  | ; The routine runs on the hot-added CPU in the following "big real mode", | ||||||
|  | ; 16-bit environment; per "SMI HANDLER EXECUTION ENVIRONMENT" in the Intel SDM | ||||||
|  | ; (table "Processor Register Initialization in SMM"): | ||||||
|  | ; | ||||||
|  | ;  - CS selector: 0x3000 (most significant 16 bits of SMM_DEFAULT_SMBASE). | ||||||
|  | ; | ||||||
|  | ;  - CS limit: 0xFFFF_FFFF. | ||||||
|  | ; | ||||||
|  | ;  - CS base: SMM_DEFAULT_SMBASE (0x3_0000). | ||||||
|  | ; | ||||||
|  | ;  - IP: SMM_HANDLER_OFFSET (0x8000). | ||||||
|  | ; | ||||||
|  | ;  - ES, SS, DS, FS, GS selectors: 0. | ||||||
|  | ; | ||||||
|  | ;  - ES, SS, DS, FS, GS limits: 0xFFFF_FFFF. | ||||||
|  | ; | ||||||
|  | ;  - ES, SS, DS, FS, GS bases: 0. | ||||||
|  | ; | ||||||
|  | ;  - Operand-size and address-size override prefixes can be used to access the | ||||||
|  | ;    address space beyond 1MB. | ||||||
|  | ;------------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  | SECTION .data | ||||||
|  | BITS 16 | ||||||
|  | 
 | ||||||
|  | ; | ||||||
|  | ; Bring in SMM_DEFAULT_SMBASE from | ||||||
|  | ; "MdePkg/Include/Register/Intel/SmramSaveStateMap.h". | ||||||
|  | ; | ||||||
|  | SMM_DEFAULT_SMBASE: equ 0x3_0000 | ||||||
|  | 
 | ||||||
|  | ; | ||||||
|  | ; Field offsets in FIRST_SMI_HANDLER_CONTEXT, which resides at | ||||||
|  | ; SMM_DEFAULT_SMBASE. | ||||||
|  | ; | ||||||
|  | ApicIdGate:      equ  0 ; UINT64 | ||||||
|  | NewSmbase:       equ  8 ; UINT32 | ||||||
|  | AboutToLeaveSmm: equ 12 ; UINT8 | ||||||
|  | 
 | ||||||
|  | ; | ||||||
|  | ; SMRAM Save State Map field offsets, per the AMD (not Intel) layout that QEMU | ||||||
|  | ; implements. Relative to SMM_DEFAULT_SMBASE. | ||||||
|  | ; | ||||||
|  | SaveStateRevId:    equ 0xFEFC ; UINT32 | ||||||
|  | SaveStateSmbase:   equ 0xFEF8 ; UINT32 | ||||||
|  | SaveStateSmbase64: equ 0xFF00 ; UINT32 | ||||||
|  | 
 | ||||||
|  | ; | ||||||
|  | ; CPUID constants, from "MdePkg/Include/Register/Intel/Cpuid.h". | ||||||
|  | ; | ||||||
|  | CPUID_SIGNATURE:         equ 0x00 | ||||||
|  | CPUID_EXTENDED_TOPOLOGY: equ 0x0B | ||||||
|  | CPUID_VERSION_INFO:      equ 0x01 | ||||||
|  | 
 | ||||||
|  | GLOBAL ASM_PFX (mFirstSmiHandler)     ; UINT8[] | ||||||
|  | GLOBAL ASM_PFX (mFirstSmiHandlerSize) ; UINT16 | ||||||
|  | 
 | ||||||
|  | ASM_PFX (mFirstSmiHandler): | ||||||
|  |   ; | ||||||
|  |   ; Get our own APIC ID first, so we can contend for ApicIdGate. | ||||||
|  |   ; | ||||||
|  |   ; This basically reimplements GetInitialApicId() from | ||||||
|  |   ; "UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c". | ||||||
|  |   ; | ||||||
|  |   mov eax, CPUID_SIGNATURE | ||||||
|  |   cpuid | ||||||
|  |   cmp eax, CPUID_EXTENDED_TOPOLOGY | ||||||
|  |   jb GetApicIdFromVersionInfo | ||||||
|  | 
 | ||||||
|  |   mov eax, CPUID_EXTENDED_TOPOLOGY | ||||||
|  |   mov ecx, 0 | ||||||
|  |   cpuid | ||||||
|  |   test ebx, 0xFFFF | ||||||
|  |   jz GetApicIdFromVersionInfo | ||||||
|  | 
 | ||||||
|  |   ; | ||||||
|  |   ; EDX has the APIC ID, save it to ESI. | ||||||
|  |   ; | ||||||
|  |   mov esi, edx | ||||||
|  |   jmp KnockOnGate | ||||||
|  | 
 | ||||||
|  | GetApicIdFromVersionInfo: | ||||||
|  |   mov eax, CPUID_VERSION_INFO | ||||||
|  |   cpuid | ||||||
|  |   shr ebx, 24 | ||||||
|  |   ; | ||||||
|  |   ; EBX has the APIC ID, save it to ESI. | ||||||
|  |   ; | ||||||
|  |   mov esi, ebx | ||||||
|  | 
 | ||||||
|  | KnockOnGate: | ||||||
|  |   ; | ||||||
|  |   ; See if ApicIdGate shows our own APIC ID. If so, swap it to MAX_UINT64 | ||||||
|  |   ; (close the gate), and advance. Otherwise, keep knocking. | ||||||
|  |   ; | ||||||
|  |   ; InterlockedCompareExchange64(): | ||||||
|  |   ; - Value                   := &FIRST_SMI_HANDLER_CONTEXT.ApicIdGate | ||||||
|  |   ; - CompareValue  (EDX:EAX) := APIC ID (from ESI) | ||||||
|  |   ; - ExchangeValue (ECX:EBX) := MAX_UINT64 | ||||||
|  |   ; | ||||||
|  |   mov edx, 0 | ||||||
|  |   mov eax, esi | ||||||
|  |   mov ecx, 0xFFFF_FFFF | ||||||
|  |   mov ebx, 0xFFFF_FFFF | ||||||
|  |   lock cmpxchg8b [ds : dword (SMM_DEFAULT_SMBASE + ApicIdGate)] | ||||||
|  |   jz ApicIdMatch | ||||||
|  |   pause | ||||||
|  |   jmp KnockOnGate | ||||||
|  | 
 | ||||||
|  | ApicIdMatch: | ||||||
|  |   ; | ||||||
|  |   ; Update the SMBASE field in the SMRAM Save State Map. | ||||||
|  |   ; | ||||||
|  |   ; First, calculate the address of the SMBASE field, based on the SMM Revision | ||||||
|  |   ; ID; store the result in EBX. | ||||||
|  |   ; | ||||||
|  |   mov eax, dword [ds : dword (SMM_DEFAULT_SMBASE + SaveStateRevId)] | ||||||
|  |   test eax, 0xFFFF | ||||||
|  |   jz LegacySaveStateMap | ||||||
|  | 
 | ||||||
|  |   mov ebx, SMM_DEFAULT_SMBASE + SaveStateSmbase64 | ||||||
|  |   jmp UpdateSmbase | ||||||
|  | 
 | ||||||
|  | LegacySaveStateMap: | ||||||
|  |   mov ebx, SMM_DEFAULT_SMBASE + SaveStateSmbase | ||||||
|  | 
 | ||||||
|  | UpdateSmbase: | ||||||
|  |   ; | ||||||
|  |   ; Load the new SMBASE value into EAX. | ||||||
|  |   ; | ||||||
|  |   mov eax, dword [ds : dword (SMM_DEFAULT_SMBASE + NewSmbase)] | ||||||
|  |   ; | ||||||
|  |   ; Save it to the SMBASE field whose address we calculated in EBX. | ||||||
|  |   ; | ||||||
|  |   mov dword [ds : dword ebx], eax | ||||||
|  |   ; | ||||||
|  |   ; Set AboutToLeaveSmm. | ||||||
|  |   ; | ||||||
|  |   mov byte [ds : dword (SMM_DEFAULT_SMBASE + AboutToLeaveSmm)], 1 | ||||||
|  |   ; | ||||||
|  |   ; We're done; leave SMM and continue to the pen. | ||||||
|  |   ; | ||||||
|  |   rsm | ||||||
|  | 
 | ||||||
|  | ASM_PFX (mFirstSmiHandlerSize): | ||||||
|  |   dw $ - ASM_PFX (mFirstSmiHandler) | ||||||
							
								
								
									
										47
									
								
								OvmfPkg/CpuHotplugSmm/FirstSmiHandlerContext.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								OvmfPkg/CpuHotplugSmm/FirstSmiHandlerContext.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | |||||||
|  | /** @file
 | ||||||
|  |   Define the FIRST_SMI_HANDLER_CONTEXT structure, which is an exchange area | ||||||
|  |   between the SMM Monarch and the hot-added CPU, for relocating the SMBASE of | ||||||
|  |   the hot-added CPU. | ||||||
|  | 
 | ||||||
|  |   Copyright (c) 2020, Red Hat, Inc. | ||||||
|  | 
 | ||||||
|  |   SPDX-License-Identifier: BSD-2-Clause-Patent | ||||||
|  | **/ | ||||||
|  | 
 | ||||||
|  | #ifndef FIRST_SMI_HANDLER_CONTEXT_H_ | ||||||
|  | #define FIRST_SMI_HANDLER_CONTEXT_H_ | ||||||
|  | 
 | ||||||
|  | //
 | ||||||
|  | // The following structure is used to communicate between the SMM Monarch
 | ||||||
|  | // (running the root MMI handler) and the hot-added CPU (handling its first
 | ||||||
|  | // SMI). It is placed at SMM_DEFAULT_SMBASE, which is in SMRAM under QEMU's
 | ||||||
|  | // "SMRAM at default SMBASE" feature.
 | ||||||
|  | //
 | ||||||
|  | #pragma pack (1) | ||||||
|  | typedef struct { | ||||||
|  |   //
 | ||||||
|  |   // When ApicIdGate is MAX_UINT64, then no hot-added CPU may proceed with
 | ||||||
|  |   // SMBASE relocation.
 | ||||||
|  |   //
 | ||||||
|  |   // Otherwise, the hot-added CPU whose APIC ID equals ApicIdGate may proceed
 | ||||||
|  |   // with SMBASE relocation.
 | ||||||
|  |   //
 | ||||||
|  |   // This field is intentionally wider than APIC_ID (UINT32) because we need a
 | ||||||
|  |   // "gate locked" value that is different from all possible APIC_IDs.
 | ||||||
|  |   //
 | ||||||
|  |   UINT64 ApicIdGate; | ||||||
|  |   //
 | ||||||
|  |   // The new SMBASE value for the hot-added CPU to set in the SMRAM Save State
 | ||||||
|  |   // Map, before leaving SMM with the RSM instruction.
 | ||||||
|  |   //
 | ||||||
|  |   UINT32 NewSmbase; | ||||||
|  |   //
 | ||||||
|  |   // The hot-added CPU sets this field to 1 right before executing the RSM
 | ||||||
|  |   // instruction. This tells the SMM Monarch to proceed to polling the last
 | ||||||
|  |   // byte of the normal RAM reserved page (Post-SMM Pen).
 | ||||||
|  |   //
 | ||||||
|  |   UINT8 AboutToLeaveSmm; | ||||||
|  | } FIRST_SMI_HANDLER_CONTEXT; | ||||||
|  | #pragma pack () | ||||||
|  | 
 | ||||||
|  | #endif // FIRST_SMI_HANDLER_CONTEXT_H_
 | ||||||
| @ -7,13 +7,21 @@ | |||||||
| **/ | **/ | ||||||
| 
 | 
 | ||||||
| #include <Base.h>                             // BASE_1MB | #include <Base.h>                             // BASE_1MB | ||||||
|  | #include <Library/BaseLib.h>                  // CpuPause() | ||||||
| #include <Library/BaseMemoryLib.h>            // CopyMem() | #include <Library/BaseMemoryLib.h>            // CopyMem() | ||||||
| #include <Library/DebugLib.h>                 // DEBUG() | #include <Library/DebugLib.h>                 // DEBUG() | ||||||
|  | #include <Library/LocalApicLib.h>             // SendInitSipiSipi() | ||||||
|  | #include <Library/SynchronizationLib.h>       // InterlockedCompareExchange64() | ||||||
|  | #include <Register/Intel/SmramSaveStateMap.h> // SMM_DEFAULT_SMBASE | ||||||
|  | 
 | ||||||
|  | #include "FirstSmiHandlerContext.h"           // FIRST_SMI_HANDLER_CONTEXT | ||||||
| 
 | 
 | ||||||
| #include "Smbase.h" | #include "Smbase.h" | ||||||
| 
 | 
 | ||||||
| extern CONST UINT8 mPostSmmPen[]; | extern CONST UINT8 mPostSmmPen[]; | ||||||
| extern CONST UINT16 mPostSmmPenSize; | extern CONST UINT16 mPostSmmPenSize; | ||||||
|  | extern CONST UINT8 mFirstSmiHandler[]; | ||||||
|  | extern CONST UINT16 mFirstSmiHandlerSize; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|   Allocate a non-SMRAM reserved memory page for the Post-SMM Pen for hot-added |   Allocate a non-SMRAM reserved memory page for the Post-SMM Pen for hot-added | ||||||
| @ -108,3 +116,152 @@ SmbaseReleasePostSmmPen ( | |||||||
| { | { | ||||||
|   BootServices->FreePages (PenAddress, 1); |   BootServices->FreePages (PenAddress, 1); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |   Place the handler routine for the first SMIs of hot-added CPUs at | ||||||
|  |   (SMM_DEFAULT_SMBASE + SMM_HANDLER_OFFSET). | ||||||
|  | 
 | ||||||
|  |   Note that this effects an "SMRAM to SMRAM" copy. | ||||||
|  | 
 | ||||||
|  |   Additionally, shut the APIC ID gate in FIRST_SMI_HANDLER_CONTEXT. | ||||||
|  | 
 | ||||||
|  |   This function may only be called from the entry point function of the driver, | ||||||
|  |   and only after PcdQ35SmramAtDefaultSmbase has been determined to be TRUE. | ||||||
|  | **/ | ||||||
|  | VOID | ||||||
|  | SmbaseInstallFirstSmiHandler ( | ||||||
|  |   VOID | ||||||
|  |   ) | ||||||
|  | { | ||||||
|  |   FIRST_SMI_HANDLER_CONTEXT *Context; | ||||||
|  | 
 | ||||||
|  |   CopyMem ((VOID *)(UINTN)(SMM_DEFAULT_SMBASE + SMM_HANDLER_OFFSET), | ||||||
|  |     mFirstSmiHandler, mFirstSmiHandlerSize); | ||||||
|  | 
 | ||||||
|  |   Context = (VOID *)(UINTN)SMM_DEFAULT_SMBASE; | ||||||
|  |   Context->ApicIdGate = MAX_UINT64; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |   Relocate the SMBASE on a hot-added CPU. Then pen the hot-added CPU in the | ||||||
|  |   normal RAM reserved memory page, set up earlier with | ||||||
|  |   SmbaseAllocatePostSmmPen() and SmbaseReinstallPostSmmPen(). | ||||||
|  | 
 | ||||||
|  |   The SMM Monarch is supposed to call this function from the root MMI handler. | ||||||
|  | 
 | ||||||
|  |   The SMM Monarch is responsible for calling SmbaseInstallFirstSmiHandler(), | ||||||
|  |   SmbaseAllocatePostSmmPen(), and SmbaseReinstallPostSmmPen() before calling | ||||||
|  |   this function. | ||||||
|  | 
 | ||||||
|  |   If the OS maliciously boots the hot-added CPU ahead of letting the ACPI CPU | ||||||
|  |   hotplug event handler broadcast the CPU hotplug MMI, then the hot-added CPU | ||||||
|  |   returns to the OS rather than to the pen, upon RSM. In that case, this | ||||||
|  |   function will hang forever (unless the OS happens to signal back through the | ||||||
|  |   last byte of the pen page). | ||||||
|  | 
 | ||||||
|  |   @param[in] ApicId      The APIC ID of the hot-added CPU whose SMBASE should | ||||||
|  |                          be relocated. | ||||||
|  | 
 | ||||||
|  |   @param[in] Smbase      The new SMBASE address. The root MMI handler is | ||||||
|  |                          responsible for passing in a free ("unoccupied") | ||||||
|  |                          SMBASE address that was pre-configured by | ||||||
|  |                          PiSmmCpuDxeSmm in CPU_HOT_PLUG_DATA. | ||||||
|  | 
 | ||||||
|  |   @param[in] PenAddress  The address of the Post-SMM Pen for hot-added CPUs, as | ||||||
|  |                          returned by SmbaseAllocatePostSmmPen(), and installed | ||||||
|  |                          by SmbaseReinstallPostSmmPen(). | ||||||
|  | 
 | ||||||
|  |   @retval EFI_SUCCESS            The SMBASE of the hot-added CPU with APIC ID | ||||||
|  |                                  ApicId has been relocated to Smbase. The | ||||||
|  |                                  hot-added CPU has reported back about leaving | ||||||
|  |                                  SMM. | ||||||
|  | 
 | ||||||
|  |   @retval EFI_PROTOCOL_ERROR     Synchronization bug encountered around | ||||||
|  |                                  FIRST_SMI_HANDLER_CONTEXT.ApicIdGate. | ||||||
|  | 
 | ||||||
|  |   @retval EFI_INVALID_PARAMETER  Smbase does not fit in 32 bits. No relocation | ||||||
|  |                                  has been attempted. | ||||||
|  | **/ | ||||||
|  | EFI_STATUS | ||||||
|  | SmbaseRelocate ( | ||||||
|  |   IN APIC_ID ApicId, | ||||||
|  |   IN UINTN   Smbase, | ||||||
|  |   IN UINT32  PenAddress | ||||||
|  |   ) | ||||||
|  | { | ||||||
|  |   EFI_STATUS                         Status; | ||||||
|  |   volatile UINT8                     *SmmVacated; | ||||||
|  |   volatile FIRST_SMI_HANDLER_CONTEXT *Context; | ||||||
|  |   UINT64                             ExchangeResult; | ||||||
|  | 
 | ||||||
|  |   if (Smbase > MAX_UINT32) { | ||||||
|  |     Status = EFI_INVALID_PARAMETER; | ||||||
|  |     DEBUG ((DEBUG_ERROR, "%a: ApicId=" FMT_APIC_ID " Smbase=0x%Lx: %r\n", | ||||||
|  |       __FUNCTION__, ApicId, (UINT64)Smbase, Status)); | ||||||
|  |     return Status; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   SmmVacated = (UINT8 *)(UINTN)PenAddress + (EFI_PAGE_SIZE - 1); | ||||||
|  |   Context = (VOID *)(UINTN)SMM_DEFAULT_SMBASE; | ||||||
|  | 
 | ||||||
|  |   //
 | ||||||
|  |   // Clear AboutToLeaveSmm, so we notice when the hot-added CPU is just about
 | ||||||
|  |   // to reach RSM, and we can proceed to polling the last byte of the reserved
 | ||||||
|  |   // page (which could be attacked by the OS).
 | ||||||
|  |   //
 | ||||||
|  |   Context->AboutToLeaveSmm = 0; | ||||||
|  | 
 | ||||||
|  |   //
 | ||||||
|  |   // Clear the last byte of the reserved page, so we notice when the hot-added
 | ||||||
|  |   // CPU checks back in from the pen.
 | ||||||
|  |   //
 | ||||||
|  |   *SmmVacated = 0; | ||||||
|  | 
 | ||||||
|  |   //
 | ||||||
|  |   // Boot the hot-added CPU.
 | ||||||
|  |   //
 | ||||||
|  |   // If the OS is benign, and so the hot-added CPU is still in RESET state,
 | ||||||
|  |   // then the broadcast SMI is still pending for it; it will now launch
 | ||||||
|  |   // directly into SMM.
 | ||||||
|  |   //
 | ||||||
|  |   // If the OS is malicious, the hot-added CPU has been booted already, and so
 | ||||||
|  |   // it is already spinning on the APIC ID gate. In that case, the
 | ||||||
|  |   // INIT-SIPI-SIPI below will be ignored.
 | ||||||
|  |   //
 | ||||||
|  |   SendInitSipiSipi (ApicId, PenAddress); | ||||||
|  | 
 | ||||||
|  |   //
 | ||||||
|  |   // Expose the desired new SMBASE value to the hot-added CPU.
 | ||||||
|  |   //
 | ||||||
|  |   Context->NewSmbase = (UINT32)Smbase; | ||||||
|  | 
 | ||||||
|  |   //
 | ||||||
|  |   // Un-gate SMBASE relocation for the hot-added CPU whose APIC ID is ApicId.
 | ||||||
|  |   //
 | ||||||
|  |   ExchangeResult = InterlockedCompareExchange64 (&Context->ApicIdGate, | ||||||
|  |                      MAX_UINT64, ApicId); | ||||||
|  |   if (ExchangeResult != MAX_UINT64) { | ||||||
|  |     Status = EFI_PROTOCOL_ERROR; | ||||||
|  |     DEBUG ((DEBUG_ERROR, "%a: ApicId=" FMT_APIC_ID " ApicIdGate=0x%Lx: %r\n", | ||||||
|  |       __FUNCTION__, ApicId, ExchangeResult, Status)); | ||||||
|  |     return Status; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   //
 | ||||||
|  |   // Wait until the hot-added CPU is just about to execute RSM.
 | ||||||
|  |   //
 | ||||||
|  |   while (Context->AboutToLeaveSmm == 0) { | ||||||
|  |     CpuPause (); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   //
 | ||||||
|  |   // Now wait until the hot-added CPU reports back from the pen (or the OS
 | ||||||
|  |   // attacks the last byte of the reserved page).
 | ||||||
|  |   //
 | ||||||
|  |   while (*SmmVacated == 0) { | ||||||
|  |     CpuPause (); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   Status = EFI_SUCCESS; | ||||||
|  |   return Status; | ||||||
|  | } | ||||||
|  | |||||||
| @ -12,6 +12,8 @@ | |||||||
| #include <Uefi/UefiBaseType.h> // EFI_STATUS | #include <Uefi/UefiBaseType.h> // EFI_STATUS | ||||||
| #include <Uefi/UefiSpec.h>     // EFI_BOOT_SERVICES | #include <Uefi/UefiSpec.h>     // EFI_BOOT_SERVICES | ||||||
| 
 | 
 | ||||||
|  | #include "ApicId.h"            // APIC_ID | ||||||
|  | 
 | ||||||
| EFI_STATUS | EFI_STATUS | ||||||
| SmbaseAllocatePostSmmPen ( | SmbaseAllocatePostSmmPen ( | ||||||
|   OUT UINT32                  *PenAddress, |   OUT UINT32                  *PenAddress, | ||||||
| @ -29,4 +31,16 @@ SmbaseReleasePostSmmPen ( | |||||||
|   IN CONST EFI_BOOT_SERVICES *BootServices |   IN CONST EFI_BOOT_SERVICES *BootServices | ||||||
|   ); |   ); | ||||||
| 
 | 
 | ||||||
|  | VOID | ||||||
|  | SmbaseInstallFirstSmiHandler ( | ||||||
|  |   VOID | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  | EFI_STATUS | ||||||
|  | SmbaseRelocate ( | ||||||
|  |   IN APIC_ID ApicId, | ||||||
|  |   IN UINTN   Smbase, | ||||||
|  |   IN UINT32  PenAddress | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
| #endif // SMBASE_H_
 | #endif // SMBASE_H_
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user