+++ /dev/null
-/** @file\r
-\r
- Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
- Portions Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<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 "CpuDxe.h"\r
-\r
-#include <Chipset/AArch64.h>\r
-\r
-VOID\r
-ExceptionHandlersStart (\r
- VOID\r
- );\r
-\r
-VOID\r
-ExceptionHandlersEnd (\r
- VOID\r
- );\r
-\r
-VOID\r
-CommonExceptionEntry (\r
- VOID\r
- );\r
-\r
-VOID\r
-AsmCommonExceptionEntry (\r
- VOID\r
- );\r
-\r
-\r
-EFI_EXCEPTION_CALLBACK gExceptionHandlers[MAX_AARCH64_EXCEPTION + 1];\r
-EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[MAX_AARCH64_EXCEPTION + 1];\r
-\r
-\r
-\r
-/**\r
- This function registers and enables the handler specified by InterruptHandler for a processor\r
- interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the\r
- handler for the processor interrupt or exception type specified by InterruptType is uninstalled.\r
- The installed handler is called once for each processor interrupt or exception.\r
-\r
- @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts\r
- are enabled and FALSE if interrupts are disabled.\r
- @param InterruptHandler 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 InterruptHandler is not NULL, and a handler for InterruptType was\r
- previously installed.\r
- @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not\r
- previously installed.\r
- @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.\r
-\r
-**/\r
-EFI_STATUS\r
-RegisterInterruptHandler (\r
- IN EFI_EXCEPTION_TYPE InterruptType,\r
- IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
- )\r
-{\r
- if (InterruptType > MAX_AARCH64_EXCEPTION) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {\r
- return EFI_ALREADY_STARTED;\r
- }\r
-\r
- gExceptionHandlers[InterruptType] = InterruptHandler;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\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 <= MAX_AARCH64_EXCEPTION) {\r
- if (gExceptionHandlers[ExceptionType]) {\r
- gExceptionHandlers[ExceptionType] (ExceptionType, SystemContext);\r
- return;\r
- }\r
- } else {\r
- DEBUG ((EFI_D_ERROR, "Unknown exception type %d from %016lx\n", ExceptionType, SystemContext.SystemContextAArch64->ELR));\r
- ASSERT (FALSE);\r
- }\r
-\r
- DefaultExceptionHandler (ExceptionType, SystemContext);\r
-}\r
-\r
-\r
-\r
-EFI_STATUS\r
-InitializeExceptions (\r
- IN EFI_CPU_ARCH_PROTOCOL *Cpu\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BOOLEAN IrqEnabled;\r
- BOOLEAN FiqEnabled;\r
-\r
- Status = EFI_SUCCESS;\r
- ZeroMem (gExceptionHandlers,sizeof(*gExceptionHandlers));\r
-\r
- //\r
- // Disable interrupts\r
- //\r
- Cpu->GetInterruptState (Cpu, &IrqEnabled);\r
- Cpu->DisableInterrupt (Cpu);\r
-\r
- //\r
- // EFI does not use the FIQ, but a debugger might so we must disable\r
- // as we take over the exception vectors.\r
- //\r
- FiqEnabled = ArmGetFiqState ();\r
- ArmDisableFiq ();\r
-\r
- // The AArch64 Vector table must be 2k-byte aligned - if this assertion fails ensure 'Align=4K'\r
- // is defined into your FDF for this module.\r
- ASSERT (((UINTN)ExceptionHandlersStart & ARM_VECTOR_TABLE_ALIGNMENT) == 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
- ArmWriteVBar ((UINTN)ExceptionHandlersStart);\r
-\r
- if (FiqEnabled) {\r
- ArmEnableFiq ();\r
- }\r
-\r
- if (IrqEnabled) {\r
- //\r
- // Restore interrupt state\r
- //\r
- Status = Cpu->EnableInterrupt (Cpu);\r
- }\r
-\r
- return Status;\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
-//\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
-\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
-// This code gets copied to the ARM vector table\r
-// VectorTableStart - VectorTableEnd gets copied\r
-//\r
-VECTOR_BASE(ExceptionHandlersStart)\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(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 3f\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
-\r
- // Adjust SP to save next set\r
-3: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(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 3f\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
-\r
-3:// 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
-\r
- Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
- Copyright (c) 2014, ARM Limited. All rights reserved.<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 "CpuDxe.h"\r
-\r
-//FIXME: Will not compile on non-ARMv7 builds\r
-#include <Chipset/ArmV7.h>\r
-\r
-VOID\r
-ExceptionHandlersStart (\r
- VOID\r
- );\r
-\r
-VOID\r
-ExceptionHandlersEnd (\r
- VOID\r
- );\r
-\r
-VOID\r
-CommonExceptionEntry (\r
- VOID\r
- );\r
-\r
-VOID\r
-AsmCommonExceptionEntry (\r
- VOID\r
- );\r
-\r
-\r
-EFI_EXCEPTION_CALLBACK gExceptionHandlers[MAX_ARM_EXCEPTION + 1];\r
-EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[MAX_ARM_EXCEPTION + 1];\r
-\r
-\r
-\r
-/**\r
- This function registers and enables the handler specified by InterruptHandler for a processor\r
- interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the\r
- handler for the processor interrupt or exception type specified by InterruptType is uninstalled.\r
- The installed handler is called once for each processor interrupt or exception.\r
-\r
- @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts\r
- are enabled and FALSE if interrupts are disabled.\r
- @param InterruptHandler 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 InterruptHandler is not NULL, and a handler for InterruptType was\r
- previously installed.\r
- @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not\r
- previously installed.\r
- @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.\r
-\r
-**/\r
-EFI_STATUS\r
-RegisterInterruptHandler (\r
- IN EFI_EXCEPTION_TYPE InterruptType,\r
- IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
- )\r
-{\r
- if (InterruptType > MAX_ARM_EXCEPTION) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {\r
- return EFI_ALREADY_STARTED;\r
- }\r
-\r
- gExceptionHandlers[InterruptType] = InterruptHandler;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\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 <= MAX_ARM_EXCEPTION) {\r
- if (gExceptionHandlers[ExceptionType]) {\r
- gExceptionHandlers[ExceptionType] (ExceptionType, SystemContext);\r
- return;\r
- }\r
- } else {\r
- DEBUG ((EFI_D_ERROR, "Unknown exception type %d from %08x\n", ExceptionType, SystemContext.SystemContextArm->PC));\r
- ASSERT (FALSE);\r
- }\r
-\r
- if (ExceptionType == EXCEPT_ARM_SOFTWARE_INTERRUPT) {\r
- //\r
- // ARM JTAG debuggers some times use this vector, so it is not an error to get one\r
- //\r
- return;\r
- }\r
-\r
- DefaultExceptionHandler (ExceptionType, SystemContext);\r
-}\r
-\r
-\r
-\r
-EFI_STATUS\r
-InitializeExceptions (\r
- IN EFI_CPU_ARCH_PROTOCOL *Cpu\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Offset;\r
- UINTN Length;\r
- UINTN Index;\r
- BOOLEAN IrqEnabled;\r
- BOOLEAN FiqEnabled;\r
- EFI_PHYSICAL_ADDRESS Base;\r
- UINT32 *VectorBase;\r
-\r
- Status = EFI_SUCCESS;\r
- ZeroMem (gExceptionHandlers,sizeof(*gExceptionHandlers));\r
-\r
- //\r
- // Disable interrupts\r
- //\r
- Cpu->GetInterruptState (Cpu, &IrqEnabled);\r
- Cpu->DisableInterrupt (Cpu);\r
-\r
- //\r
- // EFI does not use the FIQ, but a debugger might so we must disable\r
- // as we take over the exception vectors.\r
- //\r
- FiqEnabled = ArmGetFiqState ();\r
- ArmDisableFiq ();\r
-\r
- if (FeaturePcdGet(PcdRelocateVectorTable) == TRUE) {\r
- //\r
- // Copy an implementation of the ARM exception vectors to PcdCpuVectorBaseAddress.\r
- //\r
- Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;\r
-\r
- // Check if the exception vector is in the low address\r
- if (PcdGet32 (PcdCpuVectorBaseAddress) == 0x0) {\r
- // Set SCTLR.V to 0 to enable VBAR to be used\r
- ArmSetLowVectors ();\r
- } else {\r
- ArmSetHighVectors ();\r
- }\r
-\r
- //\r
- // Reserve space for the exception handlers\r
- //\r
- Base = (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdCpuVectorBaseAddress);\r
- VectorBase = (UINT32 *)(UINTN)Base;\r
- Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesCode, EFI_SIZE_TO_PAGES (Length), &Base);\r
- // If the request was for memory that's not in the memory map (which is often the case for 0x00000000\r
- // on embedded systems, for example, we don't want to hang up. So we'll check here for a status of\r
- // EFI_NOT_FOUND, and continue in that case.\r
- if (EFI_ERROR(Status) && (Status != EFI_NOT_FOUND)) {\r
- ASSERT_EFI_ERROR (Status);\r
- }\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 (gDebuggerExceptionHandlers));\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
- // Patch in the common Assembly exception handler\r
- //\r
- Offset = (UINTN)CommonExceptionEntry - (UINTN)ExceptionHandlersStart;\r
- *(UINTN *) ((UINT8 *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress) + Offset) = (UINTN)AsmCommonExceptionEntry;\r
-\r
- //\r
- // Initialize the C entry points for interrupts\r
- //\r
- for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) {\r
- if (!FeaturePcdGet(PcdDebuggerExceptionSupport) ||\r
- (gDebuggerExceptionHandlers[Index] == 0) || (gDebuggerExceptionHandlers[Index] == (VOID *)(UINTN)0xEAFFFFFE)) {\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
- Status = RegisterInterruptHandler (Index, NULL);\r
- ASSERT_EFI_ERROR (Status);\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 *)PcdGet32(PcdCpuVectorBaseAddress), Length);\r
-\r
- //Note: On ARM processor with the Security Extension, the Vector Table can be located anywhere in the memory.\r
- // The Vector Base Address Register defines the location\r
- ArmWriteVBar (PcdGet32(PcdCpuVectorBaseAddress));\r
- } else {\r
- // The Vector table must be 32-byte aligned\r
- if (((UINT32)ExceptionHandlersStart & ARM_VECTOR_TABLE_ALIGNMENT) != 0) {\r
- ASSERT (0);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- // We do not copy the Exception Table at PcdGet32(PcdCpuVectorBaseAddress). We just set Vector Base Address to point into CpuDxe code.\r
- ArmWriteVBar ((UINT32)ExceptionHandlersStart);\r
- }\r
-\r
- if (FiqEnabled) {\r
- ArmEnableFiq ();\r
- }\r
-\r
- if (IrqEnabled) {\r
- //\r
- // Restore interrupt state\r
- //\r
- Status = Cpu->EnableInterrupt (Cpu);\r
- }\r
-\r
- return Status;\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
-#\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
-//\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
CpuDxe.h\r
CpuMpCore.c\r
CpuMmuCommon.c\r
+ Exception.c\r
\r
[Sources.ARM]\r
Arm/Mmu.c\r
- Arm/Exception.c\r
- Arm/ExceptionSupport.asm | RVCT\r
- Arm/ExceptionSupport.S | GCC\r
\r
[Sources.AARCH64]\r
AArch64/Mmu.c\r
- AArch64/Exception.c\r
- AArch64/ExceptionSupport.S\r
\r
[Packages]\r
ArmPkg/ArmPkg.dec\r
BaseMemoryLib\r
CacheMaintenanceLib\r
CpuLib\r
+ CpuExceptionHandlerLib\r
DebugLib\r
DefaultExceptionHandlerLib\r
DxeServicesTableLib\r
gEfiDebugImageInfoTableGuid\r
gArmMpCoreInfoGuid\r
gIdleLoopEventGuid\r
+ gEfiVectorHandoffTableGuid\r
\r
[Pcd.common]\r
gArmTokenSpaceGuid.PcdVFPEnabled\r
- gArmTokenSpaceGuid.PcdCpuVectorBaseAddress\r
\r
[FeaturePcd.common]\r
gArmTokenSpaceGuid.PcdCpuDxeProduceDebugSupport\r
- gArmTokenSpaceGuid.PcdRelocateVectorTable\r
gArmTokenSpaceGuid.PcdDebuggerExceptionSupport\r
\r
[Depex]\r
--- /dev/null
+/** @file\r
+\r
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
+ Portions Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<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 "CpuDxe.h"\r
+#include <Library/CpuExceptionHandlerLib.h>\r
+#include <Guid/VectorHandoffTable.h>\r
+\r
+EFI_STATUS\r
+InitializeExceptions (\r
+ IN EFI_CPU_ARCH_PROTOCOL *Cpu\r
+ ) {\r
+ EFI_STATUS Status;\r
+ EFI_VECTOR_HANDOFF_INFO *VectorInfoList;\r
+ EFI_VECTOR_HANDOFF_INFO *VectorInfo;\r
+ BOOLEAN IrqEnabled;\r
+ BOOLEAN FiqEnabled;\r
+\r
+ VectorInfo = (EFI_VECTOR_HANDOFF_INFO *)NULL;\r
+ Status = EfiGetSystemConfigurationTable(&gEfiVectorHandoffTableGuid, (VOID **)&VectorInfoList);\r
+ if (Status == EFI_SUCCESS && VectorInfoList != NULL) {\r
+ VectorInfo = VectorInfoList;\r
+ }\r
+\r
+ // intialize the CpuExceptionHandlerLib so we take over the exception vector table from the DXE Core\r
+ InitializeCpuExceptionHandlers(VectorInfo);\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Disable interrupts\r
+ //\r
+ Cpu->GetInterruptState (Cpu, &IrqEnabled);\r
+ Cpu->DisableInterrupt (Cpu);\r
+\r
+ //\r
+ // EFI does not use the FIQ, but a debugger might so we must disable\r
+ // as we take over the exception vectors.\r
+ //\r
+ FiqEnabled = ArmGetFiqState ();\r
+ ArmDisableFiq ();\r
+\r
+ if (FiqEnabled) {\r
+ ArmEnableFiq ();\r
+ }\r
+\r
+ if (IrqEnabled) {\r
+ //\r
+ // Restore interrupt state\r
+ //\r
+ Status = Cpu->EnableInterrupt (Cpu);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+This function registers and enables the handler specified by InterruptHandler for a processor\r
+interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the\r
+handler for the processor interrupt or exception type specified by InterruptType is uninstalled.\r
+The installed handler is called once for each processor interrupt or exception.\r
+\r
+@param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts\r
+are enabled and FALSE if interrupts are disabled.\r
+@param InterruptHandler 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 InterruptHandler is not NULL, and a handler for InterruptType was\r
+previously installed.\r
+@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not\r
+previously installed.\r
+@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+RegisterInterruptHandler(\r
+ IN EFI_EXCEPTION_TYPE InterruptType,\r
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
+ ) {\r
+ // pass down to CpuExceptionHandlerLib\r
+ return (EFI_STATUS)RegisterCpuInterruptHandler(InterruptType, InterruptHandler);\r
+}\r