TianoCore EDK2 master
Loading...
Searching...
No Matches
ArchExceptionHandler.c
Go to the documentation of this file.
1
10
19VOID
21 OUT IA32_IDT_GATE_DESCRIPTOR *IdtEntry,
22 IN UINTN InterruptHandler
23 )
24{
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;
28}
29
38 IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry
39 )
40{
41 return (UINTN)IdtEntry->Bits.OffsetLow + (((UINTN)IdtEntry->Bits.OffsetHigh) << 16);
42}
43
51VOID
53 IN UINTN ExceptionType,
54 IN EFI_SYSTEM_CONTEXT SystemContext,
55 IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData
56 )
57{
58 IA32_EFLAGS32 Eflags;
59 RESERVED_VECTORS_DATA *ReservedVectors;
60
61 ReservedVectors = ExceptionHandlerData->ReservedVectors;
62 //
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.
66 //
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;
71 //
72 // Clear IF flag to avoid old IDT handler enable interrupt by IRET
73 //
74 Eflags.UintN = SystemContext.SystemContextIa32->Eflags;
75 Eflags.Bits.IF = 0;
76 SystemContext.SystemContextIa32->Eflags = Eflags.UintN;
77 //
78 // Modify the EIP in stack, then old IDT handler will return to HookAfterStubBegin.
79 //
80 SystemContext.SystemContextIa32->Eip = (UINTN)ReservedVectors[ExceptionType].HookAfterStubHeaderCode;
81}
82
90VOID
92 IN UINTN ExceptionType,
93 IN EFI_SYSTEM_CONTEXT SystemContext,
94 IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData
95 )
96{
97 RESERVED_VECTORS_DATA *ReservedVectors;
98
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;
104}
105
120 IN VOID *Buffer,
121 IN OUT UINTN *BufferSize
122 )
123{
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;
130 VOID *NewGdtTable;
131 UINTN StackTop;
132 UINTN Index;
133 UINTN Vector;
134 UINTN TssBase;
135 UINT8 *StackSwitchExceptions;
136 UINTN NeedBufferSize;
138
139 if (BufferSize == NULL) {
140 return EFI_INVALID_PARAMETER;
141 }
142
143 //
144 // Total needed size includes stack size, new GDT table size, TSS size.
145 // Add another DESCRIPTOR size for alignment requiremet.
146 //
147 // Layout of memory needed for each processor:
148 // --------------------------------
149 // | |
150 // | Stack Size | X ExceptionNumber
151 // | |
152 // --------------------------------
153 // | Alignment | (just in case)
154 // --------------------------------
155 // | |
156 // | Original GDT |
157 // | |
158 // --------------------------------
159 // | Current task descriptor |
160 // --------------------------------
161 // | |
162 // | Exception task descriptors | X ExceptionNumber
163 // | |
164 // --------------------------------
165 // | Current task-state segment |
166 // --------------------------------
167 // | |
168 // | Exception task-state segment | X ExceptionNumber
169 // | |
170 // --------------------------------
171 //
172 AsmReadGdtr (&Gdtr);
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 +
176 CPU_TSS_SIZE;
177
178 if (*BufferSize < NeedBufferSize) {
179 *BufferSize = NeedBufferSize;
180 return EFI_BUFFER_TOO_SMALL;
181 }
182
183 if (Buffer == NULL) {
184 return EFI_INVALID_PARAMETER;
185 }
186
187 AsmReadIdtr (&Idtr);
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;
194
195 CopyMem (NewGdtTable, (VOID *)Gdtr.Base, Gdtr.Limit + 1);
196 Gdtr.Base = (UINTN)NewGdtTable;
197 Gdtr.Limit = (UINT16)(Gdtr.Limit + CPU_TSS_DESC_SIZE);
198
199 //
200 // Fixup current task descriptor. Task-state segment for current task will
201 // be filled by processor during task switching.
202 //
203 TssBase = (UINTN)Tss;
204
205 TssDesc->Uint64 = 0;
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;
210 TssDesc->Bits.P = 1;
211 TssDesc->Bits.LimitHigh = 0;
212 TssDesc->Bits.BaseHigh = (UINT8)(TssBase >> 24);
213
214 //
215 // Fixup exception task descriptor and task-state segment
216 //
217 AsmGetTssTemplateMap (&TemplateMap);
218 //
219 // Plus 1 byte is for compact stack layout in case StackTop is already aligned.
220 //
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) {
225 TssDesc += 1;
226 Tss += 1;
227
228 //
229 // Fixup TSS descriptor
230 //
231 TssBase = (UINTN)Tss;
232
233 TssDesc->Uint64 = 0;
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;
238 TssDesc->Bits.P = 1;
239 TssDesc->Bits.LimitHigh = 0;
240 TssDesc->Bits.BaseHigh = (UINT8)(TssBase >> 24);
241
242 //
243 // Fixup TSS
244 //
245 Vector = StackSwitchExceptions[Index];
246 if ((Vector >= CPU_EXCEPTION_NUM) ||
247 (Vector >= (Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR)))
248 {
249 continue;
250 }
251
252 ZeroMem (Tss, sizeof (*Tss));
253 Tss->EIP = (UINT32)(TemplateMap.ExceptionStart
254 + Vector * TemplateMap.ExceptionStubHeaderSize);
255 Tss->EFLAGS = 0x2;
256 Tss->ESP = StackTop;
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 ();
264
265 StackTop -= CPU_KNOWN_GOOD_STACK_SIZE;
266
267 //
268 // Update IDT to use Task Gate for given exception
269 //
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;
275 }
276
277 //
278 // Publish GDT
279 //
280 AsmWriteGdtr (&Gdtr);
281
282 //
283 // Load current task
284 //
285 AsmWriteTr ((UINT16)((UINTN)TssDescBase - Gdtr.Base));
286
287 return EFI_SUCCESS;
288}
289
296VOID
297EFIAPI
299 IN EFI_EXCEPTION_TYPE ExceptionType,
300 IN EFI_SYSTEM_CONTEXT SystemContext
301 )
302{
304 "!!!! IA32 Exception Type - %02x(%a) CPU Apic ID - %08x !!!!\n",
305 ExceptionType,
306 GetExceptionNameStr (ExceptionType),
307 GetApicId ()
308 );
309 if ((mErrorCodeFlag & (1 << ExceptionType)) != 0) {
311 "ExceptionData - %08x",
312 SystemContext.SystemContextIa32->ExceptionData
313 );
314 if (ExceptionType == EXCEPT_IA32_PAGE_FAULT) {
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
325 );
326 }
327
329 }
330
332 "EIP - %08x, CS - %08x, EFLAGS - %08x\n",
333 SystemContext.SystemContextIa32->Eip,
334 SystemContext.SystemContextIa32->Cs,
335 SystemContext.SystemContextIa32->Eflags
336 );
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
343 );
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
350 );
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
358 );
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
365 );
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
372 );
374 "DR6 - %08x, DR7 - %08x\n",
375 SystemContext.SystemContextIa32->Dr6,
376 SystemContext.SystemContextIa32->Dr7
377 );
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]
384 );
386 "LDTR - %08x, TR - %08x\n",
387 SystemContext.SystemContextIa32->Ldtr,
388 SystemContext.SystemContextIa32->Tr
389 );
391 "FXSAVE_STATE - %08x\n",
392 &SystemContext.SystemContextIa32->FxSaveState
393 );
394}
395
402VOID
404 IN EFI_EXCEPTION_TYPE ExceptionType,
405 IN EFI_SYSTEM_CONTEXT SystemContext
406 )
407{
408 DumpCpuContext (ExceptionType, SystemContext);
409 //
410 // Dump module image base and module entry point by EIP
411 //
412 if ((ExceptionType == EXCEPT_IA32_PAGE_FAULT) &&
413 ((SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != 0))
414 {
415 //
416 // The EIP in SystemContext could not be used
417 // if it is page fault with I/D set.
418 //
419 DumpModuleImageInfo ((*(UINTN *)(UINTN)SystemContext.SystemContextIa32->Esp));
420 } else {
421 DumpModuleImageInfo (SystemContext.SystemContextIa32->Eip);
422 }
423}
UINT64 UINTN
#define CPU_STACK_ALIGNMENT
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID DumpModuleImageInfo(IN UINTN CurrentEip)
VOID EFIAPI AsmGetTssTemplateMap(OUT EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap)
STATIC CONST CHAR8 * GetExceptionNameStr(IN EFI_EXCEPTION_TYPE ExceptionType)
STATIC VOID EFIAPI InternalPrintMessage(IN CONST CHAR8 *Format,...)
VOID ArchSaveExceptionContext(IN UINTN ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext, IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData)
VOID EFIAPI DumpCpuContext(IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext)
VOID ArchRestoreExceptionContext(IN UINTN ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext, IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData)
VOID DumpImageAndCpuContent(IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext)
UINTN ArchGetIdtHandler(IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry)
EFI_STATUS ArchSetupExceptionStack(IN VOID *Buffer, IN OUT UINTN *BufferSize)
VOID ArchUpdateIdtEntry(OUT IA32_IDT_GATE_DESCRIPTOR *IdtEntry, IN UINTN InterruptHandler)
UINT16 EFIAPI AsmReadFs(VOID)
UINT16 EFIAPI AsmReadEs(VOID)
UINTN EFIAPI AsmReadCr3(VOID)
UINT16 EFIAPI AsmReadGs(VOID)
UINT16 EFIAPI AsmReadSs(VOID)
UINT16 EFIAPI AsmReadCs(VOID)
UINT16 EFIAPI AsmReadDs(VOID)
UINT32 EFIAPI GetApicId(VOID)
Definition: BaseXApicLib.c:337
#define NULL
Definition: Base.h:319
#define ALIGN_POINTER(Pointer, Alignment)
Definition: Base.h:963
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
INTN EFI_EXCEPTION_TYPE
Definition: DebugSupport.h:35
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
VOID EFIAPI AsmReadGdtr(OUT IA32_DESCRIPTOR *Gdtr)
Definition: X86ReadGdtr.c:24
VOID EFIAPI AsmReadIdtr(OUT IA32_DESCRIPTOR *Idtr)
Definition: X86ReadIdtr.c:24
VOID EFIAPI AsmWriteTr(IN UINT16 Selector)
VOID EFIAPI AsmWriteGdtr(IN CONST IA32_DESCRIPTOR *Gdtr)