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