UefiCpuPkg/PiSmmCpuDxeSmm: patch "XdSupported" with PatchInstructionX86()
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / Ia32 / SmiEntry.nasm
1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2016 - 2018, 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 ; SmiEntry.nasm
14 ;
15 ; Abstract:
16 ;
17 ; Code template of the SMI handler for a particular processor
18 ;
19 ;-------------------------------------------------------------------------------
20
21 %define MSR_IA32_MISC_ENABLE 0x1A0
22 %define MSR_EFER 0xc0000080
23 %define MSR_EFER_XD 0x800
24
25 ;
26 ; Constants relating to PROCESSOR_SMM_DESCRIPTOR
27 ;
28 %define DSC_OFFSET 0xfb00
29 %define DSC_GDTPTR 0x30
30 %define DSC_GDTSIZ 0x38
31 %define DSC_CS 14
32 %define DSC_DS 16
33 %define DSC_SS 18
34 %define DSC_OTHERSEG 20
35
36 %define PROTECT_MODE_CS 0x8
37 %define PROTECT_MODE_DS 0x20
38 %define TSS_SEGMENT 0x40
39
40 extern ASM_PFX(SmiRendezvous)
41 extern ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
42 extern ASM_PFX(CpuSmmDebugEntry)
43 extern ASM_PFX(CpuSmmDebugExit)
44
45 global ASM_PFX(gcSmiHandlerTemplate)
46 global ASM_PFX(gcSmiHandlerSize)
47 global ASM_PFX(gPatchSmiCr3)
48 global ASM_PFX(gPatchSmiStack)
49 global ASM_PFX(gPatchSmbase)
50 extern ASM_PFX(mXdSupported)
51 global ASM_PFX(gPatchXdSupported)
52 extern ASM_PFX(gSmiHandlerIdtr)
53
54 SECTION .text
55
56 BITS 16
57 ASM_PFX(gcSmiHandlerTemplate):
58 _SmiEntryPoint:
59 mov bx, _GdtDesc - _SmiEntryPoint + 0x8000
60 mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ]
61 dec ax
62 mov [cs:bx], ax
63 mov eax, [cs:DSC_OFFSET + DSC_GDTPTR]
64 mov [cs:bx + 2], eax
65 mov ebp, eax ; ebp = GDT base
66 o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx]
67 mov ax, PROTECT_MODE_CS
68 mov [cs:bx-0x2],ax
69 mov edi, strict dword 0 ; source operand will be patched
70 ASM_PFX(gPatchSmbase):
71 lea eax, [edi + (@32bit - _SmiEntryPoint) + 0x8000]
72 mov [cs:bx-0x6],eax
73 mov ebx, cr0
74 and ebx, 0x9ffafff3
75 or ebx, 0x23
76 mov cr0, ebx
77 jmp dword 0x0:0x0
78 _GdtDesc:
79 DW 0
80 DD 0
81
82 BITS 32
83 @32bit:
84 mov ax, PROTECT_MODE_DS
85 o16 mov ds, ax
86 o16 mov es, ax
87 o16 mov fs, ax
88 o16 mov gs, ax
89 o16 mov ss, ax
90 mov esp, strict dword 0 ; source operand will be patched
91 ASM_PFX(gPatchSmiStack):
92 mov eax, ASM_PFX(gSmiHandlerIdtr)
93 lidt [eax]
94 jmp ProtFlatMode
95
96 ProtFlatMode:
97 mov eax, strict dword 0 ; source operand will be patched
98 ASM_PFX(gPatchSmiCr3):
99 mov cr3, eax
100 ;
101 ; Need to test for CR4 specific bit support
102 ;
103 mov eax, 1
104 cpuid ; use CPUID to determine if specific CR4 bits are supported
105 xor eax, eax ; Clear EAX
106 test edx, BIT2 ; Check for DE capabilities
107 jz .0
108 or eax, BIT3
109 .0:
110 test edx, BIT6 ; Check for PAE capabilities
111 jz .1
112 or eax, BIT5
113 .1:
114 test edx, BIT7 ; Check for MCE capabilities
115 jz .2
116 or eax, BIT6
117 .2:
118 test edx, BIT24 ; Check for FXSR capabilities
119 jz .3
120 or eax, BIT9
121 .3:
122 test edx, BIT25 ; Check for SSE capabilities
123 jz .4
124 or eax, BIT10
125 .4: ; as cr4.PGE is not set here, refresh cr3
126 mov cr4, eax ; in PreModifyMtrrs() to flush TLB.
127
128 cmp byte [dword ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))], 0
129 jz .6
130 ; Load TSS
131 mov byte [ebp + TSS_SEGMENT + 5], 0x89 ; clear busy flag
132 mov eax, TSS_SEGMENT
133 ltr ax
134 .6:
135
136 ; enable NXE if supported
137 mov al, strict byte 1 ; source operand may be patched
138 ASM_PFX(gPatchXdSupported):
139 cmp al, 0
140 jz @SkipXd
141 ;
142 ; Check XD disable bit
143 ;
144 mov ecx, MSR_IA32_MISC_ENABLE
145 rdmsr
146 push edx ; save MSR_IA32_MISC_ENABLE[63-32]
147 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
148 jz .5
149 and dx, 0xFFFB ; clear XD Disable bit if it is set
150 wrmsr
151 .5:
152 mov ecx, MSR_EFER
153 rdmsr
154 or ax, MSR_EFER_XD ; enable NXE
155 wrmsr
156 jmp @XdDone
157 @SkipXd:
158 sub esp, 4
159 @XdDone:
160
161 mov ebx, cr0
162 or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE
163 mov cr0, ebx
164 lea ebx, [edi + DSC_OFFSET]
165 mov ax, [ebx + DSC_DS]
166 mov ds, eax
167 mov ax, [ebx + DSC_OTHERSEG]
168 mov es, eax
169 mov fs, eax
170 mov gs, eax
171 mov ax, [ebx + DSC_SS]
172 mov ss, eax
173
174 ; jmp _SmiHandler ; instruction is not needed
175
176 global ASM_PFX(SmiHandler)
177 ASM_PFX(SmiHandler):
178 mov ebx, [esp + 4] ; CPU Index
179 push ebx
180 mov eax, ASM_PFX(CpuSmmDebugEntry)
181 call eax
182 add esp, 4
183
184 push ebx
185 mov eax, ASM_PFX(SmiRendezvous)
186 call eax
187 add esp, 4
188
189 push ebx
190 mov eax, ASM_PFX(CpuSmmDebugExit)
191 call eax
192 add esp, 4
193
194 mov eax, ASM_PFX(mXdSupported)
195 mov al, [eax]
196 cmp al, 0
197 jz .7
198 pop edx ; get saved MSR_IA32_MISC_ENABLE[63-32]
199 test edx, BIT2
200 jz .7
201 mov ecx, MSR_IA32_MISC_ENABLE
202 rdmsr
203 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM
204 wrmsr
205
206 .7:
207 rsm
208
209 ASM_PFX(gcSmiHandlerSize): DW $ - _SmiEntryPoint
210
211 global ASM_PFX(PiSmmCpuSmiEntryFixupAddress)
212 ASM_PFX(PiSmmCpuSmiEntryFixupAddress):
213 ret