MdePkg/BaseLib: add PatchInstructionX86()
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / X64 / SmiEntry.asm
CommitLineData
427e3573 1;------------------------------------------------------------------------------ ;\r
717fb604 2; Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
427e3573
MK
3; This program and the accompanying materials\r
4; are licensed and made available under the terms and conditions of the BSD License\r
5; which accompanies this distribution. The full text of the license may be found at\r
6; http://opensource.org/licenses/bsd-license.php.\r
7;\r
8; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
9; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
10;\r
11; Module Name:\r
12;\r
13; SmiEntry.asm\r
14;\r
15; Abstract:\r
16;\r
17; Code template of the SMI handler for a particular processor\r
18;\r
19;-------------------------------------------------------------------------------\r
20\r
21;\r
22; Variables referenced by C code\r
23;\r
24EXTERNDEF SmiRendezvous:PROC\r
f45f2d4a
JY
25EXTERNDEF CpuSmmDebugEntry:PROC\r
26EXTERNDEF CpuSmmDebugExit:PROC\r
427e3573
MK
27EXTERNDEF gcSmiHandlerTemplate:BYTE\r
28EXTERNDEF gcSmiHandlerSize:WORD\r
29EXTERNDEF gSmiCr3:DWORD\r
30EXTERNDEF gSmiStack:DWORD\r
31EXTERNDEF gSmbase:DWORD\r
717fb604 32EXTERNDEF mXdSupported:BYTE\r
427e3573
MK
33EXTERNDEF gSmiHandlerIdtr:FWORD\r
34\r
717fb604
JY
35MSR_IA32_MISC_ENABLE EQU 1A0h\r
36MSR_EFER EQU 0c0000080h\r
37MSR_EFER_XD EQU 0800h\r
427e3573
MK
38\r
39;\r
40; Constants relating to PROCESSOR_SMM_DESCRIPTOR\r
41;\r
42DSC_OFFSET EQU 0fb00h\r
43DSC_GDTPTR EQU 30h\r
44DSC_GDTSIZ EQU 38h\r
45DSC_CS EQU 14\r
46DSC_DS EQU 16\r
47DSC_SS EQU 18\r
48DSC_OTHERSEG EQU 20\r
49;\r
50; Constants relating to CPU State Save Area\r
51;\r
52SSM_DR6 EQU 0ffd0h\r
53SSM_DR7 EQU 0ffc8h\r
54\r
55PROTECT_MODE_CS EQU 08h\r
56PROTECT_MODE_DS EQU 20h\r
57LONG_MODE_CS EQU 38h\r
58TSS_SEGMENT EQU 40h\r
59GDT_SIZE EQU 50h\r
60\r
61 .code\r
62\r
63gcSmiHandlerTemplate LABEL BYTE\r
64\r
65_SmiEntryPoint:\r
66 ;\r
67 ; The encoding of BX in 16-bit addressing mode is the same as of RDI in 64-\r
68 ; bit addressing mode. And that coincidence has been used in the following\r
69 ; "64-bit like" 16-bit code. Be aware that once RDI is referenced as a\r
70 ; base address register, it is actually BX that is referenced.\r
71 ;\r
72 DB 0bbh ; mov bx, imm16\r
73 DW offset _GdtDesc - _SmiEntryPoint + 8000h ; bx = GdtDesc offset\r
74; fix GDT descriptor\r
75 DB 2eh, 0a1h ; mov ax, cs:[offset16]\r
76 DW DSC_OFFSET + DSC_GDTSIZ\r
77 DB 48h ; dec ax\r
78 DB 2eh\r
79 mov [rdi], eax ; mov cs:[bx], ax\r
80 DB 66h, 2eh, 0a1h ; mov eax, cs:[offset16]\r
81 DW DSC_OFFSET + DSC_GDTPTR\r
82 DB 2eh\r
83 mov [rdi + 2], ax ; mov cs:[bx + 2], eax\r
84 DB 66h, 2eh\r
85 lgdt fword ptr [rdi] ; lgdt fword ptr cs:[bx]\r
86; Patch ProtectedMode Segment\r
87 DB 0b8h ; mov ax, imm16\r
88 DW PROTECT_MODE_CS ; set AX for segment directly\r
89 DB 2eh\r
90 mov [rdi - 2], eax ; mov cs:[bx - 2], ax\r
91; Patch ProtectedMode entry\r
92 DB 66h, 0bfh ; mov edi, SMBASE\r
93gSmbase DD ?\r
94 lea ax, [edi + (@ProtectedMode - _SmiEntryPoint) + 8000h]\r
95 DB 2eh\r
96 mov [rdi - 6], ax ; mov cs:[bx - 6], eax\r
97; Switch into @ProtectedMode\r
98 mov rbx, cr0\r
99 DB 66h\r
100 and ebx, 9ffafff3h\r
101 DB 66h\r
102 or ebx, 00000023h\r
103\r
104 mov cr0, rbx\r
105 DB 66h, 0eah\r
106 DD ?\r
107 DW ?\r
108\r
109_GdtDesc FWORD ?\r
110@ProtectedMode:\r
111 mov ax, PROTECT_MODE_DS\r
112 mov ds, ax\r
113 mov es, ax\r
114 mov fs, ax\r
115 mov gs, ax\r
116 mov ss, ax\r
117 DB 0bch ; mov esp, imm32\r
118gSmiStack DD ?\r
119 jmp ProtFlatMode\r
120\r
121ProtFlatMode:\r
122 DB 0b8h ; mov eax, offset gSmiCr3\r
123gSmiCr3 DD ?\r
124 mov cr3, rax\r
125 mov eax, 668h ; as cr4.PGE is not set here, refresh cr3\r
126 mov cr4, rax ; in PreModifyMtrrs() to flush TLB.\r
127; Load TSS\r
128 sub esp, 8 ; reserve room in stack\r
129 sgdt fword ptr [rsp]\r
130 mov eax, [rsp + 2] ; eax = GDT base\r
131 add esp, 8\r
427e3573
MK
132 mov dl, 89h\r
133 mov [rax + TSS_SEGMENT + 5], dl ; clear busy flag\r
134 mov eax, TSS_SEGMENT\r
135 ltr ax\r
136\r
717fb604
JY
137; enable NXE if supported\r
138 DB 0b0h ; mov al, imm8\r
139mXdSupported DB 1\r
140 cmp al, 0\r
141 jz @SkipXd\r
142;\r
143; Check XD disable bit\r
144;\r
145 mov ecx, MSR_IA32_MISC_ENABLE\r
146 rdmsr\r
147 sub esp, 4\r
148 push rdx ; save MSR_IA32_MISC_ENABLE[63-32]\r
149 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]\r
150 jz @f\r
151 and dx, 0FFFBh ; clear XD Disable bit if it is set\r
152 wrmsr\r
153@@:\r
154 mov ecx, MSR_EFER\r
155 rdmsr\r
156 or ax, MSR_EFER_XD ; enable NXE\r
157 wrmsr\r
158 jmp @XdDone\r
159@SkipXd:\r
160 sub esp, 8\r
161@XdDone:\r
162\r
427e3573
MK
163; Switch into @LongMode\r
164 push LONG_MODE_CS ; push cs hardcore here\r
165 call Base ; push return address for retf later\r
166Base:\r
167 add dword ptr [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg\r
717fb604
JY
168\r
169 mov ecx, MSR_EFER\r
427e3573 170 rdmsr\r
717fb604 171 or ah, 1 ; enable LME\r
427e3573
MK
172 wrmsr\r
173 mov rbx, cr0\r
717fb604 174 or ebx, 080010023h ; enable paging + WP + NE + MP + PE\r
427e3573
MK
175 mov cr0, rbx\r
176 retf\r
177@LongMode: ; long mode (64-bit code) starts here\r
178 mov rax, offset gSmiHandlerIdtr\r
179 lidt fword ptr [rax]\r
180 lea ebx, [rdi + DSC_OFFSET]\r
181 mov ax, [rbx + DSC_DS]\r
182 mov ds, eax\r
183 mov ax, [rbx + DSC_OTHERSEG]\r
184 mov es, eax\r
185 mov fs, eax\r
186 mov gs, eax\r
187 mov ax, [rbx + DSC_SS]\r
188 mov ss, eax\r
189; jmp _SmiHandler ; instruction is not needed\r
190\r
191_SmiHandler:\r
f45f2d4a 192 mov rbx, [rsp] ; rbx <- CpuIndex\r
427e3573
MK
193\r
194 ;\r
195 ; Save FP registers\r
196 ;\r
717fb604 197 sub rsp, 200h\r
427e3573
MK
198 DB 48h ; FXSAVE64\r
199 fxsave [rsp]\r
200\r
201 add rsp, -20h\r
f45f2d4a
JY
202\r
203 mov rcx, rbx\r
204 mov rax, CpuSmmDebugEntry\r
205 call rax\r
717fb604 206\r
f45f2d4a
JY
207 mov rcx, rbx\r
208 mov rax, SmiRendezvous ; rax <- absolute addr of SmiRedezvous\r
209 call rax\r
717fb604 210\r
f45f2d4a
JY
211 mov rcx, rbx\r
212 mov rax, CpuSmmDebugExit\r
427e3573 213 call rax\r
717fb604 214\r
427e3573
MK
215 add rsp, 20h\r
216\r
217 ;\r
218 ; Restore FP registers\r
219 ;\r
220 DB 48h ; FXRSTOR64\r
221 fxrstor [rsp]\r
222\r
717fb604
JY
223 add rsp, 200h\r
224\r
b6fea56c 225 mov rax, offset ASM_PFX(mXdSupported)\r
717fb604
JY
226 mov al, [rax]\r
227 cmp al, 0\r
228 jz @f\r
229 pop rdx ; get saved MSR_IA32_MISC_ENABLE[63-32]\r
230 test edx, BIT2\r
231 jz @f\r
232 mov ecx, MSR_IA32_MISC_ENABLE\r
233 rdmsr\r
234 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM\r
235 wrmsr\r
236\r
237@@:\r
427e3573
MK
238 rsm\r
239\r
240gcSmiHandlerSize DW $ - _SmiEntryPoint\r
241\r
242 END\r