]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuException.c
CpuException: Add InitializeSeparateExceptionStacks
[mirror_edk2.git] / UefiCpuPkg / Library / CpuExceptionHandlerLib / PeiCpuException.c
CommitLineData
a81abf16
JF
1/** @file\r
2 CPU exception handler library implementation for PEIM module.\r
3\r
2a09527e 4Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>\r
0acd8697 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
a81abf16
JF
6\r
7**/\r
8\r
9#include <PiPei.h>\r
10#include "CpuExceptionCommon.h"\r
11#include <Library/DebugLib.h>\r
12#include <Library/HobLib.h>\r
13#include <Library/MemoryAllocationLib.h>\r
fc0e7fd5 14#include <Library/PcdLib.h>\r
a81abf16 15\r
053e878b 16CONST UINTN mDoFarReturnFlag = 0;\r
a81abf16 17\r
374168ae 18typedef struct {\r
053e878b
MK
19 UINT8 ExceptionStubHeader[HOOKAFTER_STUB_SIZE];\r
20 EXCEPTION_HANDLER_DATA *ExceptionHandlerData;\r
374168ae 21} EXCEPTION0_STUB_HEADER;\r
a81abf16
JF
22\r
23/**\r
374168ae
RN
24 Get exception handler data pointer from IDT[0].\r
25\r
26 The exception #0 stub header is duplicated in an allocated pool with extra 4-byte/8-byte to store the\r
27 exception handler data. The new allocated memory layout follows structure EXCEPTION0_STUB_HEADER.\r
28 The code assumes that all processors uses the same exception handler for #0 exception.\r
a81abf16 29\r
dd563742 30 @return pointer to exception handler data.\r
a81abf16
JF
31**/\r
32EXCEPTION_HANDLER_DATA *\r
33GetExceptionHandlerData (\r
34 VOID\r
35 )\r
36{\r
053e878b
MK
37 IA32_DESCRIPTOR IdtDescriptor;\r
38 IA32_IDT_GATE_DESCRIPTOR *IdtTable;\r
39 EXCEPTION0_STUB_HEADER *Exception0StubHeader;\r
374168ae
RN
40\r
41 AsmReadIdtr (&IdtDescriptor);\r
42 IdtTable = (IA32_IDT_GATE_DESCRIPTOR *)IdtDescriptor.Base;\r
34c3405c 43\r
374168ae
RN
44 Exception0StubHeader = (EXCEPTION0_STUB_HEADER *)ArchGetIdtHandler (&IdtTable[0]);\r
45 return Exception0StubHeader->ExceptionHandlerData;\r
46}\r
a81abf16 47\r
374168ae
RN
48/**\r
49 Set exception handler data pointer to IDT[0].\r
50\r
51 The exception #0 stub header is duplicated in an allocated pool with extra 4-byte/8-byte to store the\r
52 exception handler data. The new allocated memory layout follows structure EXCEPTION0_STUB_HEADER.\r
53 The code assumes that all processors uses the same exception handler for #0 exception.\r
54\r
34c3405c 55 @param ExceptionHandlerData pointer to exception handler data.\r
374168ae
RN
56**/\r
57VOID\r
58SetExceptionHandlerData (\r
053e878b 59 IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData\r
374168ae
RN
60 )\r
61{\r
053e878b
MK
62 EXCEPTION0_STUB_HEADER *Exception0StubHeader;\r
63 IA32_DESCRIPTOR IdtDescriptor;\r
64 IA32_IDT_GATE_DESCRIPTOR *IdtTable;\r
65\r
374168ae
RN
66 //\r
67 // Duplicate the exception #0 stub header in pool and cache the ExceptionHandlerData just after the stub header.\r
68 // So AP can get the ExceptionHandlerData by reading the IDT[0].\r
69 //\r
70 AsmReadIdtr (&IdtDescriptor);\r
71 IdtTable = (IA32_IDT_GATE_DESCRIPTOR *)IdtDescriptor.Base;\r
34c3405c 72\r
374168ae
RN
73 Exception0StubHeader = AllocatePool (sizeof (*Exception0StubHeader));\r
74 ASSERT (Exception0StubHeader != NULL);\r
75 CopyMem (\r
76 Exception0StubHeader->ExceptionStubHeader,\r
77 (VOID *)ArchGetIdtHandler (&IdtTable[0]),\r
78 sizeof (Exception0StubHeader->ExceptionStubHeader)\r
79 );\r
80 Exception0StubHeader->ExceptionHandlerData = ExceptionHandlerData;\r
81 ArchUpdateIdtEntry (&IdtTable[0], (UINTN)Exception0StubHeader->ExceptionStubHeader);\r
a81abf16
JF
82}\r
83\r
84/**\r
85 Common exception handler.\r
86\r
87 @param ExceptionType Exception type.\r
88 @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.\r
89**/\r
90VOID\r
91EFIAPI\r
92CommonExceptionHandler (\r
053e878b
MK
93 IN EFI_EXCEPTION_TYPE ExceptionType,\r
94 IN EFI_SYSTEM_CONTEXT SystemContext\r
a81abf16
JF
95 )\r
96{\r
97 EXCEPTION_HANDLER_DATA *ExceptionHandlerData;\r
98\r
99 ExceptionHandlerData = GetExceptionHandlerData ();\r
100 CommonExceptionHandlerWorker (ExceptionType, SystemContext, ExceptionHandlerData);\r
101}\r
102\r
103/**\r
104 Initializes all CPU exceptions entries and provides the default exception handlers.\r
dd563742 105\r
a81abf16
JF
106 Caller should try to get an array of interrupt and/or exception vectors that are in use and need to\r
107 persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification.\r
dd563742 108 If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL.\r
a81abf16 109 If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly.\r
dd563742 110 Note: Before invoking this API, caller must allocate memory for IDT table and load\r
a81abf16
JF
111 IDTR by AsmWriteIdtr().\r
112\r
113 @param[in] VectorInfo Pointer to reserved vector list.\r
dd563742
JF
114\r
115 @retval EFI_SUCCESS CPU Exception Entries have been successfully initialized\r
a81abf16
JF
116 with default exception handlers.\r
117 @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.\r
118 @retval EFI_UNSUPPORTED This function is not supported.\r
119\r
120**/\r
121EFI_STATUS\r
122EFIAPI\r
123InitializeCpuExceptionHandlers (\r
053e878b 124 IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL\r
a81abf16
JF
125 )\r
126{\r
053e878b
MK
127 EFI_STATUS Status;\r
128 EXCEPTION_HANDLER_DATA *ExceptionHandlerData;\r
129 RESERVED_VECTORS_DATA *ReservedVectors;\r
a81abf16
JF
130\r
131 ReservedVectors = AllocatePool (sizeof (RESERVED_VECTORS_DATA) * CPU_EXCEPTION_NUM);\r
132 ASSERT (ReservedVectors != NULL);\r
133\r
134 ExceptionHandlerData = AllocatePool (sizeof (EXCEPTION_HANDLER_DATA));\r
135 ASSERT (ExceptionHandlerData != NULL);\r
2a09527e 136 ExceptionHandlerData->IdtEntryCount = CPU_EXCEPTION_NUM;\r
a81abf16
JF
137 ExceptionHandlerData->ReservedVectors = ReservedVectors;\r
138 ExceptionHandlerData->ExternalInterruptHandler = NULL;\r
139 InitializeSpinLock (&ExceptionHandlerData->DisplayMessageSpinLock);\r
140\r
141 Status = InitializeCpuExceptionHandlersWorker (VectorInfo, ExceptionHandlerData);\r
142 if (EFI_ERROR (Status)) {\r
143 FreePool (ReservedVectors);\r
144 FreePool (ExceptionHandlerData);\r
145 return Status;\r
146 }\r
147\r
374168ae 148 SetExceptionHandlerData (ExceptionHandlerData);\r
a81abf16
JF
149 return EFI_SUCCESS;\r
150}\r
151\r
0ff5aa9c 152/**\r
e7abb94d 153 Setup separate stacks for certain exception handlers.\r
0ff5aa9c 154\r
e7abb94d 155 InitData is optional and processor arch dependent.\r
0ff5aa9c 156\r
e7abb94d
RN
157 @param[in] InitData Pointer to data optional for information about how\r
158 to assign stacks for certain exception handlers.\r
0ff5aa9c 159\r
e7abb94d
RN
160 @retval EFI_SUCCESS The stacks are assigned successfully.\r
161 @retval EFI_UNSUPPORTED This function is not supported.\r
0ff5aa9c
JW
162\r
163**/\r
164EFI_STATUS\r
165EFIAPI\r
e7abb94d 166InitializeSeparateExceptionStacks (\r
053e878b 167 IN CPU_EXCEPTION_INIT_DATA *InitData OPTIONAL\r
0ff5aa9c
JW
168 )\r
169{\r
e7abb94d
RN
170 if (InitData == NULL) {\r
171 return EFI_UNSUPPORTED;\r
fc0e7fd5
JW
172 }\r
173\r
e7abb94d 174 return ArchSetupExceptionStack (InitData);\r
0ff5aa9c 175}\r