]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuDxe/X64/CpuAsm.asm
Add CPU DXE driver for IA32 & X64 processor architectures.
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / X64 / CpuAsm.asm
diff --git a/UefiCpuPkg/CpuDxe/X64/CpuAsm.asm b/UefiCpuPkg/CpuDxe/X64/CpuAsm.asm
new file mode 100755 (executable)
index 0000000..05d9bca
--- /dev/null
@@ -0,0 +1,345 @@
+      TITLE   CpuAsm.asm: \r
+;------------------------------------------------------------------------------\r
+;*\r
+;*   Copyright 2008 - 2009, Intel Corporation                                                         \r
+;*   All rights reserved. This program and the accompanying materials                          \r
+;*   are licensed and made available under the terms and conditions of the BSD License         \r
+;*   which accompanies this distribution.  The full text of the license may be found at        \r
+;*   http://opensource.org/licenses/bsd-license.php                                            \r
+;*                                                                                             \r
+;*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+;*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+;*   \r
+;*    CpuAsm.asm\r
+;*  \r
+;*   Abstract:\r
+;*\r
+;------------------------------------------------------------------------------\r
+\r
+    .code\r
+\r
+EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions\r
+\r
+;\r
+; point to the external interrupt vector table\r
+;\r
+ExternalVectorTablePtr QWORD 0\r
+\r
+InitializeExternalVectorTablePtr PROC PUBLIC\r
+    mov  ExternalVectorTablePtr, rcx\r
+    ret\r
+InitializeExternalVectorTablePtr ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; SetCodeSelector (\r
+;   UINT16 Selector\r
+;   );\r
+;------------------------------------------------------------------------------\r
+SetCodeSelector PROC PUBLIC\r
+    sub     rsp, 0x10\r
+    lea     rax, setCodeSelectorLongJump\r
+    mov     [rsp], rax\r
+    mov     [rsp+4], cx\r
+    jmp     fword ptr [rsp]\r
+setCodeSelectorLongJump:\r
+    add     rsp, 0x10\r
+    ret\r
+SetCodeSelector ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; SetDataSelectors (\r
+;   UINT16 Selector\r
+;   );\r
+;------------------------------------------------------------------------------\r
+SetDataSelectors PROC PUBLIC\r
+    mov     ss, cx\r
+    mov     ds, cx\r
+    mov     es, cx\r
+    mov     fs, cx\r
+    mov     gs, cx\r
+    ret\r
+SetDataSelectors ENDP\r
+\r
+;---------------------------------------;\r
+; CommonInterruptEntry                  ;\r
+;---------------------------------------;\r
+; The follow algorithm is used for the common interrupt routine.\r
+\r
+CommonInterruptEntry PROC PUBLIC  \r
+    cli\r
+    ;\r
+    ; All interrupt handlers are invoked through interrupt gates, so\r
+    ; IF flag automatically cleared at the entry point\r
+    ;\r
+    ;\r
+    ; Calculate vector number\r
+    ;\r
+    xchg    rcx, [rsp] ; get the return address of call, actually, it is the address of vector number.\r
+    movzx   ecx, word ptr [rcx]\r
+    cmp     ecx, 32         ; Intel reserved vector for exceptions?\r
+    jae     NoErrorCode\r
+    bt      mErrorCodeFlag, ecx\r
+    jc      @F\r
+\r
+NoErrorCode:\r
+\r
+    ;\r
+    ; Push a dummy error code on the stack\r
+    ; to maintain coherent stack map\r
+    ;\r
+    push    [rsp]\r
+    mov     qword ptr [rsp + 8], 0\r
+@@:       \r
+    push    rbp\r
+    mov     rbp, rsp\r
+\r
+    ;\r
+    ; Stack:\r
+    ; +---------------------+ <-- 16-byte aligned ensured by processor\r
+    ; +    Old SS           +\r
+    ; +---------------------+\r
+    ; +    Old RSP          +\r
+    ; +---------------------+\r
+    ; +    RFlags           +\r
+    ; +---------------------+\r
+    ; +    CS               +\r
+    ; +---------------------+\r
+    ; +    RIP              +\r
+    ; +---------------------+\r
+    ; +    Error Code       +\r
+    ; +---------------------+\r
+    ; + RCX / Vector Number +\r
+    ; +---------------------+\r
+    ; +    RBP              +\r
+    ; +---------------------+ <-- RBP, 16-byte aligned\r
+    ;\r
+\r
+\r
+    ;\r
+    ; Since here the stack pointer is 16-byte aligned, so\r
+    ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64\r
+    ; is 16-byte aligned\r
+    ;\r
+\r
+;; UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+;; UINT64  R8, R9, R10, R11, R12, R13, R14, R15;\r
+    push r15\r
+    push r14\r
+    push r13\r
+    push r12\r
+    push r11\r
+    push r10\r
+    push r9\r
+    push r8\r
+    push rax\r
+    push qword ptr [rbp + 8]   ; RCX\r
+    push rdx\r
+    push rbx\r
+    push qword ptr [rbp + 48]  ; RSP\r
+    push qword ptr [rbp]       ; RBP\r
+    push rsi\r
+    push rdi\r
+\r
+;; UINT64  Gs, Fs, Es, Ds, Cs, Ss;  insure high 16 bits of each is zero\r
+    movzx   rax, word ptr [rbp + 56]\r
+    push    rax                      ; for ss\r
+    movzx   rax, word ptr [rbp + 32]\r
+    push    rax                      ; for cs\r
+    mov     rax, ds\r
+    push    rax\r
+    mov     rax, es\r
+    push    rax\r
+    mov     rax, fs\r
+    push    rax\r
+    mov     rax, gs\r
+    push    rax\r
+\r
+    mov     [rbp + 8], rcx               ; save vector number\r
+\r
+;; UINT64  Rip;\r
+    push    qword ptr [rbp + 24]\r
+\r
+;; UINT64  Gdtr[2], Idtr[2];\r
+    xor     rax, rax\r
+    push    rax\r
+    push    rax\r
+    sidt    [rsp]\r
+    xchg    rax, [rsp + 2]\r
+    xchg    rax, [rsp]\r
+    xchg    rax, [rsp + 8]\r
+\r
+    xor     rax, rax\r
+    push    rax\r
+    push    rax\r
+    sgdt    [rsp]\r
+    xchg    rax, [rsp + 2]\r
+    xchg    rax, [rsp]\r
+    xchg    rax, [rsp + 8]\r
+\r
+;; UINT64  Ldtr, Tr;\r
+    xor     rax, rax\r
+    str     ax\r
+    push    rax\r
+    sldt    ax\r
+    push    rax\r
+\r
+;; UINT64  RFlags;\r
+    push    qword ptr [rbp + 40]\r
+\r
+;; UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
+    mov     rax, cr8\r
+    push    rax\r
+    mov     rax, cr4\r
+    or      rax, 208h\r
+    mov     cr4, rax\r
+    push    rax\r
+    mov     rax, cr3\r
+    push    rax\r
+    mov     rax, cr2\r
+    push    rax\r
+    xor     rax, rax\r
+    push    rax\r
+    mov     rax, cr0\r
+    push    rax\r
+\r
+;; UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+    mov     rax, dr7\r
+    push    rax\r
+;; clear Dr7 while executing debugger itself\r
+    xor     rax, rax\r
+    mov     dr7, rax\r
+\r
+    mov     rax, dr6\r
+    push    rax\r
+;; insure all status bits in dr6 are clear...\r
+    xor     rax, rax\r
+    mov     dr6, rax\r
+\r
+    mov     rax, dr3\r
+    push    rax\r
+    mov     rax, dr2\r
+    push    rax\r
+    mov     rax, dr1\r
+    push    rax\r
+    mov     rax, dr0\r
+    push    rax\r
+\r
+;; FX_SAVE_STATE_X64 FxSaveState;\r
+    sub rsp, 512\r
+    mov rdi, rsp\r
+    db 0fh, 0aeh, 07h ;fxsave [rdi]\r
+\r
+;; UINT32  ExceptionData;\r
+    push    qword ptr [rbp + 16]\r
+\r
+;; call into exception handler\r
+    mov     rcx, [rbp + 8]\r
+    mov     rax, ExternalVectorTablePtr  ; get the interrupt vectors base\r
+    mov     rax, [rax + rcx * 8]       \r
+    or      rax, rax                        ; NULL?\r
+\r
+    je    nonNullValue;\r
+\r
+;; Prepare parameter and call\r
+;  mov     rcx, [rbp + 8]\r
+    mov     rdx, rsp\r
+    ;\r
+    ; Per X64 calling convention, allocate maximum parameter stack space\r
+    ; and make sure RSP is 16-byte aligned\r
+    ;\r
+    sub     rsp, 4 * 8 + 8\r
+    call    rax\r
+    add     rsp, 4 * 8 + 8\r
+\r
+nonNullValue:\r
+    cli\r
+;; UINT64  ExceptionData;\r
+    add     rsp, 8\r
+\r
+;; FX_SAVE_STATE_X64 FxSaveState;\r
+\r
+    mov rsi, rsp\r
+    db 0fh, 0aeh, 0Eh ; fxrstor [rsi]\r
+    add rsp, 512\r
+\r
+;; UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+    pop     rax\r
+    mov     dr0, rax\r
+    pop     rax\r
+    mov     dr1, rax\r
+    pop     rax\r
+    mov     dr2, rax\r
+    pop     rax\r
+    mov     dr3, rax\r
+;; skip restore of dr6.  We cleared dr6 during the context save.\r
+    add     rsp, 8\r
+    pop     rax\r
+    mov     dr7, rax\r
+\r
+;; UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
+    pop     rax\r
+    mov     cr0, rax\r
+    add     rsp, 8   ; not for Cr1\r
+    pop     rax\r
+    mov     cr2, rax\r
+    pop     rax\r
+    mov     cr3, rax\r
+    pop     rax\r
+    mov     cr4, rax\r
+    pop     rax\r
+    mov     cr8, rax\r
+\r
+;; UINT64  RFlags;\r
+    pop     qword ptr [rbp + 40]\r
+\r
+;; UINT64  Ldtr, Tr;\r
+;; UINT64  Gdtr[2], Idtr[2];\r
+;; Best not let anyone mess with these particular registers...\r
+    add     rsp, 48\r
+\r
+;; UINT64  Rip;\r
+    pop     qword ptr [rbp + 24]\r
+\r
+;; UINT64  Gs, Fs, Es, Ds, Cs, Ss;\r
+    pop     rax\r
+    ; mov     gs, rax ; not for gs\r
+    pop     rax\r
+    ; mov     fs, rax ; not for fs\r
+    ; (X64 will not use fs and gs, so we do not restore it)\r
+    pop     rax\r
+    mov     es, rax\r
+    pop     rax\r
+    mov     ds, rax\r
+    pop     qword ptr [rbp + 32]  ; for cs\r
+    pop     qword ptr [rbp + 56]  ; for ss\r
+\r
+;; UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+;; UINT64  R8, R9, R10, R11, R12, R13, R14, R15;\r
+    pop     rdi\r
+    pop     rsi\r
+    add     rsp, 8               ; not for rbp\r
+    pop     qword ptr [rbp + 48] ; for rsp\r
+    pop     rbx\r
+    pop     rdx\r
+    pop     rcx\r
+    pop     rax\r
+    pop     r8\r
+    pop     r9\r
+    pop     r10\r
+    pop     r11\r
+    pop     r12\r
+    pop     r13\r
+    pop     r14\r
+    pop     r15\r
+\r
+    mov     rsp, rbp\r
+    pop     rbp\r
+    add     rsp, 16\r
+    iretq\r
+\r
+CommonInterruptEntry ENDP\r
+\r
+END\r
+\r