In original ExitBootService callback function, we will send INIT IPI to all APs and place APs into wait-for-sipi state. However, it prevents APs to response any SMI. As a result, SMM BSP needs to do a specified timeout delay on each SMI.
This fix is to place APs into hlt-loop state to let APs response SMI correctly. Moreover, we change AP mode into protected mode on x64 image. It could avoid access page table when AP runs hlt-loop code, because page table is located in boot service data range may re-used by OS. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeff Fan <[email protected]> CC: Michael Kinney <[email protected]> CC: Laszlo Ersek <[email protected]> --- UefiCpuPkg/CpuDxe/CpuDxe.inf | 2 ++ UefiCpuPkg/CpuDxe/CpuMp.c | 19 ++++++++++++++--- UefiCpuPkg/CpuDxe/CpuMp.h | 12 +++++++++++ UefiCpuPkg/CpuDxe/Ia32/ArchFuncs.c | 37 +++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuDxe/X64/ArchFuncs.c | 42 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 UefiCpuPkg/CpuDxe/Ia32/ArchFuncs.c create mode 100644 UefiCpuPkg/CpuDxe/X64/ArchFuncs.c diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.inf b/UefiCpuPkg/CpuDxe/CpuDxe.inf index 9db5303..8ea4c38 100644 --- a/UefiCpuPkg/CpuDxe/CpuDxe.inf +++ b/UefiCpuPkg/CpuDxe/CpuDxe.inf @@ -62,6 +62,7 @@ Ia32/MpAsm.asm | MSFT Ia32/MpAsm.asm | INTEL Ia32/MpAsm.nasm | GCC + Ia32/ArchFuncs.c [Sources.X64] X64/CpuAsm.asm | MSFT @@ -70,6 +71,7 @@ X64/MpAsm.asm | MSFT X64/MpAsm.asm | INTEL X64/MpAsm.nasm | GCC + X64/ArchFuncs.c [Protocols] gEfiCpuArchProtocolGuid ## PRODUCES diff --git a/UefiCpuPkg/CpuDxe/CpuMp.c b/UefiCpuPkg/CpuDxe/CpuMp.c index 04c2f1f..883b5d7 100644 --- a/UefiCpuPkg/CpuDxe/CpuMp.c +++ b/UefiCpuPkg/CpuDxe/CpuMp.c @@ -30,6 +30,8 @@ VOID *mApStackStart = 0; volatile BOOLEAN mAPsAlreadyInitFinished = FALSE; volatile BOOLEAN mStopCheckAllAPsStatus = TRUE; +volatile STARTUP_CODE *StartupCode; + EFI_MP_SERVICES_PROTOCOL mMpServicesTemplate = { GetNumberOfProcessors, GetProcessorInfo, @@ -1659,11 +1661,22 @@ ExitBootServicesCallback ( IN VOID *Context ) { + EFI_STATUS Status; + // - // Avoid APs access invalid buff datas which allocated by BootServices, - // so we send INIT IPI to APs to let them wait for SIPI state. + // Place AP in procted mode to run hlt-loop in ACPI NVS range. + // It avoids OS crashed page table and this driver in boot service range. // - SendInitIpiAllExcludingSelf (); + Status = mMpServicesTemplate.StartupAllAPs ( + &mMpServicesTemplate, + ChangeApMode, + FALSE, + NULL, + 0, + (VOID *) &StartupCode->CpuApRunHltLoopCode, + NULL + ); + ASSERT_EFI_ERROR (Status); } /** diff --git a/UefiCpuPkg/CpuDxe/CpuMp.h b/UefiCpuPkg/CpuDxe/CpuMp.h index 907e993..3040b2e 100644 --- a/UefiCpuPkg/CpuDxe/CpuMp.h +++ b/UefiCpuPkg/CpuDxe/CpuMp.h @@ -21,6 +21,7 @@ #include <Library/SynchronizationLib.h> #include <Library/HobLib.h> #include <Library/ReportStatusCodeLib.h> +#include <Library/DebugLib.h> #pragma pack(1) @@ -763,5 +764,16 @@ SetMtrrsFromBuffer ( IN VOID *Buffer ); +/** + This function will place AP to Hlt-Loop state. + + @param Buffer Pointer to Hlt-Loop entry point. +**/ +VOID +EFIAPI +ChangeApMode ( + IN VOID *Buffer + ); + #endif // _CPU_MP_H_ diff --git a/UefiCpuPkg/CpuDxe/Ia32/ArchFuncs.c b/UefiCpuPkg/CpuDxe/Ia32/ArchFuncs.c new file mode 100644 index 0000000..32bfab5 --- /dev/null +++ b/UefiCpuPkg/CpuDxe/Ia32/ArchFuncs.c @@ -0,0 +1,37 @@ +/** @file + Arch specific functions. + + Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <CpuMp.h> + +/** + This function will place AP to Hlt-Loop state. + + @param Buffer Pointer to Hlt-Loop entry point. +**/ +VOID +EFIAPI +ChangeApMode ( + IN VOID *Buffer + ) +{ + STACKLESS_AP_ENTRY_POINT ApHltLoopFunc; + + ApHltLoopFunc = (STACKLESS_AP_ENTRY_POINT) (UINTN) Buffer; + (*ApHltLoopFunc) (); + + // + // If should never reach here + // + ASSERT (FALSE); +} diff --git a/UefiCpuPkg/CpuDxe/X64/ArchFuncs.c b/UefiCpuPkg/CpuDxe/X64/ArchFuncs.c new file mode 100644 index 0000000..4117f0a --- /dev/null +++ b/UefiCpuPkg/CpuDxe/X64/ArchFuncs.c @@ -0,0 +1,42 @@ +/** @file + Arch specific functions. + + Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <CpuMp.h> +#include <CpuGdt.h> + +/** + This function will place AP to Hlt-Loop state. + + @param Buffer Pointer to Hlt-Loop entry point. +**/ +VOID +EFIAPI +ChangeApMode ( + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + + AsmDisablePaging64 ( + SYS_CODE_SEL, + (UINT32) (UINTN) Buffer, + 0, + 0, + (UINT32) (UINTN) &Status + ); + // + // If should never reach here + // + ASSERT (FALSE); +} -- 1.9.5.msysgit.0 _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

