VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c@ 77662

最後變更 在這個檔案從77662是 77662,由 vboxsync 提交於 6 年 前

EFI: First step in UDK2018 merge. Does not build yet.

  • 屬性 svn:eol-style 設為 native
檔案大小: 10.5 KB
 
1/** @file
2 CPU Exception Library provides PEI/DXE/SMM CPU common exception handler.
3
4Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>
5This program and the accompanying materials are licensed and made available under
6the terms and conditions of the BSD License that accompanies this distribution.
7The full text of the license may be found at
8http://opensource.org/licenses/bsd-license.php.
9
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13**/
14
15#include "CpuExceptionCommon.h"
16#include <Library/DebugLib.h>
17
18/**
19 Internal worker function for common exception handler.
20
21 @param ExceptionType Exception type.
22 @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
23 @param ExceptionHandlerData Pointer to exception handler data.
24**/
25VOID
26CommonExceptionHandlerWorker (
27 IN EFI_EXCEPTION_TYPE ExceptionType,
28 IN EFI_SYSTEM_CONTEXT SystemContext,
29 IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData
30 )
31{
32 EXCEPTION_HANDLER_CONTEXT *ExceptionHandlerContext;
33 RESERVED_VECTORS_DATA *ReservedVectors;
34 EFI_CPU_INTERRUPT_HANDLER *ExternalInterruptHandler;
35
36 ExceptionHandlerContext = (EXCEPTION_HANDLER_CONTEXT *) (UINTN) (SystemContext.SystemContextIa32);
37 ReservedVectors = ExceptionHandlerData->ReservedVectors;
38 ExternalInterruptHandler = ExceptionHandlerData->ExternalInterruptHandler;
39
40 switch (ReservedVectors[ExceptionType].Attribute) {
41 case EFI_VECTOR_HANDOFF_HOOK_BEFORE:
42 //
43 // Need to jmp to old IDT handler after this exception handler
44 //
45 ExceptionHandlerContext->ExceptionDataFlag = (mErrorCodeFlag & (1 << ExceptionType)) ? TRUE : FALSE;
46 ExceptionHandlerContext->OldIdtHandler = ReservedVectors[ExceptionType].ExceptonHandler;
47 break;
48 case EFI_VECTOR_HANDOFF_HOOK_AFTER:
49 while (TRUE) {
50 //
51 // If if anyone has gotten SPIN_LOCK for owner running hook after
52 //
53 if (AcquireSpinLockOrFail (&ReservedVectors[ExceptionType].SpinLock)) {
54 //
55 // Need to execute old IDT handler before running this exception handler
56 //
57 ReservedVectors[ExceptionType].ApicId = GetApicId ();
58 ArchSaveExceptionContext (ExceptionType, SystemContext, ExceptionHandlerData);
59 ExceptionHandlerContext->ExceptionDataFlag = (mErrorCodeFlag & (1 << ExceptionType)) ? TRUE : FALSE;
60 ExceptionHandlerContext->OldIdtHandler = ReservedVectors[ExceptionType].ExceptonHandler;
61 return;
62 }
63 //
64 // If failed to acquire SPIN_LOCK, check if it was locked by processor itself
65 //
66 if (ReservedVectors[ExceptionType].ApicId == GetApicId ()) {
67 //
68 // Old IDT handler has been executed, then restore CPU exception content to
69 // run new exception handler.
70 //
71 ArchRestoreExceptionContext (ExceptionType, SystemContext, ExceptionHandlerData);
72 //
73 // Rlease spin lock for ApicId
74 //
75 ReleaseSpinLock (&ReservedVectors[ExceptionType].SpinLock);
76 break;
77 }
78 CpuPause ();
79 }
80 break;
81 case 0xffffffff:
82 break;
83 default:
84 //
85 // It should never reach here
86 //
87 CpuDeadLoop ();
88 break;
89 }
90
91 if (ExternalInterruptHandler != NULL &&
92 ExternalInterruptHandler[ExceptionType] != NULL) {
93 (ExternalInterruptHandler[ExceptionType]) (ExceptionType, SystemContext);
94 } else if (ExceptionType < CPU_EXCEPTION_NUM) {
95 //
96 // Get Spinlock to display CPU information
97 //
98 while (!AcquireSpinLockOrFail (&ExceptionHandlerData->DisplayMessageSpinLock)) {
99 CpuPause ();
100 }
101 //
102 // Initialize the serial port before dumping.
103 //
104 SerialPortInitialize ();
105 //
106 // Display ExceptionType, CPU information and Image information
107 //
108 DumpImageAndCpuContent (ExceptionType, SystemContext);
109 //
110 // Release Spinlock of output message
111 //
112 ReleaseSpinLock (&ExceptionHandlerData->DisplayMessageSpinLock);
113 //
114 // Enter a dead loop if needn't to execute old IDT handler further
115 //
116 if (ReservedVectors[ExceptionType].Attribute != EFI_VECTOR_HANDOFF_HOOK_BEFORE) {
117 CpuDeadLoop ();
118 }
119 }
120}
121
122/**
123 Internal worker function to update IDT entries accordling to vector attributes.
124
125 @param[in] IdtTable Pointer to IDT table.
126 @param[in] TemplateMap Pointer to a buffer where the address map is
127 returned.
128 @param[in] ExceptionHandlerData Pointer to exception handler data.
129
130**/
131VOID
132UpdateIdtTable (
133 IN IA32_IDT_GATE_DESCRIPTOR *IdtTable,
134 IN EXCEPTION_HANDLER_TEMPLATE_MAP *TemplateMap,
135 IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData
136 )
137{
138 UINT16 CodeSegment;
139 UINTN Index;
140 UINTN InterruptHandler;
141 RESERVED_VECTORS_DATA *ReservedVectors;
142
143 ReservedVectors = ExceptionHandlerData->ReservedVectors;
144 //
145 // Use current CS as the segment selector of interrupt gate in IDT
146 //
147 CodeSegment = AsmReadCs ();
148
149 for (Index = 0; Index < ExceptionHandlerData->IdtEntryCount; Index ++) {
150 IdtTable[Index].Bits.Selector = CodeSegment;
151 //
152 // Check reserved vectors attributes
153 //
154 switch (ReservedVectors[Index].Attribute) {
155 case EFI_VECTOR_HANDOFF_DO_NOT_HOOK:
156 //
157 // Keep original IDT entry
158 //
159 continue;
160 case EFI_VECTOR_HANDOFF_HOOK_AFTER:
161 InitializeSpinLock (&ReservedVectors[Index].SpinLock);
162 CopyMem (
163 (VOID *) ReservedVectors[Index].HookAfterStubHeaderCode,
164 (VOID *) TemplateMap->HookAfterStubHeaderStart,
165 TemplateMap->ExceptionStubHeaderSize
166 );
167 AsmVectorNumFixup (
168 (VOID *) ReservedVectors[Index].HookAfterStubHeaderCode,
169 (UINT8) Index,
170 (VOID *) TemplateMap->HookAfterStubHeaderStart
171 );
172 //
173 // Go on the following code
174 //
175 case EFI_VECTOR_HANDOFF_HOOK_BEFORE:
176 //
177 // Save original IDT handler address
178 //
179 ReservedVectors[Index].ExceptonHandler = ArchGetIdtHandler (&IdtTable[Index]);
180 //
181 // Go on the following code
182 //
183 default:
184 //
185 // Update new IDT entry
186 //
187 InterruptHandler = TemplateMap->ExceptionStart + Index * TemplateMap->ExceptionStubHeaderSize;
188 ArchUpdateIdtEntry (&IdtTable[Index], InterruptHandler);
189 break;
190 }
191 }
192}
193
194/**
195 Internal worker function to initialize exception handler.
196
197 @param[in] VectorInfo Pointer to reserved vector list.
198 @param[in, out] ExceptionHandlerData Pointer to exception handler data.
199
200 @retval EFI_SUCCESS CPU Exception Entries have been successfully initialized
201 with default exception handlers.
202 @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.
203 @retval EFI_UNSUPPORTED This function is not supported.
204
205**/
206EFI_STATUS
207InitializeCpuExceptionHandlersWorker (
208 IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL,
209 IN OUT EXCEPTION_HANDLER_DATA *ExceptionHandlerData
210 )
211{
212 EFI_STATUS Status;
213 IA32_DESCRIPTOR IdtDescriptor;
214 UINTN IdtEntryCount;
215 EXCEPTION_HANDLER_TEMPLATE_MAP TemplateMap;
216 IA32_IDT_GATE_DESCRIPTOR *IdtTable;
217 RESERVED_VECTORS_DATA *ReservedVectors;
218
219 ReservedVectors = ExceptionHandlerData->ReservedVectors;
220 SetMem ((VOID *) ReservedVectors, sizeof (RESERVED_VECTORS_DATA) * CPU_EXCEPTION_NUM, 0xff);
221 if (VectorInfo != NULL) {
222 Status = ReadAndVerifyVectorInfo (VectorInfo, ReservedVectors, CPU_EXCEPTION_NUM);
223 if (EFI_ERROR (Status)) {
224 return EFI_INVALID_PARAMETER;
225 }
226 }
227
228 //
229 // Read IDT descriptor and calculate IDT size
230 //
231 AsmReadIdtr (&IdtDescriptor);
232 IdtEntryCount = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);
233 if (IdtEntryCount > CPU_EXCEPTION_NUM) {
234 //
235 // CPU exeption library only setup CPU_EXCEPTION_NUM exception handler at most
236 //
237 IdtEntryCount = CPU_EXCEPTION_NUM;
238 }
239
240 IdtTable = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
241 AsmGetTemplateAddressMap (&TemplateMap);
242 ASSERT (TemplateMap.ExceptionStubHeaderSize <= HOOKAFTER_STUB_SIZE);
243
244 ExceptionHandlerData->IdtEntryCount = IdtEntryCount;
245 UpdateIdtTable (IdtTable, &TemplateMap, ExceptionHandlerData);
246
247 return EFI_SUCCESS;
248}
249
250/**
251 Registers a function to be called from the processor interrupt handler.
252
253 @param[in] InterruptType Defines which interrupt or exception to hook.
254 @param[in] InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
255 when a processor interrupt occurs. If this parameter is NULL, then the handler
256 will be uninstalled
257 @param[in] ExceptionHandlerData Pointer to exception handler data.
258
259 @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
260 @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
261 previously installed.
262 @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
263 previously installed.
264 @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported,
265 or this function is not supported.
266**/
267EFI_STATUS
268RegisterCpuInterruptHandlerWorker (
269 IN EFI_EXCEPTION_TYPE InterruptType,
270 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler,
271 IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData
272 )
273{
274 UINTN EnabledInterruptNum;
275 RESERVED_VECTORS_DATA *ReservedVectors;
276 EFI_CPU_INTERRUPT_HANDLER *ExternalInterruptHandler;
277
278 EnabledInterruptNum = ExceptionHandlerData->IdtEntryCount;
279 ReservedVectors = ExceptionHandlerData->ReservedVectors;
280 ExternalInterruptHandler = ExceptionHandlerData->ExternalInterruptHandler;
281
282 if (InterruptType < 0 || InterruptType >= (EFI_EXCEPTION_TYPE)EnabledInterruptNum ||
283 ReservedVectors[InterruptType].Attribute == EFI_VECTOR_HANDOFF_DO_NOT_HOOK) {
284 return EFI_UNSUPPORTED;
285 }
286
287 if (InterruptHandler == NULL && ExternalInterruptHandler[InterruptType] == NULL) {
288 return EFI_INVALID_PARAMETER;
289 }
290
291 if (InterruptHandler != NULL && ExternalInterruptHandler[InterruptType] != NULL) {
292 return EFI_ALREADY_STARTED;
293 }
294
295 ExternalInterruptHandler[InterruptType] = InterruptHandler;
296 return EFI_SUCCESS;
297}
298
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette