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 ; SmiException.nasm 14 ; 15 ; Abstract: 16 ; 17 ; Exception handlers used in SM mode 18 ; 19 ;------------------------------------------------------------------------------- 20 21 extern ASM_PFX(SmiPFHandler) 22 23 global ASM_PFX(gcSmiIdtr) 24 global ASM_PFX(gcSmiGdtr) 25 global ASM_PFX(gcPsd) 26 27 SECTION .data 28 29 NullSeg: DQ 0 ; reserved by architecture 30 CodeSeg32: 31 DW -1 ; LimitLow 32 DW 0 ; BaseLow 33 DB 0 ; BaseMid 34 DB 0x9b 35 DB 0xcf ; LimitHigh 36 DB 0 ; BaseHigh 37 ProtModeCodeSeg32: 38 DW -1 ; LimitLow 39 DW 0 ; BaseLow 40 DB 0 ; BaseMid 41 DB 0x9b 42 DB 0xcf ; LimitHigh 43 DB 0 ; BaseHigh 44 ProtModeSsSeg32: 45 DW -1 ; LimitLow 46 DW 0 ; BaseLow 47 DB 0 ; BaseMid 48 DB 0x93 49 DB 0xcf ; LimitHigh 50 DB 0 ; BaseHigh 51 DataSeg32: 52 DW -1 ; LimitLow 53 DW 0 ; BaseLow 54 DB 0 ; BaseMid 55 DB 0x93 56 DB 0xcf ; LimitHigh 57 DB 0 ; BaseHigh 58 CodeSeg16: 59 DW -1 60 DW 0 61 DB 0 62 DB 0x9b 63 DB 0x8f 64 DB 0 65 DataSeg16: 66 DW -1 67 DW 0 68 DB 0 69 DB 0x93 70 DB 0x8f 71 DB 0 72 CodeSeg64: 73 DW -1 ; LimitLow 74 DW 0 ; BaseLow 75 DB 0 ; BaseMid 76 DB 0x9b 77 DB 0xaf ; LimitHigh 78 DB 0 ; BaseHigh 79 ; TSS Segment for X64 specially 80 TssSeg: 81 DW TSS_DESC_SIZE ; LimitLow 82 DW 0 ; BaseLow 83 DB 0 ; BaseMid 84 DB 0x89 85 DB 0x80 ; LimitHigh 86 DB 0 ; BaseHigh 87 DD 0 ; BaseUpper 88 DD 0 ; Reserved 89 GDT_SIZE equ $ - NullSeg 90 91 ; Create TSS Descriptor just after GDT 92 TssDescriptor: 93 DD 0 ; Reserved 94 DQ 0 ; RSP0 95 DQ 0 ; RSP1 96 DQ 0 ; RSP2 97 DD 0 ; Reserved 98 DD 0 ; Reserved 99 DQ 0 ; IST1 100 DQ 0 ; IST2 101 DQ 0 ; IST3 102 DQ 0 ; IST4 103 DQ 0 ; IST5 104 DQ 0 ; IST6 105 DQ 0 ; IST7 106 DD 0 ; Reserved 107 DD 0 ; Reserved 108 DW 0 ; Reserved 109 DW 0 ; I/O Map Base Address 110 TSS_DESC_SIZE equ $ - TssDescriptor 111 112 ; 113 ; This structure serves as a template for all processors. 114 ; 115 ASM_PFX(gcPsd): 116 DB 'PSDSIG ' 117 DW PSD_SIZE 118 DW 2 119 DW 1 << 2 120 DW CODE_SEL 121 DW DATA_SEL 122 DW DATA_SEL 123 DW DATA_SEL 124 DW 0 125 DQ 0 126 DQ 0 127 DQ 0 ; fixed in InitializeMpServiceData() 128 DQ NullSeg 129 DD GDT_SIZE 130 DD 0 131 times 24 DB 0 132 DQ 0 133 PSD_SIZE equ $ - ASM_PFX(gcPsd) 134 135 ; 136 ; CODE & DATA segments for SMM runtime 137 ; 138 CODE_SEL equ CodeSeg64 - NullSeg 139 DATA_SEL equ DataSeg32 - NullSeg 140 CODE32_SEL equ CodeSeg32 - NullSeg 141 142 ASM_PFX(gcSmiGdtr): 143 DW GDT_SIZE - 1 144 DQ NullSeg 145 146 ASM_PFX(gcSmiIdtr): 147 DW 0 148 DQ 0 149 150 DEFAULT REL 151 SECTION .text 152 153 ;------------------------------------------------------------------------------ 154 ; _SmiExceptionEntryPoints is the collection of exception entrypoints followed 155 ; by a common exception handler. 156 ; 157 ; Stack frame would be as follows as specified in IA32 manuals: 158 ; 159 ; +---------------------+ <-- 16-byte aligned ensured by processor 160 ; + Old SS + 161 ; +---------------------+ 162 ; + Old RSP + 163 ; +---------------------+ 164 ; + RFlags + 165 ; +---------------------+ 166 ; + CS + 167 ; +---------------------+ 168 ; + RIP + 169 ; +---------------------+ 170 ; + Error Code + 171 ; +---------------------+ 172 ; + Vector Number + 173 ; +---------------------+ 174 ; + RBP + 175 ; +---------------------+ <-- RBP, 16-byte aligned 176 ; 177 ; RSP set to odd multiple of 8 at @CommonEntryPoint means ErrCode PRESENT 178 ;------------------------------------------------------------------------------ 179 global ASM_PFX(PageFaultIdtHandlerSmmProfile) 180 ASM_PFX(PageFaultIdtHandlerSmmProfile): 181 push 0xe ; Page Fault 182 test spl, 8 ; odd multiple of 8 => ErrCode present 183 jnz .0 184 push qword [rsp] ; duplicate INT# if no ErrCode 185 mov qword [rsp + 8], 0 186 .0: 187 push rbp 188 mov rbp, rsp 189 190 ; 191 ; Since here the stack pointer is 16-byte aligned, so 192 ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64 193 ; is 16-byte aligned 194 ; 195 196 ;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; 197 ;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15; 198 push r15 199 push r14 200 push r13 201 push r12 202 push r11 203 push r10 204 push r9 205 push r8 206 push rax 207 push rcx 208 push rdx 209 push rbx 210 push qword [rbp + 48] ; RSP 211 push qword [rbp] ; RBP 212 push rsi 213 push rdi 214 215 ;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero 216 movzx rax, word [rbp + 56] 217 push rax ; for ss 218 movzx rax, word [rbp + 32] 219 push rax ; for cs 220 mov rax, ds 221 push rax 222 mov rax, es 223 push rax 224 mov rax, fs 225 push rax 226 mov rax, gs 227 push rax 228 229 ;; UINT64 Rip; 230 push qword [rbp + 24] 231 232 ;; UINT64 Gdtr[2], Idtr[2]; 233 sub rsp, 16 234 sidt [rsp] 235 sub rsp, 16 236 sgdt [rsp] 237 238 ;; UINT64 Ldtr, Tr; 239 xor rax, rax 240 str ax 241 push rax 242 sldt ax 243 push rax 244 245 ;; UINT64 RFlags; 246 push qword [rbp + 40] 247 248 ;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8; 249 mov rax, cr8 250 push rax 251 mov rax, cr4 252 or rax, 0x208 253 mov cr4, rax 254 push rax 255 mov rax, cr3 256 push rax 257 mov rax, cr2 258 push rax 259 xor rax, rax 260 push rax 261 mov rax, cr0 262 push rax 263 264 ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; 265 mov rax, dr7 266 push rax 267 mov rax, dr6 268 push rax 269 mov rax, dr3 270 push rax 271 mov rax, dr2 272 push rax 273 mov rax, dr1 274 push rax 275 mov rax, dr0 276 push rax 277 278 ;; FX_SAVE_STATE_X64 FxSaveState; 279 280 sub rsp, 512 281 mov rdi, rsp 282 db 0xf, 0xae, 00000111y ;fxsave [rdi] 283 284 ; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear 285 cld 286 287 ;; UINT32 ExceptionData; 288 push qword [rbp + 16] 289 290 ;; call into exception handler 291 mov rcx, [rbp + 8] 292 mov rax, ASM_PFX(SmiPFHandler) 293 294 ;; Prepare parameter and call 295 mov rdx, rsp 296 ; 297 ; Per X64 calling convention, allocate maximum parameter stack space 298 ; and make sure RSP is 16-byte aligned 299 ; 300 sub rsp, 4 * 8 + 8 301 call rax 302 add rsp, 4 * 8 + 8 303 jmp .1 304 305 .1: 306 ;; UINT64 ExceptionData; 307 add rsp, 8 308 309 ;; FX_SAVE_STATE_X64 FxSaveState; 310 311 mov rsi, rsp 312 db 0xf, 0xae, 00001110y ; fxrstor [rsi] 313 add rsp, 512 314 315 ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; 316 ;; Skip restoration of DRx registers to support debuggers 317 ;; that set breakpoints in interrupt/exception context 318 add rsp, 8 * 6 319 320 ;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8; 321 pop rax 322 mov cr0, rax 323 add rsp, 8 ; not for Cr1 324 pop rax 325 mov cr2, rax 326 pop rax 327 mov cr3, rax 328 pop rax 329 mov cr4, rax 330 pop rax 331 mov cr8, rax 332 333 ;; UINT64 RFlags; 334 pop qword [rbp + 40] 335 336 ;; UINT64 Ldtr, Tr; 337 ;; UINT64 Gdtr[2], Idtr[2]; 338 ;; Best not let anyone mess with these particular registers... 339 add rsp, 48 340 341 ;; UINT64 Rip; 342 pop qword [rbp + 24] 343 344 ;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; 345 pop rax 346 ; mov gs, rax ; not for gs 347 pop rax 348 ; mov fs, rax ; not for fs 349 ; (X64 will not use fs and gs, so we do not restore it) 350 pop rax 351 mov es, rax 352 pop rax 353 mov ds, rax 354 pop qword [rbp + 32] ; for cs 355 pop qword [rbp + 56] ; for ss 356 357 ;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; 358 ;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15; 359 pop rdi 360 pop rsi 361 add rsp, 8 ; not for rbp 362 pop qword [rbp + 48] ; for rsp 363 pop rbx 364 pop rdx 365 pop rcx 366 pop rax 367 pop r8 368 pop r9 369 pop r10 370 pop r11 371 pop r12 372 pop r13 373 pop r14 374 pop r15 375 376 mov rsp, rbp 377 378 ; Enable TF bit after page fault handler runs 379 bts dword [rsp + 40], 8 ;RFLAGS 380 381 pop rbp 382 add rsp, 16 ; skip INT# & ErrCode 383 iretq 384 385