UefiCpuPkg/PiSmmCpuDxeSmm: patch "gSmiCr3" with PatchInstructionX86()
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / Ia32 / 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 %define MSR_IA32_MISC_ENABLE 0x1A0
22 %define MSR_EFER 0xc0000080
23 %define MSR_EFER_XD 0x800
24
25 ;
26 ; Constants relating to PROCESSOR_SMM_DESCRIPTOR
27 ;
28 %define DSC_OFFSET 0xfb00
29 %define DSC_GDTPTR 0x30
30 %define DSC_GDTSIZ 0x38
31 %define DSC_CS 14
32 %define DSC_DS 16
33 %define DSC_SS 18
34 %define DSC_OTHERSEG 20
35
36 %define PROTECT_MODE_CS 0x8
37 %define PROTECT_MODE_DS 0x20
38 %define TSS_SEGMENT 0x40
39
40 extern ASM_PFX(SmiRendezvous)
41 extern ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
42 extern ASM_PFX(CpuSmmDebugEntry)
43 extern ASM_PFX(CpuSmmDebugExit)
44
45 global ASM_PFX(gcSmiHandlerTemplate)
46 global ASM_PFX(gcSmiHandlerSize)
47 global ASM_PFX(gPatchSmiCr3)
48 global ASM_PFX(gPatchSmiStack)
49 global ASM_PFX(gPatchSmbase)
50 global ASM_PFX(mXdSupported)
51 extern ASM_PFX(gSmiHandlerIdtr)
52
53 SECTION .text
54
55 BITS 16
56 ASM_PFX(gcSmiHandlerTemplate):
57 _SmiEntryPoint:
58 mov bx, _GdtDesc - _SmiEntryPoint + 0x8000
59 mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ]
60 dec ax
61 mov [cs:bx], ax
62 mov eax, [cs:DSC_OFFSET + DSC_GDTPTR]
63 mov [cs:bx + 2], eax
64 mov ebp, eax ; ebp = GDT base
65 o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx]
66 mov ax, PROTECT_MODE_CS
67 mov [cs:bx-0x2],ax
68 mov edi, strict dword 0 ; source operand will be patched
69 ASM_PFX(gPatchSmbase):
70 lea eax, [edi + (@32bit - _SmiEntryPoint) + 0x8000]
71 mov [cs:bx-0x6],eax
72 mov ebx, cr0
73 and ebx, 0x9ffafff3
74 or ebx, 0x23
75 mov cr0, ebx
76 jmp dword 0x0:0x0
77 _GdtDesc:
78 DW 0
79 DD 0
80
81 BITS 32
82 @32bit:
83 mov ax, PROTECT_MODE_DS
84 o16 mov ds, ax
85 o16 mov es, ax
86 o16 mov fs, ax
87 o16 mov gs, ax
88 o16 mov ss, ax
89 mov esp, strict dword 0 ; source operand will be patched
90 ASM_PFX(gPatchSmiStack):
91 mov eax, ASM_PFX(gSmiHandlerIdtr)
92 lidt [eax]
93 jmp ProtFlatMode
94
95 ProtFlatMode:
96 mov eax, strict dword 0 ; source operand will be patched
97 ASM_PFX(gPatchSmiCr3):
98 mov cr3, eax
99 ;
100 ; Need to test for CR4 specific bit support
101 ;
102 mov eax, 1
103 cpuid ; use CPUID to determine if specific CR4 bits are supported
104 xor eax, eax ; Clear EAX
105 test edx, BIT2 ; Check for DE capabilities
106 jz .0
107 or eax, BIT3
108 .0:
109 test edx, BIT6 ; Check for PAE capabilities
110 jz .1
111 or eax, BIT5
112 .1:
113 test edx, BIT7 ; Check for MCE capabilities
114 jz .2
115 or eax, BIT6
116 .2:
117 test edx, BIT24 ; Check for FXSR capabilities
118 jz .3
119 or eax, BIT9
120 .3:
121 test edx, BIT25 ; Check for SSE capabilities
122 jz .4
123 or eax, BIT10
124 .4: ; as cr4.PGE is not set here, refresh cr3
125 mov cr4, eax ; in PreModifyMtrrs() to flush TLB.
126
127 cmp byte [dword ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))], 0
128 jz .6
129 ; Load TSS
130 mov byte [ebp + TSS_SEGMENT + 5], 0x89 ; clear busy flag
131 mov eax, TSS_SEGMENT
132 ltr ax
133 .6:
134
135 ; enable NXE if supported
136 DB 0b0h ; mov al, imm8
137 ASM_PFX(mXdSupported): DB 1
138 cmp al, 0
139 jz @SkipXd
140 ;
141 ; Check XD disable bit
142 ;
143 mov ecx, MSR_IA32_MISC_ENABLE
144 rdmsr
145 push edx ; save MSR_IA32_MISC_ENABLE[63-32]
146 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
147 jz .5
148 and dx, 0xFFFB ; clear XD Disable bit if it is set
149 wrmsr
150 .5:
151 mov ecx, MSR_EFER
152 rdmsr
153 or ax, MSR_EFER_XD ; enable NXE
154 wrmsr
155 jmp @XdDone
156 @SkipXd:
157 sub esp, 4
158 @XdDone:
159
160 mov ebx, cr0
161 or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE
162 mov cr0, ebx
163 lea ebx, [edi + DSC_OFFSET]
164 mov ax, [ebx + DSC_DS]
165 mov ds, eax
166 mov ax, [ebx + DSC_OTHERSEG]
167 mov es, eax
168 mov fs, eax
169 mov gs, eax
170 mov ax, [ebx + DSC_SS]
171 mov ss, eax
172
173 ; jmp _SmiHandler ; instruction is not needed
174
175 global ASM_PFX(SmiHandler)
176 ASM_PFX(SmiHandler):
177 mov ebx, [esp + 4] ; CPU Index
178 push ebx
179 mov eax, ASM_PFX(CpuSmmDebugEntry)
180 call eax
181 add esp, 4
182
183 push ebx
184 mov eax, ASM_PFX(SmiRendezvous)
185 call eax
186 add esp, 4
187
188 push ebx
189 mov eax, ASM_PFX(CpuSmmDebugExit)
190 call eax
191 add esp, 4
192
193 mov eax, ASM_PFX(mXdSupported)
194 mov al, [eax]
195 cmp al, 0
196 jz .7
197 pop edx ; get saved MSR_IA32_MISC_ENABLE[63-32]
198 test edx, BIT2
199 jz .7
200 mov ecx, MSR_IA32_MISC_ENABLE
201 rdmsr
202 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM
203 wrmsr
204
205 .7:
206 rsm
207
208 ASM_PFX(gcSmiHandlerSize): DW $ - _SmiEntryPoint
209
210 global ASM_PFX(PiSmmCpuSmiEntryFixupAddress)
211 ASM_PFX(PiSmmCpuSmiEntryFixupAddress):
212 ret