2 IA32 CPU Exception Handler functons.
4 Copyright (c) 2012 - 2022, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "CpuExceptionCommon.h"
12 Return address map of exception handler template so that C code can generate
15 @param IdtEntry Pointer to IDT entry to be updated.
16 @param InterruptHandler IDT handler value.
21 OUT IA32_IDT_GATE_DESCRIPTOR
*IdtEntry
,
22 IN UINTN InterruptHandler
25 IdtEntry
->Bits
.OffsetLow
= (UINT16
)(UINTN
)InterruptHandler
;
26 IdtEntry
->Bits
.OffsetHigh
= (UINT16
)((UINTN
)InterruptHandler
>> 16);
27 IdtEntry
->Bits
.GateType
= IA32_IDT_GATE_TYPE_INTERRUPT_32
;
31 Read IDT handler value from IDT entry.
33 @param IdtEntry Pointer to IDT entry to be read.
38 IN IA32_IDT_GATE_DESCRIPTOR
*IdtEntry
41 return (UINTN
)IdtEntry
->Bits
.OffsetLow
+ (((UINTN
)IdtEntry
->Bits
.OffsetHigh
) << 16);
45 Save CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
47 @param[in] ExceptionType Exception type.
48 @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT.
49 @param[in] ExceptionHandlerData Pointer to exception handler data.
52 ArchSaveExceptionContext (
53 IN UINTN ExceptionType
,
54 IN EFI_SYSTEM_CONTEXT SystemContext
,
55 IN EXCEPTION_HANDLER_DATA
*ExceptionHandlerData
59 RESERVED_VECTORS_DATA
*ReservedVectors
;
61 ReservedVectors
= ExceptionHandlerData
->ReservedVectors
;
63 // Save Exception context in global variable in first entry of the exception handler.
64 // So when original exception handler returns to the new exception handler (second entry),
65 // the Eflags/Cs/Eip/ExceptionData can be used.
67 ReservedVectors
[ExceptionType
].OldFlags
= SystemContext
.SystemContextIa32
->Eflags
;
68 ReservedVectors
[ExceptionType
].OldCs
= SystemContext
.SystemContextIa32
->Cs
;
69 ReservedVectors
[ExceptionType
].OldIp
= SystemContext
.SystemContextIa32
->Eip
;
70 ReservedVectors
[ExceptionType
].ExceptionData
= SystemContext
.SystemContextIa32
->ExceptionData
;
72 // Clear IF flag to avoid old IDT handler enable interrupt by IRET
74 Eflags
.UintN
= SystemContext
.SystemContextIa32
->Eflags
;
76 SystemContext
.SystemContextIa32
->Eflags
= Eflags
.UintN
;
78 // Modify the EIP in stack, then old IDT handler will return to HookAfterStubBegin.
80 SystemContext
.SystemContextIa32
->Eip
= (UINTN
)ReservedVectors
[ExceptionType
].HookAfterStubHeaderCode
;
84 Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
86 @param[in] ExceptionType Exception type.
87 @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT.
88 @param[in] ExceptionHandlerData Pointer to exception handler data.
91 ArchRestoreExceptionContext (
92 IN UINTN ExceptionType
,
93 IN EFI_SYSTEM_CONTEXT SystemContext
,
94 IN EXCEPTION_HANDLER_DATA
*ExceptionHandlerData
97 RESERVED_VECTORS_DATA
*ReservedVectors
;
99 ReservedVectors
= ExceptionHandlerData
->ReservedVectors
;
100 SystemContext
.SystemContextIa32
->Eflags
= ReservedVectors
[ExceptionType
].OldFlags
;
101 SystemContext
.SystemContextIa32
->Cs
= ReservedVectors
[ExceptionType
].OldCs
;
102 SystemContext
.SystemContextIa32
->Eip
= ReservedVectors
[ExceptionType
].OldIp
;
103 SystemContext
.SystemContextIa32
->ExceptionData
= ReservedVectors
[ExceptionType
].ExceptionData
;
107 Setup separate stacks for certain exception handlers.
109 @param[in] Buffer Point to buffer used to separate exception stack.
110 @param[in, out] BufferSize On input, it indicates the byte size of Buffer.
111 If the size is not enough, the return status will
112 be EFI_BUFFER_TOO_SMALL, and output BufferSize
113 will be the size it needs.
115 @retval EFI_SUCCESS The stacks are assigned successfully.
116 @retval EFI_BUFFER_TOO_SMALL This BufferSize is too small.
119 ArchSetupExceptionStack (
121 IN OUT UINTN
*BufferSize
124 IA32_DESCRIPTOR Gdtr
;
125 IA32_DESCRIPTOR Idtr
;
126 IA32_IDT_GATE_DESCRIPTOR
*IdtTable
;
127 IA32_TSS_DESCRIPTOR
*TssDesc
;
128 IA32_TSS_DESCRIPTOR
*TssDescBase
;
129 IA32_TASK_STATE_SEGMENT
*Tss
;
135 UINT8
*StackSwitchExceptions
;
136 UINTN NeedBufferSize
;
137 EXCEPTION_HANDLER_TEMPLATE_MAP TemplateMap
;
139 if (BufferSize
== NULL
) {
140 return EFI_INVALID_PARAMETER
;
144 // Total needed size includes stack size, new GDT table size, TSS size.
145 // Add another DESCRIPTOR size for alignment requiremet.
147 // Layout of memory needed for each processor:
148 // --------------------------------
150 // | Stack Size | X ExceptionNumber
152 // --------------------------------
153 // | Alignment | (just in case)
154 // --------------------------------
158 // --------------------------------
159 // | Current task descriptor |
160 // --------------------------------
162 // | Exception task descriptors | X ExceptionNumber
164 // --------------------------------
165 // | Current task-state segment |
166 // --------------------------------
168 // | Exception task-state segment | X ExceptionNumber
170 // --------------------------------
173 NeedBufferSize
= CPU_STACK_SWITCH_EXCEPTION_NUMBER
* CPU_KNOWN_GOOD_STACK_SIZE
+
174 sizeof (IA32_TSS_DESCRIPTOR
) +
175 Gdtr
.Limit
+ 1 + CPU_TSS_DESC_SIZE
+
178 if (*BufferSize
< NeedBufferSize
) {
179 *BufferSize
= NeedBufferSize
;
180 return EFI_BUFFER_TOO_SMALL
;
183 if (Buffer
== NULL
) {
184 return EFI_INVALID_PARAMETER
;
188 StackSwitchExceptions
= CPU_STACK_SWITCH_EXCEPTION_LIST
;
189 StackTop
= (UINTN
)Buffer
+ CPU_STACK_SWITCH_EXCEPTION_NUMBER
* CPU_KNOWN_GOOD_STACK_SIZE
;
190 NewGdtTable
= ALIGN_POINTER (StackTop
, sizeof (IA32_TSS_DESCRIPTOR
));
191 TssDesc
= (IA32_TSS_DESCRIPTOR
*)((UINTN
)NewGdtTable
+ Gdtr
.Limit
+ 1);
192 Tss
= (IA32_TASK_STATE_SEGMENT
*)((UINTN
)TssDesc
+ CPU_TSS_DESC_SIZE
);
193 TssDescBase
= TssDesc
;
195 CopyMem (NewGdtTable
, (VOID
*)Gdtr
.Base
, Gdtr
.Limit
+ 1);
196 Gdtr
.Base
= (UINTN
)NewGdtTable
;
197 Gdtr
.Limit
= (UINT16
)(Gdtr
.Limit
+ CPU_TSS_DESC_SIZE
);
200 // Fixup current task descriptor. Task-state segment for current task will
201 // be filled by processor during task switching.
203 TssBase
= (UINTN
)Tss
;
206 TssDesc
->Bits
.LimitLow
= sizeof (IA32_TASK_STATE_SEGMENT
) - 1;
207 TssDesc
->Bits
.BaseLow
= (UINT16
)TssBase
;
208 TssDesc
->Bits
.BaseMid
= (UINT8
)(TssBase
>> 16);
209 TssDesc
->Bits
.Type
= IA32_GDT_TYPE_TSS
;
211 TssDesc
->Bits
.LimitHigh
= 0;
212 TssDesc
->Bits
.BaseHigh
= (UINT8
)(TssBase
>> 24);
215 // Fixup exception task descriptor and task-state segment
217 AsmGetTssTemplateMap (&TemplateMap
);
219 // Plus 1 byte is for compact stack layout in case StackTop is already aligned.
221 StackTop
= StackTop
- CPU_STACK_ALIGNMENT
+ 1;
222 StackTop
= (UINTN
)ALIGN_POINTER (StackTop
, CPU_STACK_ALIGNMENT
);
223 IdtTable
= (IA32_IDT_GATE_DESCRIPTOR
*)Idtr
.Base
;
224 for (Index
= 0; Index
< CPU_STACK_SWITCH_EXCEPTION_NUMBER
; ++Index
) {
229 // Fixup TSS descriptor
231 TssBase
= (UINTN
)Tss
;
234 TssDesc
->Bits
.LimitLow
= sizeof (IA32_TASK_STATE_SEGMENT
) - 1;
235 TssDesc
->Bits
.BaseLow
= (UINT16
)TssBase
;
236 TssDesc
->Bits
.BaseMid
= (UINT8
)(TssBase
>> 16);
237 TssDesc
->Bits
.Type
= IA32_GDT_TYPE_TSS
;
239 TssDesc
->Bits
.LimitHigh
= 0;
240 TssDesc
->Bits
.BaseHigh
= (UINT8
)(TssBase
>> 24);
245 Vector
= StackSwitchExceptions
[Index
];
246 if ((Vector
>= CPU_EXCEPTION_NUM
) ||
247 (Vector
>= (Idtr
.Limit
+ 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR
)))
252 ZeroMem (Tss
, sizeof (*Tss
));
253 Tss
->EIP
= (UINT32
)(TemplateMap
.ExceptionStart
254 + Vector
* TemplateMap
.ExceptionStubHeaderSize
);
257 Tss
->CR3
= AsmReadCr3 ();
258 Tss
->ES
= AsmReadEs ();
259 Tss
->CS
= AsmReadCs ();
260 Tss
->SS
= AsmReadSs ();
261 Tss
->DS
= AsmReadDs ();
262 Tss
->FS
= AsmReadFs ();
263 Tss
->GS
= AsmReadGs ();
265 StackTop
-= CPU_KNOWN_GOOD_STACK_SIZE
;
268 // Update IDT to use Task Gate for given exception
270 IdtTable
[Vector
].Bits
.OffsetLow
= 0;
271 IdtTable
[Vector
].Bits
.Selector
= (UINT16
)((UINTN
)TssDesc
- Gdtr
.Base
);
272 IdtTable
[Vector
].Bits
.Reserved_0
= 0;
273 IdtTable
[Vector
].Bits
.GateType
= IA32_IDT_GATE_TYPE_TASK
;
274 IdtTable
[Vector
].Bits
.OffsetHigh
= 0;
280 AsmWriteGdtr (&Gdtr
);
285 AsmWriteTr ((UINT16
)((UINTN
)TssDescBase
- Gdtr
.Base
));
291 Display processor context.
293 @param[in] ExceptionType Exception type.
294 @param[in] SystemContext Processor context to be display.
299 IN EFI_EXCEPTION_TYPE ExceptionType
,
300 IN EFI_SYSTEM_CONTEXT SystemContext
303 InternalPrintMessage (
304 "!!!! IA32 Exception Type - %02x(%a) CPU Apic ID - %08x !!!!\n",
306 GetExceptionNameStr (ExceptionType
),
309 if ((mErrorCodeFlag
& (1 << ExceptionType
)) != 0) {
310 InternalPrintMessage (
311 "ExceptionData - %08x",
312 SystemContext
.SystemContextIa32
->ExceptionData
314 if (ExceptionType
== EXCEPT_IA32_PAGE_FAULT
) {
315 InternalPrintMessage (
316 " I:%x R:%x U:%x W:%x P:%x PK:%x SS:%x SGX:%x",
317 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_ID
) != 0,
318 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_RSVD
) != 0,
319 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_US
) != 0,
320 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_WR
) != 0,
321 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_P
) != 0,
322 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_PK
) != 0,
323 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_SS
) != 0,
324 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_SGX
) != 0
328 InternalPrintMessage ("\n");
331 InternalPrintMessage (
332 "EIP - %08x, CS - %08x, EFLAGS - %08x\n",
333 SystemContext
.SystemContextIa32
->Eip
,
334 SystemContext
.SystemContextIa32
->Cs
,
335 SystemContext
.SystemContextIa32
->Eflags
337 InternalPrintMessage (
338 "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x\n",
339 SystemContext
.SystemContextIa32
->Eax
,
340 SystemContext
.SystemContextIa32
->Ecx
,
341 SystemContext
.SystemContextIa32
->Edx
,
342 SystemContext
.SystemContextIa32
->Ebx
344 InternalPrintMessage (
345 "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",
346 SystemContext
.SystemContextIa32
->Esp
,
347 SystemContext
.SystemContextIa32
->Ebp
,
348 SystemContext
.SystemContextIa32
->Esi
,
349 SystemContext
.SystemContextIa32
->Edi
351 InternalPrintMessage (
352 "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x\n",
353 SystemContext
.SystemContextIa32
->Ds
,
354 SystemContext
.SystemContextIa32
->Es
,
355 SystemContext
.SystemContextIa32
->Fs
,
356 SystemContext
.SystemContextIa32
->Gs
,
357 SystemContext
.SystemContextIa32
->Ss
359 InternalPrintMessage (
360 "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",
361 SystemContext
.SystemContextIa32
->Cr0
,
362 SystemContext
.SystemContextIa32
->Cr2
,
363 SystemContext
.SystemContextIa32
->Cr3
,
364 SystemContext
.SystemContextIa32
->Cr4
366 InternalPrintMessage (
367 "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",
368 SystemContext
.SystemContextIa32
->Dr0
,
369 SystemContext
.SystemContextIa32
->Dr1
,
370 SystemContext
.SystemContextIa32
->Dr2
,
371 SystemContext
.SystemContextIa32
->Dr3
373 InternalPrintMessage (
374 "DR6 - %08x, DR7 - %08x\n",
375 SystemContext
.SystemContextIa32
->Dr6
,
376 SystemContext
.SystemContextIa32
->Dr7
378 InternalPrintMessage (
379 "GDTR - %08x %08x, IDTR - %08x %08x\n",
380 SystemContext
.SystemContextIa32
->Gdtr
[0],
381 SystemContext
.SystemContextIa32
->Gdtr
[1],
382 SystemContext
.SystemContextIa32
->Idtr
[0],
383 SystemContext
.SystemContextIa32
->Idtr
[1]
385 InternalPrintMessage (
386 "LDTR - %08x, TR - %08x\n",
387 SystemContext
.SystemContextIa32
->Ldtr
,
388 SystemContext
.SystemContextIa32
->Tr
390 InternalPrintMessage (
391 "FXSAVE_STATE - %08x\n",
392 &SystemContext
.SystemContextIa32
->FxSaveState
397 Display CPU information.
399 @param ExceptionType Exception type.
400 @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
403 DumpImageAndCpuContent (
404 IN EFI_EXCEPTION_TYPE ExceptionType
,
405 IN EFI_SYSTEM_CONTEXT SystemContext
408 DumpCpuContext (ExceptionType
, SystemContext
);
410 // Dump module image base and module entry point by EIP
412 if ((ExceptionType
== EXCEPT_IA32_PAGE_FAULT
) &&
413 ((SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_ID
) != 0))
416 // The EIP in SystemContext could not be used
417 // if it is page fault with I/D set.
419 DumpModuleImageInfo ((*(UINTN
*)(UINTN
)SystemContext
.SystemContextIa32
->Esp
));
421 DumpModuleImageInfo (SystemContext
.SystemContextIa32
->Eip
);