]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiException.nasm
UefiCpuPkg/dec: Add PcdCpuSmmStaticPageTable.
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / Ia32 / SmiException.nasm
CommitLineData
28ee5816
LG
1;------------------------------------------------------------------------------ ;\r
2; Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
3; This program and the accompanying materials\r
4; are licensed and made available under the terms and conditions of the BSD License\r
5; which accompanies this distribution. The full text of the license may be found at\r
6; http://opensource.org/licenses/bsd-license.php.\r
7;\r
8; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
9; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
10;\r
11; Module Name:\r
12;\r
13; SmiException.nasm\r
14;\r
15; Abstract:\r
16;\r
17; Exception handlers used in SM mode\r
18;\r
19;-------------------------------------------------------------------------------\r
20\r
21extern ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))\r
22extern ASM_PFX(gSmiMtrrs)\r
23extern ASM_PFX(SmiPFHandler)\r
24\r
25global ASM_PFX(gcSmiIdtr)\r
26global ASM_PFX(gcSmiGdtr)\r
27global ASM_PFX(gcPsd)\r
28\r
29 SECTION .data\r
30\r
31NullSeg: DQ 0 ; reserved by architecture\r
32CodeSeg32:\r
33 DW -1 ; LimitLow\r
34 DW 0 ; BaseLow\r
35 DB 0 ; BaseMid\r
36 DB 0x9b\r
37 DB 0xcf ; LimitHigh\r
38 DB 0 ; BaseHigh\r
39ProtModeCodeSeg32:\r
40 DW -1 ; LimitLow\r
41 DW 0 ; BaseLow\r
42 DB 0 ; BaseMid\r
43 DB 0x9b\r
44 DB 0xcf ; LimitHigh\r
45 DB 0 ; BaseHigh\r
46ProtModeSsSeg32:\r
47 DW -1 ; LimitLow\r
48 DW 0 ; BaseLow\r
49 DB 0 ; BaseMid\r
50 DB 0x93\r
51 DB 0xcf ; LimitHigh\r
52 DB 0 ; BaseHigh\r
53DataSeg32:\r
54 DW -1 ; LimitLow\r
55 DW 0 ; BaseLow\r
56 DB 0 ; BaseMid\r
57 DB 0x93\r
58 DB 0xcf ; LimitHigh\r
59 DB 0 ; BaseHigh\r
60CodeSeg16:\r
61 DW -1\r
62 DW 0\r
63 DB 0\r
64 DB 0x9b\r
65 DB 0x8f\r
66 DB 0\r
67DataSeg16:\r
68 DW -1\r
69 DW 0\r
70 DB 0\r
71 DB 0x93\r
72 DB 0x8f\r
73 DB 0\r
74CodeSeg64:\r
75 DW -1 ; LimitLow\r
76 DW 0 ; BaseLow\r
77 DB 0 ; BaseMid\r
78 DB 0x9b\r
79 DB 0xaf ; LimitHigh\r
80 DB 0 ; BaseHigh\r
81GDT_SIZE equ $ - NullSeg\r
82\r
83TssSeg:\r
84 DW TSS_DESC_SIZE ; LimitLow\r
85 DW 0 ; BaseLow\r
86 DB 0 ; BaseMid\r
87 DB 0x89\r
88 DB 0x80 ; LimitHigh\r
89 DB 0 ; BaseHigh\r
90ExceptionTssSeg:\r
91 DW TSS_DESC_SIZE ; LimitLow\r
92 DW 0 ; BaseLow\r
93 DB 0 ; BaseMid\r
94 DB 0x89\r
95 DB 0x80 ; LimitHigh\r
96 DB 0 ; BaseHigh\r
97\r
98CODE_SEL equ CodeSeg32 - NullSeg\r
99DATA_SEL equ DataSeg32 - NullSeg\r
100TSS_SEL equ TssSeg - NullSeg\r
101EXCEPTION_TSS_SEL equ ExceptionTssSeg - NullSeg\r
102\r
103struc IA32_TSS\r
104 resw 1\r
105 resw 1\r
106 .ESP0: resd 1\r
107 .SS0: resw 1\r
108 resw 1\r
109 .ESP1: resd 1\r
110 .SS1: resw 1\r
111 resw 1\r
112 .ESP2: resd 1\r
113 .SS2: resw 1\r
114 resw 1\r
115 ._CR3: resd 1\r
116 .EIP: resd 1\r
117 .EFLAGS: resd 1\r
118 ._EAX: resd 1\r
119 ._ECX: resd 1\r
120 ._EDX: resd 1\r
121 ._EBX: resd 1\r
122 ._ESP: resd 1\r
123 ._EBP: resd 1\r
124 ._ESI: resd 1\r
125 ._EDI: resd 1\r
126 ._ES: resw 1\r
127 resw 1\r
128 ._CS: resw 1\r
129 resw 1\r
130 ._SS: resw 1\r
131 resw 1\r
132 ._DS: resw 1\r
133 resw 1\r
134 ._FS: resw 1\r
135 resw 1\r
136 ._GS: resw 1\r
137 resw 1\r
138 .LDT: resw 1\r
139 resw 1\r
140 resw 1\r
141 resw 1\r
142endstruc\r
143\r
144; Create 2 TSS segments just after GDT\r
145TssDescriptor:\r
146 DW 0 ; PreviousTaskLink\r
147 DW 0 ; Reserved\r
148 DD 0 ; ESP0\r
149 DW 0 ; SS0\r
150 DW 0 ; Reserved\r
151 DD 0 ; ESP1\r
152 DW 0 ; SS1\r
153 DW 0 ; Reserved\r
154 DD 0 ; ESP2\r
155 DW 0 ; SS2\r
156 DW 0 ; Reserved\r
157 DD 0 ; CR3\r
158 DD 0 ; EIP\r
159 DD 0 ; EFLAGS\r
160 DD 0 ; EAX\r
161 DD 0 ; ECX\r
162 DD 0 ; EDX\r
163 DD 0 ; EBX\r
164 DD 0 ; ESP\r
165 DD 0 ; EBP\r
166 DD 0 ; ESI\r
167 DD 0 ; EDI\r
168 DW 0 ; ES\r
169 DW 0 ; Reserved\r
170 DW 0 ; CS\r
171 DW 0 ; Reserved\r
172 DW 0 ; SS\r
173 DW 0 ; Reserved\r
174 DW 0 ; DS\r
175 DW 0 ; Reserved\r
176 DW 0 ; FS\r
177 DW 0 ; Reserved\r
178 DW 0 ; GS\r
179 DW 0 ; Reserved\r
180 DW 0 ; LDT Selector\r
181 DW 0 ; Reserved\r
182 DW 0 ; T\r
183 DW 0 ; I/O Map Base\r
184TSS_DESC_SIZE equ $ - TssDescriptor\r
185\r
186ExceptionTssDescriptor:\r
187 DW 0 ; PreviousTaskLink\r
188 DW 0 ; Reserved\r
189 DD 0 ; ESP0\r
190 DW 0 ; SS0\r
191 DW 0 ; Reserved\r
192 DD 0 ; ESP1\r
193 DW 0 ; SS1\r
194 DW 0 ; Reserved\r
195 DD 0 ; ESP2\r
196 DW 0 ; SS2\r
197 DW 0 ; Reserved\r
198 DD 0 ; CR3\r
199 DD PFHandlerEntry ; EIP\r
200 DD 00000002 ; EFLAGS\r
201 DD 0 ; EAX\r
202 DD 0 ; ECX\r
203 DD 0 ; EDX\r
204 DD 0 ; EBX\r
205 DD 0 ; ESP\r
206 DD 0 ; EBP\r
207 DD 0 ; ESI\r
208 DD 0 ; EDI\r
209 DW DATA_SEL ; ES\r
210 DW 0 ; Reserved\r
211 DW CODE_SEL ; CS\r
212 DW 0 ; Reserved\r
213 DW DATA_SEL ; SS\r
214 DW 0 ; Reserved\r
215 DW DATA_SEL ; DS\r
216 DW 0 ; Reserved\r
217 DW DATA_SEL ; FS\r
218 DW 0 ; Reserved\r
219 DW DATA_SEL ; GS\r
220 DW 0 ; Reserved\r
221 DW 0 ; LDT Selector\r
222 DW 0 ; Reserved\r
223 DW 0 ; T\r
224 DW 0 ; I/O Map Base\r
225\r
226ASM_PFX(gcPsd):\r
227 DB 'PSDSIG '\r
228 DW PSD_SIZE\r
229 DW 2\r
230 DW 1 << 2\r
231 DW CODE_SEL\r
232 DW DATA_SEL\r
233 DW DATA_SEL\r
234 DW DATA_SEL\r
235 DW 0\r
236 DQ 0\r
237 DQ 0\r
238 DQ 0\r
239 DD 0\r
240 DD NullSeg\r
241 DD GDT_SIZE\r
242 DD 0\r
243 times 24 DB 0\r
244 DD 0\r
245 DD ASM_PFX(gSmiMtrrs)\r
246PSD_SIZE equ $ - ASM_PFX(gcPsd)\r
247\r
248ASM_PFX(gcSmiGdtr):\r
249 DW GDT_SIZE - 1\r
250 DD NullSeg\r
251\r
252ASM_PFX(gcSmiIdtr):\r
253 DW IDT_SIZE - 1\r
254 DD _SmiIDT\r
255\r
256_SmiIDT:\r
257%rep 32\r
258 DW 0 ; Offset 0:15\r
259 DW CODE_SEL ; Segment selector\r
260 DB 0 ; Unused\r
261 DB 0x8e ; Interrupt Gate, Present\r
262 DW 0 ; Offset 16:31\r
263%endrep\r
264\r
265IDT_SIZE equ $ - _SmiIDT\r
266\r
267TaskGateDescriptor:\r
268 DW 0 ; Reserved\r
269 DW EXCEPTION_TSS_SEL ; TSS Segment selector\r
270 DB 0 ; Reserved\r
271 DB 0x85 ; Task Gate, present, DPL = 0\r
272 DW 0 ; Reserved\r
273\r
274 SECTION .text\r
275;------------------------------------------------------------------------------\r
276; PageFaultIdtHandlerSmmProfile is the entry point page fault only\r
277;\r
278;\r
279; Stack:\r
280; +---------------------+\r
281; + EFlags +\r
282; +---------------------+\r
283; + CS +\r
284; +---------------------+\r
285; + EIP +\r
286; +---------------------+\r
287; + Error Code +\r
288; +---------------------+\r
289; + Vector Number +\r
290; +---------------------+\r
291; + EBP +\r
292; +---------------------+ <-- EBP\r
293;\r
294;\r
295;------------------------------------------------------------------------------\r
296global ASM_PFX(PageFaultIdtHandlerSmmProfile)\r
297ASM_PFX(PageFaultIdtHandlerSmmProfile):\r
298 push 0xe ; Page Fault\r
299\r
300 push ebp\r
301 mov ebp, esp\r
302\r
303 ;\r
304 ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32\r
305 ; is 16-byte aligned\r
306 ;\r
307 and esp, 0xfffffff0\r
308 sub esp, 12\r
309\r
310;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
311 push eax\r
312 push ecx\r
313 push edx\r
314 push ebx\r
315 lea ecx, [ebp + 6 * 4]\r
316 push ecx ; ESP\r
317 push dword [ebp] ; EBP\r
318 push esi\r
319 push edi\r
320\r
321;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
322 mov eax, ss\r
323 push eax\r
324 movzx eax, word [ebp + 4 * 4]\r
325 push eax\r
326 mov eax, ds\r
327 push eax\r
328 mov eax, es\r
329 push eax\r
330 mov eax, fs\r
331 push eax\r
332 mov eax, gs\r
333 push eax\r
334\r
335;; UINT32 Eip;\r
336 mov eax, [ebp + 3 * 4]\r
337 push eax\r
338\r
339;; UINT32 Gdtr[2], Idtr[2];\r
340 sub esp, 8\r
341 sidt [esp]\r
342 mov eax, [esp + 2]\r
343 xchg eax, [esp]\r
344 and eax, 0xFFFF\r
345 mov [esp+4], eax\r
346\r
347 sub esp, 8\r
348 sgdt [esp]\r
349 mov eax, [esp + 2]\r
350 xchg eax, [esp]\r
351 and eax, 0xFFFF\r
352 mov [esp+4], eax\r
353\r
354;; UINT32 Ldtr, Tr;\r
355 xor eax, eax\r
356 str ax\r
357 push eax\r
358 sldt ax\r
359 push eax\r
360\r
361;; UINT32 EFlags;\r
362 mov eax, [ebp + 5 * 4]\r
363 push eax\r
364\r
365;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
366 mov eax, cr4\r
367 or eax, 0x208\r
368 mov cr4, eax\r
369 push eax\r
370 mov eax, cr3\r
371 push eax\r
372 mov eax, cr2\r
373 push eax\r
374 xor eax, eax\r
375 push eax\r
376 mov eax, cr0\r
377 push eax\r
378\r
379;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
380 mov eax, dr7\r
381 push eax\r
382 mov eax, dr6\r
383 push eax\r
384 mov eax, dr3\r
385 push eax\r
386 mov eax, dr2\r
387 push eax\r
388 mov eax, dr1\r
389 push eax\r
390 mov eax, dr0\r
391 push eax\r
392\r
393;; FX_SAVE_STATE_IA32 FxSaveState;\r
394 sub esp, 512\r
395 mov edi, esp\r
396 db 0xf, 0xae, 0x7 ;fxsave [edi]\r
397\r
398; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear\r
399 cld\r
400\r
401;; UINT32 ExceptionData;\r
402 push dword [ebp + 2 * 4]\r
403\r
404;; call into exception handler\r
405\r
406;; Prepare parameter and call\r
407 mov edx, esp\r
408 push edx\r
409 mov edx, dword [ebp + 1 * 4]\r
410 push edx\r
411\r
412 ;\r
413 ; Call External Exception Handler\r
414 ;\r
415 mov eax, ASM_PFX(SmiPFHandler)\r
416 call eax\r
417 add esp, 8\r
418\r
419;; UINT32 ExceptionData;\r
420 add esp, 4\r
421\r
422;; FX_SAVE_STATE_IA32 FxSaveState;\r
423 mov esi, esp\r
424 db 0xf, 0xae, 0xe ; fxrstor [esi]\r
425 add esp, 512\r
426\r
427;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
428;; Skip restoration of DRx registers to support debuggers\r
429;; that set breakpoint in interrupt/exception context\r
430 add esp, 4 * 6\r
431\r
432;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
433 pop eax\r
434 mov cr0, eax\r
435 add esp, 4 ; not for Cr1\r
436 pop eax\r
437 mov cr2, eax\r
438 pop eax\r
439 mov cr3, eax\r
440 pop eax\r
441 mov cr4, eax\r
442\r
443;; UINT32 EFlags;\r
444 pop dword [ebp + 5 * 4]\r
445\r
446;; UINT32 Ldtr, Tr;\r
447;; UINT32 Gdtr[2], Idtr[2];\r
448;; Best not let anyone mess with these particular registers...\r
449 add esp, 24\r
450\r
451;; UINT32 Eip;\r
452 pop dword [ebp + 3 * 4]\r
453\r
454;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
455;; NOTE - modified segment registers could hang the debugger... We\r
456;; could attempt to insulate ourselves against this possibility,\r
457;; but that poses risks as well.\r
458;;\r
459 pop gs\r
460 pop fs\r
461 pop es\r
462 pop ds\r
463 pop dword [ebp + 4 * 4]\r
464 pop ss\r
465\r
466;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
467 pop edi\r
468 pop esi\r
469 add esp, 4 ; not for ebp\r
470 add esp, 4 ; not for esp\r
471 pop ebx\r
472 pop edx\r
473 pop ecx\r
474 pop eax\r
475\r
476 mov esp, ebp\r
477 pop ebp\r
478\r
479; Enable TF bit after page fault handler runs\r
480 bts dword [esp + 16], 8 ; EFLAGS\r
481\r
482 add esp, 8 ; skip INT# & ErrCode\r
483Return:\r
484 iretd\r
485;\r
486; Page Fault Exception Handler entry when SMM Stack Guard is enabled\r
487; Executiot starts here after a task switch\r
488;\r
489PFHandlerEntry:\r
490;\r
491; Get this processor's TSS\r
492;\r
493 sub esp, 8\r
494 sgdt [esp + 2]\r
495 mov eax, [esp + 4] ; GDT base\r
496 add esp, 8\r
497 mov ecx, [eax + TSS_SEL + 2]\r
498 shl ecx, 8\r
499 mov cl, [eax + TSS_SEL + 7]\r
500 ror ecx, 8 ; ecx = TSS base\r
501\r
502 mov ebp, esp\r
503\r
504 ;\r
505 ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32\r
506 ; is 16-byte aligned\r
507 ;\r
508 and esp, 0xfffffff0\r
509 sub esp, 12\r
510\r
511;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
512 push dword [ecx + IA32_TSS._EAX]\r
513 push dword [ecx + IA32_TSS._ECX]\r
514 push dword [ecx + IA32_TSS._EDX]\r
515 push dword [ecx + IA32_TSS._EBX]\r
516 push dword [ecx + IA32_TSS._ESP]\r
517 push dword [ecx + IA32_TSS._EBP]\r
518 push dword [ecx + IA32_TSS._ESI]\r
519 push dword [ecx + IA32_TSS._EDI]\r
520\r
521;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
522 movzx eax, word [ecx + IA32_TSS._SS]\r
523 push eax\r
524 movzx eax, word [ecx + IA32_TSS._CS]\r
525 push eax\r
526 movzx eax, word [ecx + IA32_TSS._DS]\r
527 push eax\r
528 movzx eax, word [ecx + IA32_TSS._ES]\r
529 push eax\r
530 movzx eax, word [ecx + IA32_TSS._FS]\r
531 push eax\r
532 movzx eax, word [ecx + IA32_TSS._GS]\r
533 push eax\r
534\r
535;; UINT32 Eip;\r
536 push dword [ecx + IA32_TSS.EIP]\r
537\r
538;; UINT32 Gdtr[2], Idtr[2];\r
539 sub esp, 8\r
540 sidt [esp]\r
541 mov eax, [esp + 2]\r
542 xchg eax, [esp]\r
543 and eax, 0xFFFF\r
544 mov [esp+4], eax\r
545\r
546 sub esp, 8\r
547 sgdt [esp]\r
548 mov eax, [esp + 2]\r
549 xchg eax, [esp]\r
550 and eax, 0xFFFF\r
551 mov [esp+4], eax\r
552\r
553;; UINT32 Ldtr, Tr;\r
554 mov eax, TSS_SEL\r
555 push eax\r
556 movzx eax, word [ecx + IA32_TSS.LDT]\r
557 push eax\r
558\r
559;; UINT32 EFlags;\r
560 push dword [ecx + IA32_TSS.EFLAGS]\r
561\r
562;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
563 mov eax, cr4\r
564 or eax, 0x208\r
565 mov cr4, eax\r
566 push eax\r
567 mov eax, cr3\r
568 push eax\r
569 mov eax, cr2\r
570 push eax\r
571 xor eax, eax\r
572 push eax\r
573 mov eax, cr0\r
574 push eax\r
575\r
576;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
577 mov eax, dr7\r
578 push eax\r
579 mov eax, dr6\r
580 push eax\r
581 mov eax, dr3\r
582 push eax\r
583 mov eax, dr2\r
584 push eax\r
585 mov eax, dr1\r
586 push eax\r
587 mov eax, dr0\r
588 push eax\r
589\r
590;; FX_SAVE_STATE_IA32 FxSaveState;\r
591;; Clear TS bit in CR0 to avoid Device Not Available Exception (#NM)\r
592;; when executing fxsave/fxrstor instruction\r
593 clts\r
594 sub esp, 512\r
595 mov edi, esp\r
596 db 0xf, 0xae, 0x7 ;fxsave [edi]\r
597\r
598; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear\r
599 cld\r
600\r
601;; UINT32 ExceptionData;\r
602 push dword [ebp]\r
603\r
604;; call into exception handler\r
605 mov ebx, ecx\r
606 mov eax, ASM_PFX(SmiPFHandler)\r
607\r
608;; Prepare parameter and call\r
609 mov edx, esp\r
610 push edx\r
611 mov edx, 14\r
612 push edx\r
613\r
614 ;\r
615 ; Call External Exception Handler\r
616 ;\r
617 call eax\r
618 add esp, 8\r
619\r
620 mov ecx, ebx\r
621;; UINT32 ExceptionData;\r
622 add esp, 4\r
623\r
624;; FX_SAVE_STATE_IA32 FxSaveState;\r
625 mov esi, esp\r
626 db 0xf, 0xae, 0xe ; fxrstor [esi]\r
627 add esp, 512\r
628\r
629;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
630;; Skip restoration of DRx registers to support debuggers\r
631;; that set breakpoints in interrupt/exception context\r
632 add esp, 4 * 6\r
633\r
634;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
635 pop eax\r
636 mov cr0, eax\r
637 add esp, 4 ; not for Cr1\r
638 pop eax\r
639 mov cr2, eax\r
640 pop eax\r
641 mov dword [ecx + IA32_TSS._CR3], eax\r
642 pop eax\r
643 mov cr4, eax\r
644\r
645;; UINT32 EFlags;\r
646 pop dword [ecx + IA32_TSS.EFLAGS]\r
647\r
648;; UINT32 Ldtr, Tr;\r
649;; UINT32 Gdtr[2], Idtr[2];\r
650;; Best not let anyone mess with these particular registers...\r
651 add esp, 24\r
652\r
653;; UINT32 Eip;\r
654 pop dword [ecx + IA32_TSS.EIP]\r
655\r
656;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
657;; NOTE - modified segment registers could hang the debugger... We\r
658;; could attempt to insulate ourselves against this possibility,\r
659;; but that poses risks as well.\r
660;;\r
661 pop eax\r
662o16 mov [ecx + IA32_TSS._GS], ax\r
663 pop eax\r
664o16 mov [ecx + IA32_TSS._FS], ax\r
665 pop eax\r
666o16 mov [ecx + IA32_TSS._ES], ax\r
667 pop eax\r
668o16 mov [ecx + IA32_TSS._DS], ax\r
669 pop eax\r
670o16 mov [ecx + IA32_TSS._CS], ax\r
671 pop eax\r
672o16 mov [ecx + IA32_TSS._SS], ax\r
673\r
674;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
675 pop dword [ecx + IA32_TSS._EDI]\r
676 pop dword [ecx + IA32_TSS._ESI]\r
677 add esp, 4 ; not for ebp\r
678 add esp, 4 ; not for esp\r
679 pop dword [ecx + IA32_TSS._EBX]\r
680 pop dword [ecx + IA32_TSS._EDX]\r
681 pop dword [ecx + IA32_TSS._ECX]\r
682 pop dword [ecx + IA32_TSS._EAX]\r
683\r
684 mov esp, ebp\r
685\r
686; Set single step DB# if SMM profile is enabled and page fault exception happens\r
687 cmp byte [dword ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))], 0\r
688 jz @Done2\r
689\r
690; Create return context for iretd in stub function\r
691 mov eax, dword [ecx + IA32_TSS._ESP] ; Get old stack pointer\r
692 mov ebx, dword [ecx + IA32_TSS.EIP]\r
693 mov [eax - 0xc], ebx ; create EIP in old stack\r
694 movzx ebx, word [ecx + IA32_TSS._CS]\r
695 mov [eax - 0x8], ebx ; create CS in old stack\r
696 mov ebx, dword [ecx + IA32_TSS.EFLAGS]\r
697 bts ebx, 8\r
698 mov [eax - 0x4], ebx ; create eflags in old stack\r
699 mov eax, dword [ecx + IA32_TSS._ESP] ; Get old stack pointer\r
700 sub eax, 0xc ; minus 12 byte\r
701 mov dword [ecx + IA32_TSS._ESP], eax ; Set new stack pointer\r
702; Replace the EIP of interrupted task with stub function\r
703 mov eax, ASM_PFX(PageFaultStubFunction)\r
704 mov dword [ecx + IA32_TSS.EIP], eax\r
705; Jump to the iretd so next page fault handler as a task will start again after iretd.\r
706@Done2:\r
707 add esp, 4 ; skip ErrCode\r
708\r
709 jmp Return\r
710\r
711global ASM_PFX(PageFaultStubFunction)\r
712ASM_PFX(PageFaultStubFunction):\r
713;\r
714; we need clean TS bit in CR0 to execute\r
715; x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions.\r
716;\r
717 clts\r
718 iretd\r
719\r
720global ASM_PFX(InitializeIDTSmmStackGuard)\r
721ASM_PFX(InitializeIDTSmmStackGuard):\r
722 push ebx\r
723;\r
724; If SMM Stack Guard feature is enabled, the Page Fault Exception entry in IDT\r
725; is a Task Gate Descriptor so that when a Page Fault Exception occurrs,\r
726; the processors can use a known good stack in case stack is ran out.\r
727;\r
728 lea ebx, [_SmiIDT + 14 * 8]\r
729 lea edx, [TaskGateDescriptor]\r
730 mov eax, [edx]\r
731 mov [ebx], eax\r
732 mov eax, [edx + 4]\r
733 mov [ebx + 4], eax\r
734 pop ebx\r
735 ret\r