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