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