]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuDxe/Ia32/CpuAsm.asm
Add CPU DXE driver for IA32 & X64 processor architectures.
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / Ia32 / CpuAsm.asm
diff --git a/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.asm b/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.asm
new file mode 100755 (executable)
index 0000000..dfcbc0d
--- /dev/null
@@ -0,0 +1,384 @@
+      TITLE   CpuAsm.asm:\r
+;------------------------------------------------------------------------------\r
+;*\r
+;*   Copyright 2006 - 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
+    .686\r
+    .model  flat,C\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 DWORD 0\r
+\r
+InitializeExternalVectorTablePtr PROC PUBLIC\r
+    mov     eax, [esp+4]\r
+    mov     ExternalVectorTablePtr, eax\r
+    ret\r
+InitializeExternalVectorTablePtr ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; SetCodeSelector (\r
+;   UINT16 Selector\r
+;   );\r
+;------------------------------------------------------------------------------\r
+SetCodeSelector PROC PUBLIC\r
+    mov     ecx, [esp+4]\r
+    sub     esp, 0x10\r
+    lea     eax, setCodeSelectorLongJump\r
+    mov     [esp], eax\r
+    mov     [esp+4], cx\r
+    jmp     fword ptr [esp]\r
+setCodeSelectorLongJump:\r
+    add     esp, 0x10\r
+    ret\r
+SetCodeSelector ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; SetDataSelectors (\r
+;   UINT16 Selector\r
+;   );\r
+;------------------------------------------------------------------------------\r
+SetDataSelectors PROC PUBLIC\r
+    mov     ecx, [esp+4]\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
+    ;\r
+    ; Calculate vector number\r
+    ;\r
+    ; Get the return address of call, actually, it is the\r
+    ; address of vector number.\r
+    ;\r
+    xchg    ecx, [esp]\r
+    mov     cx, [ecx]\r
+    and     ecx, 0FFFFh\r
+    cmp     ecx, 32         ; Intel reserved vector for exceptions?\r
+    jae     NoErrorCode\r
+    bt      mErrorCodeFlag, ecx\r
+    jc      HasErrorCode\r
+\r
+NoErrorCode:\r
+\r
+    ;\r
+    ; Stack:\r
+    ; +---------------------+\r
+    ; +    EFlags           +\r
+    ; +---------------------+\r
+    ; +    CS               +\r
+    ; +---------------------+\r
+    ; +    EIP              +\r
+    ; +---------------------+\r
+    ; +    ECX              +\r
+    ; +---------------------+ <-- ESP\r
+    ;\r
+    ; Registers:\r
+    ;   ECX - Vector Number\r
+    ;\r
+\r
+    ;\r
+    ; Put Vector Number on stack\r
+    ;\r
+    push    ecx\r
+\r
+    ;\r
+    ; Put 0 (dummy) error code on stack, and restore ECX\r
+    ;\r
+    xor     ecx, ecx  ; ECX = 0\r
+    xchg    ecx, [esp+4]\r
+\r
+    jmp     ErrorCodeAndVectorOnStack\r
+\r
+HasErrorCode:\r
+\r
+    ;\r
+    ; Stack:\r
+    ; +---------------------+\r
+    ; +    EFlags           +\r
+    ; +---------------------+\r
+    ; +    CS               +\r
+    ; +---------------------+\r
+    ; +    EIP              +\r
+    ; +---------------------+\r
+    ; +    Error Code       +\r
+    ; +---------------------+\r
+    ; +    ECX              +\r
+    ; +---------------------+ <-- ESP\r
+    ;\r
+    ; Registers:\r
+    ;   ECX - Vector Number\r
+    ;\r
+\r
+    ;\r
+    ; Put Vector Number on stack and restore ECX\r
+    ;\r
+    xchg    ecx, [esp]\r
+\r
+    ;\r
+    ; Fall through to join main routine code\r
+    ; at ErrorCodeAndVectorOnStack\r
+    ;\r
+@@:\r
+    jmp @B\r
+\r
+ErrorCodeAndVectorOnStack:\r
+    push    ebp\r
+    mov     ebp, esp\r
+\r
+    ;\r
+    ; Stack:\r
+    ; +---------------------+\r
+    ; +    EFlags           +\r
+    ; +---------------------+\r
+    ; +    CS               +\r
+    ; +---------------------+\r
+    ; +    EIP              +\r
+    ; +---------------------+\r
+    ; +    Error Code       +\r
+    ; +---------------------+\r
+    ; +    Vector Number    +\r
+    ; +---------------------+\r
+    ; +    EBP              +\r
+    ; +---------------------+ <-- EBP\r
+    ;\r
+\r
+    ;\r
+    ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32\r
+    ; is 16-byte aligned\r
+    ;\r
+    and     esp, 0fffffff0h\r
+    sub     esp, 12\r
+\r
+;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+    push    eax\r
+    push    ecx\r
+    push    edx\r
+    push    ebx\r
+    lea     ecx, [ebp + 6 * 4]\r
+    push    ecx                          ; ESP\r
+    push    dword ptr [ebp]              ; EBP\r
+    push    esi\r
+    push    edi\r
+\r
+;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;\r
+    mov     eax, ss\r
+    push    eax\r
+    movzx   eax, word ptr [ebp + 4 * 4]\r
+    push    eax\r
+    mov     eax, ds\r
+    push    eax\r
+    mov     eax, es\r
+    push    eax\r
+    mov     eax, fs\r
+    push    eax\r
+    mov     eax, gs\r
+    push    eax\r
+\r
+;; UINT32  Eip;\r
+    mov     eax, [ebp + 3 * 4]\r
+    push    eax\r
+\r
+;; UINT32  Gdtr[2], Idtr[2];\r
+    sub     esp, 8\r
+    sidt    [esp]\r
+    mov     eax, [esp + 2]\r
+    xchg    eax, [esp]\r
+    and     eax, 0FFFFh\r
+    mov     [esp+4], eax\r
+\r
+    sub     esp, 8\r
+    sgdt    [esp]\r
+    mov     eax, [esp + 2]\r
+    xchg    eax, [esp]\r
+    and     eax, 0FFFFh\r
+    mov     [esp+4], eax\r
+\r
+;; UINT32  Ldtr, Tr;\r
+    xor     eax, eax\r
+    str     ax\r
+    push    eax\r
+    sldt    ax\r
+    push    eax\r
+\r
+;; UINT32  EFlags;\r
+    mov     eax, [ebp + 5 * 4]\r
+    push    eax\r
+\r
+;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;\r
+    mov     eax, cr4\r
+    or      eax, 208h\r
+    mov     cr4, eax\r
+    push    eax\r
+    mov     eax, cr3\r
+    push    eax\r
+    mov     eax, cr2\r
+    push    eax\r
+    xor     eax, eax\r
+    push    eax\r
+    mov     eax, cr0\r
+    push    eax\r
+\r
+;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+    mov     eax, dr7\r
+    push    eax\r
+;; clear Dr7 while executing debugger itself\r
+    xor     eax, eax\r
+    mov     dr7, eax\r
+\r
+    mov     eax, dr6\r
+    push    eax\r
+;; insure all status bits in dr6 are clear...\r
+    xor     eax, eax\r
+    mov     dr6, eax\r
+\r
+    mov     eax, dr3\r
+    push    eax\r
+    mov     eax, dr2\r
+    push    eax\r
+    mov     eax, dr1\r
+    push    eax\r
+    mov     eax, dr0\r
+    push    eax\r
+\r
+;; FX_SAVE_STATE_IA32 FxSaveState;\r
+    sub     esp, 512\r
+    mov     edi, esp\r
+    db      0fh, 0aeh, 07h ;fxsave [edi]\r
+\r
+;; UINT32  ExceptionData;\r
+    push    dword ptr [ebp + 2 * 4]\r
+\r
+;; call into exception handler\r
+    mov     eax, ExternalVectorTablePtr  ; get the interrupt vectors base\r
+    or      eax, eax                        ; NULL?\r
+    jz      nullExternalExceptionHandler\r
+\r
+    mov     ecx, [ebp + 4]\r
+    mov     eax, [eax + ecx * 4]\r
+    or      eax, eax                        ; NULL?\r
+    jz      nullExternalExceptionHandler\r
+\r
+;; Prepare parameter and call\r
+    mov     edx, esp\r
+    push    edx\r
+    mov     edx, dword ptr [ebp + 1 * 4]\r
+    push    edx\r
+\r
+    ;\r
+    ; Call External Exception Handler\r
+    ;\r
+    call    eax\r
+    add     esp, 8\r
+\r
+nullExternalExceptionHandler:\r
+\r
+    cli\r
+;; UINT32  ExceptionData;\r
+    add     esp, 4\r
+\r
+;; FX_SAVE_STATE_IA32 FxSaveState;\r
+    mov     esi, esp\r
+    db      0fh, 0aeh, 0eh ; fxrstor [esi]\r
+    add     esp, 512\r
+\r
+;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+    pop     eax\r
+    mov     dr0, eax\r
+    pop     eax\r
+    mov     dr1, eax\r
+    pop     eax\r
+    mov     dr2, eax\r
+    pop     eax\r
+    mov     dr3, eax\r
+;; skip restore of dr6.  We cleared dr6 during the context save.\r
+    add     esp, 4\r
+    pop     eax\r
+    mov     dr7, eax\r
+\r
+;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;\r
+    pop     eax\r
+    mov     cr0, eax\r
+    add     esp, 4    ; not for Cr1\r
+    pop     eax\r
+    mov     cr2, eax\r
+    pop     eax\r
+    mov     cr3, eax\r
+    pop     eax\r
+    mov     cr4, eax\r
+\r
+;; UINT32  EFlags;\r
+    pop     dword ptr [ebp + 5 * 4]\r
+\r
+;; UINT32  Ldtr, Tr;\r
+;; UINT32  Gdtr[2], Idtr[2];\r
+;; Best not let anyone mess with these particular registers...\r
+    add     esp, 24\r
+\r
+;; UINT32  Eip;\r
+    pop     dword ptr [ebp + 3 * 4]\r
+\r
+;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;\r
+;; NOTE - modified segment registers could hang the debugger...  We\r
+;;        could attempt to insulate ourselves against this possibility,\r
+;;        but that poses risks as well.\r
+;;\r
+    pop     gs\r
+    pop     fs\r
+    pop     es\r
+    pop     ds\r
+    pop     dword ptr [ebp + 4 * 4]\r
+    pop     ss\r
+\r
+;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+    pop     edi\r
+    pop     esi\r
+    add     esp, 4   ; not for ebp\r
+    add     esp, 4   ; not for esp\r
+    pop     ebx\r
+    pop     edx\r
+    pop     ecx\r
+    pop     eax\r
+\r
+    mov     esp, ebp\r
+    pop     ebp\r
+    add     esp, 8\r
+    iretd\r
+\r
+CommonInterruptEntry ENDP\r
+\r
+END\r