UefiCpuPkg/PiSmmCpuDxeSmm: Add paging protection.
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / 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 PROCESSOR_SMM_DESCRIPTOR
31 ;
32 %define DSC_OFFSET 0xfb00
33 %define DSC_GDTPTR 0x30
34 %define DSC_GDTSIZ 0x38
35 %define DSC_CS 14
36 %define DSC_DS 16
37 %define DSC_SS 18
38 %define DSC_OTHERSEG 20
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(gSmiHandlerIdtr)
53 extern ASM_PFX(CpuSmmDebugEntry)
54 extern ASM_PFX(CpuSmmDebugExit)
55
56 global ASM_PFX(gSmbase)
57 global ASM_PFX(mXdSupported)
58 global ASM_PFX(gSmiStack)
59 global ASM_PFX(gSmiCr3)
60 global ASM_PFX(gcSmiHandlerTemplate)
61 global ASM_PFX(gcSmiHandlerSize)
62
63 DEFAULT REL
64 SECTION .text
65
66 BITS 16
67 ASM_PFX(gcSmiHandlerTemplate):
68 _SmiEntryPoint:
69 mov bx, _GdtDesc - _SmiEntryPoint + 0x8000
70 mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ]
71 dec ax
72 mov [cs:bx], ax
73 mov eax, [cs:DSC_OFFSET + DSC_GDTPTR]
74 mov [cs:bx + 2], eax
75 o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx]
76 mov ax, PROTECT_MODE_CS
77 mov [cs:bx-0x2],ax
78 DB 0x66, 0xbf ; mov edi, SMBASE
79 ASM_PFX(gSmbase): DD 0
80 lea eax, [edi + (@ProtectedMode - _SmiEntryPoint) + 0x8000]
81 mov [cs:bx-0x6],eax
82 mov ebx, cr0
83 and ebx, 0x9ffafff3
84 or ebx, 0x23
85 mov cr0, ebx
86 jmp dword 0x0:0x0
87 _GdtDesc:
88 DW 0
89 DD 0
90
91 BITS 32
92 @ProtectedMode:
93 mov ax, PROTECT_MODE_DS
94 o16 mov ds, ax
95 o16 mov es, ax
96 o16 mov fs, ax
97 o16 mov gs, ax
98 o16 mov ss, ax
99 DB 0xbc ; mov esp, imm32
100 ASM_PFX(gSmiStack): DD 0
101 jmp ProtFlatMode
102
103 BITS 64
104 ProtFlatMode:
105 DB 0xb8 ; mov eax, offset gSmiCr3
106 ASM_PFX(gSmiCr3): DD 0
107 mov cr3, rax
108 mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3
109 mov cr4, rax ; in PreModifyMtrrs() to flush TLB.
110 ; Load TSS
111 sub esp, 8 ; reserve room in stack
112 sgdt [rsp]
113 mov eax, [rsp + 2] ; eax = GDT base
114 add esp, 8
115 mov dl, 0x89
116 mov [rax + TSS_SEGMENT + 5], dl ; clear busy flag
117 mov eax, TSS_SEGMENT
118 ltr ax
119
120 ; enable NXE if supported
121 DB 0xb0 ; mov al, imm8
122 ASM_PFX(mXdSupported): DB 1
123 cmp al, 0
124 jz @SkipXd
125 ;
126 ; Check XD disable bit
127 ;
128 mov ecx, MSR_IA32_MISC_ENABLE
129 rdmsr
130 sub esp, 4
131 push rdx ; save MSR_IA32_MISC_ENABLE[63-32]
132 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
133 jz .0
134 and dx, 0xFFFB ; clear XD Disable bit if it is set
135 wrmsr
136 .0:
137 mov ecx, MSR_EFER
138 rdmsr
139 or ax, MSR_EFER_XD ; enable NXE
140 wrmsr
141 jmp @XdDone
142 @SkipXd:
143 sub esp, 8
144 @XdDone:
145
146 ; Switch into @LongMode
147 push LONG_MODE_CS ; push cs hardcore here
148 call Base ; push return address for retf later
149 Base:
150 add dword [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg
151
152 mov ecx, MSR_EFER
153 rdmsr
154 or ah, 1 ; enable LME
155 wrmsr
156 mov rbx, cr0
157 or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE
158 mov cr0, rbx
159 retf
160 @LongMode: ; long mode (64-bit code) starts here
161 mov rax, ASM_PFX(gSmiHandlerIdtr)
162 lidt [rax]
163 lea ebx, [rdi + DSC_OFFSET]
164 mov ax, [rbx + DSC_DS]
165 mov ds, eax
166 mov ax, [rbx + DSC_OTHERSEG]
167 mov es, eax
168 mov fs, eax
169 mov gs, eax
170 mov ax, [rbx + DSC_SS]
171 mov ss, eax
172 ; jmp _SmiHandler ; instruction is not needed
173
174 _SmiHandler:
175 mov rbx, [rsp + 0x8] ; rcx <- 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(mXdSupported)
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 gcSmiHandlerSize DW $ - _SmiEntryPoint
224