]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuException.c
UefiCpuPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / UefiCpuPkg / Library / CpuExceptionHandlerLib / PeiCpuException.c
index 8d8d16ecbd7e3f817bd0576b83b8ee8d6c1fe75a..d256643435e55ab6e25dba69a63bc78c6db1af9b 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
   CPU exception handler library implementation for PEIM module.\r
 \r
-Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials are licensed and made available under\r
-the terms and conditions of the BSD License that accompanies this distribution.\r
-The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php.\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -17,13 +11,21 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/DebugLib.h>\r
 #include <Library/HobLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
+#include <Library/PcdLib.h>\r
 \r
 CONST UINTN    mDoFarReturnFlag  = 0;\r
 \r
-EFI_GUID mCpuExceptrionHandlerLibHobGuid = CPU_EXCEPTION_HANDLER_LIB_HOB_GUID;\r
+typedef struct {\r
+  UINT8                   ExceptionStubHeader[HOOKAFTER_STUB_SIZE];\r
+  EXCEPTION_HANDLER_DATA  *ExceptionHandlerData;\r
+} EXCEPTION0_STUB_HEADER;\r
 \r
 /**\r
-  Get exception handler data pointer from GUIDed HOb.\r
+  Get exception handler data pointer from IDT[0].\r
+\r
+  The exception #0 stub header is duplicated in an allocated pool with extra 4-byte/8-byte to store the\r
+  exception handler data. The new allocated memory layout follows structure EXCEPTION0_STUB_HEADER.\r
+  The code assumes that all processors uses the same exception handler for #0 exception.\r
 \r
   @return  pointer to exception handler data.\r
 **/\r
