2 IA32 CPU Exception Handler functons.
4 Copyright (c) 2012 - 2017, 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
71 ReservedVectors
[ExceptionType
].OldFlags
= SystemContext
.SystemContextIa32
->Eflags
;
72 ReservedVectors
[ExceptionType
].OldCs
= SystemContext
.SystemContextIa32
->Cs
;
73 ReservedVectors
[ExceptionType
].OldIp
= SystemContext
.SystemContextIa32
->Eip
;
74 ReservedVectors
[ExceptionType
].ExceptionData
= SystemContext
.SystemContextIa32
->ExceptionData
;
76 // Clear IF flag to avoid old IDT handler enable interrupt by IRET
78 Eflags
.UintN
= SystemContext
.SystemContextIa32
->Eflags
;
80 SystemContext
.SystemContextIa32
->Eflags
= Eflags
.UintN
;
82 // Modify the EIP in stack, then old IDT handler will return to the stub code
84 SystemContext
.SystemContextIa32
->Eip
= (UINTN
) ReservedVectors
[ExceptionType
].HookAfterStubHeaderCode
;
88 Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
90 @param[in] ExceptionType Exception type.
91 @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT.
92 @param[in] ExceptionHandlerData Pointer to exception handler data.
95 ArchRestoreExceptionContext (
96 IN UINTN ExceptionType
,
97 IN EFI_SYSTEM_CONTEXT SystemContext
,
98 IN EXCEPTION_HANDLER_DATA
*ExceptionHandlerData
101 RESERVED_VECTORS_DATA
*ReservedVectors
;
103 ReservedVectors
= ExceptionHandlerData
->ReservedVectors
;
104 SystemContext
.SystemContextIa32
->Eflags
= ReservedVectors
[ExceptionType
].OldFlags
;
105 SystemContext
.SystemContextIa32
->Cs
= ReservedVectors
[ExceptionType
].OldCs
;
106 SystemContext
.SystemContextIa32
->Eip
= ReservedVectors
[ExceptionType
].OldIp
;
107 SystemContext
.SystemContextIa32
->ExceptionData
= ReservedVectors
[ExceptionType
].ExceptionData
;
111 Setup separate stack for given exceptions.
113 @param[in] StackSwitchData Pointer to data required for setuping up
116 @retval EFI_SUCCESS The exceptions have been successfully
117 initialized with new stack.
118 @retval EFI_INVALID_PARAMETER StackSwitchData contains invalid content.
122 ArchSetupExcpetionStack (
123 IN CPU_EXCEPTION_INIT_DATA
*StackSwitchData
126 IA32_DESCRIPTOR Gdtr
;
127 IA32_DESCRIPTOR Idtr
;
128 IA32_IDT_GATE_DESCRIPTOR
*IdtTable
;
129 IA32_TSS_DESCRIPTOR
*TssDesc
;
130 IA32_TASK_STATE_SEGMENT
*Tss
;
136 EXCEPTION_HANDLER_TEMPLATE_MAP TemplateMap
;
138 if (StackSwitchData
== NULL
||
139 StackSwitchData
->Ia32
.Revision
!= CPU_EXCEPTION_INIT_DATA_REV
||
140 StackSwitchData
->Ia32
.KnownGoodStackTop
== 0 ||
141 StackSwitchData
->Ia32
.KnownGoodStackSize
== 0 ||
142 StackSwitchData
->Ia32
.StackSwitchExceptions
== NULL
||
143 StackSwitchData
->Ia32
.StackSwitchExceptionNumber
== 0 ||
144 StackSwitchData
->Ia32
.StackSwitchExceptionNumber
> CPU_EXCEPTION_NUM
||
145 StackSwitchData
->Ia32
.GdtTable
== NULL
||
146 StackSwitchData
->Ia32
.IdtTable
== NULL
||
147 StackSwitchData
->Ia32
.ExceptionTssDesc
== NULL
||
148 StackSwitchData
->Ia32
.ExceptionTss
== NULL
) {
149 return EFI_INVALID_PARAMETER
;
153 // The caller is responsible for that the GDT table, no matter the existing
154 // one or newly allocated, has enough space to hold descriptors for exception
155 // task-state segments.
157 if (((UINTN
)StackSwitchData
->Ia32
.GdtTable
& (IA32_GDT_ALIGNMENT
- 1)) != 0) {
158 return EFI_INVALID_PARAMETER
;
161 if ((UINTN
)StackSwitchData
->Ia32
.ExceptionTssDesc
< (UINTN
)(StackSwitchData
->Ia32
.GdtTable
)) {
162 return EFI_INVALID_PARAMETER
;
165 if ((UINTN
)StackSwitchData
->Ia32
.ExceptionTssDesc
+ StackSwitchData
->Ia32
.ExceptionTssDescSize
>
166 ((UINTN
)(StackSwitchData
->Ia32
.GdtTable
) + StackSwitchData
->Ia32
.GdtTableSize
)) {
167 return EFI_INVALID_PARAMETER
;
171 // We need one descriptor and one TSS for current task and every exception
174 if (StackSwitchData
->Ia32
.ExceptionTssDescSize
<
175 sizeof (IA32_TSS_DESCRIPTOR
) * (StackSwitchData
->Ia32
.StackSwitchExceptionNumber
+ 1)) {
176 return EFI_INVALID_PARAMETER
;
178 if (StackSwitchData
->Ia32
.ExceptionTssSize
<
179 sizeof (IA32_TASK_STATE_SEGMENT
) * (StackSwitchData
->Ia32
.StackSwitchExceptionNumber
+ 1)) {
180 return EFI_INVALID_PARAMETER
;
183 TssDesc
= StackSwitchData
->Ia32
.ExceptionTssDesc
;
184 Tss
= StackSwitchData
->Ia32
.ExceptionTss
;
187 // Initialize new GDT table and/or IDT table, if any
192 GdtSize
= (UINTN
)TssDesc
+
193 sizeof (IA32_TSS_DESCRIPTOR
) *
194 (StackSwitchData
->Ia32
.StackSwitchExceptionNumber
+ 1) -
195 (UINTN
)(StackSwitchData
->Ia32
.GdtTable
);
196 if ((UINTN
)StackSwitchData
->Ia32
.GdtTable
!= Gdtr
.Base
) {
197 CopyMem (StackSwitchData
->Ia32
.GdtTable
, (VOID
*)Gdtr
.Base
, Gdtr
.Limit
+ 1);
198 Gdtr
.Base
= (UINTN
)StackSwitchData
->Ia32
.GdtTable
;
199 Gdtr
.Limit
= (UINT16
)GdtSize
- 1;
202 if ((UINTN
)StackSwitchData
->Ia32
.IdtTable
!= Idtr
.Base
) {
203 Idtr
.Base
= (UINTN
)StackSwitchData
->Ia32
.IdtTable
;
205 if (StackSwitchData
->Ia32
.IdtTableSize
> 0) {
206 Idtr
.Limit
= (UINT16
)(StackSwitchData
->Ia32
.IdtTableSize
- 1);
210 // Fixup current task descriptor. Task-state segment for current task will
211 // be filled by processor during task switching.
213 TssBase
= (UINTN
)Tss
;
215 TssDesc
->Bits
.LimitLow
= sizeof(IA32_TASK_STATE_SEGMENT
) - 1;
216 TssDesc
->Bits
.BaseLow
= (UINT16
)TssBase
;
217 TssDesc
->Bits
.BaseMid
= (UINT8
)(TssBase
>> 16);
218 TssDesc
->Bits
.Type
= IA32_GDT_TYPE_TSS
;
219 TssDesc
->Bits
.Present
= 1;
220 TssDesc
->Bits
.LimitHigh
= 0;
221 TssDesc
->Bits
.BaseHigh
= (UINT8
)(TssBase
>> 24);
224 // Fixup exception task descriptor and task-state segment
226 AsmGetTssTemplateMap (&TemplateMap
);
227 StackTop
= StackSwitchData
->Ia32
.KnownGoodStackTop
- CPU_STACK_ALIGNMENT
;
228 StackTop
= (UINTN
)ALIGN_POINTER (StackTop
, CPU_STACK_ALIGNMENT
);
229 IdtTable
= StackSwitchData
->Ia32
.IdtTable
;
230 for (Index
= 0; Index
< StackSwitchData
->Ia32
.StackSwitchExceptionNumber
; ++Index
) {
235 // Fixup TSS descriptor
237 TssBase
= (UINTN
)Tss
;
239 TssDesc
->Bits
.LimitLow
= sizeof(IA32_TASK_STATE_SEGMENT
) - 1;
240 TssDesc
->Bits
.BaseLow
= (UINT16
)TssBase
;
241 TssDesc
->Bits
.BaseMid
= (UINT8
)(TssBase
>> 16);
242 TssDesc
->Bits
.Type
= IA32_GDT_TYPE_TSS
;
243 TssDesc
->Bits
.Present
= 1;
244 TssDesc
->Bits
.LimitHigh
= 0;
245 TssDesc
->Bits
.BaseHigh
= (UINT8
)(TssBase
>> 24);
250 Vector
= StackSwitchData
->Ia32
.StackSwitchExceptions
[Index
];
251 if (Vector
>= CPU_EXCEPTION_NUM
||
252 Vector
>= (Idtr
.Limit
+ 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR
)) {
256 Tss
->Eip
= (UINT32
)(TemplateMap
.ExceptionStart
257 + Vector
* TemplateMap
.ExceptionStubHeaderSize
);
260 Tss
->Cr3
= AsmReadCr3 ();
261 Tss
->Es
= AsmReadEs ();
262 Tss
->Cs
= AsmReadCs ();
263 Tss
->Ss
= AsmReadSs ();
264 Tss
->Ds
= AsmReadDs ();
265 Tss
->Fs
= AsmReadFs ();
266 Tss
->Gs
= AsmReadGs ();
268 StackTop
-= StackSwitchData
->Ia32
.KnownGoodStackSize
;
271 // Update IDT to use Task Gate for given exception
273 IdtTable
[Vector
].Bits
.OffsetLow
= 0;
274 IdtTable
[Vector
].Bits
.Selector
= (UINT16
)((UINTN
)TssDesc
- Gdtr
.Base
);
275 IdtTable
[Vector
].Bits
.Reserved_0
= 0;
276 IdtTable
[Vector
].Bits
.GateType
= IA32_IDT_GATE_TYPE_TASK
;
277 IdtTable
[Vector
].Bits
.OffsetHigh
= 0;
283 AsmWriteGdtr (&Gdtr
);
288 AsmWriteTr ((UINT16
)((UINTN
)StackSwitchData
->Ia32
.ExceptionTssDesc
- Gdtr
.Base
));
293 AsmWriteIdtr (&Idtr
);
299 Display processor context.
301 @param[in] ExceptionType Exception type.
302 @param[in] SystemContext Processor context to be display.
307 IN EFI_EXCEPTION_TYPE ExceptionType
,
308 IN EFI_SYSTEM_CONTEXT SystemContext
311 InternalPrintMessage (
312 "!!!! IA32 Exception Type - %02x(%a) CPU Apic ID - %08x !!!!\n",
314 GetExceptionNameStr (ExceptionType
),
317 if ((mErrorCodeFlag
& (1 << ExceptionType
)) != 0) {
318 InternalPrintMessage (
319 "ExceptionData - %08x",
320 SystemContext
.SystemContextIa32
->ExceptionData
322 if (ExceptionType
== EXCEPT_IA32_PAGE_FAULT
) {
323 InternalPrintMessage (
324 " I:%x R:%x U:%x W:%x P:%x PK:%x S:%x",
325 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_ID
) != 0,
326 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_RSVD
) != 0,
327 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_US
) != 0,
328 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_WR
) != 0,
329 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_P
) != 0,
330 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_PK
) != 0,
331 (SystemContext
.SystemContextIa32
->ExceptionData
& IA32_PF_EC_SGX
) != 0
334 InternalPrintMessage ("\n");
336 InternalPrintMessage (
337 "EIP - %08x, CS - %08x, EFLAGS - %08x\n",
338 SystemContext
.SystemContextIa32
->Eip
,
339 SystemContext
.SystemContextIa32
->Cs
,
340 SystemContext
.SystemContextIa32
->Eflags
342 InternalPrintMessage (
343 "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x\n",
344 SystemContext
.SystemContextIa32
->Eax
,
345 SystemContext
.SystemContextIa32
->Ecx
,
346 SystemContext
.SystemContextIa32
->Edx
,
347 SystemContext
.SystemContextIa32
->Ebx
349 InternalPrintMessage (
350 "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",
351 SystemContext
.SystemContextIa32
->Esp
,
352 SystemContext
.SystemContextIa32
->Ebp
,
353 SystemContext
.SystemContextIa32
->Esi
,
354 SystemContext
.SystemContextIa32
->Edi
356 InternalPrintMessage (
357 "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x\n",
358 SystemContext
.SystemContextIa32
->Ds
,
359 SystemContext
.SystemContextIa32
->Es
,
360 SystemContext
.SystemContextIa32
->Fs
,
361 SystemContext
.SystemContextIa32
->Gs
,
362 SystemContext
.SystemContextIa32
->Ss
364 InternalPrintMessage (
365 "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",
366 SystemContext
.SystemContextIa32
->Cr0
,
367 SystemContext
.SystemContextIa32
->Cr2
,
368 SystemContext
.SystemContextIa32
->Cr3
,
369 SystemContext
.SystemContextIa32
->Cr4
371 InternalPrintMessage (
372 "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",
373 SystemContext
.SystemContextIa32
->Dr0
,
374 SystemContext
.SystemContextIa32
->Dr1
,
375 SystemContext
.SystemContextIa32
->Dr2
,
376 SystemContext
.SystemContextIa32
->Dr3
378 InternalPrintMessage (
379 "DR6 - %08x, DR7 - %08x\n",
380 SystemContext
.SystemContextIa32
->Dr6
,
381 SystemContext
.SystemContextIa32
->Dr7
383 InternalPrintMessage (
384 "GDTR - %08x %08x, IDTR - %08x %08x\n",
385 SystemContext
.SystemContextIa32
->Gdtr
[0],
386 SystemContext
.SystemContextIa32
->Gdtr
[1],
387 SystemContext
.SystemContextIa32
->Idtr
[0],
388 SystemContext
.SystemContextIa32
->Idtr
[1]
390 InternalPrintMessage (
391 "LDTR - %08x, TR - %08x\n",
392 SystemContext
.SystemContextIa32
->Ldtr
,
393 SystemContext
.SystemContextIa32
->Tr
395 InternalPrintMessage (
396 "FXSAVE_STATE - %08x\n",
397 &SystemContext
.SystemContextIa32
->FxSaveState
402 Display CPU information.
404 @param ExceptionType Exception type.
405 @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
408 DumpImageAndCpuContent (
409 IN EFI_EXCEPTION_TYPE ExceptionType
,
410 IN EFI_SYSTEM_CONTEXT SystemContext
413 DumpCpuContext (ExceptionType
, SystemContext
);
415 // Dump module image base and module entry point by EIP
417 DumpModuleImageInfo (SystemContext
.SystemContextIa32
->Eip
);