summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64')
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c427
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h43
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm400
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/Xcode5ExceptionHandlerAsm.nasm455
4 files changed, 1325 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
new file mode 100644
index 00000000..a0257aa8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
@@ -0,0 +1,427 @@
+/** @file
+ x64 CPU Exception Handler.
+
+ Copyright (c) 2012 - 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CpuExceptionCommon.h"
+
+/**
+ Return address map of exception handler template so that C code can generate
+ exception tables.
+
+ @param IdtEntry Pointer to IDT entry to be updated.
+ @param InterruptHandler IDT handler value.
+**/
+VOID
+ArchUpdateIdtEntry (
+ OUT IA32_IDT_GATE_DESCRIPTOR *IdtEntry,
+ IN UINTN InterruptHandler
+ )
+{
+ IdtEntry->Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
+ IdtEntry->Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
+ IdtEntry->Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32);
+ IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+}
+
+/**
+ Read IDT handler value from IDT entry.
+
+ @param IdtEntry Pointer to IDT entry to be read.
+
+**/
+UINTN
+ArchGetIdtHandler (
+ IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry
+ )
+{
+ return IdtEntry->Bits.OffsetLow + (((UINTN) IdtEntry->Bits.OffsetHigh) << 16) +
+ (((UINTN) IdtEntry->Bits.OffsetUpper) << 32);
+}
+
+/**
+ Save CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
+
+ @param[in] ExceptionType Exception type.
+ @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+ @param[in] ExceptionHandlerData Pointer to exception handler data.
+**/
+VOID
+ArchSaveExceptionContext (
+ IN UINTN ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData
+ )
+{
+ IA32_EFLAGS32 Eflags;
+ RESERVED_VECTORS_DATA *ReservedVectors;
+
+ ReservedVectors = ExceptionHandlerData->ReservedVectors;
+ //
+ // Save Exception context in global variable in first entry of the exception handler.
+ // So when original exception handler returns to the new exception handler (second entry),
+ // the Eflags/Cs/Eip/ExceptionData can be used.
+ //
+ ReservedVectors[ExceptionType].OldSs = SystemContext.SystemContextX64->Ss;
+ ReservedVectors[ExceptionType].OldSp = SystemContext.SystemContextX64->Rsp;
+ ReservedVectors[ExceptionType].OldFlags = SystemContext.SystemContextX64->Rflags;
+ ReservedVectors[ExceptionType].OldCs = SystemContext.SystemContextX64->Cs;
+ ReservedVectors[ExceptionType].OldIp = SystemContext.SystemContextX64->Rip;
+ ReservedVectors[ExceptionType].ExceptionData = SystemContext.SystemContextX64->ExceptionData;
+ //
+ // Clear IF flag to avoid old IDT handler enable interrupt by IRET
+ //
+ Eflags.UintN = SystemContext.SystemContextX64->Rflags;
+ Eflags.Bits.IF = 0;
+ SystemContext.SystemContextX64->Rflags = Eflags.UintN;
+ //
+ // Modify the EIP in stack, then old IDT handler will return to HookAfterStubBegin.
+ //
+ SystemContext.SystemContextX64->Rip = (UINTN) ReservedVectors[ExceptionType].HookAfterStubHeaderCode;
+}
+
+/**
+ Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
+
+ @param[in] ExceptionType Exception type.
+ @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+ @param[in] ExceptionHandlerData Pointer to exception handler data.
+**/
+VOID
+ArchRestoreExceptionContext (
+ IN UINTN ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData
+ )
+{
+ RESERVED_VECTORS_DATA *ReservedVectors;
+
+ ReservedVectors = ExceptionHandlerData->ReservedVectors;
+ SystemContext.SystemContextX64->Ss = ReservedVectors[ExceptionType].OldSs;
+ SystemContext.SystemContextX64->Rsp = ReservedVectors[ExceptionType].OldSp;
+ SystemContext.SystemContextX64->Rflags = ReservedVectors[ExceptionType].OldFlags;
+ SystemContext.SystemContextX64->Cs = ReservedVectors[ExceptionType].OldCs;
+ SystemContext.SystemContextX64->Rip = ReservedVectors[ExceptionType].OldIp;
+ SystemContext.SystemContextX64->ExceptionData = ReservedVectors[ExceptionType].ExceptionData;
+}
+
+/**
+ Setup separate stack for given exceptions.
+
+ @param[in] StackSwitchData Pointer to data required for setuping up
+ stack switch.
+
+ @retval EFI_SUCCESS The exceptions have been successfully
+ initialized with new stack.
+ @retval EFI_INVALID_PARAMETER StackSwitchData contains invalid content.
+
+**/
+EFI_STATUS
+ArchSetupExceptionStack (
+ IN CPU_EXCEPTION_INIT_DATA *StackSwitchData
+ )
+{
+ IA32_DESCRIPTOR Gdtr;
+ IA32_DESCRIPTOR Idtr;
+ IA32_IDT_GATE_DESCRIPTOR *IdtTable;
+ IA32_TSS_DESCRIPTOR *TssDesc;
+ IA32_TASK_STATE_SEGMENT *Tss;
+ UINTN StackTop;
+ UINTN Index;
+ UINTN Vector;
+ UINTN TssBase;
+ UINTN GdtSize;
+
+ if (StackSwitchData == NULL ||
+ StackSwitchData->Ia32.Revision != CPU_EXCEPTION_INIT_DATA_REV ||
+ StackSwitchData->X64.KnownGoodStackTop == 0 ||
+ StackSwitchData->X64.KnownGoodStackSize == 0 ||
+ StackSwitchData->X64.StackSwitchExceptions == NULL ||
+ StackSwitchData->X64.StackSwitchExceptionNumber == 0 ||
+ StackSwitchData->X64.StackSwitchExceptionNumber > CPU_EXCEPTION_NUM ||
+ StackSwitchData->X64.GdtTable == NULL ||
+ StackSwitchData->X64.IdtTable == NULL ||
+ StackSwitchData->X64.ExceptionTssDesc == NULL ||
+ StackSwitchData->X64.ExceptionTss == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // The caller is responsible for that the GDT table, no matter the existing
+ // one or newly allocated, has enough space to hold descriptors for exception
+ // task-state segments.
+ //
+ if (((UINTN)StackSwitchData->X64.GdtTable & (IA32_GDT_ALIGNMENT - 1)) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((UINTN)StackSwitchData->X64.ExceptionTssDesc < (UINTN)(StackSwitchData->X64.GdtTable)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((UINTN)StackSwitchData->X64.ExceptionTssDesc + StackSwitchData->X64.ExceptionTssDescSize) >
+ ((UINTN)(StackSwitchData->X64.GdtTable) + StackSwitchData->X64.GdtTableSize)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // One task gate descriptor and one task-state segment are needed.
+ //
+ if (StackSwitchData->X64.ExceptionTssDescSize < sizeof (IA32_TSS_DESCRIPTOR)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (StackSwitchData->X64.ExceptionTssSize < sizeof (IA32_TASK_STATE_SEGMENT)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Interrupt stack table supports only 7 vectors.
+ //
+ TssDesc = StackSwitchData->X64.ExceptionTssDesc;
+ Tss = StackSwitchData->X64.ExceptionTss;
+ if (StackSwitchData->X64.StackSwitchExceptionNumber > ARRAY_SIZE (Tss->IST)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Initialize new GDT table and/or IDT table, if any
+ //
+ AsmReadIdtr (&Idtr);
+ AsmReadGdtr (&Gdtr);
+
+ GdtSize = (UINTN)TssDesc + sizeof (IA32_TSS_DESCRIPTOR) -
+ (UINTN)(StackSwitchData->X64.GdtTable);
+ if ((UINTN)StackSwitchData->X64.GdtTable != Gdtr.Base) {
+ CopyMem (StackSwitchData->X64.GdtTable, (VOID *)Gdtr.Base, Gdtr.Limit + 1);
+ Gdtr.Base = (UINTN)StackSwitchData->X64.GdtTable;
+ Gdtr.Limit = (UINT16)GdtSize - 1;
+ }
+
+ if ((UINTN)StackSwitchData->X64.IdtTable != Idtr.Base) {
+ Idtr.Base = (UINTN)StackSwitchData->X64.IdtTable;
+ }
+ if (StackSwitchData->X64.IdtTableSize > 0) {
+ Idtr.Limit = (UINT16)(StackSwitchData->X64.IdtTableSize - 1);
+ }
+
+ //
+ // Fixup current task descriptor. Task-state segment for current task will
+ // be filled by processor during task switching.
+ //
+ TssBase = (UINTN)Tss;
+
+ TssDesc->Uint128.Uint64 = 0;
+ TssDesc->Uint128.Uint64_1= 0;
+ TssDesc->Bits.LimitLow = sizeof(IA32_TASK_STATE_SEGMENT) - 1;
+ TssDesc->Bits.BaseLow = (UINT16)TssBase;
+ TssDesc->Bits.BaseMidl = (UINT8)(TssBase >> 16);
+ TssDesc->Bits.Type = IA32_GDT_TYPE_TSS;
+ TssDesc->Bits.P = 1;
+ TssDesc->Bits.LimitHigh = 0;
+ TssDesc->Bits.BaseMidh = (UINT8)(TssBase >> 24);
+ TssDesc->Bits.BaseHigh = (UINT32)(TssBase >> 32);
+
+ //
+ // Fixup exception task descriptor and task-state segment
+ //
+ ZeroMem (Tss, sizeof (*Tss));
+ StackTop = StackSwitchData->X64.KnownGoodStackTop - CPU_STACK_ALIGNMENT;
+ StackTop = (UINTN)ALIGN_POINTER (StackTop, CPU_STACK_ALIGNMENT);
+ IdtTable = StackSwitchData->X64.IdtTable;
+ for (Index = 0; Index < StackSwitchData->X64.StackSwitchExceptionNumber; ++Index) {
+ //
+ // Fixup IST
+ //
+ Tss->IST[Index] = StackTop;
+ StackTop -= StackSwitchData->X64.KnownGoodStackSize;
+
+ //
+ // Set the IST field to enable corresponding IST
+ //
+ Vector = StackSwitchData->X64.StackSwitchExceptions[Index];
+ if (Vector >= CPU_EXCEPTION_NUM ||
+ Vector >= (Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR)) {
+ continue;
+ }
+ IdtTable[Vector].Bits.Reserved_0 = (UINT8)(Index + 1);
+ }
+
+ //
+ // Publish GDT
+ //
+ AsmWriteGdtr (&Gdtr);
+
+ //
+ // Load current task
+ //
+ AsmWriteTr ((UINT16)((UINTN)StackSwitchData->X64.ExceptionTssDesc - Gdtr.Base));
+
+ //
+ // Publish IDT
+ //
+ AsmWriteIdtr (&Idtr);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Display CPU information.
+
+ @param ExceptionType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+**/
+VOID
+EFIAPI
+DumpCpuContext (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ InternalPrintMessage (
+ "!!!! X64 Exception Type - %02x(%a) CPU Apic ID - %08x !!!!\n",
+ ExceptionType,
+ GetExceptionNameStr (ExceptionType),
+ GetApicId ()
+ );
+ if ((mErrorCodeFlag & (1 << ExceptionType)) != 0) {
+ InternalPrintMessage (
+ "ExceptionData - %016lx",
+ SystemContext.SystemContextX64->ExceptionData
+ );
+ if (ExceptionType == EXCEPT_IA32_PAGE_FAULT) {
+ InternalPrintMessage (
+ " I:%x R:%x U:%x W:%x P:%x PK:%x SS:%x SGX:%x",
+ (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_ID) != 0,
+ (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_RSVD) != 0,
+ (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_US) != 0,
+ (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_WR) != 0,
+ (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_P) != 0,
+ (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_PK) != 0,
+ (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_SS) != 0,
+ (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_SGX) != 0
+ );
+ }
+ InternalPrintMessage ("\n");
+ }
+ InternalPrintMessage (
+ "RIP - %016lx, CS - %016lx, RFLAGS - %016lx\n",
+ SystemContext.SystemContextX64->Rip,
+ SystemContext.SystemContextX64->Cs,
+ SystemContext.SystemContextX64->Rflags
+ );
+ InternalPrintMessage (
+ "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",
+ SystemContext.SystemContextX64->Rax,
+ SystemContext.SystemContextX64->Rcx,
+ SystemContext.SystemContextX64->Rdx
+ );
+ InternalPrintMessage (
+ "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",
+ SystemContext.SystemContextX64->Rbx,
+ SystemContext.SystemContextX64->Rsp,
+ SystemContext.SystemContextX64->Rbp
+ );
+ InternalPrintMessage (
+ "RSI - %016lx, RDI - %016lx\n",
+ SystemContext.SystemContextX64->Rsi,
+ SystemContext.SystemContextX64->Rdi
+ );
+ InternalPrintMessage (
+ "R8 - %016lx, R9 - %016lx, R10 - %016lx\n",
+ SystemContext.SystemContextX64->R8,
+ SystemContext.SystemContextX64->R9,
+ SystemContext.SystemContextX64->R10
+ );
+ InternalPrintMessage (
+ "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",
+ SystemContext.SystemContextX64->R11,
+ SystemContext.SystemContextX64->R12,
+ SystemContext.SystemContextX64->R13
+ );
+ InternalPrintMessage (
+ "R14 - %016lx, R15 - %016lx\n",
+ SystemContext.SystemContextX64->R14,
+ SystemContext.SystemContextX64->R15
+ );
+ InternalPrintMessage (
+ "DS - %016lx, ES - %016lx, FS - %016lx\n",
+ SystemContext.SystemContextX64->Ds,
+ SystemContext.SystemContextX64->Es,
+ SystemContext.SystemContextX64->Fs
+ );
+ InternalPrintMessage (
+ "GS - %016lx, SS - %016lx\n",
+ SystemContext.SystemContextX64->Gs,
+ SystemContext.SystemContextX64->Ss
+ );
+ InternalPrintMessage (
+ "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",
+ SystemContext.SystemContextX64->Cr0,
+ SystemContext.SystemContextX64->Cr2,
+ SystemContext.SystemContextX64->Cr3
+ );
+ InternalPrintMessage (
+ "CR4 - %016lx, CR8 - %016lx\n",
+ SystemContext.SystemContextX64->Cr4,
+ SystemContext.SystemContextX64->Cr8
+ );
+ InternalPrintMessage (
+ "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",
+ SystemContext.SystemContextX64->Dr0,
+ SystemContext.SystemContextX64->Dr1,
+ SystemContext.SystemContextX64->Dr2
+ );
+ InternalPrintMessage (
+ "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",
+ SystemContext.SystemContextX64->Dr3,
+ SystemContext.SystemContextX64->Dr6,
+ SystemContext.SystemContextX64->Dr7
+ );
+ InternalPrintMessage (
+ "GDTR - %016lx %016lx, LDTR - %016lx\n",
+ SystemContext.SystemContextX64->Gdtr[0],
+ SystemContext.SystemContextX64->Gdtr[1],
+ SystemContext.SystemContextX64->Ldtr
+ );
+ InternalPrintMessage (
+ "IDTR - %016lx %016lx, TR - %016lx\n",
+ SystemContext.SystemContextX64->Idtr[0],
+ SystemContext.SystemContextX64->Idtr[1],
+ SystemContext.SystemContextX64->Tr
+ );
+ InternalPrintMessage (
+ "FXSAVE_STATE - %016lx\n",
+ &SystemContext.SystemContextX64->FxSaveState
+ );
+}
+
+/**
+ Display CPU information.
+
+ @param ExceptionType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+**/
+VOID
+DumpImageAndCpuContent (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ DumpCpuContext (ExceptionType, SystemContext);
+ //
+ // Dump module image base and module entry point by RIP
+ //
+ if ((ExceptionType == EXCEPT_IA32_PAGE_FAULT) &&
+ ((SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_ID) != 0)) {
+ //
+ // The RIP in SystemContext could not be used
+ // if it is page fault with I/D set.
+ //
+ DumpModuleImageInfo ((*(UINTN *)(UINTN)SystemContext.SystemContextX64->Rsp));
+ } else {
+ DumpModuleImageInfo (SystemContext.SystemContextX64->Rip);
+ }
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h
new file mode 100644
index 00000000..97271c04
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h
@@ -0,0 +1,43 @@
+/** @file
+ X64 arch definition for CPU Exception Handler Library.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _ARCH_CPU_INTERRUPT_DEFS_H_
+#define _ARCH_CPU_INTERRUPT_DEFS_H_
+
+typedef struct {
+ EFI_SYSTEM_CONTEXT_X64 SystemContext;
+ BOOLEAN ExceptionDataFlag;
+ UINTN OldIdtHandler;
+} EXCEPTION_HANDLER_CONTEXT;
+
+//
+// Register Structure Definitions
+//
+typedef struct {
+ EFI_STATUS_CODE_DATA Header;
+ EFI_SYSTEM_CONTEXT_X64 SystemContext;
+} CPU_STATUS_CODE_TEMPLATE;
+
+typedef struct {
+ SPIN_LOCK SpinLock;
+ UINT32 ApicId;
+ UINT32 Attribute;
+ UINTN ExceptonHandler;
+ UINTN OldSs;
+ UINTN OldSp;
+ UINTN OldFlags;
+ UINTN OldCs;
+ UINTN OldIp;
+ UINTN ExceptionData;
+ UINT8 HookAfterStubHeaderCode[HOOKAFTER_STUB_SIZE];
+} RESERVED_VECTORS_DATA;
+
+#define CPU_TSS_DESC_SIZE sizeof (IA32_TSS_DESCRIPTOR)
+#define CPU_TSS_SIZE sizeof (IA32_TASK_STATE_SEGMENT)
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm
new file mode 100644
index 00000000..1f112909
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm
@@ -0,0 +1,400 @@
+;------------------------------------------------------------------------------ ;
+; Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; ExceptionHandlerAsm.Asm
+;
+; Abstract:
+;
+; x64 CPU Exception Handler
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+;
+; CommonExceptionHandler()
+;
+
+%define VC_EXCEPTION 29
+
+extern ASM_PFX(mErrorCodeFlag) ; Error code flags for exceptions
+extern ASM_PFX(mDoFarReturnFlag) ; Do far return flag
+extern ASM_PFX(CommonExceptionHandler)
+
+SECTION .data
+
+DEFAULT REL
+SECTION .text
+
+ALIGN 8
+
+AsmIdtVectorBegin:
+%rep 32
+ db 0x6a ; push #VectorNum
+ db ($ - AsmIdtVectorBegin) / ((AsmIdtVectorEnd - AsmIdtVectorBegin) / 32) ; VectorNum
+ push rax
+ mov rax, ASM_PFX(CommonInterruptEntry)
+ jmp rax
+%endrep
+AsmIdtVectorEnd:
+
+HookAfterStubHeaderBegin:
+ db 0x6a ; push
+@VectorNum:
+ db 0 ; 0 will be fixed
+ push rax
+ mov rax, HookAfterStubHeaderEnd
+ jmp rax
+HookAfterStubHeaderEnd:
+ mov rax, rsp
+ and sp, 0xfff0 ; make sure 16-byte aligned for exception context
+ sub rsp, 0x18 ; reserve room for filling exception data later
+ push rcx
+ mov rcx, [rax + 8]
+ bt [ASM_PFX(mErrorCodeFlag)], ecx
+ jnc .0
+ push qword [rsp] ; push additional rcx to make stack alignment
+.0:
+ xchg rcx, [rsp] ; restore rcx, save Exception Number in stack
+ push qword [rax] ; push rax into stack to keep code consistence
+
+;---------------------------------------;
+; CommonInterruptEntry ;
+;---------------------------------------;
+; The follow algorithm is used for the common interrupt routine.
+; Entry from each interrupt with a push eax and eax=interrupt number
+; Stack frame would be as follows as specified in IA32 manuals:
+;
+; +---------------------+ <-- 16-byte aligned ensured by processor
+; + Old SS +
+; +---------------------+
+; + Old RSP +
+; +---------------------+
+; + RFlags +
+; +---------------------+
+; + CS +
+; +---------------------+
+; + RIP +
+; +---------------------+
+; + Error Code +
+; +---------------------+
+; + Vector Number +
+; +---------------------+
+; + RBP +
+; +---------------------+ <-- RBP, 16-byte aligned
+; The follow algorithm is used for the common interrupt routine.
+global ASM_PFX(CommonInterruptEntry)
+ASM_PFX(CommonInterruptEntry):
+ cli
+ pop rax
+ ;
+ ; All interrupt handlers are invoked through interrupt gates, so
+ ; IF flag automatically cleared at the entry point
+ ;
+ xchg rcx, [rsp] ; Save rcx into stack and save vector number into rcx
+ and rcx, 0xFF
+ cmp ecx, 32 ; Intel reserved vector for exceptions?
+ jae NoErrorCode
+ bt [ASM_PFX(mErrorCodeFlag)], ecx
+ jc HasErrorCode
+
+NoErrorCode:
+
+ ;
+ ; Push a dummy error code on the stack
+ ; to maintain coherent stack map
+ ;
+ push qword [rsp]
+ mov qword [rsp + 8], 0
+HasErrorCode:
+ push rbp
+ mov rbp, rsp
+ push 0 ; clear EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
+ push 0 ; clear EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
+
+ ;
+ ; 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 [rbp + 8] ; RCX
+ push rdx
+ push rbx
+ push qword [rbp + 48] ; RSP
+ push qword [rbp] ; RBP
+ push rsi
+ push rdi
+
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
+ movzx rax, word [rbp + 56]
+ push rax ; for ss
+ movzx rax, word [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 [rbp + 24]
+
+;; UINT64 Gdtr[2], Idtr[2];
+ xor rax, rax
+ push rax
+ push rax
+ sidt [rsp]
+ mov bx, word [rsp]
+ mov rax, qword [rsp + 2]
+ mov qword [rsp], rax
+ mov word [rsp + 8], bx
+
+ xor rax, rax
+ push rax
+ push rax
+ sgdt [rsp]
+ mov bx, word [rsp]
+ mov rax, qword [rsp + 2]
+ mov qword [rsp], rax
+ mov word [rsp + 8], bx
+
+;; UINT64 Ldtr, Tr;
+ xor rax, rax
+ str ax
+ push rax
+ sldt ax
+ push rax
+
+;; UINT64 RFlags;
+ push qword [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;
+ cmp qword [rbp + 8], VC_EXCEPTION
+ je VcDebugRegs ; For SEV-ES (#VC) Debug registers ignored
+
+ mov rax, dr7
+ push rax
+ mov rax, dr6
+ push rax
+ mov rax, dr3
+ push rax
+ mov rax, dr2
+ push rax
+ mov rax, dr1
+ push rax
+ mov rax, dr0
+ push rax
+ jmp DrFinish
+
+VcDebugRegs:
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7 are skipped for #VC to avoid exception recursion
+ xor rax, rax
+ push rax
+ push rax
+ push rax
+ push rax
+ push rax
+ push rax
+
+DrFinish:
+;; FX_SAVE_STATE_X64 FxSaveState;
+ sub rsp, 512
+ mov rdi, rsp
+ db 0xf, 0xae, 0x7 ;fxsave [rdi]
+
+;; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
+ cld
+
+;; UINT32 ExceptionData;
+ push qword [rbp + 16]
+
+;; 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
+ mov rax, ASM_PFX(CommonExceptionHandler)
+ call rax
+ add rsp, 4 * 8 + 8
+
+ cli
+;; UINT64 ExceptionData;
+ add rsp, 8
+
+;; FX_SAVE_STATE_X64 FxSaveState;
+
+ mov rsi, rsp
+ db 0xf, 0xae, 0xE ; fxrstor [rsi]
+ add rsp, 512
+
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+;; Skip restoration of DRx registers to support in-circuit emualators
+;; or debuggers set breakpoint in interrupt/exception context
+ add rsp, 8 * 6
+
+;; 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 [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 [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 [rbp + 32] ; for cs
+ pop qword [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 [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
+ cmp qword [rsp - 32], 0 ; check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
+ jz DoReturn
+ cmp qword [rsp - 40], 1 ; check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
+ jz ErrorCode
+ jmp qword [rsp - 32]
+ErrorCode:
+ sub rsp, 8
+ jmp qword [rsp - 24]
+
+DoReturn:
+ cmp qword [ASM_PFX(mDoFarReturnFlag)], 0 ; Check if need to do far return instead of IRET
+ jz DoIret
+ push rax
+ mov rax, rsp ; save old RSP to rax
+ mov rsp, [rsp + 0x20]
+ push qword [rax + 0x10] ; save CS in new location
+ push qword [rax + 0x8] ; save EIP in new location
+ push qword [rax + 0x18] ; save EFLAGS in new location
+ mov rax, [rax] ; restore rax
+ popfq ; restore EFLAGS
+ DB 0x48 ; prefix to composite "retq" with next "retf"
+ retf ; far return
+DoIret:
+ iretq
+
+;-------------------------------------------------------------------------------------
+; GetTemplateAddressMap (&AddressMap);
+;-------------------------------------------------------------------------------------
+; comments here for definition of address map
+global ASM_PFX(AsmGetTemplateAddressMap)
+ASM_PFX(AsmGetTemplateAddressMap):
+ mov rax, AsmIdtVectorBegin
+ mov qword [rcx], rax
+ mov qword [rcx + 0x8], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32
+ mov rax, HookAfterStubHeaderBegin
+ mov qword [rcx + 0x10], rax
+ ret
+
+;-------------------------------------------------------------------------------------
+; AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr);
+;-------------------------------------------------------------------------------------
+global ASM_PFX(AsmVectorNumFixup)
+ASM_PFX(AsmVectorNumFixup):
+ mov rax, rdx
+ mov [rcx + (@VectorNum - HookAfterStubHeaderBegin)], al
+ ret
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/Xcode5ExceptionHandlerAsm.nasm b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/Xcode5ExceptionHandlerAsm.nasm
new file mode 100644
index 00000000..a8edfc01
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/Xcode5ExceptionHandlerAsm.nasm
@@ -0,0 +1,455 @@
+;------------------------------------------------------------------------------ ;
+; Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; ExceptionHandlerAsm.Asm
+;
+; Abstract:
+;
+; x64 CPU Exception Handler
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+%include "Nasm.inc"
+
+;
+; CommonExceptionHandler()
+;
+
+%define VC_EXCEPTION 29
+
+extern ASM_PFX(mErrorCodeFlag) ; Error code flags for exceptions
+extern ASM_PFX(mDoFarReturnFlag) ; Do far return flag
+extern ASM_PFX(CommonExceptionHandler)
+extern ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
+
+SECTION .data
+
+DEFAULT REL
+SECTION .text
+
+ALIGN 8
+
+AsmIdtVectorBegin:
+%rep 32
+ db 0x6a ; push #VectorNum
+ db ($ - AsmIdtVectorBegin) / ((AsmIdtVectorEnd - AsmIdtVectorBegin) / 32) ; VectorNum
+ push rax
+ mov rax, strict qword 0 ; mov rax, ASM_PFX(CommonInterruptEntry)
+ jmp rax
+%endrep
+AsmIdtVectorEnd:
+
+HookAfterStubHeaderBegin:
+ db 0x6a ; push
+@VectorNum:
+ db 0 ; 0 will be fixed
+ push rax
+ mov rax, strict qword 0 ; mov rax, HookAfterStubHeaderEnd
+JmpAbsoluteAddress:
+ jmp rax
+HookAfterStubHeaderEnd:
+ mov rax, rsp
+ and sp, 0xfff0 ; make sure 16-byte aligned for exception context
+ sub rsp, 0x18 ; reserve room for filling exception data later
+ push rcx
+ mov rcx, [rax + 8]
+ bt [ASM_PFX(mErrorCodeFlag)], ecx
+ jnc .0
+ push qword [rsp] ; push additional rcx to make stack alignment
+.0:
+ xchg rcx, [rsp] ; restore rcx, save Exception Number in stack
+ push qword [rax] ; push rax into stack to keep code consistence
+
+;---------------------------------------;
+; CommonInterruptEntry ;
+;---------------------------------------;
+; The follow algorithm is used for the common interrupt routine.
+; Entry from each interrupt with a push eax and eax=interrupt number
+; Stack frame would be as follows as specified in IA32 manuals:
+;
+; +---------------------+ <-- 16-byte aligned ensured by processor
+; + Old SS +
+; +---------------------+
+; + Old RSP +
+; +---------------------+
+; + RFlags +
+; +---------------------+
+; + CS +
+; +---------------------+
+; + RIP +
+; +---------------------+
+; + Error Code +
+; +---------------------+
+; + Vector Number +
+; +---------------------+
+; + RBP +
+; +---------------------+ <-- RBP, 16-byte aligned
+; The follow algorithm is used for the common interrupt routine.
+global ASM_PFX(CommonInterruptEntry)
+ASM_PFX(CommonInterruptEntry):
+ cli
+ pop rax
+ ;
+ ; All interrupt handlers are invoked through interrupt gates, so
+ ; IF flag automatically cleared at the entry point
+ ;
+ xchg rcx, [rsp] ; Save rcx into stack and save vector number into rcx
+ and rcx, 0xFF
+ cmp ecx, 32 ; Intel reserved vector for exceptions?
+ jae NoErrorCode
+ bt [ASM_PFX(mErrorCodeFlag)], ecx
+ jc HasErrorCode
+
+NoErrorCode:
+
+ ;
+ ; Push a dummy error code on the stack
+ ; to maintain coherent stack map
+ ;
+ push qword [rsp]
+ mov qword [rsp + 8], 0
+HasErrorCode:
+ push rbp
+ mov rbp, rsp
+ push 0 ; clear EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
+ push 0 ; clear EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
+
+ ;
+ ; 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 [rbp + 8] ; RCX
+ push rdx
+ push rbx
+ push qword [rbp + 48] ; RSP
+ push qword [rbp] ; RBP
+ push rsi
+ push rdi
+
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
+ movzx rax, word [rbp + 56]
+ push rax ; for ss
+ movzx rax, word [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 [rbp + 24]
+
+;; UINT64 Gdtr[2], Idtr[2];
+ xor rax, rax
+ push rax
+ push rax
+ sidt [rsp]
+ mov bx, word [rsp]
+ mov rax, qword [rsp + 2]
+ mov qword [rsp], rax
+ mov word [rsp + 8], bx
+
+ xor rax, rax
+ push rax
+ push rax
+ sgdt [rsp]
+ mov bx, word [rsp]
+ mov rax, qword [rsp + 2]
+ mov qword [rsp], rax
+ mov word [rsp + 8], bx
+
+;; UINT64 Ldtr, Tr;
+ xor rax, rax
+ str ax
+ push rax
+ sldt ax
+ push rax
+
+;; UINT64 RFlags;
+ push qword [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;
+ cmp qword [rbp + 8], VC_EXCEPTION
+ je VcDebugRegs ; For SEV-ES (#VC) Debug registers ignored
+
+ mov rax, dr7
+ push rax
+ mov rax, dr6
+ push rax
+ mov rax, dr3
+ push rax
+ mov rax, dr2
+ push rax
+ mov rax, dr1
+ push rax
+ mov rax, dr0
+ push rax
+ jmp DrFinish
+
+VcDebugRegs:
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7 are skipped for #VC to avoid exception recursion
+ xor rax, rax
+ push rax
+ push rax
+ push rax
+ push rax
+ push rax
+ push rax
+
+DrFinish:
+;; FX_SAVE_STATE_X64 FxSaveState;
+ sub rsp, 512
+ mov rdi, rsp
+ db 0xf, 0xae, 0x7 ;fxsave [rdi]
+
+;; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
+ cld
+
+;; UINT32 ExceptionData;
+ push qword [rbp + 16]
+
+;; 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 ASM_PFX(CommonExceptionHandler)
+ add rsp, 4 * 8 + 8
+
+ cli
+;; UINT64 ExceptionData;
+ add rsp, 8
+
+;; FX_SAVE_STATE_X64 FxSaveState;
+
+ mov rsi, rsp
+ db 0xf, 0xae, 0xE ; fxrstor [rsi]
+ add rsp, 512
+
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+;; Skip restoration of DRx registers to support in-circuit emualators
+;; or debuggers set breakpoint in interrupt/exception context
+ add rsp, 8 * 6
+
+;; 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 [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 [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 [rbp + 32] ; for cs
+ pop qword [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 [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
+ cmp qword [rsp - 32], 0 ; check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
+ jz DoReturn
+ cmp qword [rsp - 40], 1 ; check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
+ jz ErrorCode
+ jmp qword [rsp - 32]
+ErrorCode:
+ sub rsp, 8
+ jmp qword [rsp - 24]
+
+DoReturn:
+ cmp qword [ASM_PFX(mDoFarReturnFlag)], 0 ; Check if need to do far return instead of IRET
+ jz DoIret
+ push rax
+ mov rax, rsp ; save old RSP to rax
+ mov rsp, [rsp + 0x20]
+ push qword [rax + 0x10] ; save CS in new location
+ push qword [rax + 0x8] ; save EIP in new location
+ push qword [rax + 0x18] ; save EFLAGS in new location
+ mov rax, [rax] ; restore rax
+ popfq ; restore EFLAGS
+
+ ; The follow algorithm is used for clear shadow stack token busy bit.
+ ; The comment is based on the sample shadow stack.
+ ; The sample shadow stack layout :
+ ; Address | Context
+ ; +-------------------------+
+ ; 0xFD0 | FREE | it is 0xFD8|0x02|(LMA & CS.L), after SAVEPREVSSP.
+ ; +-------------------------+
+ ; 0xFD8 | Prev SSP |
+ ; +-------------------------+
+ ; 0xFE0 | RIP |
+ ; +-------------------------+
+ ; 0xFE8 | CS |
+ ; +-------------------------+
+ ; 0xFF0 | 0xFF0 | BUSY | BUSY flag cleared after CLRSSBSY
+ ; +-------------------------+
+ ; 0xFF8 | 0xFD8|0x02|(LMA & CS.L) |
+ ; +-------------------------+
+ ; Instructions for Intel Control Flow Enforcement Technology (CET) are supported since NASM version 2.15.01.
+ push rax ; SSP should be 0xFD8 at this point
+ cmp byte [dword ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))], 0
+ jz CetDone
+ mov rax, cr4
+ and rax, 0x800000 ; check if CET is enabled
+ jz CetDone
+ mov rax, 0x04 ; advance past cs:lip:prevssp;supervisor shadow stack token
+ INCSSP_RAX ; After this SSP should be 0xFF8
+ SAVEPREVSSP ; now the shadow stack restore token will be created at 0xFD0
+ READSSP_RAX ; Read new SSP, SSP should be 0x1000
+ push rax
+ sub rax, 0x10
+ CLRSSBSY_RAX ; Clear token at 0xFF0, SSP should be 0 after this
+ sub rax, 0x20
+ RSTORSSP_RAX ; Restore to token at 0xFD0, new SSP will be 0xFD0
+ pop rax
+ mov rax, 0x01 ; Pop off the new save token created
+ INCSSP_RAX ; SSP should be 0xFD8 now
+CetDone:
+ pop rax ; restore rax
+
+ DB 0x48 ; prefix to composite "retq" with next "retf"
+ retf ; far return
+DoIret:
+ iretq
+
+;-------------------------------------------------------------------------------------
+; GetTemplateAddressMap (&AddressMap);
+;-------------------------------------------------------------------------------------
+; comments here for definition of address map
+global ASM_PFX(AsmGetTemplateAddressMap)
+ASM_PFX(AsmGetTemplateAddressMap):
+ lea rax, [AsmIdtVectorBegin]
+ mov qword [rcx], rax
+ mov qword [rcx + 0x8], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32
+ lea rax, [HookAfterStubHeaderBegin]
+ mov qword [rcx + 0x10], rax
+
+; Fix up CommonInterruptEntry address
+ lea rax, [ASM_PFX(CommonInterruptEntry)]
+ lea rcx, [AsmIdtVectorBegin]
+%rep 32
+ mov qword [rcx + (JmpAbsoluteAddress - 8 - HookAfterStubHeaderBegin)], rax
+ add rcx, (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32
+%endrep
+; Fix up HookAfterStubHeaderEnd
+ lea rax, [HookAfterStubHeaderEnd]
+ lea rcx, [JmpAbsoluteAddress]
+ mov qword [rcx - 8], rax
+
+ ret
+
+;-------------------------------------------------------------------------------------
+; AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr);
+;-------------------------------------------------------------------------------------
+global ASM_PFX(AsmVectorNumFixup)
+ASM_PFX(AsmVectorNumFixup):
+ mov rax, rdx
+ mov [rcx + (@VectorNum - HookAfterStubHeaderBegin)], al
+ ret
+