UefiCpuPkg/PiSmmCpuDxeSmm: patch "XdSupported" with PatchInstructionX86()
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / X64 / 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 ;
22 ; Variables referrenced by C code
23 ;
24
25 %define MSR_IA32_MISC_ENABLE 0x1A0
26 %define MSR_EFER 0xc0000080
27 %define MSR_EFER_XD 0x800
28
29 ;
30 ; Constants relating to PROCESSOR_SMM_DESCRIPTOR
31 ;
32 %define DSC_OFFSET 0xfb00
33 %define DSC_GDTPTR 0x30
34 %define DSC_GDTSIZ 0x38
35 %define DSC_CS 14
36 %define DSC_DS 16
37 %define DSC_SS 18
38 %define DSC_OTHERSEG 20
39 ;
40 ; Constants relating to CPU State Save Area
41 ;
42 %define SSM_DR6 0xffd0
43 %define SSM_DR7 0xffc8
44
45 %define PROTECT_MODE_CS 0x8
46 %define PROTECT_MODE_DS 0x20
47 %define LONG_MODE_CS 0x38
48 %define TSS_SEGMENT 0x40
49 %define GDT_SIZE 0x50
50
51 extern ASM_PFX(SmiRendezvous)
52 extern ASM_PFX(gSmiHandlerIdtr)
53 extern ASM_PFX(CpuSmmDebugEntry)
54 extern ASM_PFX(CpuSmmDebugExit)
55
56 global ASM_PFX(gPatchSmbase)
57 extern ASM_PFX(mXdSupported)
58 global ASM_PFX(gPatchXdSupported)
59 global ASM_PFX(gPatchSmiStack)
60 global ASM_PFX(gPatchSmiCr3)
61 global ASM_PFX(gcSmiHandlerTemplate)
62 global ASM_PFX(gcSmiHandlerSize)
63
64 DEFAULT REL
65 SECTION .text
66
67 BITS 16
68 ASM_PFX(gcSmiHandlerTemplate):
69 _SmiEntryPoint:
70 mov bx, _GdtDesc - _SmiEntryPoint + 0x8000
71 mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ]
72 dec ax
73 mov [cs:bx], ax
74 mov eax, [cs:DSC_OFFSET + DSC_GDTPTR]
75 mov [cs:bx + 2], eax
76 o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx]
77 mov ax, PROTECT_MODE_CS
78 mov [cs:bx-0x2],ax
79 mov edi, strict dword 0 ; source operand will be patched
80 ASM_PFX(gPatchSmbase):
81 lea eax, [edi + (@ProtectedMode - _SmiEntryPoint) + 0x8000]
82 mov [cs:bx-0x6],eax
83 mov ebx, cr0
84 and ebx, 0x9ffafff3
85 or ebx, 0x23
86 mov cr0, ebx
87 jmp dword 0x0:0x0
88 _GdtDesc:
89 DW 0
90 DD 0
91
92 BITS 32
93 @ProtectedMode:
94 mov ax, PROTECT_MODE_DS
95 o16 mov ds, ax
96 o16 mov es, ax
97 o16 mov fs, ax
98 o16 mov gs, ax
99 o16 mov ss, ax
100 mov esp, strict dword 0 ; source operand will be patched
101 ASM_PFX(gPatchSmiStack):
102 jmp ProtFlatMode
103
104 BITS 64
105 ProtFlatMode:
106 mov eax, strict dword 0 ; source operand will be patched
107 ASM_PFX(gPatchSmiCr3):
108 mov cr3, rax
109 mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3
110 mov cr4, rax ; in PreModifyMtrrs() to flush TLB.
111 ; Load TSS
112 sub esp, 8 ; reserve room in stack
113 sgdt [rsp]
114 mov eax, [rsp + 2] ; eax = GDT base
115 add esp, 8
116 mov dl, 0x89
117 mov [rax + TSS_SEGMENT + 5], dl ; clear busy flag
118 mov eax, TSS_SEGMENT
119 ltr ax
120
121 ; enable NXE if supported
122 mov al, strict byte 1 ; source operand may be patched
123 ASM_PFX(gPatchXdSupported):
124 cmp al, 0
125 jz @SkipXd
126 ;
127 ; Check XD disable bit
128 ;
129 mov ecx, MSR_IA32_MISC_ENABLE
130 rdmsr
131 sub esp, 4
132 push rdx ; save MSR_IA32_MISC_ENABLE[63-32]
133 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
134 jz .0
135 and dx, 0xFFFB ; clear XD Disable bit if it is set
136 wrmsr
137 .0:
138 mov ecx, MSR_EFER
139 rdmsr
140 or ax, MSR_EFER_XD ; enable NXE
141 wrmsr
142 jmp @XdDone
143 @SkipXd:
144 sub esp, 8
145 @XdDone:
146
147 ; Switch into @LongMode
148 push LONG_MODE_CS ; push cs hardcore here
149 call Base ; push return address for retf later
150 Base:
151 add dword [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg
152
153 mov ecx, MSR_EFER
154 rdmsr
155 or ah, 1 ; enable LME
156 wrmsr
157 mov rbx, cr0
158 or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE
159 mov cr0, rbx
160 retf
161 @LongMode: ; long mode (64-bit code) starts here
162 mov rax, strict qword 0 ; mov rax, ASM_PFX(gSmiHandlerIdtr)
163 SmiHandlerIdtrAbsAddr:
164 lidt [rax]
165 lea ebx, [rdi + DSC_OFFSET]
166 mov ax, [rbx + DSC_DS]
167 mov ds, eax
168 mov ax, [rbx + DSC_OTHERSEG]
169 mov es, eax
170 mov fs, eax
171 mov gs, eax
172 mov ax, [rbx + DSC_SS]
173 mov ss, eax
174 mov rax, strict qword 0 ; mov rax, _SmiHandler
175 _SmiHandlerAbsAddr:
176 jmp rax
177
178 _SmiHandler:
179 mov rbx, [rsp + 0x8] ; rcx <- CpuIndex
180
181 ;
182 ; Save FP registers
183 ;
184 sub rsp, 0x200
185 DB 0x48 ; FXSAVE64
186 fxsave [rsp]
187
188 add rsp, -0x20
189
190 mov rcx, rbx
191 call ASM_PFX(CpuSmmDebugEntry)
192
193 mov rcx, rbx
194 call ASM_PFX(SmiRendezvous)
195
196 mov rcx, rbx
197 call ASM_PFX(CpuSmmDebugExit)
198
199 add rsp, 0x20
200
201 ;
202 ; Restore FP registers
203 ;
204 DB 0x48 ; FXRSTOR64
205 fxrstor [rsp]
206
207 add rsp, 0x200
208
209 lea rax, [ASM_PFX(mXdSupported)]
210 mov al, [rax]
211 cmp al, 0
212 jz .1
213 pop rdx ; get saved MSR_IA32_MISC_ENABLE[63-32]
214 test edx, BIT2
215 jz .1
216 mov ecx, MSR_IA32_MISC_ENABLE
217 rdmsr
218 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM
219 wrmsr
220
221 .1:
222 rsm
223
224 ASM_PFX(gcSmiHandlerSize) DW $ - _SmiEntryPoint
225
226 global ASM_PFX(PiSmmCpuSmiEntryFixupAddress)
227 ASM_PFX(PiSmmCpuSmiEntryFixupAddress):
228 lea rax, [ASM_PFX(gSmiHandlerIdtr)]
229 lea rcx, [SmiHandlerIdtrAbsAddr]
230 mov qword [rcx - 8], rax
231
232 lea rax, [_SmiHandler]
233 lea rcx, [_SmiHandlerAbsAddr]
234 mov qword [rcx - 8], rax
235 ret