]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/SmmCpuFeaturesLib/X64/SmiEntry.nasm
UefiCpuPkg/SmmCpuFeaturesLibStm: Add STM library instance
[mirror_edk2.git] / UefiCpuPkg / Library / SmmCpuFeaturesLib / X64 / SmiEntry.nasm
1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2016, 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 TXT_PROCESSOR_SMM_DESCRIPTOR
31 ;
32 %define DSC_OFFSET 0xfb00
33 %define DSC_GDTPTR 0x48
34 %define DSC_GDTSIZ 0x50
35 %define DSC_CS 0x14
36 %define DSC_DS 0x16
37 %define DSC_SS 0x18
38 %define DSC_OTHERSEG 0x1a
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(gStmSmiHandlerIdtr)
53 extern ASM_PFX(CpuSmmDebugEntry)
54 extern ASM_PFX(CpuSmmDebugExit)
55
56 global ASM_PFX(gStmSmbase)
57 global ASM_PFX(gStmXdSupported)
58 global ASM_PFX(gStmSmiStack)
59 global ASM_PFX(gStmSmiCr3)
60 global ASM_PFX(gcStmSmiHandlerTemplate)
61 global ASM_PFX(gcStmSmiHandlerSize)
62 global ASM_PFX(gcStmSmiHandlerOffset)
63
64 DEFAULT REL
65 SECTION .text
66
67 BITS 16
68 ASM_PFX(gcStmSmiHandlerTemplate):
69 _StmSmiEntryPoint:
70 mov bx, _StmGdtDesc - _StmSmiEntryPoint + 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 DB 0x66, 0xbf ; mov edi, SMBASE
80 ASM_PFX(gStmSmbase): DD 0
81 lea eax, [edi + (@ProtectedMode - _StmSmiEntryPoint) + 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 _StmGdtDesc:
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 DB 0xbc ; mov esp, imm32
101 ASM_PFX(gStmSmiStack): DD 0
102 jmp ProtFlatMode
103
104 BITS 64
105 ProtFlatMode:
106 DB 0xb8 ; mov eax, offset gStmSmiCr3
107 ASM_PFX(gStmSmiCr3): DD 0
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 DB 0xb0 ; mov al, imm8
123 ASM_PFX(gStmXdSupported): DB 1
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, ASM_PFX(gStmSmiHandlerIdtr)
163 lidt [rax]
164 lea ebx, [rdi + DSC_OFFSET]
165 mov ax, [rbx + DSC_DS]
166 mov ds, eax
167 mov ax, [rbx + DSC_OTHERSEG]
168 mov es, eax
169 mov fs, eax
170 mov gs, eax
171 mov ax, [rbx + DSC_SS]
172 mov ss, eax
173
174 CommonHandler:
175 mov rbx, [rsp + 0x08] ; rbx <- CpuIndex
176
177 ;
178 ; Save FP registers
179 ;
180 sub rsp, 0x200
181 DB 0x48 ; FXSAVE64
182 fxsave [rsp]
183
184 add rsp, -0x20
185
186 mov rcx, rbx
187 mov rax, CpuSmmDebugEntry
188 call rax
189
190 mov rcx, rbx
191 mov rax, SmiRendezvous ; rax <- absolute addr of SmiRedezvous
192 call rax
193
194 mov rcx, rbx
195 mov rax, CpuSmmDebugExit
196 call rax
197
198 add rsp, 0x20
199
200 ;
201 ; Restore FP registers
202 ;
203 DB 0x48 ; FXRSTOR64
204 fxrstor [rsp]
205
206 add rsp, 0x200
207
208 mov rax, ASM_PFX(gStmXdSupported)
209 mov al, [rax]
210 cmp al, 0
211 jz .1
212 pop rdx ; get saved MSR_IA32_MISC_ENABLE[63-32]
213 test edx, BIT2
214 jz .1
215 mov ecx, MSR_IA32_MISC_ENABLE
216 rdmsr
217 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM
218 wrmsr
219
220 .1:
221 rsm
222
223 _StmSmiHandler:
224 ;
225 ; Check XD disable bit
226 ;
227 xor r8, r8
228 mov rax, ASM_PFX(gStmXdSupported)
229 mov al, [rax]
230 cmp al, 0
231 jz @StmXdDone
232 mov ecx, MSR_IA32_MISC_ENABLE
233 rdmsr
234 mov r8, rdx ; save MSR_IA32_MISC_ENABLE[63-32]
235 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
236 jz .0
237 and dx, 0xFFFB ; clear XD Disable bit if it is set
238 wrmsr
239 .0:
240 mov ecx, MSR_EFER
241 rdmsr
242 or ax, MSR_EFER_XD ; enable NXE
243 wrmsr
244 @StmXdDone:
245 push r8
246
247 ; below step is needed, because STM does not run above code.
248 ; we have to run below code to set IDT/CR0/CR4
249
250 mov rax, ASM_PFX(gStmSmiHandlerIdtr)
251 lidt [rax]
252
253 mov rax, cr0
254 or eax, 0x80010023 ; enable paging + WP + NE + MP + PE
255 mov cr0, rax
256 mov rax, cr4
257 mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3
258 mov cr4, rax ; in PreModifyMtrrs() to flush TLB.
259 ; STM init finish
260 jmp CommonHandler
261
262 ASM_PFX(gcStmSmiHandlerSize) : DW $ - _StmSmiEntryPoint
263 ASM_PFX(gcStmSmiHandlerOffset) : DW _StmSmiHandler - _StmSmiEntryPoint