@@ -32,18 +34,50 @@ GetExceptionHandlerData (
   VOID\r
   )\r
 {\r
-  EFI_HOB_GUID_TYPE       *GuidHob;\r
-  VOID                    *DataInHob;\r
-  EXCEPTION_HANDLER_DATA  *ExceptionHandlerData;\r
+  IA32_DESCRIPTOR                  IdtDescriptor;\r
+  IA32_IDT_GATE_DESCRIPTOR         *IdtTable;\r
+  EXCEPTION0_STUB_HEADER           *Exception0StubHeader;\r
 \r
-  ExceptionHandlerData = NULL;\r
-  GuidHob = GetFirstGuidHob (&mCpuExceptrionHandlerLibHobGuid);\r
-  if (GuidHob != NULL) {\r
-    DataInHob = GET_GUID_HOB_DATA (GuidHob);\r
-    ExceptionHandlerData = (EXCEPTION_HANDLER_DATA *)(*(UINTN *)DataInHob);\r
-  }\r
-  ASSERT (ExceptionHandlerData != NULL);\r
-  return ExceptionHandlerData;\r
+  AsmReadIdtr (&IdtDescriptor);\r
+  IdtTable = (IA32_IDT_GATE_DESCRIPTOR *)IdtDescriptor.Base;\r
+\r
+  Exception0StubHeader = (EXCEPTION0_STUB_HEADER *)ArchGetIdtHandler (&IdtTable[0]);\r
+  return Exception0StubHeader->ExceptionHandlerData;\r
+}\r
+\r
+/**\r
+  Set exception handler data pointer to IDT[0].\r
+\r
+  The exception #0 stub header is duplicated in an allocated pool with extra 4-byte/8-byte to store the\r
+  exception handler data. The new allocated memory layout follows structure EXCEPTION0_STUB_HEADER.\r
+  The code assumes that all processors uses the same exception handler for #0 exception.\r
+\r
+  @param ExceptionHandlerData  pointer to exception handler data.\r
+**/\r
+VOID\r
+SetExceptionHandlerData (\r
+  IN EXCEPTION_HANDLER_DATA        *ExceptionHandlerData\r
+  )\r
+{\r
+  EXCEPTION0_STUB_HEADER           *Exception0StubHeader;\r
+  IA32_DESCRIPTOR                  IdtDescriptor;\r
+  IA32_IDT_GATE_DESCRIPTOR         *IdtTable;\r
+  //\r
+  // Duplicate the exception #0 stub header in pool and cache the ExceptionHandlerData just after the stub header.\r
+  // So AP can get the ExceptionHandlerData by reading the IDT[0].\r
+  //\r
+  AsmReadIdtr (&IdtDescriptor);\r
+  IdtTable = (IA32_IDT_GATE_DESCRIPTOR *)IdtDescriptor.Base;\r
+\r
+  Exception0StubHeader = AllocatePool (sizeof (*Exception0StubHeader));\r
+  ASSERT (Exception0StubHeader != NULL);\r
+  CopyMem (\r
+    Exception0StubHeader->ExceptionStubHeader,\r
+    (VOID *)ArchGetIdtHandler (&IdtTable[0]),\r
+    sizeof (Exception0StubHeader->ExceptionStubHeader)\r
+    );\r
+  Exception0StubHeader->ExceptionHandlerData = ExceptionHandlerData;\r
+  ArchUpdateIdtEntry (&IdtTable[0], (UINTN)Exception0StubHeader->ExceptionStubHeader);\r
 }\r
 \r
 /**\r
@@ -109,15 +143,7 @@ InitializeCpuExceptionHandlers (
     return Status;\r
   }\r
 \r
-  //\r
-  // Build location of CPU MP DATA buffer in HOB\r
-  //\r
-  BuildGuidDataHob (\r
-    &mCpuExceptrionHandlerLibHobGuid,\r
-    (VOID *)&ExceptionHandlerData,\r
-    sizeof(UINT64)\r
-    );\r
-\r
+  SetExceptionHandlerData (ExceptionHandlerData);\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -177,4 +203,60 @@ RegisterCpuInterruptHandler (
   )\r
 {\r
   return EFI_UNSUPPORTED;\r
-}
\ No newline at end of file
+}\r
+\r
+/**\r
+  Initializes all CPU exceptions entries with optional extra initializations.\r
+\r
+  By default, this method should include all functionalities implemented by\r
+  InitializeCpuExceptionHandlers(), plus extra initialization works, if any.\r
+  This could be done by calling InitializeCpuExceptionHandlers() directly\r
+  in this method besides the extra works.\r
+\r
+  InitData is optional and its use and content are processor arch dependent.\r
+  The typical usage of it is to convey resources which have to be reserved\r
+  elsewhere and are necessary for the extra initializations of exception.\r
+\r
+  @param[in]  VectorInfo    Pointer to reserved vector list.\r
+  @param[in]  InitData      Pointer to data optional for extra initializations\r
+                            of exception.\r
+\r
+  @retval EFI_SUCCESS             The exceptions have been successfully\r
+                                  initialized.\r
+  @retval EFI_INVALID_PARAMETER   VectorInfo or InitData contains invalid\r
+                                  content.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeCpuExceptionHandlersEx (\r
+  IN EFI_VECTOR_HANDOFF_INFO            *VectorInfo OPTIONAL,\r
+  IN CPU_EXCEPTION_INIT_DATA            *InitData OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+\r
+  //\r
+  // To avoid repeat initialization of default handlers, the caller should pass\r
+  // an extended init data with InitDefaultHandlers set to FALSE. There's no\r
+  // need to call this method to just initialize default handlers. Call non-ex\r
+  // version instead; or this method must be implemented as a simple wrapper of\r
+  // non-ex version of it, if this version has to be called.\r
+  //\r
+  if (InitData == NULL || InitData->Ia32.InitDefaultHandlers) {\r
+    Status = InitializeCpuExceptionHandlers (VectorInfo);\r
+  } else {\r
+    Status = EFI_SUCCESS;\r
+  }\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Initializing stack switch is only necessary for Stack Guard functionality.\r
+    //\r
+    if (PcdGetBool (PcdCpuStackGuard) && InitData != NULL) {\r
+      Status = ArchSetupExceptionStack (InitData);\r
+    }\r
+  }\r
+\r
+  return  Status;\r
+}\r