VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c

最後變更 在這個檔案是 99404,由 vboxsync 提交於 2 年 前

Devices/EFI/FirmwareNew: Update to edk2-stable202302 and make it build, bugref:4643

  • 屬性 svn:eol-style 設為 native
檔案大小: 14.1 KB
 
1/** @file
2 x64 CPU Exception Handler.
3
4 Copyright (c) 2012 - 2022, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7**/
8
9#include "CpuExceptionCommon.h"
10
11/**
12 Return address map of exception handler template so that C code can generate
13 exception tables.
14
15 @param IdtEntry Pointer to IDT entry to be updated.
16 @param InterruptHandler IDT handler value.
17**/
18VOID
19ArchUpdateIdtEntry (
20 OUT IA32_IDT_GATE_DESCRIPTOR *IdtEntry,
21 IN UINTN InterruptHandler
22 )
23{
24 IdtEntry->Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
25 IdtEntry->Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
26 IdtEntry->Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32);
27 IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
28}
29
30/**
31 Read IDT handler value from IDT entry.
32
33 @param IdtEntry Pointer to IDT entry to be read.
34
35**/
36UINTN
37ArchGetIdtHandler (
38 IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry
39 )
40{
41 return IdtEntry->Bits.OffsetLow + (((UINTN)IdtEntry->Bits.OffsetHigh) << 16) +
42 (((UINTN)IdtEntry->Bits.OffsetUpper) << 32);
43}
44
45/**
46 Save CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
47
48 @param[in] ExceptionType Exception type.
49 @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT.
50 @param[in] ExceptionHandlerData Pointer to exception handler data.
51**/
52VOID
53ArchSaveExceptionContext (
54 IN UINTN ExceptionType,
55 IN EFI_SYSTEM_CONTEXT SystemContext,
56 IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData
57 )
58{
59 IA32_EFLAGS32 Eflags;
60 RESERVED_VECTORS_DATA *ReservedVectors;
61
62 ReservedVectors = ExceptionHandlerData->ReservedVectors;
63 //
64 // Save Exception context in global variable in first entry of the exception handler.
65 // So when original exception handler returns to the new exception handler (second entry),
66 // the Eflags/Cs/Eip/ExceptionData can be used.
67 //
68 ReservedVectors[ExceptionType].OldSs = SystemContext.SystemContextX64->Ss;
69 ReservedVectors[ExceptionType].OldSp = SystemContext.SystemContextX64->Rsp;
70 ReservedVectors[ExceptionType].OldFlags = SystemContext.SystemContextX64->Rflags;
71 ReservedVectors[ExceptionType].OldCs = SystemContext.SystemContextX64->Cs;
72 ReservedVectors[ExceptionType].OldIp = SystemContext.SystemContextX64->Rip;
73 ReservedVectors[ExceptionType].ExceptionData = SystemContext.SystemContextX64->ExceptionData;
74 //
75 // Clear IF flag to avoid old IDT handler enable interrupt by IRET
76 //
77 Eflags.UintN = SystemContext.SystemContextX64->Rflags;
78 Eflags.Bits.IF = 0;
79 SystemContext.SystemContextX64->Rflags = Eflags.UintN;
80 //
81 // Modify the EIP in stack, then old IDT handler will return to HookAfterStubBegin.
82 //
83 SystemContext.SystemContextX64->Rip = (UINTN)ReservedVectors[ExceptionType].HookAfterStubHeaderCode;
84}
85
86/**
87 Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
88
89 @param[in] ExceptionType Exception type.
90 @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT.
91 @param[in] ExceptionHandlerData Pointer to exception handler data.
92**/
93VOID
94ArchRestoreExceptionContext (
95 IN UINTN ExceptionType,
96 IN EFI_SYSTEM_CONTEXT SystemContext,
97 IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData
98 )
99{
100 RESERVED_VECTORS_DATA *ReservedVectors;
101
102 ReservedVectors = ExceptionHandlerData->ReservedVectors;
103 SystemContext.SystemContextX64->Ss = ReservedVectors[ExceptionType].OldSs;
104 SystemContext.SystemContextX64->Rsp = ReservedVectors[ExceptionType].OldSp;
105 SystemContext.SystemContextX64->Rflags = ReservedVectors[ExceptionType].OldFlags;
106 SystemContext.SystemContextX64->Cs = ReservedVectors[ExceptionType].OldCs;
107 SystemContext.SystemContextX64->Rip = ReservedVectors[ExceptionType].OldIp;
108 SystemContext.SystemContextX64->ExceptionData = ReservedVectors[ExceptionType].ExceptionData;
109}
110
111/**
112 Setup separate stacks for certain exception handlers.
113
114 @param[in] Buffer Point to buffer used to separate exception stack.
115 @param[in, out] BufferSize On input, it indicates the byte size of Buffer.
116 If the size is not enough, the return status will
117 be EFI_BUFFER_TOO_SMALL, and output BufferSize
118 will be the size it needs.
119
120 @retval EFI_SUCCESS The stacks are assigned successfully.
121 @retval EFI_BUFFER_TOO_SMALL This BufferSize is too small.
122 @retval EFI_UNSUPPORTED This function is not supported.
123**/
124EFI_STATUS
125ArchSetupExceptionStack (
126 IN VOID *Buffer,
127 IN OUT UINTN *BufferSize
128 )
129{
130 IA32_DESCRIPTOR Gdtr;
131 IA32_DESCRIPTOR Idtr;
132 IA32_IDT_GATE_DESCRIPTOR *IdtTable;
133 IA32_TSS_DESCRIPTOR *TssDesc;
134 IA32_TASK_STATE_SEGMENT *Tss;
135 VOID *NewGdtTable;
136 UINTN StackTop;
137 UINTN Index;
138 UINTN Vector;
139 UINTN TssBase;
140 UINT8 *StackSwitchExceptions;
141 UINTN NeedBufferSize;
142
143 if (BufferSize == NULL) {
144 return EFI_INVALID_PARAMETER;
145 }
146
147 //
148 // Interrupt stack table supports only 7 vectors.
149 //
150 if (CPU_STACK_SWITCH_EXCEPTION_NUMBER > ARRAY_SIZE (Tss->IST)) {
151 return EFI_UNSUPPORTED;
152 }
153
154 //
155 // Total needed size includes stack size, new GDT table size, TSS size.
156 // Add another DESCRIPTOR size for alignment requiremet.
157 //
158 // Layout of memory needed for each processor:
159 // --------------------------------
160 // | |
161 // | Stack Size | X ExceptionNumber
162 // | |
163 // --------------------------------
164 // | Alignment | (just in case)
165 // --------------------------------
166 // | |
167 // | Original GDT |
168 // | |
169 // --------------------------------
170 // | |
171 // | Exception task descriptors | X 1
172 // | |
173 // --------------------------------
174 // | |
175 // | Exception task-state segment | X 1
176 // | |
177 // --------------------------------
178 //
179 AsmReadGdtr (&Gdtr);
180 NeedBufferSize = CPU_STACK_SWITCH_EXCEPTION_NUMBER * CPU_KNOWN_GOOD_STACK_SIZE +
181 sizeof (IA32_TSS_DESCRIPTOR) +
182 Gdtr.Limit + 1 + CPU_TSS_DESC_SIZE +
183 CPU_TSS_SIZE;
184
185 if (*BufferSize < NeedBufferSize) {
186 *BufferSize = NeedBufferSize;
187 return EFI_BUFFER_TOO_SMALL;
188 }
189
190 if (Buffer == NULL) {
191 return EFI_INVALID_PARAMETER;
192 }
193
194 AsmReadIdtr (&Idtr);
195 StackSwitchExceptions = CPU_STACK_SWITCH_EXCEPTION_LIST;
196 StackTop = (UINTN)Buffer + CPU_STACK_SWITCH_EXCEPTION_NUMBER * CPU_KNOWN_GOOD_STACK_SIZE;
197 NewGdtTable = ALIGN_POINTER (StackTop, sizeof (IA32_TSS_DESCRIPTOR));
198 TssDesc = (IA32_TSS_DESCRIPTOR *)((UINTN)NewGdtTable + Gdtr.Limit + 1);
199 Tss = (IA32_TASK_STATE_SEGMENT *)((UINTN)TssDesc + CPU_TSS_DESC_SIZE);
200
201 CopyMem (NewGdtTable, (VOID *)Gdtr.Base, Gdtr.Limit + 1);
202 Gdtr.Base = (UINTN)NewGdtTable;
203 Gdtr.Limit = (UINT16)(Gdtr.Limit + CPU_TSS_DESC_SIZE);
204
205 //
206 // Fixup current task descriptor. Task-state segment for current task will
207 // be filled by processor during task switching.
208 //
209 TssBase = (UINTN)Tss;
210
211 TssDesc->Uint128.Uint64 = 0;
212 TssDesc->Uint128.Uint64_1 = 0;
213 TssDesc->Bits.LimitLow = sizeof (IA32_TASK_STATE_SEGMENT) - 1;
214 TssDesc->Bits.BaseLow = (UINT16)TssBase;
215 TssDesc->Bits.BaseMidl = (UINT8)(TssBase >> 16);
216 TssDesc->Bits.Type = IA32_GDT_TYPE_TSS;
217 TssDesc->Bits.P = 1;
218 TssDesc->Bits.LimitHigh = 0;
219 TssDesc->Bits.BaseMidh = (UINT8)(TssBase >> 24);
220 TssDesc->Bits.BaseHigh = (UINT32)(TssBase >> 32);
221
222 //
223 // Fixup exception task descriptor and task-state segment
224 //
225 ZeroMem (Tss, sizeof (*Tss));
226 //
227 // Plus 1 byte is for compact stack layout in case StackTop is already aligned.
228 //
229 StackTop = StackTop - CPU_STACK_ALIGNMENT + 1;
230 StackTop = (UINTN)ALIGN_POINTER (StackTop, CPU_STACK_ALIGNMENT);
231 IdtTable = (IA32_IDT_GATE_DESCRIPTOR *)Idtr.Base;
232 for (Index = 0; Index < CPU_STACK_SWITCH_EXCEPTION_NUMBER; ++Index) {
233 //
234 // Fixup IST
235 //
236 Tss->IST[Index] = StackTop;
237 StackTop -= CPU_KNOWN_GOOD_STACK_SIZE;
238
239 //
240 // Set the IST field to enable corresponding IST
241 //
242 Vector = StackSwitchExceptions[Index];
243 if ((Vector >= CPU_EXCEPTION_NUM) ||
244 (Vector >= (Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR)))
245 {
246 continue;
247 }
248
249 IdtTable[Vector].Bits.Reserved_0 = (UINT8)(Index + 1);
250 }
251
252 //
253 // Publish GDT
254 //
255 AsmWriteGdtr (&Gdtr);
256
257 //
258 // Load current task
259 //
260 AsmWriteTr ((UINT16)((UINTN)TssDesc - Gdtr.Base));
261
262 return EFI_SUCCESS;
263}
264
265/**
266 Display CPU information.
267
268 @param ExceptionType Exception type.
269 @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
270**/
271VOID
272EFIAPI
273DumpCpuContext (
274 IN EFI_EXCEPTION_TYPE ExceptionType,
275 IN EFI_SYSTEM_CONTEXT SystemContext
276 )
277{
278 InternalPrintMessage (
279 "!!!! X64 Exception Type - %02x(%a) CPU Apic ID - %08x !!!!\n",
280 ExceptionType,
281 GetExceptionNameStr (ExceptionType),
282 GetApicId ()
283 );
284 if ((mErrorCodeFlag & (1 << ExceptionType)) != 0) {
285 InternalPrintMessage (
286 "ExceptionData - %016lx",
287 SystemContext.SystemContextX64->ExceptionData
288 );
289 if (ExceptionType == EXCEPT_IA32_PAGE_FAULT) {
290 InternalPrintMessage (
291 " I:%x R:%x U:%x W:%x P:%x PK:%x SS:%x SGX:%x",
292 (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_ID) != 0,
293 (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_RSVD) != 0,
294 (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_US) != 0,
295 (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_WR) != 0,
296 (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_P) != 0,
297 (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_PK) != 0,
298 (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_SS) != 0,
299 (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_SGX) != 0
300 );
301 }
302
303 InternalPrintMessage ("\n");
304 }
305
306 InternalPrintMessage (
307 "RIP - %016lx, CS - %016lx, RFLAGS - %016lx\n",
308 SystemContext.SystemContextX64->Rip,
309 SystemContext.SystemContextX64->Cs,
310 SystemContext.SystemContextX64->Rflags
311 );
312 InternalPrintMessage (
313 "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",
314 SystemContext.SystemContextX64->Rax,
315 SystemContext.SystemContextX64->Rcx,
316 SystemContext.SystemContextX64->Rdx
317 );
318 InternalPrintMessage (
319 "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",
320 SystemContext.SystemContextX64->Rbx,
321 SystemContext.SystemContextX64->Rsp,
322 SystemContext.SystemContextX64->Rbp
323 );
324 InternalPrintMessage (
325 "RSI - %016lx, RDI - %016lx\n",
326 SystemContext.SystemContextX64->Rsi,
327 SystemContext.SystemContextX64->Rdi
328 );
329 InternalPrintMessage (
330 "R8 - %016lx, R9 - %016lx, R10 - %016lx\n",
331 SystemContext.SystemContextX64->R8,
332 SystemContext.SystemContextX64->R9,
333 SystemContext.SystemContextX64->R10
334 );
335 InternalPrintMessage (
336 "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",
337 SystemContext.SystemContextX64->R11,
338 SystemContext.SystemContextX64->R12,
339 SystemContext.SystemContextX64->R13
340 );
341 InternalPrintMessage (
342 "R14 - %016lx, R15 - %016lx\n",
343 SystemContext.SystemContextX64->R14,
344 SystemContext.SystemContextX64->R15
345 );
346 InternalPrintMessage (
347 "DS - %016lx, ES - %016lx, FS - %016lx\n",
348 SystemContext.SystemContextX64->Ds,
349 SystemContext.SystemContextX64->Es,
350 SystemContext.SystemContextX64->Fs
351 );
352 InternalPrintMessage (
353 "GS - %016lx, SS - %016lx\n",
354 SystemContext.SystemContextX64->Gs,
355 SystemContext.SystemContextX64->Ss
356 );
357 InternalPrintMessage (
358 "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",
359 SystemContext.SystemContextX64->Cr0,
360 SystemContext.SystemContextX64->Cr2,
361 SystemContext.SystemContextX64->Cr3
362 );
363 InternalPrintMessage (
364 "CR4 - %016lx, CR8 - %016lx\n",
365 SystemContext.SystemContextX64->Cr4,
366 SystemContext.SystemContextX64->Cr8
367 );
368 InternalPrintMessage (
369 "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",
370 SystemContext.SystemContextX64->Dr0,
371 SystemContext.SystemContextX64->Dr1,
372 SystemContext.SystemContextX64->Dr2
373 );
374 InternalPrintMessage (
375 "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",
376 SystemContext.SystemContextX64->Dr3,
377 SystemContext.SystemContextX64->Dr6,
378 SystemContext.SystemContextX64->Dr7
379 );
380 InternalPrintMessage (
381 "GDTR - %016lx %016lx, LDTR - %016lx\n",
382 SystemContext.SystemContextX64->Gdtr[0],
383 SystemContext.SystemContextX64->Gdtr[1],
384 SystemContext.SystemContextX64->Ldtr
385 );
386 InternalPrintMessage (
387 "IDTR - %016lx %016lx, TR - %016lx\n",
388 SystemContext.SystemContextX64->Idtr[0],
389 SystemContext.SystemContextX64->Idtr[1],
390 SystemContext.SystemContextX64->Tr
391 );
392 InternalPrintMessage (
393 "FXSAVE_STATE - %016lx\n",
394 &SystemContext.SystemContextX64->FxSaveState
395 );
396}
397
398/**
399 Display CPU information.
400
401 @param ExceptionType Exception type.
402 @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
403**/
404VOID
405DumpImageAndCpuContent (
406 IN EFI_EXCEPTION_TYPE ExceptionType,
407 IN EFI_SYSTEM_CONTEXT SystemContext
408 )
409{
410 DumpCpuContext (ExceptionType, SystemContext);
411 //
412 // Dump module image base and module entry point by RIP
413 //
414 if ((ExceptionType == EXCEPT_IA32_PAGE_FAULT) &&
415 ((SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_ID) != 0))
416 {
417 //
418 // The RIP in SystemContext could not be used
419 // if it is page fault with I/D set.
420 //
421 DumpModuleImageInfo ((*(UINTN *)(UINTN)SystemContext.SystemContextX64->Rsp));
422 } else {
423 DumpModuleImageInfo (SystemContext.SystemContextX64->Rip);
424 }
425}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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