Home | History | Annotate | Download | only in X64
      1 ;------------------------------------------------------------------------------ ;
      2 ; Copyright (c) 2012 - 2014, 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 ;   ExceptionHandlerAsm.Asm
     14 ;
     15 ; Abstract:
     16 ;
     17 ;   x64 CPU Exception Handler
     18 ;
     19 ; Notes:
     20 ;
     21 ;------------------------------------------------------------------------------
     22 
     23 ;
     24 ; CommonExceptionHandler()
     25 ;
     26 
     27 extern ASM_PFX(mErrorCodeFlag)    ; Error code flags for exceptions
     28 extern ASM_PFX(mDoFarReturnFlag)  ; Do far return flag
     29 extern ASM_PFX(CommonExceptionHandler)
     30 
     31 SECTION .data
     32 
     33 DEFAULT REL
     34 SECTION .text
     35 
     36 ALIGN   8
     37 
     38 AsmIdtVectorBegin:
     39 %rep  32
     40     db      0x6a        ; push  #VectorNum
     41     db      ($ - AsmIdtVectorBegin) / ((AsmIdtVectorEnd - AsmIdtVectorBegin) / 32) ; VectorNum
     42     push    rax
     43     mov     rax, ASM_PFX(CommonInterruptEntry)
     44     jmp     rax
     45 %endrep
     46 AsmIdtVectorEnd:
     47 
     48 HookAfterStubHeaderBegin:
     49     db      0x6a        ; push
     50 @VectorNum:
     51     db      0          ; 0 will be fixed
     52     push    rax
     53     mov     rax, HookAfterStubHeaderEnd
     54     jmp     rax
     55 HookAfterStubHeaderEnd:
     56     mov     rax, rsp
     57     and     sp,  0xfff0        ; make sure 16-byte aligned for exception context
     58     sub     rsp, 0x18           ; reserve room for filling exception data later
     59     push    rcx
     60     mov     rcx, [rax + 8]
     61     bt      [ASM_PFX(mErrorCodeFlag)], ecx
     62     jnc     .0
     63     push    qword [rsp]             ; push additional rcx to make stack alignment
     64 .0:
     65     xchg    rcx, [rsp]        ; restore rcx, save Exception Number in stack
     66     push    qword [rax]             ; push rax into stack to keep code consistence
     67 
     68 ;---------------------------------------;
     69 ; CommonInterruptEntry                  ;
     70 ;---------------------------------------;
     71 ; The follow algorithm is used for the common interrupt routine.
     72 ; Entry from each interrupt with a push eax and eax=interrupt number
     73 ; Stack frame would be as follows as specified in IA32 manuals:
     74 ;
     75 ; +---------------------+ <-- 16-byte aligned ensured by processor
     76 ; +    Old SS           +
     77 ; +---------------------+
     78 ; +    Old RSP          +
     79 ; +---------------------+
     80 ; +    RFlags           +
     81 ; +---------------------+
     82 ; +    CS               +
     83 ; +---------------------+
     84 ; +    RIP              +
     85 ; +---------------------+
     86 ; +    Error Code       +
     87 ; +---------------------+
     88 ; +   Vector Number     +
     89 ; +---------------------+
     90 ; +    RBP              +
     91 ; +---------------------+ <-- RBP, 16-byte aligned
     92 ; The follow algorithm is used for the common interrupt routine.
     93 global ASM_PFX(CommonInterruptEntry)
     94 ASM_PFX(CommonInterruptEntry):
     95     cli
     96     pop     rax
     97     ;
     98     ; All interrupt handlers are invoked through interrupt gates, so
     99     ; IF flag automatically cleared at the entry point
    100     ;
    101     xchg    rcx, [rsp]      ; Save rcx into stack and save vector number into rcx
    102     and     rcx, 0xFF
    103     cmp     ecx, 32         ; Intel reserved vector for exceptions?
    104     jae     NoErrorCode
    105     bt      [ASM_PFX(mErrorCodeFlag)], ecx
    106     jc      HasErrorCode
    107 
    108 NoErrorCode:
    109 
    110     ;
    111     ; Push a dummy error code on the stack
    112     ; to maintain coherent stack map
    113     ;
    114     push    qword [rsp]
    115     mov     qword [rsp + 8], 0
    116 HasErrorCode:
    117     push    rbp
    118     mov     rbp, rsp
    119     push    0             ; clear EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
    120     push    0             ; clear EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
    121 
    122     ;
    123     ; Stack:
    124     ; +---------------------+ <-- 16-byte aligned ensured by processor
    125     ; +    Old SS           +
    126     ; +---------------------+
    127     ; +    Old RSP          +
    128     ; +---------------------+
    129     ; +    RFlags           +
    130     ; +---------------------+
    131     ; +    CS               +
    132     ; +---------------------+
    133     ; +    RIP              +
    134     ; +---------------------+
    135     ; +    Error Code       +
    136     ; +---------------------+
    137     ; + RCX / Vector Number +
    138     ; +---------------------+
    139     ; +    RBP              +
    140     ; +---------------------+ <-- RBP, 16-byte aligned
    141     ;
    142 
    143     ;
    144     ; Since here the stack pointer is 16-byte aligned, so
    145     ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
    146     ; is 16-byte aligned
    147     ;
    148 
    149 ;; UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
    150 ;; UINT64  R8, R9, R10, R11, R12, R13, R14, R15;
    151     push r15
    152     push r14
    153     push r13
    154     push r12
    155     push r11
    156     push r10
    157     push r9
    158     push r8
    159     push rax
    160     push qword [rbp + 8]   ; RCX
    161     push rdx
    162     push rbx
    163     push qword [rbp + 48]  ; RSP
    164     push qword [rbp]       ; RBP
    165     push rsi
    166     push rdi
    167 
    168 ;; UINT64  Gs, Fs, Es, Ds, Cs, Ss;  insure high 16 bits of each is zero
    169     movzx   rax, word [rbp + 56]
    170     push    rax                      ; for ss
    171     movzx   rax, word [rbp + 32]
    172     push    rax                      ; for cs
    173     mov     rax, ds
    174     push    rax
    175     mov     rax, es
    176     push    rax
    177     mov     rax, fs
    178     push    rax
    179     mov     rax, gs
    180     push    rax
    181 
    182     mov     [rbp + 8], rcx               ; save vector number
    183 
    184 ;; UINT64  Rip;
    185     push    qword [rbp + 24]
    186 
    187 ;; UINT64  Gdtr[2], Idtr[2];
    188     xor     rax, rax
    189     push    rax
    190     push    rax
    191     sidt    [rsp]
    192     xchg    rax, [rsp + 2]
    193     xchg    rax, [rsp]
    194     xchg    rax, [rsp + 8]
    195 
    196     xor     rax, rax
    197     push    rax
    198     push    rax
    199     sgdt    [rsp]
    200     xchg    rax, [rsp + 2]
    201     xchg    rax, [rsp]
    202     xchg    rax, [rsp + 8]
    203 
    204 ;; UINT64  Ldtr, Tr;
    205     xor     rax, rax
    206     str     ax
    207     push    rax
    208     sldt    ax
    209     push    rax
    210 
    211 ;; UINT64  RFlags;
    212     push    qword [rbp + 40]
    213 
    214 ;; UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
    215     mov     rax, cr8
    216     push    rax
    217     mov     rax, cr4
    218     or      rax, 0x208
    219     mov     cr4, rax
    220     push    rax
    221     mov     rax, cr3
    222     push    rax
    223     mov     rax, cr2
    224     push    rax
    225     xor     rax, rax
    226     push    rax
    227     mov     rax, cr0
    228     push    rax
    229 
    230 ;; UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
    231     mov     rax, dr7
    232     push    rax
    233     mov     rax, dr6
    234     push    rax
    235     mov     rax, dr3
    236     push    rax
    237     mov     rax, dr2
    238     push    rax
    239     mov     rax, dr1
    240     push    rax
    241     mov     rax, dr0
    242     push    rax
    243 
    244 ;; FX_SAVE_STATE_X64 FxSaveState;
    245     sub rsp, 512
    246     mov rdi, rsp
    247     db 0xf, 0xae, 0x7 ;fxsave [rdi]
    248 
    249 ;; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
    250     cld
    251 
    252 ;; UINT32  ExceptionData;
    253     push    qword [rbp + 16]
    254 
    255 ;; Prepare parameter and call
    256     mov     rcx, [rbp + 8]
    257     mov     rdx, rsp
    258     ;
    259     ; Per X64 calling convention, allocate maximum parameter stack space
    260     ; and make sure RSP is 16-byte aligned
    261     ;
    262     sub     rsp, 4 * 8 + 8
    263     mov     rax, ASM_PFX(CommonExceptionHandler)
    264     call    rax
    265     add     rsp, 4 * 8 + 8
    266 
    267     cli
    268 ;; UINT64  ExceptionData;
    269     add     rsp, 8
    270 
    271 ;; FX_SAVE_STATE_X64 FxSaveState;
    272 
    273     mov rsi, rsp
    274     db 0xf, 0xae, 0xE ; fxrstor [rsi]
    275     add rsp, 512
    276 
    277 ;; UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
    278 ;; Skip restoration of DRx registers to support in-circuit emualators
    279 ;; or debuggers set breakpoint in interrupt/exception context
    280     add     rsp, 8 * 6
    281 
    282 ;; UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
    283     pop     rax
    284     mov     cr0, rax
    285     add     rsp, 8   ; not for Cr1
    286     pop     rax
    287     mov     cr2, rax
    288     pop     rax
    289     mov     cr3, rax
    290     pop     rax
    291     mov     cr4, rax
    292     pop     rax
    293     mov     cr8, rax
    294 
    295 ;; UINT64  RFlags;
    296     pop     qword [rbp + 40]
    297 
    298 ;; UINT64  Ldtr, Tr;
    299 ;; UINT64  Gdtr[2], Idtr[2];
    300 ;; Best not let anyone mess with these particular registers...
    301     add     rsp, 48
    302 
    303 ;; UINT64  Rip;
    304     pop     qword [rbp + 24]
    305 
    306 ;; UINT64  Gs, Fs, Es, Ds, Cs, Ss;
    307     pop     rax
    308     ; mov     gs, rax ; not for gs
    309     pop     rax
    310     ; mov     fs, rax ; not for fs
    311     ; (X64 will not use fs and gs, so we do not restore it)
    312     pop     rax
    313     mov     es, rax
    314     pop     rax
    315     mov     ds, rax
    316     pop     qword [rbp + 32]  ; for cs
    317     pop     qword [rbp + 56]  ; for ss
    318 
    319 ;; UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
    320 ;; UINT64  R8, R9, R10, R11, R12, R13, R14, R15;
    321     pop     rdi
    322     pop     rsi
    323     add     rsp, 8               ; not for rbp
    324     pop     qword [rbp + 48] ; for rsp
    325     pop     rbx
    326     pop     rdx
    327     pop     rcx
    328     pop     rax
    329     pop     r8
    330     pop     r9
    331     pop     r10
    332     pop     r11
    333     pop     r12
    334     pop     r13
    335     pop     r14
    336     pop     r15
    337 
    338     mov     rsp, rbp
    339     pop     rbp
    340     add     rsp, 16
    341     cmp     qword [rsp - 32], 0  ; check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
    342     jz      DoReturn
    343     cmp     qword [rsp - 40], 1  ; check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
    344     jz      ErrorCode
    345     jmp     qword [rsp - 32]
    346 ErrorCode:
    347     sub     rsp, 8
    348     jmp     qword [rsp - 24]
    349 
    350 DoReturn:
    351     cmp     qword [ASM_PFX(mDoFarReturnFlag)], 0   ; Check if need to do far return instead of IRET
    352     jz      DoIret
    353     push    rax
    354     mov     rax, rsp          ; save old RSP to rax
    355     mov     rsp, [rsp + 0x20]
    356     push    qword [rax + 0x10]       ; save CS in new location
    357     push    qword [rax + 0x8]        ; save EIP in new location
    358     push    qword [rax + 0x18]       ; save EFLAGS in new location
    359     mov     rax, [rax]        ; restore rax
    360     popfq                     ; restore EFLAGS
    361     DB      0x48               ; prefix to composite "retq" with next "retf"
    362     retf                      ; far return
    363 DoIret:
    364     iretq
    365 
    366 ;-------------------------------------------------------------------------------------
    367 ;  GetTemplateAddressMap (&AddressMap);
    368 ;-------------------------------------------------------------------------------------
    369 ; comments here for definition of address map
    370 global ASM_PFX(AsmGetTemplateAddressMap)
    371 ASM_PFX(AsmGetTemplateAddressMap):
    372     mov     rax, AsmIdtVectorBegin
    373     mov     qword [rcx], rax
    374     mov     qword [rcx + 0x8],  (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32
    375     mov     rax, HookAfterStubHeaderBegin
    376     mov     qword [rcx + 0x10], rax
    377     ret
    378 
    379 ;-------------------------------------------------------------------------------------
    380 ;  AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr);
    381 ;-------------------------------------------------------------------------------------
    382 global ASM_PFX(AsmVectorNumFixup)
    383 ASM_PFX(AsmVectorNumFixup):
    384     mov     rax, rdx
    385     mov     [rcx + (@VectorNum - HookAfterStubHeaderBegin)], al
    386     ret
    387 
    388