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