2 IA32 CPU Exception Handler functons.
4 Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "CpuExceptionCommon.h"
18 Return address map of exception handler template so that C code can generate
21 @param IdtEntry Pointer to IDT entry to be updated.
22 @param InterruptHandler IDT handler value.
27 IN IA32_IDT_GATE_DESCRIPTOR
*IdtEntry
,
28 IN UINTN InterruptHandler
31 IdtEntry
->Bits
.OffsetLow
= (UINT16
)(UINTN
)InterruptHandler
;
32 IdtEntry
->Bits
.OffsetHigh
= (UINT16
)((UINTN
)InterruptHandler
>> 16);
33 IdtEntry
->Bits
.GateType
= IA32_IDT_GATE_TYPE_INTERRUPT_32
;
37 Read IDT handler value from IDT entry.
39 @param IdtEntry Pointer to IDT entry to be read.
44 IN IA32_IDT_GATE_DESCRIPTOR
*IdtEntry
47 return (UINTN
)IdtEntry
->Bits
.OffsetLow
+ (((UINTN
)IdtEntry
->Bits
.OffsetHigh
) << 16);
51 Save CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
53 @param[in] ExceptionType Exception type.
54 @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT.
55 @param[in] ExceptionHandlerData Pointer to exception handler data.
58 ArchSaveExceptionContext (
59 IN UINTN ExceptionType
,
60 IN EFI_SYSTEM_CONTEXT SystemContext
,
61 IN EXCEPTION_HANDLER_DATA
*ExceptionHandlerData
65 RESERVED_VECTORS_DATA
*ReservedVectors
;
67 ReservedVectors
= ExceptionHandlerData
->ReservedVectors
;
69 // Save Exception context in global variable in first entry of the exception handler.
70 // So when original exception handler returns to the new exception handler (second entry),
71 // the Eflags/Cs/Eip/ExceptionData can be used.
73 ReservedVectors
[ExceptionType
].OldFlags
= SystemContext
.SystemContextIa32
->Eflags
;
74 ReservedVectors
[ExceptionType
].OldCs
= SystemContext
.SystemContextIa32
->Cs
;
75 ReservedVectors
[ExceptionType
].OldIp
= SystemContext
.SystemContextIa32
->Eip
;
76 ReservedVectors
[ExceptionType
].ExceptionData
= SystemContext
.SystemContextIa32
->ExceptionData
;
78 // Clear IF flag to avoid old IDT handler enable interrupt by IRET
80 Eflags
.UintN
= SystemContext
.SystemContextIa32
->Eflags
;
82 SystemContext
.SystemContextIa32
->Eflags
= Eflags
.UintN
;
84 // Modify the EIP in stack, then old IDT handler will return to HookAfterStubBegin.
86 SystemContext
.SystemContextIa32
->Eip
= (UINTN
) ReservedVectors
[ExceptionType
].HookAfterStubHeaderCode
;
90 Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
92 @param[in] ExceptionType Exception type.
93 @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT.
94 @param[in] ExceptionHandlerData Pointer to exception handler data.
97 ArchRestoreExceptionContext (
98 IN UINTN ExceptionType
,
99 IN EFI_SYSTEM_CONTEXT SystemContext
,
100 IN EXCEPTION_HANDLER_DATA
*ExceptionHandlerData
103 RESERVED_VECTORS_DATA
*ReservedVectors
;
105 ReservedVectors
= ExceptionHandlerData
->ReservedVectors
;
106 SystemContext
.SystemContextIa32
->Eflags
= ReservedVectors
[ExceptionType
].OldFlags
;
107 SystemContext
.SystemContextIa32
->Cs
= ReservedVectors
[ExceptionType
].OldCs
;
108 SystemContext
.SystemContextIa32
->Eip
= ReservedVectors
[ExceptionType
].OldIp
;
109 SystemContext
.SystemContextIa32
->ExceptionData
= ReservedVectors
[ExceptionType
].ExceptionData
;
113 Setup separate stack for given exceptions.
115 @param[in] StackSwitchData Pointer to data required for setuping up
118 @retval EFI_SUCCESS The exceptions have been successfully
119 initialized with new stack.
120 @retval EFI_INVALID_PARAMETER StackSwitchData contains invalid content.
124 ArchSetupExceptionStack (
125 IN CPU_EXCEPTION_INIT_DATA
*StackSwitchData
128 IA32_DESCRIPTOR Gdtr
;
129 IA32_DESCRIPTOR Idtr
;
130 IA32_IDT_GATE_DESCRIPTOR
*IdtTable
;
131 IA32_TSS_DESCRIPTOR
*TssDesc
;
132 IA32_TASK_STATE_SEGMENT
*Tss
;
138 EXCEPTION_HANDLER_TEMPLATE_MAP TemplateMap
;
140 if (StackSwitchData
== NULL
||
141 StackSwitchData
->Ia32
.Revision
!= CPU_EXCEPTION_INIT_DATA_REV
||
142 StackSwitchData
->Ia32
.KnownGoodStackTop
== 0 ||
143 StackSwitchData
->Ia32
.KnownGoodStackSize
== 0 ||
144 StackSwitchData
->Ia32
.StackSwitchExceptions
== NULL
||
145 StackSwitchData
->Ia32
.StackSwitchExceptionNumber
== 0 ||
146 StackSwitchData
->Ia32
.StackSwitchExceptionNumber
> CPU_EXCEPTION_NUM
||
147 StackSwitchData
->Ia32
.GdtTable
== NULL
||
148 StackSwitchData
->Ia32
.IdtTable
== NULL
||
149 StackSwitchData
->Ia32
.ExceptionTssDesc
== NULL
||
150 StackSwitchData
->Ia32
.ExceptionTss
== NULL
) {
151 return EFI_INVALID_PARAMETER
;
155 // The caller is responsible for that the GDT table, no matter the existing
156 // one or newly allocated, has enough space to hold descriptors for exception
157 // task-state segments.
159 if (((UINTN
)StackSwitchData
->Ia32
.GdtTable
& (IA32_GDT_ALIGNMENT
- 1)) != 0) {
160 return EFI_INVALID_PARAMETER
;
163 if ((UINTN
)StackSwitchData
->Ia32
.ExceptionTssDesc
< (UINTN
)(StackSwitchData
->Ia32
.GdtTable
)) {
164 return EFI_INVALID_PARAMETER
;
167 if ((UINTN
)StackSwitchData
->Ia32
.ExceptionTssDesc
+ StackSwitchData
->Ia32
.ExceptionTssDescSize
>
168 ((UINTN
)(StackSwitchData
->Ia32
.GdtTable
) + StackSwitchData
->Ia32
.GdtTableSize
)) {
169 return EFI_INVALID_PARAMETER
;
173 // We need one descriptor and one TSS for current task and every exception
176 if (StackSwitchData
->Ia32
.ExceptionTssDescSize
<
177 sizeof (IA32_TSS_DESCRIPTOR
) * (StackSwitchData
->Ia32
.StackSwitchExceptionNumber
+ 1)) {
178 return EFI_INVALID_PARAMETER
;
180 if (StackSwitchData
->Ia32
.ExceptionTssSize
<
181 sizeof (IA32_TASK_STATE_SEGMENT
) * (StackSwitchData
->Ia32
.StackSwitchExceptionNumber
+ 1)) {
182 return EFI_INVALID_PARAMETER
;
185 TssDesc
= StackSwitchData
->Ia32
.ExceptionTssDesc
;
186 Tss
= StackSwitchData
->Ia32
.ExceptionTss
;
189 // Initialize new GDT table and/or IDT table, if any
194 GdtSize
= (UINTN
)TssDesc
+
195 sizeof (IA32_TSS_DESCRIPTOR
) *
196 (StackSwitchData
->Ia32
.StackSwitchExceptionNumber
+ 1) -
197 (UINTN
)(StackSwitchData
->Ia32
.GdtTable
);
198 if ((UINTN
)StackSwitchData
->Ia32
.GdtTable
!= Gdtr
.Base
) {
199 CopyMem (StackSwitchData
->Ia32
.GdtTable
, (VOID
*)Gdtr
.Base
, Gdtr
.Limit
+ 1);
200 Gdtr
.Base
= (UINTN
)StackSwitchData
->Ia32
.GdtTable
;
201 Gdtr
.Limit
= (UINT16
)GdtSize
- 1;
204 if ((UINTN
)StackSwitchData
->Ia32
.IdtTable
!= Idtr
.Base
) {
205 Idtr
.Base
= (UINTN
)StackSwitchData
->Ia32
.IdtTable
;
207 if (StackSwitchData
->Ia32
.IdtTableSize
> 0) {
208 Idtr
.Limit
= (UINT16
)(StackSwitchData
->Ia32
.IdtTableSize
- 1);
212 // Fixup current task descriptor. Task-state segment for current task will
213 // be filled by processor during task switching.
215 TssBase
= (UINTN
)Tss
;
218 TssDesc
->Bits
.LimitLow
= sizeof(IA32_TASK_STATE_SEGMENT
) - 1;
219 TssDesc
->Bits
.BaseLow
= (UINT16
)TssBase
;
220 TssDesc
->Bits
.BaseMid
= (UINT8
)(TssBase
>> 16);
221 TssDesc
->Bits
.Type
= IA32_GDT_TYPE_TSS
;
223 TssDesc
->Bits
.LimitHigh
= 0;
224 TssDesc
->Bits
.BaseHigh
= (UINT8
)(TssBase
>> 24);
227 // Fixup exception task descriptor and task-state segment
229 AsmGetTssTemplateMap (&TemplateMap
);
230 StackTop
= StackSwitchData
->Ia32
.KnownGoodStackTop
- CPU_STACK_ALIGNMENT
;
231 StackTop
= (UINTN
)ALIGN_POINTER (StackTop
, CPU_STACK_ALIGNMENT
);
232 IdtTable
= StackSwitchData
->Ia32
.IdtTable
;
233 for (Index
= 0; Index
< StackSwitchData
->Ia32
.StackSwitchExceptionNumber
; ++Index
) {
238 // Fixup TSS descriptor
240 TssBase
= (UINTN
)Tss
;
243 TssDesc
->Bits
.LimitLow
= sizeof(IA32_TASK_STATE_SEGMENT
) - 1;
244 TssDesc
->Bits
.BaseLow
= (UINT16
)TssBase
;
245 TssDesc
->Bits
.BaseMid
= (UINT8
)(TssBase
>> 16);
246 TssDesc
->Bits
.Type
= IA32_GDT_TYPE_TSS
;
248 TssDesc
->Bits
.LimitHigh
= 0;
249 TssDesc
->Bits
.BaseHigh
= (UINT8
)(TssBase
>> 24);
254 Vector
= StackSwitchData
->Ia32
.StackSwitchExceptions
[Index
];
255 if (Vector
>= CPU_EXCEPTION_NUM
||
256 Vector
>= (Idtr
.Limit
+ 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR
)) {
260 ZeroMem (Tss
, sizeof (*Tss
));
261 Tss
->EIP
= (UINT32
)(TemplateMap
.ExceptionStart
262 + Vector
* TemplateMap
.ExceptionStubHeaderSize
);
265 Tss
->CR3
= AsmReadCr3 ();
266 Tss
->ES
= AsmReadEs ();
267 Tss
->CS
= AsmReadCs ();
268 Tss
->SS
= AsmReadSs ();
269 Tss
->DS
= AsmReadDs ();
270 Tss
->FS
= AsmReadFs ();
271 Tss
->GS
= AsmReadGs ();
273 StackTop
-= StackSwitchData
->Ia32
.KnownGoodStackSize
;
276 // Update IDT to use Task Gate for given exception
278 IdtTable
[Vector
].Bits
.OffsetLow
= 0;
279 IdtTable
[Vector
].Bits
.Selector
= (UINT16
)((UINTN
)TssDesc
- Gdtr
.Base
);
280 IdtTable
[Vector
].Bits
.Reserved_0
= 0;
281 IdtTable
[Vector
].Bits
.GateType
= IA32_IDT_GATE_TYPE_TASK
;
282 IdtTable
[Vector
].Bits
.OffsetHigh
= 0;
288 AsmWriteGdtr (&Gdtr
);
293 AsmWriteTr ((UINT16
)((UINTN
)StackSwitchData
->Ia32
.ExceptionTssDesc
- Gdtr
.Base
));
298 AsmWriteIdtr (&Idtr
);
304 Display processor context.
306 @param[in] ExceptionType Exception type.
307 @param[in] SystemContext Processor context to be display.
312 IN EFI_EXCEPTION_TYPE ExceptionType
,
313 IN EFI_SYSTEM_CONTEXT SystemContext
316 InternalPrintMessage (
317 "!!!! IA32 Exception Type - %02x(%a) CPU Apic ID - %08x !!!!\n",
319 GetExceptionNameStr (ExceptionType
),
322 if ((mErrorCodeFlag
& (1 << ExceptionType
)) != 0) {
323 InternalPrintMessage (
324 "ExceptionData - %08x",
325 SystemContext
.SystemContextIa32
->ExceptionData
327 if (ExceptionType
== EXCEPT_IA32_PAGE_FAULT
) {
328 InternalPrintMessage (
329 " I:%x R:%x U:%x W:%x P:%x PK:%x S:%x",
330 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_ID
) != 0,
331 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_RSVD
) != 0,
332 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_US
) != 0,
333 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_WR
) != 0,
334 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_P
) != 0,
335 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_PK
) != 0,
336 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_SGX
) != 0
339 InternalPrintMessage ("\n");
341 InternalPrintMessage (
342 "EIP - %08x, CS - %08x, EFLAGS - %08x\n",
343 SystemContext
.SystemContextIa32
->Eip
,
344 SystemContext
.SystemContextIa32
->Cs
,
345 SystemContext
.SystemContextIa32
->Eflags
347 InternalPrintMessage (
348 "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x\n",
349 SystemContext
.SystemContextIa32
->Eax
,
350 SystemContext
.SystemContextIa32
->Ecx
,
351 SystemContext
.SystemContextIa32
->Edx
,
352 SystemContext
.SystemContextIa32
->Ebx
354 InternalPrintMessage (
355 "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",
356 SystemContext
.SystemContextIa32
->Esp
,
357 SystemContext
.SystemContextIa32
->Ebp
,
358 SystemContext
.SystemContextIa32
->Esi
,
359 SystemContext
.SystemContextIa32
->Edi
361 InternalPrintMessage (
362 "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x\n",
363 SystemContext
.SystemContextIa32
->Ds
,
364 SystemContext
.SystemContextIa32
->Es
,
365 SystemContext
.SystemContextIa32
->Fs
,
366 SystemContext
.SystemContextIa32
->Gs
,
367 SystemContext
.SystemContextIa32
->Ss
369 InternalPrintMessage (
370 "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",
371 SystemContext
.SystemContextIa32
->Cr0
,
372 SystemContext
.SystemContextIa32
->Cr2
,
373 SystemContext
.SystemContextIa32
->Cr3
,
374 SystemContext
.SystemContextIa32
->Cr4
376 InternalPrintMessage (
377 "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",
378 SystemContext
.SystemContextIa32
->Dr0
,
379 SystemContext
.SystemContextIa32
->Dr1
,
380 SystemContext
.SystemContextIa32
->Dr2
,
381 SystemContext
.SystemContextIa32
->Dr3
383 InternalPrintMessage (
384 "DR6 - %08x, DR7 - %08x\n",
385 SystemContext
.SystemContextIa32
->Dr6
,
386 SystemContext
.SystemContextIa32
->Dr7
388 InternalPrintMessage (
389 "GDTR - %08x %08x, IDTR - %08x %08x\n",
390 SystemContext
.SystemContextIa32
->Gdtr
[0],
391 SystemContext
.SystemContextIa32
->Gdtr
[1],
392 SystemContext
.SystemContextIa32
->Idtr
[0],
393 SystemContext
.SystemContextIa32
->Idtr
[1]
395 InternalPrintMessage (
396 "LDTR - %08x, TR - %08x\n",
397 SystemContext
.SystemContextIa32
->Ldtr
,
398 SystemContext
.SystemContextIa32
->Tr
400 InternalPrintMessage (
401 "FXSAVE_STATE - %08x\n",
402 &SystemContext
.SystemContextIa32
->FxSaveState
407 Display CPU information.
409 @param ExceptionType Exception type.
410 @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
413 DumpImageAndCpuContent (
414 IN EFI_EXCEPTION_TYPE ExceptionType
,
415 IN EFI_SYSTEM_CONTEXT SystemContext
418 DumpCpuContext (ExceptionType
, SystemContext
);
420 // Dump module image base and module entry point by EIP
422 if ((ExceptionType
== EXCEPT_IA32_PAGE_FAULT
) &&
423 ((SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_ID
) != 0)) {
425 // The EIP in SystemContext could not be used
426 // if it is page fault with I/D set.
428 DumpModuleImageInfo ((*(UINTN
*)(UINTN
)SystemContext
.SystemContextIa32
->Esp
));
430 DumpModuleImageInfo (SystemContext
.SystemContextIa32
->Eip
);