1#------------------------------------------------------------------------------ 2# 3# Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR> 4# This program and the accompanying materials 5# are licensed and made available under the terms and conditions of the BSD License 6# which accompanies this distribution. The full text of the license may be found at 7# http://opensource.org/licenses/bsd-license.php. 8# 9# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11# 12# Module Name: 13# 14# SmiException.S 15# 16# Abstract: 17# 18# Exception handlers used in SM mode 19# 20#------------------------------------------------------------------------------ 21 22ASM_GLOBAL ASM_PFX(SmiPFHandler) 23ASM_GLOBAL ASM_PFX(gcSmiIdtr) 24ASM_GLOBAL ASM_PFX(gcSmiGdtr) 25ASM_GLOBAL ASM_PFX(gcPsd) 26 27 .data 28 29NullSeg: .quad 0 # reserved by architecture 30CodeSeg32: 31 .word -1 # LimitLow 32 .word 0 # BaseLow 33 .byte 0 # BaseMid 34 .byte 0x9b 35 .byte 0xcf # LimitHigh 36 .byte 0 # BaseHigh 37ProtModeCodeSeg32: 38 .word -1 # LimitLow 39 .word 0 # BaseLow 40 .byte 0 # BaseMid 41 .byte 0x9b 42 .byte 0xcf # LimitHigh 43 .byte 0 # BaseHigh 44ProtModeSsSeg32: 45 .word -1 # LimitLow 46 .word 0 # BaseLow 47 .byte 0 # BaseMid 48 .byte 0x93 49 .byte 0xcf # LimitHigh 50 .byte 0 # BaseHigh 51DataSeg32: 52 .word -1 # LimitLow 53 .word 0 # BaseLow 54 .byte 0 # BaseMid 55 .byte 0x93 56 .byte 0xcf # LimitHigh 57 .byte 0 # BaseHigh 58CodeSeg16: 59 .word -1 60 .word 0 61 .byte 0 62 .byte 0x9b 63 .byte 0x8f 64 .byte 0 65DataSeg16: 66 .word -1 67 .word 0 68 .byte 0 69 .byte 0x93 70 .byte 0x8f 71 .byte 0 72CodeSeg64: 73 .word -1 # LimitLow 74 .word 0 # BaseLow 75 .byte 0 # BaseMid 76 .byte 0x9b 77 .byte 0xaf # LimitHigh 78 .byte 0 # BaseHigh 79# TSS Segment for X64 specially 80TssSeg: 81 .word TSS_DESC_SIZE - 1 # LimitLow 82 .word 0 # BaseLow 83 .byte 0 # BaseMid 84 .byte 0x89 85 .byte 0x00 # LimitHigh 86 .byte 0 # BaseHigh 87 .long 0 # BaseUpper 88 .long 0 # Reserved 89.equ GDT_SIZE, .- NullSeg 90 91TssDescriptor: 92 .space 104, 0 93.equ TSS_DESC_SIZE, .- TssDescriptor 94 95# 96# This structure serves as a template for all processors. 97# 98ASM_PFX(gcPsd): 99 .ascii "PSDSIG " 100 .word PSD_SIZE 101 .word 2 102 .word 1 << 2 103 .word CODE_SEL 104 .word DATA_SEL 105 .word DATA_SEL 106 .word DATA_SEL 107 .word 0 108 .quad 0 109 .quad 0 110 .quad 0 # fixed in InitializeMpServiceData() 111 .quad NullSeg 112 .long GDT_SIZE 113 .long 0 114 .space 24, 0 115 .quad 0 116.equ PSD_SIZE, . - ASM_PFX(gcPsd) 117 118# 119# CODE & DATA segments for SMM runtime 120# 121.equ CODE_SEL, CodeSeg64 - NullSeg 122.equ DATA_SEL, DataSeg32 - NullSeg 123.equ CODE32_SEL, CodeSeg32 - NullSeg 124 125ASM_PFX(gcSmiGdtr): 126 .word GDT_SIZE - 1 127 .quad NullSeg 128 129ASM_PFX(gcSmiIdtr): 130 .word 0 131 .quad 0 132 133 .text 134 135#------------------------------------------------------------------------------ 136# _SmiExceptionEntryPoints is the collection of exception entry points followed 137# by a common exception handler. 138# 139# Stack frame would be as follows as specified in IA32 manuals: 140# +---------------------+ <-- 16-byte aligned ensured by processor 141# + Old SS + 142# +---------------------+ 143# + Old RSP + 144# +---------------------+ 145# + RFlags + 146# +---------------------+ 147# + CS + 148# +---------------------+ 149# + RIP + 150# +---------------------+ 151# + Error Code + 152# +---------------------+ 153# + Vector Number + 154# +---------------------+ 155# + RBP + 156# +---------------------+ <-- RBP, 16-byte aligned 157# 158# RSP set to odd multiple of 8 at @CommonEntryPoint means ErrCode PRESENT 159#------------------------------------------------------------------------------ 160ASM_GLOBAL ASM_PFX(PageFaultIdtHandlerSmmProfile) 161ASM_PFX(PageFaultIdtHandlerSmmProfile): 162 pushq $0x0e # Page Fault 163 .byte 0x40, 0xf6, 0xc4, 0x08 #test spl, 8 164 jnz L1 165 pushq (%rsp) 166 movq $0, 8(%rsp) 167L1: 168 pushq %rbp 169 movq %rsp, %rbp 170 171 # 172 # Since here the stack pointer is 16-byte aligned, so 173 # EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64 174 # is 16-byte aligned 175 # 176 177## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; 178## UINT64 R8, R9, R10, R11, R12, R13, R14, R15; 179 pushq %r15 180 pushq %r14 181 pushq %r13 182 pushq %r12 183 pushq %r11 184 pushq %r10 185 pushq %r9 186 pushq %r8 187 pushq %rax 188 pushq %rcx 189 pushq %rdx 190 pushq %rbx 191 pushq 48(%rbp) # RSP 192 pushq (%rbp) # RBP 193 pushq %rsi 194 pushq %rdi 195 196## UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero 197 movzwq 56(%rbp), %rax 198 pushq %rax # for ss 199 movzwq 32(%rbp), %rax 200 pushq %rax # for cs 201 movq %ds, %rax 202 pushq %rax 203 movq %es, %rax 204 pushq %rax 205 movq %fs, %rax 206 pushq %rax 207 movq %gs, %rax 208 pushq %rax 209 210## UINT64 Rip; 211 pushq 24(%rbp) 212 213## UINT64 Gdtr[2], Idtr[2]; 214 subq $16, %rsp 215 sidt (%rsp) 216 subq $16, %rsp 217 sgdt (%rsp) 218 219## UINT64 Ldtr, Tr; 220 xorq %rax, %rax 221 strw %ax 222 pushq %rax 223 sldtw %ax 224 pushq %rax 225 226## UINT64 RFlags; 227 pushq 40(%rbp) 228 229## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8; 230 movq %cr8, %rax 231 pushq %rax 232 movq %cr4, %rax 233 orq $0x208, %rax 234 movq %rax, %cr4 235 pushq %rax 236 movq %cr3, %rax 237 pushq %rax 238 movq %cr2, %rax 239 pushq %rax 240 xorq %rax, %rax 241 pushq %rax 242 movq %cr0, %rax 243 pushq %rax 244 245## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; 246 movq %dr7, %rax 247 pushq %rax 248 movq %dr6, %rax 249 pushq %rax 250 movq %dr3, %rax 251 pushq %rax 252 movq %dr2, %rax 253 pushq %rax 254 movq %dr1, %rax 255 pushq %rax 256 movq %dr0, %rax 257 pushq %rax 258 259## FX_SAVE_STATE_X64 FxSaveState; 260 261 subq $512, %rsp 262 movq %rsp, %rdi 263 .byte 0xf, 0xae, 0x7 # fxsave [rdi] 264 265# UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear 266 cld 267 268## UINT32 ExceptionData; 269 pushq 16(%rbp) 270 271## call into exception handler 272 movq 8(%rbp), %rcx 273 movabsq $ASM_PFX(SmiPFHandler), %rax 274 275## Prepare parameter and call 276 movq %rsp, %rdx 277 # 278 # Per X64 calling convention, allocate maximum parameter stack space 279 # and make sure RSP is 16-byte aligned 280 # 281 subq $4 * 8 + 8, %rsp 282 call *%rax 283 addq $4 * 8 + 8, %rsp 284 jmp L5 285 286L5: 287## UINT64 ExceptionData; 288 addq $8, %rsp 289 290## FX_SAVE_STATE_X64 FxSaveState; 291 292 movq %rsp, %rsi 293 .byte 0xf, 0xae, 0xe # fxrstor [rsi] 294 addq $512, %rsp 295 296## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; 297## Skip restoration of DRx registers to support debuggers 298## that set breakpoints in interrupt/exception context 299 addq $8 * 6, %rsp 300 301## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8; 302 popq %rax 303 movq %rax, %cr0 304 addq $8, %rsp # not for Cr1 305 popq %rax 306 movq %rax, %cr2 307 popq %rax 308 movq %rax, %cr3 309 popq %rax 310 movq %rax, %cr4 311 popq %rax 312 movq %rax, %cr8 313 314## UINT64 RFlags; 315 popq 40(%rbp) 316 317## UINT64 Ldtr, Tr; 318## UINT64 Gdtr[2], Idtr[2]; 319## Best not let anyone mess with these particular registers... 320 addq $48, %rsp 321 322## UINT64 Rip; 323 popq 24(%rbp) 324 325## UINT64 Gs, Fs, Es, Ds, Cs, Ss; 326 popq %rax 327 # mov gs, rax ; not for gs 328 popq %rax 329 # mov fs, rax ; not for fs 330 # (X64 will not use fs and gs, so we do not restore it) 331 popq %rax 332 movq %rax, %es 333 popq %rax 334 movq %rax, %ds 335 popq 32(%rbp) # for cs 336 popq 56(%rbp) # for ss 337 338## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; 339## UINT64 R8, R9, R10, R11, R12, R13, R14, R15; 340 popq %rdi 341 popq %rsi 342 addq $8, %rsp # not for rbp 343 popq 48(%rbp) # for rsp 344 popq %rbx 345 popq %rdx 346 popq %rcx 347 popq %rax 348 popq %r8 349 popq %r9 350 popq %r10 351 popq %r11 352 popq %r12 353 popq %r13 354 popq %r14 355 popq %r15 356 357 movq %rbp, %rsp 358 359# Enable TF bit after page fault handler runs 360 btsl $8, 40(%rsp) #RFLAGS 361 362 popq %rbp 363 addq $16, %rsp # skip INT# & ErrCode 364 iretq 365 366