UncachedMemoryAllocationLib|ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf\r
DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf\r
DefaultExceptionHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf\r
+ CpuExceptionHandlerLib|ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf\r
\r
CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf\r
ArmGicLib|ArmPkg/Drivers/ArmGic/ArmGicLib.inf\r
ArmPkg/Library/SemihostLib/SemihostLib.inf\r
ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf\r
ArmPkg/Library/ArmPsciResetSystemLib/ArmPsciResetSystemLib.inf\r
+ ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf\r
+ ArmPkg/Library/ArmExceptionLib/ArmRelocateExceptionLib.inf\r
\r
ArmPkg/Drivers/CpuDxe/CpuDxe.inf\r
ArmPkg/Drivers/CpuPei/CpuPei.inf\r
--- /dev/null
+/** @file\r
+* Exception Handling support specific for AArch64\r
+*\r
+* Copyright (c) 2016 HP Development Company, L.P.\r
+*\r
+* 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
+**/\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Chipset/AArch64.h>\r
+\r
+#include <Protocol/DebugSupport.h> // for MAX_AARCH64_EXCEPTION\r
+\r
+UINTN gMaxExceptionNumber = MAX_AARCH64_EXCEPTION;\r
+EFI_EXCEPTION_CALLBACK gExceptionHandlers[MAX_AARCH64_EXCEPTION + 1] = { 0 };\r
+EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[MAX_AARCH64_EXCEPTION + 1] = { 0 };\r
+PHYSICAL_ADDRESS gExceptionVectorAlignmentMask = ARM_VECTOR_TABLE_ALIGNMENT;\r
+UINTN gDebuggerNoHandlerValue = 0; // todo: define for AArch64\r
+\r
+RETURN_STATUS ArchVectorConfig(\r
+ IN UINTN VectorBaseAddress\r
+ )\r
+{\r
+ UINTN HcrReg;\r
+\r
+ if (ArmReadCurrentEL() == AARCH64_EL2) {\r
+ HcrReg = ArmReadHcr();\r
+\r
+ // Trap General Exceptions. All exceptions that would be routed to EL1 are routed to EL2\r
+ HcrReg |= ARM_HCR_TGE;\r
+\r
+ ArmWriteHcr(HcrReg);\r
+ }\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
--- /dev/null
+//\r
+// Copyright (c) 2011 - 2014 ARM LTD. All rights reserved.<BR>\r
+// Portion of Copyright (c) 2014 NVIDIA Corporation. All rights reserved.<BR>\r
+// Copyright (c) 2016 HP Development Company, L.P.\r
+//\r
+// 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
+//------------------------------------------------------------------------------\r
+\r
+#include <Chipset/AArch64.h>\r
+#include <Library/PcdLib.h>\r
+#include <AsmMacroIoLibV8.h>\r
+#include <Protocol/DebugSupport.h> // for exception type definitions\r
+\r
+/*\r
+ This is the stack constructed by the exception handler (low address to high address).\r
+ X0 to FAR makes up the EFI_SYSTEM_CONTEXT for AArch64.\r
+\r
+ UINT64 X0; 0x000\r
+ UINT64 X1; 0x008\r
+ UINT64 X2; 0x010\r
+ UINT64 X3; 0x018\r
+ UINT64 X4; 0x020\r
+ UINT64 X5; 0x028\r
+ UINT64 X6; 0x030\r
+ UINT64 X7; 0x038\r
+ UINT64 X8; 0x040\r
+ UINT64 X9; 0x048\r
+ UINT64 X10; 0x050\r
+ UINT64 X11; 0x058\r
+ UINT64 X12; 0x060\r
+ UINT64 X13; 0x068\r
+ UINT64 X14; 0x070\r
+ UINT64 X15; 0x078\r
+ UINT64 X16; 0x080\r
+ UINT64 X17; 0x088\r
+ UINT64 X18; 0x090\r
+ UINT64 X19; 0x098\r
+ UINT64 X20; 0x0a0\r
+ UINT64 X21; 0x0a8\r
+ UINT64 X22; 0x0b0\r
+ UINT64 X23; 0x0b8\r
+ UINT64 X24; 0x0c0\r
+ UINT64 X25; 0x0c8\r
+ UINT64 X26; 0x0d0\r
+ UINT64 X27; 0x0d8\r
+ UINT64 X28; 0x0e0\r
+ UINT64 FP; 0x0e8 // x29 - Frame Pointer\r
+ UINT64 LR; 0x0f0 // x30 - Link Register\r
+ UINT64 SP; 0x0f8 // x31 - Stack Pointer\r
+\r
+ // FP/SIMD Registers. 128bit if used as Q-regs.\r
+ UINT64 V0[2]; 0x100\r
+ UINT64 V1[2]; 0x110\r
+ UINT64 V2[2]; 0x120\r
+ UINT64 V3[2]; 0x130\r
+ UINT64 V4[2]; 0x140\r
+ UINT64 V5[2]; 0x150\r
+ UINT64 V6[2]; 0x160\r
+ UINT64 V7[2]; 0x170\r
+ UINT64 V8[2]; 0x180\r
+ UINT64 V9[2]; 0x190\r
+ UINT64 V10[2]; 0x1a0\r
+ UINT64 V11[2]; 0x1b0\r
+ UINT64 V12[2]; 0x1c0\r
+ UINT64 V13[2]; 0x1d0\r
+ UINT64 V14[2]; 0x1e0\r
+ UINT64 V15[2]; 0x1f0\r
+ UINT64 V16[2]; 0x200\r
+ UINT64 V17[2]; 0x210\r
+ UINT64 V18[2]; 0x220\r
+ UINT64 V19[2]; 0x230\r
+ UINT64 V20[2]; 0x240\r
+ UINT64 V21[2]; 0x250\r
+ UINT64 V22[2]; 0x260\r
+ UINT64 V23[2]; 0x270\r
+ UINT64 V24[2]; 0x280\r
+ UINT64 V25[2]; 0x290\r
+ UINT64 V26[2]; 0x2a0\r
+ UINT64 V27[2]; 0x2b0\r
+ UINT64 V28[2]; 0x2c0\r
+ UINT64 V29[2]; 0x2d0\r
+ UINT64 V30[2]; 0x2e0\r
+ UINT64 V31[2]; 0x2f0\r
+\r
+ // System Context\r
+ UINT64 ELR; 0x300 // Exception Link Register\r
+ UINT64 SPSR; 0x308 // Saved Processor Status Register\r
+ UINT64 FPSR; 0x310 // Floating Point Status Register\r
+ UINT64 ESR; 0x318 // Exception syndrome register\r
+ UINT64 FAR; 0x320 // Fault Address Register\r
+ UINT64 Padding;0x328 // Required for stack alignment\r
+*/\r
+\r
+GCC_ASM_EXPORT(ExceptionHandlersEnd)\r
+GCC_ASM_EXPORT(CommonExceptionEntry)\r
+GCC_ASM_EXPORT(AsmCommonExceptionEntry)\r
+GCC_ASM_EXPORT(CommonCExceptionHandler)\r
+\r
+.text\r
+\r
+#define GP_CONTEXT_SIZE (32 * 8)\r
+#define FP_CONTEXT_SIZE (32 * 16)\r
+#define SYS_CONTEXT_SIZE ( 6 * 8) // 5 SYS regs + Alignment requirement (ie: the stack must be aligned on 0x10)\r
+\r
+// Cannot str x31 directly\r
+#define ALL_GP_REGS \\r
+ REG_PAIR (x0, x1, 0x000, GP_CONTEXT_SIZE); \\r
+ REG_PAIR (x2, x3, 0x010, GP_CONTEXT_SIZE); \\r
+ REG_PAIR (x4, x5, 0x020, GP_CONTEXT_SIZE); \\r
+ REG_PAIR (x6, x7, 0x030, GP_CONTEXT_SIZE); \\r
+ REG_PAIR (x8, x9, 0x040, GP_CONTEXT_SIZE); \\r
+ REG_PAIR (x10, x11, 0x050, GP_CONTEXT_SIZE); \\r
+ REG_PAIR (x12, x13, 0x060, GP_CONTEXT_SIZE); \\r
+ REG_PAIR (x14, x15, 0x070, GP_CONTEXT_SIZE); \\r
+ REG_PAIR (x16, x17, 0x080, GP_CONTEXT_SIZE); \\r
+ REG_PAIR (x18, x19, 0x090, GP_CONTEXT_SIZE); \\r
+ REG_PAIR (x20, x21, 0x0a0, GP_CONTEXT_SIZE); \\r
+ REG_PAIR (x22, x23, 0x0b0, GP_CONTEXT_SIZE); \\r
+ REG_PAIR (x24, x25, 0x0c0, GP_CONTEXT_SIZE); \\r
+ REG_PAIR (x26, x27, 0x0d0, GP_CONTEXT_SIZE); \\r
+ REG_PAIR (x28, x29, 0x0e0, GP_CONTEXT_SIZE); \\r
+ REG_ONE (x30, 0x0f0, GP_CONTEXT_SIZE);\r
+\r
+// In order to save the SP we need to put it somewhere else first.\r
+// STR only works with XZR/WZR directly\r
+#define SAVE_SP \\r
+ add x1, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE); \\r
+ REG_ONE (x1, 0x0f8, GP_CONTEXT_SIZE);\r
+\r
+#define ALL_FP_REGS \\r
+ REG_PAIR (q0, q1, 0x000, FP_CONTEXT_SIZE); \\r
+ REG_PAIR (q2, q3, 0x020, FP_CONTEXT_SIZE); \\r
+ REG_PAIR (q4, q5, 0x040, FP_CONTEXT_SIZE); \\r
+ REG_PAIR (q6, q7, 0x060, FP_CONTEXT_SIZE); \\r
+ REG_PAIR (q8, q9, 0x080, FP_CONTEXT_SIZE); \\r
+ REG_PAIR (q10, q11, 0x0a0, FP_CONTEXT_SIZE); \\r
+ REG_PAIR (q12, q13, 0x0c0, FP_CONTEXT_SIZE); \\r
+ REG_PAIR (q14, q15, 0x0e0, FP_CONTEXT_SIZE); \\r
+ REG_PAIR (q16, q17, 0x100, FP_CONTEXT_SIZE); \\r
+ REG_PAIR (q18, q19, 0x120, FP_CONTEXT_SIZE); \\r
+ REG_PAIR (q20, q21, 0x140, FP_CONTEXT_SIZE); \\r
+ REG_PAIR (q22, q23, 0x160, FP_CONTEXT_SIZE); \\r
+ REG_PAIR (q24, q25, 0x180, FP_CONTEXT_SIZE); \\r
+ REG_PAIR (q26, q27, 0x1a0, FP_CONTEXT_SIZE); \\r
+ REG_PAIR (q28, q29, 0x1c0, FP_CONTEXT_SIZE); \\r
+ REG_PAIR (q30, q31, 0x1e0, FP_CONTEXT_SIZE);\r
+\r
+#define ALL_SYS_REGS \\r
+ REG_PAIR (x1, x2, 0x000, SYS_CONTEXT_SIZE); \\r
+ REG_PAIR (x3, x4, 0x010, SYS_CONTEXT_SIZE); \\r
+ REG_ONE (x5, 0x020, SYS_CONTEXT_SIZE);\r
+\r
+//\r
+// There are two methods for installing AArch64 exception vectors:\r
+// 1. Install a copy of the vectors to a location specified by a PCD\r
+// 2. Write VBAR directly, requiring that vectors have proper alignment (2K)\r
+// The conditional below adjusts the alignment requirement based on which\r
+// exception vector initialization method is used.\r
+//\r
+\r
+#if defined(ARM_RELOCATE_VECTORS)\r
+GCC_ASM_EXPORT(ExceptionHandlersStart)\r
+ASM_PFX(ExceptionHandlersStart):\r
+#else\r
+VECTOR_BASE(ExceptionHandlersStart)\r
+#endif\r
+\r
+//\r
+// Current EL with SP0 : 0x0 - 0x180\r
+//\r
+VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_SYNC)\r
+ASM_PFX(SynchronousExceptionSP0):\r
+ b ASM_PFX(SynchronousExceptionEntry)\r
+\r
+VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_IRQ)\r
+ASM_PFX(IrqSP0):\r
+ b ASM_PFX(IrqEntry)\r
+\r
+VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_FIQ)\r
+ASM_PFX(FiqSP0):\r
+ b ASM_PFX(FiqEntry)\r
+\r
+VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_SERR)\r
+ASM_PFX(SErrorSP0):\r
+ b ASM_PFX(SErrorEntry)\r
+\r
+//\r
+// Current EL with SPx: 0x200 - 0x380\r
+//\r
+VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPx_SYNC)\r
+ASM_PFX(SynchronousExceptionSPx):\r
+ b ASM_PFX(SynchronousExceptionEntry)\r
+\r
+VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPx_IRQ)\r
+ASM_PFX(IrqSPx):\r
+ b ASM_PFX(IrqEntry)\r
+\r
+VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPx_FIQ)\r
+ASM_PFX(FiqSPx):\r
+ b ASM_PFX(FiqEntry)\r
+\r
+VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPx_SERR)\r
+ASM_PFX(SErrorSPx):\r
+ b ASM_PFX(SErrorEntry)\r
+\r
+//\r
+// Lower EL using AArch64 : 0x400 - 0x580\r
+//\r
+VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_SYNC)\r
+ASM_PFX(SynchronousExceptionA64):\r
+ b ASM_PFX(SynchronousExceptionEntry)\r
+\r
+VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_IRQ)\r
+ASM_PFX(IrqA64):\r
+ b ASM_PFX(IrqEntry)\r
+\r
+VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_FIQ)\r
+ASM_PFX(FiqA64):\r
+ b ASM_PFX(FiqEntry)\r
+\r
+VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_SERR)\r
+ASM_PFX(SErrorA64):\r
+ b ASM_PFX(SErrorEntry)\r
+\r
+//\r
+// Lower EL using AArch32 : 0x600 - 0x780\r
+//\r
+VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_SYNC)\r
+ASM_PFX(SynchronousExceptionA32):\r
+ b ASM_PFX(SynchronousExceptionEntry)\r
+\r
+VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_IRQ)\r
+ASM_PFX(IrqA32):\r
+ b ASM_PFX(IrqEntry)\r
+\r
+VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_FIQ)\r
+ASM_PFX(FiqA32):\r
+ b ASM_PFX(FiqEntry)\r
+\r
+VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_SERR)\r
+ASM_PFX(SErrorA32):\r
+ b ASM_PFX(SErrorEntry)\r
+\r
+VECTOR_END(ExceptionHandlersStart)\r
+\r
+#undef REG_PAIR\r
+#undef REG_ONE\r
+#define REG_PAIR(REG1, REG2, OFFSET, CONTEXT_SIZE) stp REG1, REG2, [sp, #(OFFSET-CONTEXT_SIZE)]\r
+#define REG_ONE(REG1, OFFSET, CONTEXT_SIZE) stur REG1, [sp, #(OFFSET-CONTEXT_SIZE)]\r
+\r
+ASM_PFX(SynchronousExceptionEntry):\r
+ // Move the stackpointer so we can reach our structure with the str instruction.\r
+ sub sp, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)\r
+\r
+ // Save all the General regs before touching x0 and x1.\r
+ // This does not save r31(SP) as it is special. We do that later.\r
+ ALL_GP_REGS\r
+\r
+ // Record the type of exception that occurred.\r
+ mov x0, #EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS\r
+\r
+ // Jump to our general handler to deal with all the common parts and process the exception.\r
+ ldr x1, ASM_PFX(CommonExceptionEntry)\r
+ br x1\r
+\r
+ASM_PFX(IrqEntry):\r
+ sub sp, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)\r
+ ALL_GP_REGS\r
+ mov x0, #EXCEPT_AARCH64_IRQ\r
+ ldr x1, ASM_PFX(CommonExceptionEntry)\r
+ br x1\r
+\r
+ASM_PFX(FiqEntry):\r
+ sub sp, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)\r
+ ALL_GP_REGS\r
+ mov x0, #EXCEPT_AARCH64_FIQ\r
+ ldr x1, ASM_PFX(CommonExceptionEntry)\r
+ br x1\r
+\r
+ASM_PFX(SErrorEntry):\r
+ sub sp, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)\r
+ ALL_GP_REGS\r
+ mov x0, #EXCEPT_AARCH64_SERROR\r
+ ldr x1, ASM_PFX(CommonExceptionEntry)\r
+ br x1\r
+\r
+\r
+//\r
+// This gets patched by the C code that patches in the vector table\r
+//\r
+.align 3\r
+ASM_PFX(CommonExceptionEntry):\r
+ .8byte ASM_PFX(AsmCommonExceptionEntry)\r
+\r
+ASM_PFX(ExceptionHandlersEnd):\r
+\r
+\r
+\r
+//\r
+// This code runs from CpuDxe driver loaded address. It is patched into\r
+// CommonExceptionEntry.\r
+//\r
+ASM_PFX(AsmCommonExceptionEntry):\r
+ /* NOTE:\r
+ We have to break up the save code because the immediate value to be used\r
+ with the SP is too big to do it all in one step so we need to shuffle the SP\r
+ along as we go. (we only have 9bits of immediate to work with) */\r
+\r
+ // Save the current Stack pointer before we start modifying it.\r
+ SAVE_SP\r
+\r
+ // Preserve the stack pointer we came in with before we modify it\r
+ EL1_OR_EL2_OR_EL3(x1)\r
+1:mrs x1, elr_el1 // Exception Link Register\r
+ mrs x2, spsr_el1 // Saved Processor Status Register 32bit\r
+ mrs x3, fpsr // Floating point Status Register 32bit\r
+ mrs x4, esr_el1 // EL1 Exception syndrome register 32bit\r
+ mrs x5, far_el1 // EL1 Fault Address Register\r
+ b 4f\r
+\r
+2:mrs x1, elr_el2 // Exception Link Register\r
+ mrs x2, spsr_el2 // Saved Processor Status Register 32bit\r
+ mrs x3, fpsr // Floating point Status Register 32bit\r
+ mrs x4, esr_el2 // EL2 Exception syndrome register 32bit\r
+ mrs x5, far_el2 // EL2 Fault Address Register\r
+ b 4f\r
+\r
+3:mrs x1, elr_el3 // Exception Link Register\r
+ mrs x2, spsr_el3 // Saved Processor Status Register 32bit\r
+ mrs x3, fpsr // Floating point Status Register 32bit\r
+ mrs x4, esr_el3 // EL3 Exception syndrome register 32bit\r
+ mrs x5, far_el3 // EL3 Fault Address Register\r
+\r
+ // Adjust SP to save next set\r
+4:add sp, sp, #FP_CONTEXT_SIZE\r
+\r
+ // Push FP regs to Stack.\r
+ ALL_FP_REGS\r
+\r
+ // Adjust SP to save next set\r
+ add sp, sp, #SYS_CONTEXT_SIZE\r
+\r
+ // Save the SYS regs\r
+ ALL_SYS_REGS\r
+\r
+ // Point to top of struct after all regs saved\r
+ sub sp, sp, #(GP_CONTEXT_SIZE + FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)\r
+\r
+ // x0 still holds the exception type.\r
+ // Set x1 to point to the top of our struct on the Stack\r
+ mov x1, sp\r
+\r
+// CommonCExceptionHandler (\r
+// IN EFI_EXCEPTION_TYPE ExceptionType, R0\r
+// IN OUT EFI_SYSTEM_CONTEXT SystemContext R1\r
+// )\r
+\r
+ // Call the handler as defined above\r
+\r
+ // For now we spin in the handler if we received an abort of some kind.\r
+ // We do not try to recover.\r
+ bl ASM_PFX(CommonCExceptionHandler) // Call exception handler\r
+\r
+\r
+// Defines for popping from stack\r
+\r
+#undef REG_PAIR\r
+#undef REG_ONE\r
+#define REG_PAIR(REG1, REG2, OFFSET, CONTEXT_SIZE) ldp REG1, REG2, [sp, #(OFFSET-CONTEXT_SIZE)]\r
+#define REG_ONE(REG1, OFFSET, CONTEXT_SIZE) ldur REG1, [sp, #(OFFSET-CONTEXT_SIZE)]\r
+\r
+ //\r
+ // Disable interrupt(IRQ and FIQ) before restoring context,\r
+ // or else the context will be corrupted by interrupt reentrance.\r
+ // Interrupt mask will be restored from spsr by hardware when we call eret\r
+ //\r
+ msr daifset, #3\r
+ isb\r
+\r
+ // Adjust SP to pop system registers\r
+ add sp, sp, #(GP_CONTEXT_SIZE + FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)\r
+ ALL_SYS_REGS\r
+\r
+ EL1_OR_EL2_OR_EL3(x6)\r
+1:msr elr_el1, x1 // Exception Link Register\r
+ msr spsr_el1,x2 // Saved Processor Status Register 32bit\r
+ msr fpsr, x3 // Floating point Status Register 32bit\r
+ msr esr_el1, x4 // EL1 Exception syndrome register 32bit\r
+ msr far_el1, x5 // EL1 Fault Address Register\r
+ b 4f\r
+2:msr elr_el2, x1 // Exception Link Register\r
+ msr spsr_el2,x2 // Saved Processor Status Register 32bit\r
+ msr fpsr, x3 // Floating point Status Register 32bit\r
+ msr esr_el2, x4 // EL2 Exception syndrome register 32bit\r
+ msr far_el2, x5 // EL2 Fault Address Register\r
+ b 4f\r
+3:msr elr_el3, x1 // Exception Link Register\r
+ msr spsr_el3,x2 // Saved Processor Status Register 32bit\r
+ msr fpsr, x3 // Floating point Status Register 32bit\r
+ msr esr_el3, x4 // EL3 Exception syndrome register 32bit\r
+ msr far_el3, x5 // EL3 Fault Address Register\r
+4:// pop all regs and return from exception.\r
+ sub sp, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)\r
+ ALL_GP_REGS\r
+\r
+ // Adjust SP to pop next set\r
+ add sp, sp, #FP_CONTEXT_SIZE\r
+ // Pop FP regs to Stack.\r
+ ALL_FP_REGS\r
+\r
+ // Adjust SP to be where we started from when we came into the handler.\r
+ // The handler can not change the SP.\r
+ add sp, sp, #SYS_CONTEXT_SIZE\r
+\r
+ eret\r
+\r
+#undef REG_PAIR\r
+#undef REG_ONE\r
--- /dev/null
+/** @file\r
+* Exception handling support specific for ARM\r
+*\r
+* Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
+* Copyright (c) 2014, ARM Limited. All rights reserved.<BR>\r
+* Copyright (c) 2016 HP Development Company, L.P.<BR>\r
+*\r
+* 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
+**/\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Chipset/ArmV7.h>\r
+\r
+#include <Library/ArmLib.h>\r
+\r
+#include <Protocol/DebugSupport.h> // for MAX_ARM_EXCEPTION\r
+\r
+UINTN gMaxExceptionNumber = MAX_ARM_EXCEPTION;\r
+EFI_EXCEPTION_CALLBACK gExceptionHandlers[MAX_ARM_EXCEPTION + 1] = { 0 };\r
+EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[MAX_ARM_EXCEPTION + 1] = { 0 };\r
+PHYSICAL_ADDRESS gExceptionVectorAlignmentMask = ARM_VECTOR_TABLE_ALIGNMENT;\r
+\r
+// Exception handler contains branch to vector location (jmp $) so no handler\r
+// NOTE: This code assumes vectors are ARM and not Thumb code\r
+UINTN gDebuggerNoHandlerValue = 0xEAFFFFFE;\r
+\r
+RETURN_STATUS ArchVectorConfig(\r
+ IN UINTN VectorBaseAddress\r
+ )\r
+{\r
+ // if the vector address corresponds to high vectors\r
+ if (VectorBaseAddress == 0xFFFF0000) {\r
+ // set SCTLR.V to enable high vectors\r
+ ArmSetHighVectors();\r
+ }\r
+ else {\r
+ // Set SCTLR.V to 0 to enable VBAR to be used\r
+ ArmSetLowVectors();\r
+ }\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
--- /dev/null
+#------------------------------------------------------------------------------\r
+#\r
+# Use ARMv6 instruction to operate on a single stack\r
+#\r
+# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
+# Copyright (c) 2014, ARM Limited. All rights reserved.<BR>\r
+# Copyright (c) 2016 HP Development Company, L.P.<BR>\r
+#\r
+# 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
+#------------------------------------------------------------------------------\r
+\r
+#include <Library/PcdLib.h>\r
+\r
+/*\r
+\r
+This is the stack constructed by the exception handler (low address to high address)\r
+ # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM\r
+ Reg Offset\r
+ === ======\r
+ R0 0x00 # stmfd SP!,{R0-R12}\r
+ R1 0x04\r
+ R2 0x08\r
+ R3 0x0c\r
+ R4 0x10\r
+ R5 0x14\r
+ R6 0x18\r
+ R7 0x1c\r
+ R8 0x20\r
+ R9 0x24\r
+ R10 0x28\r
+ R11 0x2c\r
+ R12 0x30\r
+ SP 0x34 # reserved via subtraction 0x20 (32) from SP\r
+ LR 0x38\r
+ PC 0x3c\r
+ CPSR 0x40\r
+ DFSR 0x44\r
+ DFAR 0x48\r
+ IFSR 0x4c\r
+ IFAR 0x50\r
+\r
+ LR 0x54 # SVC Link register (we need to restore it)\r
+\r
+ LR 0x58 # pushed by srsfd\r
+ CPSR 0x5c\r
+\r
+ */\r
+\r
+\r
+GCC_ASM_EXPORT(ExceptionHandlersStart)\r
+GCC_ASM_EXPORT(ExceptionHandlersEnd)\r
+GCC_ASM_EXPORT(CommonExceptionEntry)\r
+GCC_ASM_EXPORT(AsmCommonExceptionEntry)\r
+GCC_ASM_EXPORT(CommonCExceptionHandler)\r
+\r
+.text\r
+.syntax unified\r
+#if !defined(__APPLE__)\r
+.fpu neon @ makes vpush/vpop assemble\r
+#endif\r
+.align 5\r
+\r
+\r
+//\r
+// This code gets copied to the ARM vector table\r
+// ExceptionHandlersStart - ExceptionHandlersEnd gets copied\r
+//\r
+ASM_PFX(ExceptionHandlersStart):\r
+\r
+ASM_PFX(Reset):\r
+ b ASM_PFX(ResetEntry)\r
+\r
+ASM_PFX(UndefinedInstruction):\r
+ b ASM_PFX(UndefinedInstructionEntry)\r
+\r
+ASM_PFX(SoftwareInterrupt):\r
+ b ASM_PFX(SoftwareInterruptEntry)\r
+\r
+ASM_PFX(PrefetchAbort):\r
+ b ASM_PFX(PrefetchAbortEntry)\r
+\r
+ASM_PFX(DataAbort):\r
+ b ASM_PFX(DataAbortEntry)\r
+\r
+ASM_PFX(ReservedException):\r
+ b ASM_PFX(ReservedExceptionEntry)\r
+\r
+ASM_PFX(Irq):\r
+ b ASM_PFX(IrqEntry)\r
+\r
+ASM_PFX(Fiq):\r
+ b ASM_PFX(FiqEntry)\r
+\r
+ASM_PFX(ResetEntry):\r
+ srsdb #0x13! @ Store return state on SVC stack\r
+ @ We are already in SVC mode\r
+\r
+ stmfd SP!,{LR} @ Store the link register for the current mode\r
+ sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} @ Store the register state\r
+\r
+ mov R0,#0 @ ExceptionType\r
+ ldr R1,ASM_PFX(CommonExceptionEntry)\r
+ bx R1\r
+\r
+ASM_PFX(UndefinedInstructionEntry):\r
+ sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry\r
+ srsdb #0x13! @ Store return state on SVC stack\r
+ cps #0x13 @ Switch to SVC for common stack\r
+ stmfd SP!,{LR} @ Store the link register for the current mode\r
+ sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} @ Store the register state\r
+\r
+ mov R0,#1 @ ExceptionType\r
+ ldr R1,ASM_PFX(CommonExceptionEntry)\r
+ bx R1\r
+\r
+ASM_PFX(SoftwareInterruptEntry):\r
+ srsdb #0x13! @ Store return state on SVC stack\r
+ @ We are already in SVC mode\r
+ stmfd SP!,{LR} @ Store the link register for the current mode\r
+ sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} @ Store the register state\r
+\r
+ mov R0,#2 @ ExceptionType\r
+ ldr R1,ASM_PFX(CommonExceptionEntry)\r
+ bx R1\r
+\r
+ASM_PFX(PrefetchAbortEntry):\r
+ sub LR,LR,#4\r
+ srsdb #0x13! @ Store return state on SVC stack\r
+ cps #0x13 @ Switch to SVC for common stack\r
+ stmfd SP!,{LR} @ Store the link register for the current mode\r
+ sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} @ Store the register state\r
+\r
+ mov R0,#3 @ ExceptionType\r
+ ldr R1,ASM_PFX(CommonExceptionEntry)\r
+ bx R1\r
+\r
+ASM_PFX(DataAbortEntry):\r
+ sub LR,LR,#8\r
+ srsdb #0x13! @ Store return state on SVC stack\r
+ cps #0x13 @ Switch to SVC for common stack\r
+ stmfd SP!,{LR} @ Store the link register for the current mode\r
+ sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} @ Store the register state\r
+\r
+ mov R0,#4\r
+ ldr R1,ASM_PFX(CommonExceptionEntry)\r
+ bx R1\r
+\r
+ASM_PFX(ReservedExceptionEntry):\r
+ srsdb #0x13! @ Store return state on SVC stack\r
+ cps #0x13 @ Switch to SVC for common stack\r
+ stmfd SP!,{LR} @ Store the link register for the current mode\r
+ sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} @ Store the register state\r
+\r
+ mov R0,#5\r
+ ldr R1,ASM_PFX(CommonExceptionEntry)\r
+ bx R1\r
+\r
+ASM_PFX(IrqEntry):\r
+ sub LR,LR,#4\r
+ srsdb #0x13! @ Store return state on SVC stack\r
+ cps #0x13 @ Switch to SVC for common stack\r
+ stmfd SP!,{LR} @ Store the link register for the current mode\r
+ sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} @ Store the register state\r
+\r
+ mov R0,#6 @ ExceptionType\r
+ ldr R1,ASM_PFX(CommonExceptionEntry)\r
+ bx R1\r
+\r
+ASM_PFX(FiqEntry):\r
+ sub LR,LR,#4\r
+ srsdb #0x13! @ Store return state on SVC stack\r
+ cps #0x13 @ Switch to SVC for common stack\r
+ stmfd SP!,{LR} @ Store the link register for the current mode\r
+ sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} @ Store the register state\r
+ @ Since we have already switch to SVC R8_fiq - R12_fiq\r
+ @ never get used or saved\r
+ mov R0,#7 @ ExceptionType\r
+ ldr R1,ASM_PFX(CommonExceptionEntry)\r
+ bx R1\r
+\r
+//\r
+// This gets patched by the C code that patches in the vector table\r
+//\r
+ASM_PFX(CommonExceptionEntry):\r
+ .word ASM_PFX(AsmCommonExceptionEntry)\r
+\r
+ASM_PFX(ExceptionHandlersEnd):\r
+\r
+//\r
+// This code runs from CpuDxe driver loaded address. It is patched into\r
+// CommonExceptionEntry.\r
+//\r
+ASM_PFX(AsmCommonExceptionEntry):\r
+ mrc p15, 0, R1, c6, c0, 2 @ Read IFAR\r
+ str R1, [SP, #0x50] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR\r
+\r
+ mrc p15, 0, R1, c5, c0, 1 @ Read IFSR\r
+ str R1, [SP, #0x4c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR\r
+\r
+ mrc p15, 0, R1, c6, c0, 0 @ Read DFAR\r
+ str R1, [SP, #0x48] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR\r
+\r
+ mrc p15, 0, R1, c5, c0, 0 @ Read DFSR\r
+ str R1, [SP, #0x44] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR\r
+\r
+ ldr R1, [SP, #0x5c] @ srsdb saved pre-exception CPSR on the stack\r
+ str R1, [SP, #0x40] @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR\r
+\r
+ add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
+ and R3, R1, #0x1f @ Check CPSR to see if User or System Mode\r
+ cmp R3, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))\r
+ cmpne R3, #0x10 @\r
+ stmdaeq R2, {lr}^ @ save unbanked lr\r
+ @ else\r
+ stmdane R2, {lr} @ save SVC lr\r
+\r
+\r
+ ldr R5, [SP, #0x58] @ PC is the LR pushed by srsfd\r
+ @ Check to see if we have to adjust for Thumb entry\r
+ sub r4, r0, #1 @ if (ExceptionType == 1 || ExceptionType == 2)) {\r
+ cmp r4, #1 @ // UND & SVC have differnt LR adjust for Thumb\r
+ bhi NoAdjustNeeded\r
+\r
+ tst r1, #0x20 @ if ((CPSR & T)) == T) { // Thumb Mode on entry\r
+ addne R5, R5, #2 @ PC += 2;\r
+ strne R5,[SP,#0x58] @ Update LR value pushed by srsfd\r
+\r
+NoAdjustNeeded:\r
+\r
+ str R5, [SP, #0x3c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC\r
+\r
+ add R1, SP, #0x60 @ We pushed 0x60 bytes on the stack\r
+ str R1, [SP, #0x34] @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP\r
+\r
+ @ R0 is ExceptionType\r
+ mov R1,SP @ R1 is SystemContext\r
+\r
+#if (FixedPcdGet32(PcdVFPEnabled))\r
+ vpush {d0-d15} @ save vstm registers in case they are used in optimizations\r
+#endif\r
+\r
+ mov R4, SP @ Save current SP\r
+ tst R4, #4\r
+ subne SP, SP, #4 @ Adjust SP if not 8-byte aligned\r
+\r
+/*\r
+VOID\r
+EFIAPI\r
+CommonCExceptionHandler (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType, R0\r
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext R1\r
+ )\r
+\r
+*/\r
+ blx ASM_PFX(CommonCExceptionHandler) @ Call exception handler\r
+\r
+ mov SP, R4 @ Restore SP\r
+\r
+#if (FixedPcdGet32(PcdVFPEnabled))\r
+ vpop {d0-d15}\r
+#endif\r
+\r
+ ldr R1, [SP, #0x4c] @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR\r
+ mcr p15, 0, R1, c5, c0, 1 @ Write IFSR\r
+\r
+ ldr R1, [SP, #0x44] @ Restore EFI_SYSTEM_CONTEXT_ARM.DFSR\r
+ mcr p15, 0, R1, c5, c0, 0 @ Write DFSR\r
+\r
+ ldr R1,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC\r
+ str R1,[SP,#0x58] @ Store it back to srsfd stack slot so it can be restored\r
+\r
+ ldr R1,[SP,#0x40] @ EFI_SYSTEM_CONTEXT_ARM.CPSR\r
+ str R1,[SP,#0x5c] @ Store it back to srsfd stack slot so it can be restored\r
+\r
+ add R3, SP, #0x54 @ Make R3 point to SVC LR saved on entry\r
+ add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
+ and R1, R1, #0x1f @ Check to see if User or System Mode\r
+ cmp R1, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))\r
+ cmpne R1, #0x10 @\r
+ ldmibeq R2, {lr}^ @ restore unbanked lr\r
+ @ else\r
+ ldmibne R3, {lr} @ restore SVC lr, via ldmfd SP!, {LR}\r
+\r
+ ldmfd SP!,{R0-R12} @ Restore general purpose registers\r
+ @ Exception handler can not change SP\r
+\r
+ add SP,SP,#0x20 @ Clear out the remaining stack space\r
+ ldmfd SP!,{LR} @ restore the link register for this context\r
+ rfefd SP! @ return from exception via srsfd stack slot\r
+\r
--- /dev/null
+//------------------------------------------------------------------------------\r
+//\r
+// Use ARMv6 instruction to operate on a single stack\r
+//\r
+// Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
+// Copyright (c) 2014, ARM Limited. All rights reserved.<BR>\r
+// Copyright (c) 2016 HP Development Company, L.P.<BR>\r
+//\r
+// 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
+//------------------------------------------------------------------------------\r
+\r
+#include <Library/PcdLib.h>\r
+\r
+/*\r
+\r
+This is the stack constructed by the exception handler (low address to high address)\r
+ # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM\r
+ Reg Offset\r
+ === ======\r
+ R0 0x00 # stmfd SP!,{R0-R12}\r
+ R1 0x04\r
+ R2 0x08\r
+ R3 0x0c\r
+ R4 0x10\r
+ R5 0x14\r
+ R6 0x18\r
+ R7 0x1c\r
+ R8 0x20\r
+ R9 0x24\r
+ R10 0x28\r
+ R11 0x2c\r
+ R12 0x30\r
+ SP 0x34 # reserved via subtraction 0x20 (32) from SP\r
+ LR 0x38\r
+ PC 0x3c\r
+ CPSR 0x40\r
+ DFSR 0x44\r
+ DFAR 0x48\r
+ IFSR 0x4c\r
+ IFAR 0x50\r
+\r
+ LR 0x54 # SVC Link register (we need to restore it)\r
+\r
+ LR 0x58 # pushed by srsfd\r
+ CPSR 0x5c\r
+\r
+ */\r
+\r
+\r
+ EXPORT ExceptionHandlersStart\r
+ EXPORT ExceptionHandlersEnd\r
+ EXPORT CommonExceptionEntry\r
+ EXPORT AsmCommonExceptionEntry\r
+ IMPORT CommonCExceptionHandler\r
+\r
+ PRESERVE8\r
+ AREA DxeExceptionHandlers, CODE, READONLY, CODEALIGN, ALIGN=5\r
+\r
+//\r
+// This code gets copied to the ARM vector table\r
+// ExceptionHandlersStart - ExceptionHandlersEnd gets copied\r
+//\r
+ExceptionHandlersStart\r
+\r
+Reset\r
+ b ResetEntry\r
+\r
+UndefinedInstruction\r
+ b UndefinedInstructionEntry\r
+\r
+SoftwareInterrupt\r
+ b SoftwareInterruptEntry\r
+\r
+PrefetchAbort\r
+ b PrefetchAbortEntry\r
+\r
+DataAbort\r
+ b DataAbortEntry\r
+\r
+ReservedException\r
+ b ReservedExceptionEntry\r
+\r
+Irq\r
+ b IrqEntry\r
+\r
+Fiq\r
+ b FiqEntry\r
+\r
+ResetEntry\r
+ srsfd #0x13! ; Store return state on SVC stack\r
+ ; We are already in SVC mode\r
+ stmfd SP!,{LR} ; Store the link register for the current mode\r
+ sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} ; Store the register state\r
+\r
+ mov R0,#0 ; ExceptionType\r
+ ldr R1,CommonExceptionEntry\r
+ bx R1\r
+\r
+UndefinedInstructionEntry\r
+ sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry\r
+ srsfd #0x13! ; Store return state on SVC stack\r
+ cps #0x13 ; Switch to SVC for common stack\r
+ stmfd SP!,{LR} ; Store the link register for the current mode\r
+ sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} ; Store the register state\r
+\r
+ mov R0,#1 ; ExceptionType\r
+ ldr R1,CommonExceptionEntry;\r
+ bx R1\r
+\r
+SoftwareInterruptEntry\r
+ srsfd #0x13! ; Store return state on SVC stack\r
+ ; We are already in SVC mode\r
+ stmfd SP!,{LR} ; Store the link register for the current mode\r
+ sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} ; Store the register state\r
+\r
+ mov R0,#2 ; ExceptionType\r
+ ldr R1,CommonExceptionEntry\r
+ bx R1\r
+\r
+PrefetchAbortEntry\r
+ sub LR,LR,#4\r
+ srsfd #0x13! ; Store return state on SVC stack\r
+ cps #0x13 ; Switch to SVC for common stack\r
+ stmfd SP!,{LR} ; Store the link register for the current mode\r
+ sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} ; Store the register state\r
+\r
+ mov R0,#3 ; ExceptionType\r
+ ldr R1,CommonExceptionEntry\r
+ bx R1\r
+\r
+DataAbortEntry\r
+ sub LR,LR,#8\r
+ srsfd #0x13! ; Store return state on SVC stack\r
+ cps #0x13 ; Switch to SVC for common stack\r
+ stmfd SP!,{LR} ; Store the link register for the current mode\r
+ sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} ; Store the register state\r
+\r
+ mov R0,#4 ; ExceptionType\r
+ ldr R1,CommonExceptionEntry\r
+ bx R1\r
+\r
+ReservedExceptionEntry\r
+ srsfd #0x13! ; Store return state on SVC stack\r
+ cps #0x13 ; Switch to SVC for common stack\r
+ stmfd SP!,{LR} ; Store the link register for the current mode\r
+ sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} ; Store the register state\r
+\r
+ mov R0,#5 ; ExceptionType\r
+ ldr R1,CommonExceptionEntry\r
+ bx R1\r
+\r
+IrqEntry\r
+ sub LR,LR,#4\r
+ srsfd #0x13! ; Store return state on SVC stack\r
+ cps #0x13 ; Switch to SVC for common stack\r
+ stmfd SP!,{LR} ; Store the link register for the current mode\r
+ sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} ; Store the register state\r
+\r
+ mov R0,#6 ; ExceptionType\r
+ ldr R1,CommonExceptionEntry\r
+ bx R1\r
+\r
+FiqEntry\r
+ sub LR,LR,#4\r
+ srsfd #0x13! ; Store return state on SVC stack\r
+ cps #0x13 ; Switch to SVC for common stack\r
+ stmfd SP!,{LR} ; Store the link register for the current mode\r
+ sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} ; Store the register state\r
+ ; Since we have already switch to SVC R8_fiq - R12_fiq\r
+ ; never get used or saved\r
+ mov R0,#7 ; ExceptionType\r
+ ldr R1,CommonExceptionEntry\r
+ bx R1\r
+\r
+//\r
+// This gets patched by the C code that patches in the vector table\r
+//\r
+CommonExceptionEntry\r
+ dcd AsmCommonExceptionEntry\r
+\r
+ExceptionHandlersEnd\r
+\r
+//\r
+// This code runs from CpuDxe driver loaded address. It is patched into\r
+// CommonExceptionEntry.\r
+//\r
+AsmCommonExceptionEntry\r
+ mrc p15, 0, R1, c6, c0, 2 ; Read IFAR\r
+ str R1, [SP, #0x50] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR\r
+\r
+ mrc p15, 0, R1, c5, c0, 1 ; Read IFSR\r
+ str R1, [SP, #0x4c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR\r
+\r
+ mrc p15, 0, R1, c6, c0, 0 ; Read DFAR\r
+ str R1, [SP, #0x48] ; Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR\r
+\r
+ mrc p15, 0, R1, c5, c0, 0 ; Read DFSR\r
+ str R1, [SP, #0x44] ; Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR\r
+\r
+ ldr R1, [SP, #0x5c] ; srsfd saved pre-exception CPSR on the stack\r
+ str R1, [SP, #0x40] ; Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR\r
+\r
+ add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
+ and R3, R1, #0x1f ; Check CPSR to see if User or System Mode\r
+ cmp R3, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1f))\r
+ cmpne R3, #0x10 ;\r
+ stmeqed R2, {lr}^ ; save unbanked lr\r
+ ; else\r
+ stmneed R2, {lr} ; save SVC lr\r
+\r
+\r
+ ldr R5, [SP, #0x58] ; PC is the LR pushed by srsfd\r
+ ; Check to see if we have to adjust for Thumb entry\r
+ sub r4, r0, #1 ; if (ExceptionType == 1 || ExceptionType == 2)) {\r
+ cmp r4, #1 ; // UND & SVC have differnt LR adjust for Thumb\r
+ bhi NoAdjustNeeded\r
+\r
+ tst r1, #0x20 ; if ((CPSR & T)) == T) { // Thumb Mode on entry\r
+ addne R5, R5, #2 ; PC += 2;\r
+ strne R5,[SP,#0x58] ; Update LR value pushed by srsfd\r
+\r
+NoAdjustNeeded\r
+\r
+ str R5, [SP, #0x3c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.PC\r
+\r
+ add R1, SP, #0x60 ; We pushed 0x60 bytes on the stack\r
+ str R1, [SP, #0x34] ; Store it in EFI_SYSTEM_CONTEXT_ARM.SP\r
+\r
+ ; R0 is ExceptionType\r
+ mov R1,SP ; R1 is SystemContext\r
+\r
+#if (FixedPcdGet32(PcdVFPEnabled))\r
+ vpush {d0-d15} ; save vstm registers in case they are used in optimizations\r
+#endif\r
+\r
+ mov R4, SP ; Save current SP\r
+ tst R4, #4\r
+ subne SP, SP, #4 ; Adjust SP if not 8-byte aligned\r
+\r
+/*\r
+VOID\r
+EFIAPI\r
+CommonCExceptionHandler (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType, R0\r
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext R1\r
+ )\r
+\r
+*/\r
+ blx CommonCExceptionHandler ; Call exception handler\r
+\r
+ mov SP, R4 ; Restore SP\r
+\r
+#if (FixedPcdGet32(PcdVFPEnabled))\r
+ vpop {d0-d15}\r
+#endif\r
+\r
+ ldr R1, [SP, #0x4c] ; Restore EFI_SYSTEM_CONTEXT_ARM.IFSR\r
+ mcr p15, 0, R1, c5, c0, 1 ; Write IFSR\r
+\r
+ ldr R1, [SP, #0x44] ; Restore EFI_SYSTEM_CONTEXT_ARM.DFSR\r
+ mcr p15, 0, R1, c5, c0, 0 ; Write DFSR\r
+\r
+ ldr R1,[SP,#0x3c] ; EFI_SYSTEM_CONTEXT_ARM.PC\r
+ str R1,[SP,#0x58] ; Store it back to srsfd stack slot so it can be restored\r
+\r
+ ldr R1,[SP,#0x40] ; EFI_SYSTEM_CONTEXT_ARM.CPSR\r
+ str R1,[SP,#0x5c] ; Store it back to srsfd stack slot so it can be restored\r
+\r
+ add R3, SP, #0x54 ; Make R3 point to SVC LR saved on entry\r
+ add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
+ and R1, R1, #0x1f ; Check to see if User or System Mode\r
+ cmp R1, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1f))\r
+ cmpne R1, #0x10 ;\r
+ ldmeqed R2, {lr}^ ; restore unbanked lr\r
+ ; else\r
+ ldmneed R3, {lr} ; restore SVC lr, via ldmfd SP!, {LR}\r
+\r
+ ldmfd SP!,{R0-R12} ; Restore general purpose registers\r
+ ; Exception handler can not change SP\r
+\r
+ add SP,SP,#0x20 ; Clear out the remaining stack space\r
+ ldmfd SP!,{LR} ; restore the link register for this context\r
+ rfefd SP! ; return from exception via srsfd stack slot\r
+\r
+ END\r
+\r
+\r
--- /dev/null
+/* @file\r
+* Main file supporting the SEC Phase for Versatile Express\r
+*\r
+* Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
+* Copyright (c) 2011-2014, ARM Limited. All rights reserved.\r
+* Copyright (c) 2016 HP Development Company, L.P.\r
+*\r
+* 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
+**/\r
+\r
+#include <Uefi.h>\r
+#include <Library/CpuExceptionHandlerLib.h>\r
+\r
+#include <Library/ArmLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/CacheMaintenanceLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/DefaultExceptionHandlerLib.h>\r
+\r
+RETURN_STATUS\r
+CopyExceptionHandlers(\r
+ IN PHYSICAL_ADDRESS BaseAddress\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterExceptionHandler(\r
+ IN EFI_EXCEPTION_TYPE ExceptionType,\r
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
+ );\r
+\r
+VOID\r
+ExceptionHandlersStart(\r
+ VOID\r
+ );\r
+\r
+VOID\r
+ExceptionHandlersEnd(\r
+ VOID\r
+ );\r
+\r
+RETURN_STATUS ArchVectorConfig(\r
+ IN UINTN VectorBaseAddress\r
+ );\r
+\r
+// these globals are provided by the architecture specific source (Arm or AArch64)\r
+extern UINTN gMaxExceptionNumber;\r
+extern EFI_EXCEPTION_CALLBACK gExceptionHandlers[];\r
+extern EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[];\r
+extern PHYSICAL_ADDRESS gExceptionVectorAlignmentMask;\r
+extern UINTN gDebuggerNoHandlerValue;\r
+\r
+// A compiler flag adjusts the compilation of this library to a variant where\r
+// the vectors are relocated (copied) to another location versus using the\r
+// vectors in-place. Since this effects an assembly .align directive we must\r
+// address this at library build time. Since this affects the build of the\r
+// library we cannot represent this in a PCD since PCDs are evaluated on\r
+// a per-module basis.\r
+#if defined(ARM_RELOCATE_VECTORS)\r
+BOOLEAN gArmRelocateVectorTable = TRUE;\r
+#else\r
+BOOLEAN gArmRelocateVectorTable = FALSE;\r
+#endif\r
+\r
+\r
+/**\r
+Initializes all CPU exceptions entries and provides the default exception handlers.\r
+\r
+Caller should try to get an array of interrupt and/or exception vectors that are in use and need to\r
+persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification.\r
+If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL.\r
+If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly.\r
+\r
+@param[in] VectorInfo Pointer to reserved vector list.\r
+\r
+@retval EFI_SUCCESS CPU Exception Entries have been successfully initialized\r
+with default exception handlers.\r
+@retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.\r
+@retval EFI_UNSUPPORTED This function is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeCpuExceptionHandlers(\r
+ IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL\r
+ )\r
+{\r
+ RETURN_STATUS Status;\r
+ UINTN VectorBase;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ // if we are requested to copy exceptin handlers to another location\r
+ if (gArmRelocateVectorTable) {\r
+\r
+ VectorBase = PcdGet32(PcdCpuVectorBaseAddress);\r
+ Status = CopyExceptionHandlers(VectorBase);\r
+\r
+ }\r
+ else { // use VBAR to point to where our exception handlers are\r
+\r
+ // The vector table must be aligned for the architecture. If this\r
+ // assertion fails ensure the appropriate FFS alignment is in effect,\r
+ // which can be accomplished by ensuring the proper Align=X statement\r
+ // in the platform packaging rules. For ARM Align=32 is required and\r
+ // for AArch64 Align=4K is required. Align=Auto can be used but this\r
+ // is known to cause an issue with populating the reset vector area\r
+ // for encapsulated FVs.\r
+ ASSERT(((UINTN)ExceptionHandlersStart & gExceptionVectorAlignmentMask) == 0);\r
+\r
+ // We do not copy the Exception Table at PcdGet32(PcdCpuVectorBaseAddress). We just set Vector\r
+ // Base Address to point into CpuDxe code.\r
+ VectorBase = (UINTN)ExceptionHandlersStart;\r
+\r
+ Status = RETURN_SUCCESS;\r
+ }\r
+\r
+ if (!RETURN_ERROR(Status)) {\r
+ // call the architecture-specific routine to prepare for the new vector\r
+ // configuration to take effect\r
+ ArchVectorConfig(VectorBase);\r
+\r
+ ArmWriteVBar(VectorBase);\r
+ }\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+Copies exception handlers to the speciifed address.\r
+\r
+Caller should try to get an array of interrupt and/or exception vectors that are in use and need to\r
+persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification.\r
+If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL.\r
+If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly.\r
+\r
+@param[in] VectorInfo Pointer to reserved vector list.\r
+\r
+@retval EFI_SUCCESS CPU Exception Entries have been successfully initialized\r
+with default exception handlers.\r
+@retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.\r
+@retval EFI_UNSUPPORTED This function is not supported.\r
+\r
+**/\r
+RETURN_STATUS\r
+CopyExceptionHandlers(\r
+ IN PHYSICAL_ADDRESS BaseAddress\r
+ )\r
+{\r
+ RETURN_STATUS Status;\r
+ UINTN Length;\r
+ UINTN Index;\r
+ UINT32 *VectorBase;\r
+\r
+ // ensure that the destination value specifies an address meeting the vector alignment requirements\r
+ ASSERT ((BaseAddress & gExceptionVectorAlignmentMask) == 0);\r
+\r
+ //\r
+ // Copy an implementation of the exception vectors to PcdCpuVectorBaseAddress.\r
+ //\r
+ Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;\r
+\r
+ VectorBase = (UINT32 *)(UINTN)BaseAddress;\r
+\r
+ if (FeaturePcdGet(PcdDebuggerExceptionSupport) == TRUE) {\r
+ // Save existing vector table, in case debugger is already hooked in\r
+ CopyMem((VOID *)gDebuggerExceptionHandlers, (VOID *)VectorBase, sizeof (EFI_EXCEPTION_CALLBACK)* (gMaxExceptionNumber+1));\r
+ }\r
+\r
+ // Copy our assembly code into the page that contains the exception vectors.\r
+ CopyMem((VOID *)VectorBase, (VOID *)ExceptionHandlersStart, Length);\r
+\r
+ //\r
+ // Initialize the C entry points for interrupts\r
+ //\r
+ for (Index = 0; Index <= gMaxExceptionNumber; Index++) {\r
+ if (!FeaturePcdGet(PcdDebuggerExceptionSupport) ||\r
+ (gDebuggerExceptionHandlers[Index] == 0) || (gDebuggerExceptionHandlers[Index] == (VOID *)gDebuggerNoHandlerValue)) {\r
+\r
+ Status = RegisterExceptionHandler(Index, NULL);\r
+ ASSERT_EFI_ERROR(Status);\r
+ }\r
+ else {\r
+ // If the debugger has already hooked put its vector back\r
+ VectorBase[Index] = (UINT32)(UINTN)gDebuggerExceptionHandlers[Index];\r
+ }\r
+ }\r
+\r
+ // Flush Caches since we updated executable stuff\r
+ InvalidateInstructionCacheRange((VOID *)(UINTN)BaseAddress, Length);\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+Initializes all CPU interrupt/exceptions entries and provides the default interrupt/exception handlers.\r
+\r
+Caller should try to get an array of interrupt and/or exception vectors that are in use and need to\r
+persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification.\r
+If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL.\r
+If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly.\r
+\r
+@param[in] VectorInfo Pointer to reserved vector list.\r
+\r
+@retval EFI_SUCCESS All CPU interrupt/exception entries have been successfully initialized\r
+with default interrupt/exception handlers.\r
+@retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.\r
+@retval EFI_UNSUPPORTED This function is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeCpuInterruptHandlers(\r
+IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL\r
+)\r
+{\r
+ // not needed, this is what the CPU driver is for\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+Registers a function to be called from the processor exception handler. (On ARM/AArch64 this only\r
+provides exception handlers, not interrupt handling which is provided through the Hardware Interrupt\r
+Protocol.)\r
+\r
+This function registers and enables the handler specified by ExceptionHandler for a processor\r
+interrupt or exception type specified by ExceptionType. If ExceptionHandler is NULL, then the\r
+handler for the processor interrupt or exception type specified by ExceptionType is uninstalled.\r
+The installed handler is called once for each processor interrupt or exception.\r
+NOTE: This function should be invoked after InitializeCpuExceptionHandlers() or\r
+InitializeCpuInterruptHandlers() invoked, otherwise EFI_UNSUPPORTED returned.\r
+\r
+@param[in] ExceptionType Defines which interrupt or exception to hook.\r
+@param[in] ExceptionHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called\r
+when a processor interrupt occurs. If this parameter is NULL, then the handler\r
+will be uninstalled.\r
+\r
+@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.\r
+@retval EFI_ALREADY_STARTED ExceptionHandler is not NULL, and a handler for ExceptionType was\r
+previously installed.\r
+@retval EFI_INVALID_PARAMETER ExceptionHandler is NULL, and a handler for ExceptionType was not\r
+previously installed.\r
+@retval EFI_UNSUPPORTED The interrupt specified by ExceptionType is not supported,\r
+or this function is not supported.\r
+**/\r
+RETURN_STATUS\r
+RegisterCpuInterruptHandler(\r
+ IN EFI_EXCEPTION_TYPE ExceptionType,\r
+ IN EFI_CPU_INTERRUPT_HANDLER ExceptionHandler\r
+ ) {\r
+ if (ExceptionType > gMaxExceptionNumber) {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ if ((ExceptionHandler != NULL) && (gExceptionHandlers[ExceptionType] != NULL)) {\r
+ return RETURN_ALREADY_STARTED;\r
+ }\r
+\r
+ gExceptionHandlers[ExceptionType] = ExceptionHandler;\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+Register exception handler.\r
+\r
+@param This A pointer to the SMM_CPU_SERVICE_PROTOCOL instance.\r
+@param ExceptionType Defines which interrupt or exception to hook. Type EFI_EXCEPTION_TYPE and\r
+the valid values for this parameter are defined in EFI_DEBUG_SUPPORT_PROTOCOL\r
+of the UEFI 2.0 specification.\r
+@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER\r
+that is called when a processor interrupt occurs.\r
+If this parameter is NULL, then the handler will be uninstalled.\r
+\r
+@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.\r
+@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was previously installed.\r
+@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not previously installed.\r
+@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterExceptionHandler(\r
+ IN EFI_EXCEPTION_TYPE ExceptionType,\r
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
+ )\r
+{\r
+ return RegisterCpuInterruptHandler(ExceptionType, InterruptHandler);\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+CommonCExceptionHandler(\r
+ IN EFI_EXCEPTION_TYPE ExceptionType,\r
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext\r
+ )\r
+{\r
+ if (ExceptionType <= gMaxExceptionNumber) {\r
+ if (gExceptionHandlers[ExceptionType]) {\r
+ gExceptionHandlers[ExceptionType](ExceptionType, SystemContext);\r
+ return;\r
+ }\r
+ }\r
+ else {\r
+ DEBUG((EFI_D_ERROR, "Unknown exception type %d\n", ExceptionType));\r
+ ASSERT(FALSE);\r
+ }\r
+\r
+ DefaultExceptionHandler(ExceptionType, SystemContext);\r
+}\r
--- /dev/null
+## @file\r
+# Instance of CpuExceptionHandlerLib Library for ARM/AArch64 architectures\r
+#\r
+# This library instance is used for modules that will implement exception\r
+# handlers in-place (by programming VBAR). The exception handlers will be\r
+# generated with alignment as required by the processor architecture. The\r
+# alignment must be propagated into the parent FFS/FV through FDF build rules\r
+# for the relevant module types (i.e. Align=Auto).\r
+#\r
+# Note that using this library instance can cause growth to the size of the FV\r
+# due to the padding added by the build tools to meet the vector alignment\r
+# requirements and may not be desirable for space-sensitive FVs (uncompressed /\r
+# XIP components). The alternative library instance, ArmRelocateExceptionLib\r
+# should be considered for these applications.\r
+#\r
+# Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
+# Copyright (c) 2016 HP Development Company, L.P.\r
+#\r
+# 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
+#\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = ArmExceptionLib\r
+ FILE_GUID = A9796991-4E88-47F0-87C5-D96A1D270539\r
+ MODULE_TYPE = BASE\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = CpuExceptionHandlerLib\r
+\r
+[Sources.common]\r
+ ArmExceptionLib.c\r
+\r
+[Sources.Arm]\r
+ Arm/ArmException.c\r
+ Arm/ExceptionSupport.asm | RVCT\r
+ Arm/ExceptionSupport.S | GCC\r
+\r
+[Sources.AARCH64]\r
+ AArch64/AArch64Exception.c\r
+ AArch64/ExceptionSupport.S\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ ArmPkg/ArmPkg.dec\r
+\r
+[LibraryClasses]\r
+ ArmLib\r
+ DebugLib\r
+ DefaultExceptionHandlerLib\r
+ BaseMemoryLib\r
+ CacheMaintenanceLib\r
+\r
+[Pcd]\r
+ gArmTokenSpaceGuid.PcdDebuggerExceptionSupport\r
+ gArmTokenSpaceGuid.PcdCpuVectorBaseAddress\r
--- /dev/null
+## @file\r
+# Instance of CpuExceptionHandlerLib Library for ARM/AArch64 architectures\r
+#\r
+# This library instance is used when exception vectors must be relocated to\r
+# a specific address. The address is specified by PcdCpuVectorBaseAddress.\r
+# Since the alignment requirement for in-place exception handlers causes\r
+# image size to increase, this instance is useful for modules that need to\r
+# minimize space used in their FV (like XIP modules). See ArmExceptionLib.inf\r
+# for the in-place exception handler alternative.\r
+#\r
+# Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
+# Copyright (c) 2016 HP Development Company, L.P.\r
+#\r
+# 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
+#\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = ArmRelocateExceptionLib\r
+ FILE_GUID = 62AA447A-1FBA-429E-9E0D-CE0D2D8DCF58\r
+ MODULE_TYPE = BASE\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = CpuExceptionHandlerLib\r
+\r
+[Sources.common]\r
+ ArmExceptionLib.c\r
+\r
+[Sources.Arm]\r
+ Arm/ArmException.c\r
+ Arm/ExceptionSupport.asm | RVCT\r
+ Arm/ExceptionSupport.S | GCC\r
+\r
+[Sources.AARCH64]\r
+ AArch64/AArch64Exception.c\r
+ AArch64/ExceptionSupport.S\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ ArmPkg/ArmPkg.dec\r
+\r
+[LibraryClasses]\r
+ ArmLib\r
+ DebugLib\r
+ DefaultExceptionHandlerLib\r
+ BaseMemoryLib\r
+ CacheMaintenanceLib\r
+\r
+[Pcd]\r
+ gArmTokenSpaceGuid.PcdDebuggerExceptionSupport\r
+ gArmTokenSpaceGuid.PcdCpuVectorBaseAddress\r
+\r
+[BuildOptions]\r
+ # We must pass a define to specify that we are relocating vectors so the\r
+ # vector alignment is relaxed (space savings); note that this must be done\r
+ # as a define and not a PCD since it affects assembly directives.\r
+ *_*_*_PP_FLAGS = -DARM_RELOCATE_VECTORS\r
+ *_*_*_CC_FLAGS = -DARM_RELOCATE_VECTORS\r