]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm
315d0f8670757f6cdb93e5a5d0ace0c03971cb10
[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 mov rax, strict qword 0 ; mov rax, _SmiHandler
177 _SmiHandlerAbsAddr:
178 jmp rax
179
180 _SmiHandler:
181 mov rbx, [rsp + 0x8] ; rcx <- CpuIndex
182
183 ;
184 ; Save FP registers
185 ;
186 sub rsp, 0x200
187 fxsave64 [rsp]
188
189 add rsp, -0x20
190
191 mov rcx, rbx
192 call ASM_PFX(CpuSmmDebugEntry)
193
194 mov rcx, rbx
195 call ASM_PFX(SmiRendezvous)
196
197 mov rcx, rbx
198 call ASM_PFX(CpuSmmDebugExit)
199
200 add rsp, 0x20
201
202 ;
203 ; Restore FP registers
204 ;
205 fxrstor64 [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 StuffRsb64
223 rsm
224
225 ASM_PFX(gcSmiHandlerSize) DW $ - _SmiEntryPoint
226
227 global ASM_PFX(PiSmmCpuSmiEntryFixupAddress)
228 ASM_PFX(PiSmmCpuSmiEntryFixupAddress):
229 lea rax, [ASM_PFX(gSmiHandlerIdtr)]
230 lea rcx, [SmiHandlerIdtrAbsAddr]
231 mov qword [rcx - 8], rax
232
233 lea rax, [_SmiHandler]
234 lea rcx, [_SmiHandlerAbsAddr]
235 mov qword [rcx - 8], rax
236 ret