VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuException.c@ 58466

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

EFI/Firmware: Merged in the svn:eol-style, svn:mime-type and trailing whitespace cleanup that was done after the initial UDK2014.SP1 import: svn merge /vendor/edk2/UDK2014.SP1 /vendor/edk2/current .

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

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