MdePkg/BaseLib: add PatchInstructionX86()
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / Ia32 / SmiEntry.asm
CommitLineData
7947da3c 1;------------------------------------------------------------------------------ ;\r
717fb604 2; Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
7947da3c
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 .686p\r
22 .model flat,C\r
23 .xmm\r
24\r
717fb604
JY
25MSR_IA32_MISC_ENABLE EQU 1A0h\r
26MSR_EFER EQU 0c0000080h\r
27MSR_EFER_XD EQU 0800h\r
28\r
f12367a0
MK
29;\r
30; Constants relating to PROCESSOR_SMM_DESCRIPTOR\r
31;\r
7947da3c
MK
32DSC_OFFSET EQU 0fb00h\r
33DSC_GDTPTR EQU 30h\r
34DSC_GDTSIZ EQU 38h\r
35DSC_CS EQU 14\r
36DSC_DS EQU 16\r
37DSC_SS EQU 18\r
38DSC_OTHERSEG EQU 20\r
39\r
40PROTECT_MODE_CS EQU 08h\r
41PROTECT_MODE_DS EQU 20h\r
42TSS_SEGMENT EQU 40h\r
43\r
f45f2d4a
JY
44SmiRendezvous PROTO C\r
45CpuSmmDebugEntry PROTO C\r
46CpuSmmDebugExit PROTO C\r
7947da3c
MK
47\r
48EXTERNDEF gcSmiHandlerTemplate:BYTE\r
49EXTERNDEF gcSmiHandlerSize:WORD\r
50EXTERNDEF gSmiCr3:DWORD\r
51EXTERNDEF gSmiStack:DWORD\r
52EXTERNDEF gSmbase:DWORD\r
717fb604 53EXTERNDEF mXdSupported:BYTE\r
7947da3c
MK
54EXTERNDEF FeaturePcdGet (PcdCpuSmmStackGuard):BYTE\r
55EXTERNDEF gSmiHandlerIdtr:FWORD\r
56\r
57 .code\r
58\r
59gcSmiHandlerTemplate LABEL BYTE\r
60\r
61_SmiEntryPoint:\r
62 DB 0bbh ; mov bx, imm16\r
63 DW offset _GdtDesc - _SmiEntryPoint + 8000h\r
64 DB 2eh, 0a1h ; mov ax, cs:[offset16]\r
65 DW DSC_OFFSET + DSC_GDTSIZ\r
66 dec eax\r
67 mov cs:[edi], eax ; mov cs:[bx], ax\r
68 DB 66h, 2eh, 0a1h ; mov eax, cs:[offset16]\r
69 DW DSC_OFFSET + DSC_GDTPTR\r
70 mov cs:[edi + 2], ax ; mov cs:[bx + 2], eax\r
71 mov bp, ax ; ebp = GDT base\r
72 DB 66h\r
73 lgdt fword ptr cs:[edi] ; lgdt fword ptr cs:[bx]\r
74; Patch ProtectedMode Segment\r
75 DB 0b8h ; mov ax, imm16\r
76 DW PROTECT_MODE_CS ; set AX for segment directly\r
77 mov cs:[edi - 2], eax ; mov cs:[bx - 2], ax\r
78; Patch ProtectedMode entry\r
79 DB 66h, 0bfh ; mov edi, SMBASE\r
80gSmbase DD ?\r
81 DB 67h\r
82 lea ax, [edi + (@32bit - _SmiEntryPoint) + 8000h]\r
83 mov cs:[edi - 6], ax ; mov cs:[bx - 6], eax\r
84 mov ebx, cr0\r
85 DB 66h\r
86 and ebx, 9ffafff3h\r
87 DB 66h\r
88 or ebx, 23h\r
89 mov cr0, ebx\r
90 DB 66h, 0eah\r
91 DD ?\r
92 DW ?\r
93_GdtDesc FWORD ?\r
94\r
95@32bit:\r
96 mov ax, PROTECT_MODE_DS\r
97 mov ds, ax\r
98 mov es, ax\r
99 mov fs, ax\r
100 mov gs, ax\r
101 mov ss, ax\r
102 DB 0bch ; mov esp, imm32\r
103gSmiStack DD ?\r
104 mov eax, offset gSmiHandlerIdtr\r
105 lidt fword ptr [eax]\r
106 jmp ProtFlatMode\r
107\r
108ProtFlatMode:\r
109 DB 0b8h ; mov eax, imm32\r
110gSmiCr3 DD ?\r
111 mov cr3, eax\r
112;\r
113; Need to test for CR4 specific bit support\r
114;\r
115 mov eax, 1\r
116 cpuid ; use CPUID to determine if specific CR4 bits are supported\r
117 xor eax, eax ; Clear EAX\r
118 test edx, BIT2 ; Check for DE capabilities\r
119 jz @f\r
120 or eax, BIT3\r
121@@:\r
122 test edx, BIT6 ; Check for PAE capabilities\r
123 jz @f\r
124 or eax, BIT5\r
125@@:\r
126 test edx, BIT7 ; Check for MCE capabilities\r
127 jz @f\r
128 or eax, BIT6\r
129@@:\r
130 test edx, BIT24 ; Check for FXSR capabilities\r
131 jz @f\r
132 or eax, BIT9\r
133@@:\r
134 test edx, BIT25 ; Check for SSE capabilities\r
135 jz @f\r
136 or eax, BIT10\r
137@@: ; as cr4.PGE is not set here, refresh cr3\r
138 mov cr4, eax ; in PreModifyMtrrs() to flush TLB.\r
717fb604
JY
139\r
140 cmp FeaturePcdGet (PcdCpuSmmStackGuard), 0\r
141 jz @F\r
142; Load TSS\r
143 mov byte ptr [ebp + TSS_SEGMENT + 5], 89h ; clear busy flag\r
144 mov eax, TSS_SEGMENT\r
145 ltr ax\r
146@@:\r
147\r
148; enable NXE if supported\r
149 DB 0b0h ; mov al, imm8\r
150mXdSupported DB 1\r
151 cmp al, 0\r
152 jz @SkipXd\r
153;\r
154; Check XD disable bit\r
155;\r
156 mov ecx, MSR_IA32_MISC_ENABLE\r
157 rdmsr\r
158 push edx ; save MSR_IA32_MISC_ENABLE[63-32]\r
159 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]\r
160 jz @f\r
161 and dx, 0FFFBh ; clear XD Disable bit if it is set\r
162 wrmsr\r
163@@:\r
164 mov ecx, MSR_EFER\r
165 rdmsr\r
166 or ax, MSR_EFER_XD ; enable NXE\r
167 wrmsr\r
168 jmp @XdDone\r
169@SkipXd:\r
170 sub esp, 4\r
171@XdDone:\r
172\r
7947da3c 173 mov ebx, cr0\r
717fb604 174 or ebx, 080010023h ; enable paging + WP + NE + MP + PE\r
7947da3c
MK
175 mov cr0, ebx\r
176 lea ebx, [edi + DSC_OFFSET]\r
177 mov ax, [ebx + DSC_DS]\r
178 mov ds, eax\r
179 mov ax, [ebx + DSC_OTHERSEG]\r
180 mov es, eax\r
181 mov fs, eax\r
182 mov gs, eax\r
183 mov ax, [ebx + DSC_SS]\r
184 mov ss, eax\r
185\r
7947da3c
MK
186; jmp _SmiHandler ; instruction is not needed\r
187\r
188_SmiHandler PROC\r
717fb604 189 mov ebx, [esp + 4] ; CPU Index\r
f45f2d4a
JY
190 push ebx\r
191 mov eax, CpuSmmDebugEntry\r
7947da3c 192 call eax\r
717fb604 193 add esp, 4\r
7947da3c 194\r
f45f2d4a
JY
195 push ebx\r
196 mov eax, SmiRendezvous\r
197 call eax\r
717fb604
JY
198 add esp, 4\r
199\r
f45f2d4a
JY
200 push ebx\r
201 mov eax, CpuSmmDebugExit\r
202 call eax\r
717fb604 203 add esp, 4\r
7947da3c 204\r
b6fea56c 205 mov eax, offset mXdSupported\r
717fb604
JY
206 mov al, [eax]\r
207 cmp al, 0\r
208 jz @f\r
209 pop edx ; get saved MSR_IA32_MISC_ENABLE[63-32]\r
210 test edx, BIT2\r
211 jz @f\r
212 mov ecx, MSR_IA32_MISC_ENABLE\r
213 rdmsr\r
214 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM\r
215 wrmsr\r
216\r
217@@:\r
7947da3c
MK
218 rsm\r
219_SmiHandler ENDP\r
220\r
221gcSmiHandlerSize DW $ - _SmiEntryPoint\r
222\r
223 END\r