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