/** @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
#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
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
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
)\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