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