1;------------------------------------------------------------------------------ ;
2; Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
3; SPDX-License-Identifier: BSD-2-Clause-Patent
4;
5; Module Name:
6;
7;   SmiEntry.nasm
8;
9; Abstract:
10;
11;   Code template of the SMI handler for a particular processor
12;
13;-------------------------------------------------------------------------------
14
15%include "StuffRsbNasm.inc"
16
17%define MSR_IA32_MISC_ENABLE 0x1A0
18%define MSR_EFER      0xc0000080
19%define MSR_EFER_XD   0x800
20
21;
22; Constants relating to TXT_PROCESSOR_SMM_DESCRIPTOR
23;
24%define DSC_OFFSET 0xfb00
25%define DSC_GDTPTR 0x48
26%define DSC_GDTSIZ 0x50
27%define DSC_CS 0x14
28%define DSC_DS 0x16
29%define DSC_SS 0x18
30%define DSC_OTHERSEG 0x1a
31
32%define PROTECT_MODE_CS 0x8
33%define PROTECT_MODE_DS 0x20
34%define TSS_SEGMENT 0x40
35
36extern ASM_PFX(SmiRendezvous)
37extern ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
38extern ASM_PFX(CpuSmmDebugEntry)
39extern ASM_PFX(CpuSmmDebugExit)
40
41global ASM_PFX(gcStmSmiHandlerTemplate)
42global ASM_PFX(gcStmSmiHandlerSize)
43global ASM_PFX(gcStmSmiHandlerOffset)
44global ASM_PFX(gStmSmiCr3)
45global ASM_PFX(gStmSmiStack)
46global ASM_PFX(gStmSmbase)
47global ASM_PFX(gStmXdSupported)
48extern ASM_PFX(gStmSmiHandlerIdtr)
49
50ASM_PFX(gStmSmiCr3)      EQU StmSmiCr3Patch - 4
51ASM_PFX(gStmSmiStack)    EQU StmSmiStackPatch - 4
52ASM_PFX(gStmSmbase)      EQU StmSmbasePatch - 4
53ASM_PFX(gStmXdSupported) EQU StmXdSupportedPatch - 1
54
55    SECTION .text
56
57BITS 16
58ASM_PFX(gcStmSmiHandlerTemplate):
59_StmSmiEntryPoint:
60    mov     bx, _StmGdtDesc - _StmSmiEntryPoint + 0x8000
61    mov     ax,[cs:DSC_OFFSET + DSC_GDTSIZ]
62    dec     ax
63    mov     [cs:bx], ax
64    mov     eax, [cs:DSC_OFFSET + DSC_GDTPTR]
65    mov     [cs:bx + 2], eax
66    mov     ebp, eax                      ; ebp = GDT base
67o32 lgdt    [cs:bx]                       ; lgdt fword ptr cs:[bx]
68    mov     ax, PROTECT_MODE_CS
69    mov     [cs:bx-0x2],ax
70o32 mov     edi, strict dword 0
71StmSmbasePatch:
72    lea     eax, [edi + (@32bit - _StmSmiEntryPoint) + 0x8000]
73    mov     [cs:bx-0x6],eax
74    mov     ebx, cr0
75    and     ebx, 0x9ffafff3
76    or      ebx, 0x23
77    mov     cr0, ebx
78    jmp     dword 0x0:0x0
79_StmGdtDesc:
80    DW 0
81    DD 0
82
83BITS 32
84@32bit:
85    mov     ax, PROTECT_MODE_DS
86o16 mov     ds, ax
87o16 mov     es, ax
88o16 mov     fs, ax
89o16 mov     gs, ax
90o16 mov     ss, ax
91    mov     esp, strict dword 0
92StmSmiStackPatch:
93    mov     eax, ASM_PFX(gStmSmiHandlerIdtr)
94    lidt    [eax]
95    jmp     ProtFlatMode
96
97ProtFlatMode:
98    mov eax, strict dword 0
99StmSmiCr3Patch:
100    mov     cr3, eax
101;
102; Need to test for CR4 specific bit support
103;
104    mov     eax, 1
105    cpuid                               ; use CPUID to determine if specific CR4 bits are supported
106    xor     eax, eax                    ; Clear EAX
107    test    edx, BIT2                   ; Check for DE capabilities
108    jz      .0
109    or      eax, BIT3
110.0:
111    test    edx, BIT6                   ; Check for PAE capabilities
112    jz      .1
113    or      eax, BIT5
114.1:
115    test    edx, BIT7                   ; Check for MCE capabilities
116    jz      .2
117    or      eax, BIT6
118.2:
119    test    edx, BIT24                  ; Check for FXSR capabilities
120    jz      .3
121    or      eax, BIT9
122.3:
123    test    edx, BIT25                  ; Check for SSE capabilities
124    jz      .4
125    or      eax, BIT10
126.4:                                     ; as cr4.PGE is not set here, refresh cr3
127    mov     cr4, eax                    ; in PreModifyMtrrs() to flush TLB.
128
129    cmp     byte [dword ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))], 0
130    jz      .6
131; Load TSS
132    mov     byte [ebp + TSS_SEGMENT + 5], 0x89 ; clear busy flag
133    mov     eax, TSS_SEGMENT
134    ltr     ax
135.6:
136
137; enable NXE if supported
138    mov     al, strict byte 1
139StmXdSupportedPatch:
140    cmp     al, 0
141    jz      @SkipXd
142;
143; Check XD disable bit
144;
145    mov     ecx, MSR_IA32_MISC_ENABLE
146    rdmsr
147    push    edx                        ; save MSR_IA32_MISC_ENABLE[63-32]
148    test    edx, BIT2                  ; MSR_IA32_MISC_ENABLE[34]
149    jz      .5
150    and     dx, 0xFFFB                 ; clear XD Disable bit if it is set
151    wrmsr
152.5:
153    mov     ecx, MSR_EFER
154    rdmsr
155    or      ax, MSR_EFER_XD             ; enable NXE
156    wrmsr
157    jmp     @XdDone
158@SkipXd:
159    sub     esp, 4
160@XdDone:
161
162    mov     ebx, cr0
163    or      ebx, 0x80010023             ; enable paging + WP + NE + MP + PE
164    mov     cr0, ebx
165    lea     ebx, [edi + DSC_OFFSET]
166    mov     ax, [ebx + DSC_DS]
167    mov     ds, eax
168    mov     ax, [ebx + DSC_OTHERSEG]
169    mov     es, eax
170    mov     fs, eax
171    mov     gs, eax
172    mov     ax, [ebx + DSC_SS]
173    mov     ss, eax
174
175CommonHandler:
176    mov     ebx, [esp + 4]                  ; CPU Index
177    push    ebx
178    mov     eax, ASM_PFX(CpuSmmDebugEntry)
179    call    eax
180    add     esp, 4
181
182    push    ebx
183    mov     eax, ASM_PFX(SmiRendezvous)
184    call    eax
185    add     esp, 4
186
187    push    ebx
188    mov     eax, ASM_PFX(CpuSmmDebugExit)
189    call    eax
190    add     esp, 4
191
192    mov     eax, ASM_PFX(gStmXdSupported)
193    mov     al, [eax]
194    cmp     al, 0
195    jz      .7
196    pop     edx                       ; get saved MSR_IA32_MISC_ENABLE[63-32]
197    test    edx, BIT2
198    jz      .7
199    mov     ecx, MSR_IA32_MISC_ENABLE
200    rdmsr
201    or      dx, BIT2                  ; set XD Disable bit if it was set before entering into SMM
202    wrmsr
203
204.7:
205    StuffRsb32
206    rsm
207
208
209_StmSmiHandler:
210;
211; Check XD disable bit
212;
213    xor     esi, esi
214    mov     eax, ASM_PFX(gStmXdSupported)
215    mov     al, [eax]
216    cmp     al, 0
217    jz      @StmXdDone
218    mov     ecx, MSR_IA32_MISC_ENABLE
219    rdmsr
220    mov     esi, edx                   ; save MSR_IA32_MISC_ENABLE[63-32]
221    test    edx, BIT2                  ; MSR_IA32_MISC_ENABLE[34]
222    jz      .5
223    and     dx, 0xFFFB                 ; clear XD Disable bit if it is set
224    wrmsr
225.5:
226    mov     ecx, MSR_EFER
227    rdmsr
228    or      ax, MSR_EFER_XD             ; enable NXE
229    wrmsr
230@StmXdDone:
231    push    esi
232
233    ; below step is needed, because STM does not run above code.
234    ; we have to run below code to set IDT/CR0/CR4
235    mov     eax, ASM_PFX(gStmSmiHandlerIdtr)
236    lidt    [eax]
237
238    mov     eax, cr0
239    or      eax, 0x80010023             ; enable paging + WP + NE + MP + PE
240    mov     cr0, eax
241;
242; Need to test for CR4 specific bit support
243;
244    mov     eax, 1
245    cpuid                               ; use CPUID to determine if specific CR4 bits are supported
246    mov     eax, cr4                    ; init EAX
247    test    edx, BIT2                   ; Check for DE capabilities
248    jz      .0
249    or      eax, BIT3
250.0:
251    test    edx, BIT6                   ; Check for PAE capabilities
252    jz      .1
253    or      eax, BIT5
254.1:
255    test    edx, BIT7                   ; Check for MCE capabilities
256    jz      .2
257    or      eax, BIT6
258.2:
259    test    edx, BIT24                  ; Check for FXSR capabilities
260    jz      .3
261    or      eax, BIT9
262.3:
263    test    edx, BIT25                  ; Check for SSE capabilities
264    jz      .4
265    or      eax, BIT10
266.4:                                     ; as cr4.PGE is not set here, refresh cr3
267    mov     cr4, eax                    ; in PreModifyMtrrs() to flush TLB.
268    ; STM init finish
269    jmp     CommonHandler
270
271ASM_PFX(gcStmSmiHandlerSize)   : DW        $ - _StmSmiEntryPoint
272ASM_PFX(gcStmSmiHandlerOffset) : DW        _StmSmiHandler - _StmSmiEntryPoint
273
274global ASM_PFX(SmmCpuFeaturesLibStmSmiEntryFixupAddress)
275ASM_PFX(SmmCpuFeaturesLibStmSmiEntryFixupAddress):
276    ret
277