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