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

Reply via email to