diff options
author | Cohen, Eugene <eugene@hp.com> | 2016-03-07 15:16:38 +0000 |
---|---|---|
committer | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2016-03-17 09:15:14 +0100 |
commit | 5811eea0fdb56187597e50b1282e7cfab4965a65 (patch) | |
tree | 550a7e6a4d7c86d3ad19304122dd4c6a8f197a2c | |
parent | 8a47a6cb9e77e4cc4bf42391f7f970173bcead27 (diff) | |
download | edk2-platforms-5811eea0fdb56187597e50b1282e7cfab4965a65.tar.xz |
ArmPkg: update CpuDxe to use CpuExceptionHandlerLib
Use the new ARM/AArch64 implementation of the base
CpuExceptionHandlerLib library from CpuDxe to centralize
exception handling.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Eugene Cohen <eugene@hp.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
-rw-r--r-- | ArmPkg/Drivers/CpuDxe/AArch64/Exception.c | 154 | ||||
-rw-r--r-- | ArmPkg/Drivers/CpuDxe/AArch64/ExceptionSupport.S | 402 | ||||
-rw-r--r-- | ArmPkg/Drivers/CpuDxe/Arm/Exception.c | 234 | ||||
-rw-r--r-- | ArmPkg/Drivers/CpuDxe/Arm/ExceptionSupport.S | 304 | ||||
-rw-r--r-- | ArmPkg/Drivers/CpuDxe/Arm/ExceptionSupport.asm | 301 | ||||
-rw-r--r-- | ArmPkg/Drivers/CpuDxe/CpuDxe.inf | 10 | ||||
-rw-r--r-- | ArmPkg/Drivers/CpuDxe/Exception.c | 95 |
7 files changed, 98 insertions, 1402 deletions
diff --git a/ArmPkg/Drivers/CpuDxe/AArch64/Exception.c b/ArmPkg/Drivers/CpuDxe/AArch64/Exception.c deleted file mode 100644 index ce1c6ce09a..0000000000 --- a/ArmPkg/Drivers/CpuDxe/AArch64/Exception.c +++ /dev/null @@ -1,154 +0,0 @@ -/** @file
-
- Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
- Portions Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
-
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "CpuDxe.h"
-
-#include <Chipset/AArch64.h>
-
-VOID
-ExceptionHandlersStart (
- VOID
- );
-
-VOID
-ExceptionHandlersEnd (
- VOID
- );
-
-VOID
-CommonExceptionEntry (
- VOID
- );
-
-VOID
-AsmCommonExceptionEntry (
- VOID
- );
-
-
-EFI_EXCEPTION_CALLBACK gExceptionHandlers[MAX_AARCH64_EXCEPTION + 1];
-EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[MAX_AARCH64_EXCEPTION + 1];
-
-
-
-/**
- This function registers and enables the handler specified by InterruptHandler for a processor
- interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
- handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
- The installed handler is called once for each processor interrupt or exception.
-
- @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
- are enabled and FALSE if interrupts are disabled.
- @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
- when a processor interrupt occurs. If this parameter is NULL, then the handler
- will be uninstalled.
-
- @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
- @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
- previously installed.
- @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
- previously installed.
- @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
-
-**/
-EFI_STATUS
-RegisterInterruptHandler (
- IN EFI_EXCEPTION_TYPE InterruptType,
- IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
- )
-{
- if (InterruptType > MAX_AARCH64_EXCEPTION) {
- return EFI_UNSUPPORTED;
- }
-
- if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {
- return EFI_ALREADY_STARTED;
- }
-
- gExceptionHandlers[InterruptType] = InterruptHandler;
-
- return EFI_SUCCESS;
-}
-
-
-
-VOID
-EFIAPI
-CommonCExceptionHandler (
- IN EFI_EXCEPTION_TYPE ExceptionType,
- IN OUT EFI_SYSTEM_CONTEXT SystemContext
- )
-{
- if (ExceptionType <= MAX_AARCH64_EXCEPTION) {
- if (gExceptionHandlers[ExceptionType]) {
- gExceptionHandlers[ExceptionType] (ExceptionType, SystemContext);
- return;
- }
- } else {
- DEBUG ((EFI_D_ERROR, "Unknown exception type %d from %016lx\n", ExceptionType, SystemContext.SystemContextAArch64->ELR));
- ASSERT (FALSE);
- }
-
- DefaultExceptionHandler (ExceptionType, SystemContext);
-}
-
-
-
-EFI_STATUS
-InitializeExceptions (
- IN EFI_CPU_ARCH_PROTOCOL *Cpu
- )
-{
- EFI_STATUS Status;
- BOOLEAN IrqEnabled;
- BOOLEAN FiqEnabled;
-
- Status = EFI_SUCCESS;
- ZeroMem (gExceptionHandlers,sizeof(*gExceptionHandlers));
-
- //
- // Disable interrupts
- //
- Cpu->GetInterruptState (Cpu, &IrqEnabled);
- Cpu->DisableInterrupt (Cpu);
-
- //
- // EFI does not use the FIQ, but a debugger might so we must disable
- // as we take over the exception vectors.
- //
- FiqEnabled = ArmGetFiqState ();
- ArmDisableFiq ();
-
- // The AArch64 Vector table must be 2k-byte aligned - if this assertion fails ensure 'Align=4K'
- // is defined into your FDF for this module.
- ASSERT (((UINTN)ExceptionHandlersStart & ARM_VECTOR_TABLE_ALIGNMENT) == 0);
-
- // We do not copy the Exception Table at PcdGet32(PcdCpuVectorBaseAddress). We just set Vector
- // Base Address to point into CpuDxe code.
- ArmWriteVBar ((UINTN)ExceptionHandlersStart);
-
- if (FiqEnabled) {
- ArmEnableFiq ();
- }
-
- if (IrqEnabled) {
- //
- // Restore interrupt state
- //
- Status = Cpu->EnableInterrupt (Cpu);
- }
-
- return Status;
-}
diff --git a/ArmPkg/Drivers/CpuDxe/AArch64/ExceptionSupport.S b/ArmPkg/Drivers/CpuDxe/AArch64/ExceptionSupport.S deleted file mode 100644 index edf9973494..0000000000 --- a/ArmPkg/Drivers/CpuDxe/AArch64/ExceptionSupport.S +++ /dev/null @@ -1,402 +0,0 @@ -//
-// Copyright (c) 2011 - 2014 ARM LTD. All rights reserved.<BR>
-// Portion of Copyright (c) 2014 NVIDIA Corporation. All rights reserved.<BR>
-//
-// This program and the accompanying materials
-// are licensed and made available under the terms and conditions of the BSD License
-// which accompanies this distribution. The full text of the license may be found at
-// http://opensource.org/licenses/bsd-license.php
-//
-// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-//
-//------------------------------------------------------------------------------
-
-#include <Chipset/AArch64.h>
-#include <Library/PcdLib.h>
-#include <AsmMacroIoLibV8.h>
-
-/*
- This is the stack constructed by the exception handler (low address to high address).
- X0 to FAR makes up the EFI_SYSTEM_CONTEXT for AArch64.
-
- UINT64 X0; 0x000
- UINT64 X1; 0x008
- UINT64 X2; 0x010
- UINT64 X3; 0x018
- UINT64 X4; 0x020
- UINT64 X5; 0x028
- UINT64 X6; 0x030
- UINT64 X7; 0x038
- UINT64 X8; 0x040
- UINT64 X9; 0x048
- UINT64 X10; 0x050
- UINT64 X11; 0x058
- UINT64 X12; 0x060
- UINT64 X13; 0x068
- UINT64 X14; 0x070
- UINT64 X15; 0x078
- UINT64 X16; 0x080
- UINT64 X17; 0x088
- UINT64 X18; 0x090
- UINT64 X19; 0x098
- UINT64 X20; 0x0a0
- UINT64 X21; 0x0a8
- UINT64 X22; 0x0b0
- UINT64 X23; 0x0b8
- UINT64 X24; 0x0c0
- UINT64 X25; 0x0c8
- UINT64 X26; 0x0d0
- UINT64 X27; 0x0d8
- UINT64 X28; 0x0e0
- UINT64 FP; 0x0e8 // x29 - Frame Pointer
- UINT64 LR; 0x0f0 // x30 - Link Register
- UINT64 SP; 0x0f8 // x31 - Stack Pointer
-
- // FP/SIMD Registers. 128bit if used as Q-regs.
- UINT64 V0[2]; 0x100
- UINT64 V1[2]; 0x110
- UINT64 V2[2]; 0x120
- UINT64 V3[2]; 0x130
- UINT64 V4[2]; 0x140
- UINT64 V5[2]; 0x150
- UINT64 V6[2]; 0x160
- UINT64 V7[2]; 0x170
- UINT64 V8[2]; 0x180
- UINT64 V9[2]; 0x190
- UINT64 V10[2]; 0x1a0
- UINT64 V11[2]; 0x1b0
- UINT64 V12[2]; 0x1c0
- UINT64 V13[2]; 0x1d0
- UINT64 V14[2]; 0x1e0
- UINT64 V15[2]; 0x1f0
- UINT64 V16[2]; 0x200
- UINT64 V17[2]; 0x210
- UINT64 V18[2]; 0x220
- UINT64 V19[2]; 0x230
- UINT64 V20[2]; 0x240
- UINT64 V21[2]; 0x250
- UINT64 V22[2]; 0x260
- UINT64 V23[2]; 0x270
- UINT64 V24[2]; 0x280
- UINT64 V25[2]; 0x290
- UINT64 V26[2]; 0x2a0
- UINT64 V27[2]; 0x2b0
- UINT64 V28[2]; 0x2c0
- UINT64 V29[2]; 0x2d0
- UINT64 V30[2]; 0x2e0
- UINT64 V31[2]; 0x2f0
-
- // System Context
- UINT64 ELR; 0x300 // Exception Link Register
- UINT64 SPSR; 0x308 // Saved Processor Status Register
- UINT64 FPSR; 0x310 // Floating Point Status Register
- UINT64 ESR; 0x318 // Exception syndrome register
- UINT64 FAR; 0x320 // Fault Address Register
- UINT64 Padding;0x328 // Required for stack alignment
-*/
-
-GCC_ASM_EXPORT(ExceptionHandlersEnd)
-GCC_ASM_EXPORT(CommonExceptionEntry)
-GCC_ASM_EXPORT(AsmCommonExceptionEntry)
-GCC_ASM_EXPORT(CommonCExceptionHandler)
-
-.text
-
-#define GP_CONTEXT_SIZE (32 * 8)
-#define FP_CONTEXT_SIZE (32 * 16)
-#define SYS_CONTEXT_SIZE ( 6 * 8) // 5 SYS regs + Alignment requirement (ie: the stack must be aligned on 0x10)
-
-// Cannot str x31 directly
-#define ALL_GP_REGS \
- REG_PAIR (x0, x1, 0x000, GP_CONTEXT_SIZE); \
- REG_PAIR (x2, x3, 0x010, GP_CONTEXT_SIZE); \
- REG_PAIR (x4, x5, 0x020, GP_CONTEXT_SIZE); \
- REG_PAIR (x6, x7, 0x030, GP_CONTEXT_SIZE); \
- REG_PAIR (x8, x9, 0x040, GP_CONTEXT_SIZE); \
- REG_PAIR (x10, x11, 0x050, GP_CONTEXT_SIZE); \
- REG_PAIR (x12, x13, 0x060, GP_CONTEXT_SIZE); \
- REG_PAIR (x14, x15, 0x070, GP_CONTEXT_SIZE); \
- REG_PAIR (x16, x17, 0x080, GP_CONTEXT_SIZE); \
- REG_PAIR (x18, x19, 0x090, GP_CONTEXT_SIZE); \
- REG_PAIR (x20, x21, 0x0a0, GP_CONTEXT_SIZE); \
- REG_PAIR (x22, x23, 0x0b0, GP_CONTEXT_SIZE); \
- REG_PAIR (x24, x25, 0x0c0, GP_CONTEXT_SIZE); \
- REG_PAIR (x26, x27, 0x0d0, GP_CONTEXT_SIZE); \
- REG_PAIR (x28, x29, 0x0e0, GP_CONTEXT_SIZE); \
- REG_ONE (x30, 0x0f0, GP_CONTEXT_SIZE);
-
-// In order to save the SP we need to put it somewhere else first.
-// STR only works with XZR/WZR directly
-#define SAVE_SP \
- add x1, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE); \
- REG_ONE (x1, 0x0f8, GP_CONTEXT_SIZE);
-
-#define ALL_FP_REGS \
- REG_PAIR (q0, q1, 0x000, FP_CONTEXT_SIZE); \
- REG_PAIR (q2, q3, 0x020, FP_CONTEXT_SIZE); \
- REG_PAIR (q4, q5, 0x040, FP_CONTEXT_SIZE); \
- REG_PAIR (q6, q7, 0x060, FP_CONTEXT_SIZE); \
- REG_PAIR (q8, q9, 0x080, FP_CONTEXT_SIZE); \
- REG_PAIR (q10, q11, 0x0a0, FP_CONTEXT_SIZE); \
- REG_PAIR (q12, q13, 0x0c0, FP_CONTEXT_SIZE); \
- REG_PAIR (q14, q15, 0x0e0, FP_CONTEXT_SIZE); \
- REG_PAIR (q16, q17, 0x100, FP_CONTEXT_SIZE); \
- REG_PAIR (q18, q19, 0x120, FP_CONTEXT_SIZE); \
- REG_PAIR (q20, q21, 0x140, FP_CONTEXT_SIZE); \
- REG_PAIR (q22, q23, 0x160, FP_CONTEXT_SIZE); \
- REG_PAIR (q24, q25, 0x180, FP_CONTEXT_SIZE); \
- REG_PAIR (q26, q27, 0x1a0, FP_CONTEXT_SIZE); \
- REG_PAIR (q28, q29, 0x1c0, FP_CONTEXT_SIZE); \
- REG_PAIR (q30, q31, 0x1e0, FP_CONTEXT_SIZE);
-
-#define ALL_SYS_REGS \
- REG_PAIR (x1, x2, 0x000, SYS_CONTEXT_SIZE); \
- REG_PAIR (x3, x4, 0x010, SYS_CONTEXT_SIZE); \
- REG_ONE (x5, 0x020, SYS_CONTEXT_SIZE);
-
-//
-// This code gets copied to the ARM vector table
-// VectorTableStart - VectorTableEnd gets copied
-//
-VECTOR_BASE(ExceptionHandlersStart)
-
-//
-// Current EL with SP0 : 0x0 - 0x180
-//
-VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_SYNC)
-ASM_PFX(SynchronousExceptionSP0):
- b ASM_PFX(SynchronousExceptionEntry)
-
-VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_IRQ)
-ASM_PFX(IrqSP0):
- b ASM_PFX(IrqEntry)
-
-VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_FIQ)
-ASM_PFX(FiqSP0):
- b ASM_PFX(FiqEntry)
-
-VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_SERR)
-ASM_PFX(SErrorSP0):
- b ASM_PFX(SErrorEntry)
-
-//
-// Current EL with SPx: 0x200 - 0x380
-//
-VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPx_SYNC)
-ASM_PFX(SynchronousExceptionSPx):
- b ASM_PFX(SynchronousExceptionEntry)
-
-VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPx_IRQ)
-ASM_PFX(IrqSPx):
- b ASM_PFX(IrqEntry)
-
-VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPx_FIQ)
-ASM_PFX(FiqSPx):
- b ASM_PFX(FiqEntry)
-
-VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPx_SERR)
-ASM_PFX(SErrorSPx):
- b ASM_PFX(SErrorEntry)
-
-//
-// Lower EL using AArch64 : 0x400 - 0x580
-//
-VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_SYNC)
-ASM_PFX(SynchronousExceptionA64):
- b ASM_PFX(SynchronousExceptionEntry)
-
-VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_IRQ)
-ASM_PFX(IrqA64):
- b ASM_PFX(IrqEntry)
-
-VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_FIQ)
-ASM_PFX(FiqA64):
- b ASM_PFX(FiqEntry)
-
-VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_SERR)
-ASM_PFX(SErrorA64):
- b ASM_PFX(SErrorEntry)
-
-//
-// Lower EL using AArch32 : 0x600 - 0x780
-//
-VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_SYNC)
-ASM_PFX(SynchronousExceptionA32):
- b ASM_PFX(SynchronousExceptionEntry)
-
-VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_IRQ)
-ASM_PFX(IrqA32):
- b ASM_PFX(IrqEntry)
-
-VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_FIQ)
-ASM_PFX(FiqA32):
- b ASM_PFX(FiqEntry)
-
-VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_SERR)
-ASM_PFX(SErrorA32):
- b ASM_PFX(SErrorEntry)
-
-VECTOR_END(ExceptionHandlersStart)
-
-#undef REG_PAIR
-#undef REG_ONE
-#define REG_PAIR(REG1, REG2, OFFSET, CONTEXT_SIZE) stp REG1, REG2, [sp, #(OFFSET-CONTEXT_SIZE)]
-#define REG_ONE(REG1, OFFSET, CONTEXT_SIZE) stur REG1, [sp, #(OFFSET-CONTEXT_SIZE)]
-
-ASM_PFX(SynchronousExceptionEntry):
- // Move the stackpointer so we can reach our structure with the str instruction.
- sub sp, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)
-
- // Save all the General regs before touching x0 and x1.
- // This does not save r31(SP) as it is special. We do that later.
- ALL_GP_REGS
-
- // Record the type of exception that occurred.
- mov x0, #EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS
-
- // Jump to our general handler to deal with all the common parts and process the exception.
- ldr x1, ASM_PFX(CommonExceptionEntry)
- br x1
-
-ASM_PFX(IrqEntry):
- sub sp, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)
- ALL_GP_REGS
- mov x0, #EXCEPT_AARCH64_IRQ
- ldr x1, ASM_PFX(CommonExceptionEntry)
- br x1
-
-ASM_PFX(FiqEntry):
- sub sp, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)
- ALL_GP_REGS
- mov x0, #EXCEPT_AARCH64_FIQ
- ldr x1, ASM_PFX(CommonExceptionEntry)
- br x1
-
-ASM_PFX(SErrorEntry):
- sub sp, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)
- ALL_GP_REGS
- mov x0, #EXCEPT_AARCH64_SERROR
- ldr x1, ASM_PFX(CommonExceptionEntry)
- br x1
-
-
-//
-// This gets patched by the C code that patches in the vector table
-//
-.align 3
-ASM_PFX(CommonExceptionEntry):
- .8byte ASM_PFX(AsmCommonExceptionEntry)
-
-ASM_PFX(ExceptionHandlersEnd):
-
-
-
-//
-// This code runs from CpuDxe driver loaded address. It is patched into
-// CommonExceptionEntry.
-//
-ASM_PFX(AsmCommonExceptionEntry):
- /* NOTE:
- We have to break up the save code because the immediate value to be used
- with the SP is too big to do it all in one step so we need to shuffle the SP
- along as we go. (we only have 9bits of immediate to work with) */
-
- // Save the current Stack pointer before we start modifying it.
- SAVE_SP
-
- // Preserve the stack pointer we came in with before we modify it
- EL1_OR_EL2(x1)
-1:mrs x1, elr_el1 // Exception Link Register
- mrs x2, spsr_el1 // Saved Processor Status Register 32bit
- mrs x3, fpsr // Floating point Status Register 32bit
- mrs x4, esr_el1 // EL1 Exception syndrome register 32bit
- mrs x5, far_el1 // EL1 Fault Address Register
- b 3f
-
-2:mrs x1, elr_el2 // Exception Link Register
- mrs x2, spsr_el2 // Saved Processor Status Register 32bit
- mrs x3, fpsr // Floating point Status Register 32bit
- mrs x4, esr_el2 // EL2 Exception syndrome register 32bit
- mrs x5, far_el2 // EL2 Fault Address Register
-
- // Adjust SP to save next set
-3:add sp, sp, #FP_CONTEXT_SIZE
-
- // Push FP regs to Stack.
- ALL_FP_REGS
-
- // Adjust SP to save next set
- add sp, sp, #SYS_CONTEXT_SIZE
-
- // Save the SYS regs
- ALL_SYS_REGS
-
- // Point to top of struct after all regs saved
- sub sp, sp, #(GP_CONTEXT_SIZE + FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)
-
- // x0 still holds the exception type.
- // Set x1 to point to the top of our struct on the Stack
- mov x1, sp
-
-// CommonCExceptionHandler (
-// IN EFI_EXCEPTION_TYPE ExceptionType, R0
-// IN OUT EFI_SYSTEM_CONTEXT SystemContext R1
-// )
-
- // Call the handler as defined above
-
- // For now we spin in the handler if we received an abort of some kind.
- // We do not try to recover.
- bl ASM_PFX(CommonCExceptionHandler) // Call exception handler
-
-
-// Defines for popping from stack
-
-#undef REG_PAIR
-#undef REG_ONE
-#define REG_PAIR(REG1, REG2, OFFSET, CONTEXT_SIZE) ldp REG1, REG2, [sp, #(OFFSET-CONTEXT_SIZE)]
-#define REG_ONE(REG1, OFFSET, CONTEXT_SIZE) ldur REG1, [sp, #(OFFSET-CONTEXT_SIZE)]
-
- //
- // Disable interrupt(IRQ and FIQ) before restoring context,
- // or else the context will be corrupted by interrupt reentrance.
- // Interrupt mask will be restored from spsr by hardware when we call eret
- //
- msr daifset, #3
- isb
-
- // Adjust SP to pop system registers
- add sp, sp, #(GP_CONTEXT_SIZE + FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)
- ALL_SYS_REGS
-
- EL1_OR_EL2(x6)
-1:msr elr_el1, x1 // Exception Link Register
- msr spsr_el1,x2 // Saved Processor Status Register 32bit
- msr fpsr, x3 // Floating point Status Register 32bit
- msr esr_el1, x4 // EL1 Exception syndrome register 32bit
- msr far_el1, x5 // EL1 Fault Address Register
- b 3f
-2:msr elr_el2, x1 // Exception Link Register
- msr spsr_el2,x2 // Saved Processor Status Register 32bit
- msr fpsr, x3 // Floating point Status Register 32bit
- msr esr_el2, x4 // EL2 Exception syndrome register 32bit
- msr far_el2, x5 // EL2 Fault Address Register
-
-3:// pop all regs and return from exception.
- sub sp, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)
- ALL_GP_REGS
-
- // Adjust SP to pop next set
- add sp, sp, #FP_CONTEXT_SIZE
- // Pop FP regs to Stack.
- ALL_FP_REGS
-
- // Adjust SP to be where we started from when we came into the handler.
- // The handler can not change the SP.
- add sp, sp, #SYS_CONTEXT_SIZE
-
- eret
-
-#undef REG_PAIR
-#undef REG_ONE
diff --git a/ArmPkg/Drivers/CpuDxe/Arm/Exception.c b/ArmPkg/Drivers/CpuDxe/Arm/Exception.c deleted file mode 100644 index 4b05199db3..0000000000 --- a/ArmPkg/Drivers/CpuDxe/Arm/Exception.c +++ /dev/null @@ -1,234 +0,0 @@ -/** @file
-
- Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
- Copyright (c) 2014, ARM Limited. All rights reserved.<BR>
-
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "CpuDxe.h"
-
-//FIXME: Will not compile on non-ARMv7 builds
-#include <Chipset/ArmV7.h>
-
-VOID
-ExceptionHandlersStart (
- VOID
- );
-
-VOID
-ExceptionHandlersEnd (
- VOID
- );
-
-VOID
-CommonExceptionEntry (
- VOID
- );
-
-VOID
-AsmCommonExceptionEntry (
- VOID
- );
-
-
-EFI_EXCEPTION_CALLBACK gExceptionHandlers[MAX_ARM_EXCEPTION + 1];
-EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[MAX_ARM_EXCEPTION + 1];
-
-
-
-/**
- This function registers and enables the handler specified by InterruptHandler for a processor
- interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
- handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
- The installed handler is called once for each processor interrupt or exception.
-
- @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
- are enabled and FALSE if interrupts are disabled.
- @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
- when a processor interrupt occurs. If this parameter is NULL, then the handler
- will be uninstalled.
-
- @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
- @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
- previously installed.
- @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
- previously installed.
- @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
-
-**/
-EFI_STATUS
-RegisterInterruptHandler (
- IN EFI_EXCEPTION_TYPE InterruptType,
- IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
- )
-{
- if (InterruptType > MAX_ARM_EXCEPTION) {
- return EFI_UNSUPPORTED;
- }
-
- if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {
- return EFI_ALREADY_STARTED;
- }
-
- gExceptionHandlers[InterruptType] = InterruptHandler;
-
- return EFI_SUCCESS;
-}
-
-
-
-
-VOID
-EFIAPI
-CommonCExceptionHandler (
- IN EFI_EXCEPTION_TYPE ExceptionType,
- IN OUT EFI_SYSTEM_CONTEXT SystemContext
- )
-{
- if (ExceptionType <= MAX_ARM_EXCEPTION) {
- if (gExceptionHandlers[ExceptionType]) {
- gExceptionHandlers[ExceptionType] (ExceptionType, SystemContext);
- return;
- }
- } else {
- DEBUG ((EFI_D_ERROR, "Unknown exception type %d from %08x\n", ExceptionType, SystemContext.SystemContextArm->PC));
- ASSERT (FALSE);
- }
-
- if (ExceptionType == EXCEPT_ARM_SOFTWARE_INTERRUPT) {
- //
- // ARM JTAG debuggers some times use this vector, so it is not an error to get one
- //
- return;
- }
-
- DefaultExceptionHandler (ExceptionType, SystemContext);
-}
-
-
-
-EFI_STATUS
-InitializeExceptions (
- IN EFI_CPU_ARCH_PROTOCOL *Cpu
- )
-{
- EFI_STATUS Status;
- UINTN Offset;
- UINTN Length;
- UINTN Index;
- BOOLEAN IrqEnabled;
- BOOLEAN FiqEnabled;
- EFI_PHYSICAL_ADDRESS Base;
- UINT32 *VectorBase;
-
- Status = EFI_SUCCESS;
- ZeroMem (gExceptionHandlers,sizeof(*gExceptionHandlers));
-
- //
- // Disable interrupts
- //
- Cpu->GetInterruptState (Cpu, &IrqEnabled);
- Cpu->DisableInterrupt (Cpu);
-
- //
- // EFI does not use the FIQ, but a debugger might so we must disable
- // as we take over the exception vectors.
- //
- FiqEnabled = ArmGetFiqState ();
- ArmDisableFiq ();
-
- if (FeaturePcdGet(PcdRelocateVectorTable) == TRUE) {
- //
- // Copy an implementation of the ARM exception vectors to PcdCpuVectorBaseAddress.
- //
- Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;
-
- // Check if the exception vector is in the low address
- if (PcdGet32 (PcdCpuVectorBaseAddress) == 0x0) {
- // Set SCTLR.V to 0 to enable VBAR to be used
- ArmSetLowVectors ();
- } else {
- ArmSetHighVectors ();
- }
-
- //
- // Reserve space for the exception handlers
- //
- Base = (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdCpuVectorBaseAddress);
- VectorBase = (UINT32 *)(UINTN)Base;
- Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesCode, EFI_SIZE_TO_PAGES (Length), &Base);
- // If the request was for memory that's not in the memory map (which is often the case for 0x00000000
- // on embedded systems, for example, we don't want to hang up. So we'll check here for a status of
- // EFI_NOT_FOUND, and continue in that case.
- if (EFI_ERROR(Status) && (Status != EFI_NOT_FOUND)) {
- ASSERT_EFI_ERROR (Status);
- }
-
- if (FeaturePcdGet(PcdDebuggerExceptionSupport) == TRUE) {
- // Save existing vector table, in case debugger is already hooked in
- CopyMem ((VOID *)gDebuggerExceptionHandlers, (VOID *)VectorBase, sizeof (gDebuggerExceptionHandlers));
- }
-
- // Copy our assembly code into the page that contains the exception vectors.
- CopyMem ((VOID *)VectorBase, (VOID *)ExceptionHandlersStart, Length);
-
- //
- // Patch in the common Assembly exception handler
- //
- Offset = (UINTN)CommonExceptionEntry - (UINTN)ExceptionHandlersStart;
- *(UINTN *) ((UINT8 *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress) + Offset) = (UINTN)AsmCommonExceptionEntry;
-
- //
- // Initialize the C entry points for interrupts
- //
- for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) {
- if (!FeaturePcdGet(PcdDebuggerExceptionSupport) ||
- (gDebuggerExceptionHandlers[Index] == 0) || (gDebuggerExceptionHandlers[Index] == (VOID *)(UINTN)0xEAFFFFFE)) {
- // Exception handler contains branch to vector location (jmp $) so no handler
- // NOTE: This code assumes vectors are ARM and not Thumb code
- Status = RegisterInterruptHandler (Index, NULL);
- ASSERT_EFI_ERROR (Status);
- } else {
- // If the debugger has already hooked put its vector back
- VectorBase[Index] = (UINT32)(UINTN)gDebuggerExceptionHandlers[Index];
- }
- }
-
- // Flush Caches since we updated executable stuff
- InvalidateInstructionCacheRange ((VOID *)PcdGet32(PcdCpuVectorBaseAddress), Length);
-
- //Note: On ARM processor with the Security Extension, the Vector Table can be located anywhere in the memory.
- // The Vector Base Address Register defines the location
- ArmWriteVBar (PcdGet32(PcdCpuVectorBaseAddress));
- } else {
- // The Vector table must be 32-byte aligned
- if (((UINT32)ExceptionHandlersStart & ARM_VECTOR_TABLE_ALIGNMENT) != 0) {
- ASSERT (0);
- return EFI_INVALID_PARAMETER;
- }
-
- // We do not copy the Exception Table at PcdGet32(PcdCpuVectorBaseAddress). We just set Vector Base Address to point into CpuDxe code.
- ArmWriteVBar ((UINT32)ExceptionHandlersStart);
- }
-
- if (FiqEnabled) {
- ArmEnableFiq ();
- }
-
- if (IrqEnabled) {
- //
- // Restore interrupt state
- //
- Status = Cpu->EnableInterrupt (Cpu);
- }
-
- return Status;
-}
diff --git a/ArmPkg/Drivers/CpuDxe/Arm/ExceptionSupport.S b/ArmPkg/Drivers/CpuDxe/Arm/ExceptionSupport.S deleted file mode 100644 index 673b931297..0000000000 --- a/ArmPkg/Drivers/CpuDxe/Arm/ExceptionSupport.S +++ /dev/null @@ -1,304 +0,0 @@ -#------------------------------------------------------------------------------
-#
-# Use ARMv6 instruction to operate on a single stack
-#
-# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
-# Copyright (c) 2014, ARM Limited. All rights reserved.<BR>
-#
-# This program and the accompanying materials
-# are licensed and made available under the terms and conditions of the BSD License
-# which accompanies this distribution. The full text of the license may be found at
-# http://opensource.org/licenses/bsd-license.php
-#
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-#
-#------------------------------------------------------------------------------
-
-#include <Library/PcdLib.h>
-
-/*
-
-This is the stack constructed by the exception handler (low address to high address)
- # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM
- Reg Offset
- === ======
- R0 0x00 # stmfd SP!,{R0-R12}
- R1 0x04
- R2 0x08
- R3 0x0c
- R4 0x10
- R5 0x14
- R6 0x18
- R7 0x1c
- R8 0x20
- R9 0x24
- R10 0x28
- R11 0x2c
- R12 0x30
- SP 0x34 # reserved via subtraction 0x20 (32) from SP
- LR 0x38
- PC 0x3c
- CPSR 0x40
- DFSR 0x44
- DFAR 0x48
- IFSR 0x4c
- IFAR 0x50
-
- LR 0x54 # SVC Link register (we need to restore it)
-
- LR 0x58 # pushed by srsfd
- CPSR 0x5c
-
- */
-
-
-GCC_ASM_EXPORT(ExceptionHandlersStart)
-GCC_ASM_EXPORT(ExceptionHandlersEnd)
-GCC_ASM_EXPORT(CommonExceptionEntry)
-GCC_ASM_EXPORT(AsmCommonExceptionEntry)
-GCC_ASM_EXPORT(CommonCExceptionHandler)
-
-.text
-.syntax unified
-#if !defined(__APPLE__)
-.fpu neon @ makes vpush/vpop assemble
-#endif
-.align 5
-
-
-//
-// This code gets copied to the ARM vector table
-// ExceptionHandlersStart - ExceptionHandlersEnd gets copied
-//
-ASM_PFX(ExceptionHandlersStart):
-
-ASM_PFX(Reset):
- b ASM_PFX(ResetEntry)
-
-ASM_PFX(UndefinedInstruction):
- b ASM_PFX(UndefinedInstructionEntry)
-
-ASM_PFX(SoftwareInterrupt):
- b ASM_PFX(SoftwareInterruptEntry)
-
-ASM_PFX(PrefetchAbort):
- b ASM_PFX(PrefetchAbortEntry)
-
-ASM_PFX(DataAbort):
- b ASM_PFX(DataAbortEntry)
-
-ASM_PFX(ReservedException):
- b ASM_PFX(ReservedExceptionEntry)
-
-ASM_PFX(Irq):
- b ASM_PFX(IrqEntry)
-
-ASM_PFX(Fiq):
- b ASM_PFX(FiqEntry)
-
-ASM_PFX(ResetEntry):
- srsdb #0x13! @ Store return state on SVC stack
- @ We are already in SVC mode
-
- stmfd SP!,{LR} @ Store the link register for the current mode
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
- stmfd SP!,{R0-R12} @ Store the register state
-
- mov R0,#0 @ ExceptionType
- ldr R1,ASM_PFX(CommonExceptionEntry)
- bx R1
-
-ASM_PFX(UndefinedInstructionEntry):
- sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry
- srsdb #0x13! @ Store return state on SVC stack
- cps #0x13 @ Switch to SVC for common stack
- stmfd SP!,{LR} @ Store the link register for the current mode
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
- stmfd SP!,{R0-R12} @ Store the register state
-
- mov R0,#1 @ ExceptionType
- ldr R1,ASM_PFX(CommonExceptionEntry)
- bx R1
-
-ASM_PFX(SoftwareInterruptEntry):
- srsdb #0x13! @ Store return state on SVC stack
- @ We are already in SVC mode
- stmfd SP!,{LR} @ Store the link register for the current mode
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
- stmfd SP!,{R0-R12} @ Store the register state
-
- mov R0,#2 @ ExceptionType
- ldr R1,ASM_PFX(CommonExceptionEntry)
- bx R1
-
-ASM_PFX(PrefetchAbortEntry):
- sub LR,LR,#4
- srsdb #0x13! @ Store return state on SVC stack
- cps #0x13 @ Switch to SVC for common stack
- stmfd SP!,{LR} @ Store the link register for the current mode
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
- stmfd SP!,{R0-R12} @ Store the register state
-
- mov R0,#3 @ ExceptionType
- ldr R1,ASM_PFX(CommonExceptionEntry)
- bx R1
-
-ASM_PFX(DataAbortEntry):
- sub LR,LR,#8
- srsdb #0x13! @ Store return state on SVC stack
- cps #0x13 @ Switch to SVC for common stack
- stmfd SP!,{LR} @ Store the link register for the current mode
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
- stmfd SP!,{R0-R12} @ Store the register state
-
- mov R0,#4
- ldr R1,ASM_PFX(CommonExceptionEntry)
- bx R1
-
-ASM_PFX(ReservedExceptionEntry):
- srsdb #0x13! @ Store return state on SVC stack
- cps #0x13 @ Switch to SVC for common stack
- stmfd SP!,{LR} @ Store the link register for the current mode
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
- stmfd SP!,{R0-R12} @ Store the register state
-
- mov R0,#5
- ldr R1,ASM_PFX(CommonExceptionEntry)
- bx R1
-
-ASM_PFX(IrqEntry):
- sub LR,LR,#4
- srsdb #0x13! @ Store return state on SVC stack
- cps #0x13 @ Switch to SVC for common stack
- stmfd SP!,{LR} @ Store the link register for the current mode
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
- stmfd SP!,{R0-R12} @ Store the register state
-
- mov R0,#6 @ ExceptionType
- ldr R1,ASM_PFX(CommonExceptionEntry)
- bx R1
-
-ASM_PFX(FiqEntry):
- sub LR,LR,#4
- srsdb #0x13! @ Store return state on SVC stack
- cps #0x13 @ Switch to SVC for common stack
- stmfd SP!,{LR} @ Store the link register for the current mode
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
- stmfd SP!,{R0-R12} @ Store the register state
- @ Since we have already switch to SVC R8_fiq - R12_fiq
- @ never get used or saved
- mov R0,#7 @ ExceptionType
- ldr R1,ASM_PFX(CommonExceptionEntry)
- bx R1
-
-//
-// This gets patched by the C code that patches in the vector table
-//
-ASM_PFX(CommonExceptionEntry):
- .word ASM_PFX(AsmCommonExceptionEntry)
-
-ASM_PFX(ExceptionHandlersEnd):
-
-//
-// This code runs from CpuDxe driver loaded address. It is patched into
-// CommonExceptionEntry.
-//
-ASM_PFX(AsmCommonExceptionEntry):
- mrc p15, 0, R1, c6, c0, 2 @ Read IFAR
- str R1, [SP, #0x50] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR
-
- mrc p15, 0, R1, c5, c0, 1 @ Read IFSR
- str R1, [SP, #0x4c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR
-
- mrc p15, 0, R1, c6, c0, 0 @ Read DFAR
- str R1, [SP, #0x48] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR
-
- mrc p15, 0, R1, c5, c0, 0 @ Read DFSR
- str R1, [SP, #0x44] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR
-
- ldr R1, [SP, #0x5c] @ srsdb saved pre-exception CPSR on the stack
- str R1, [SP, #0x40] @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR
-
- add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
- and R3, R1, #0x1f @ Check CPSR to see if User or System Mode
- cmp R3, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))
- cmpne R3, #0x10 @
- stmdaeq R2, {lr}^ @ save unbanked lr
- @ else
- stmdane R2, {lr} @ save SVC lr
-
-
- ldr R5, [SP, #0x58] @ PC is the LR pushed by srsfd
- @ Check to see if we have to adjust for Thumb entry
- sub r4, r0, #1 @ if (ExceptionType == 1 || ExceptionType == 2)) {
- cmp r4, #1 @ // UND & SVC have differnt LR adjust for Thumb
- bhi NoAdjustNeeded
-
- tst r1, #0x20 @ if ((CPSR & T)) == T) { // Thumb Mode on entry
- addne R5, R5, #2 @ PC += 2;
- strne R5,[SP,#0x58] @ Update LR value pushed by srsfd
-
-NoAdjustNeeded:
-
- str R5, [SP, #0x3c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC
-
- add R1, SP, #0x60 @ We pushed 0x60 bytes on the stack
- str R1, [SP, #0x34] @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP
-
- @ R0 is ExceptionType
- mov R1,SP @ R1 is SystemContext
-
-#if (FixedPcdGet32(PcdVFPEnabled))
- vpush {d0-d15} @ save vstm registers in case they are used in optimizations
-#endif
-
- mov R4, SP @ Save current SP
- tst R4, #4
- subne SP, SP, #4 @ Adjust SP if not 8-byte aligned
-
-/*
-VOID
-EFIAPI
-CommonCExceptionHandler (
- IN EFI_EXCEPTION_TYPE ExceptionType, R0
- IN OUT EFI_SYSTEM_CONTEXT SystemContext R1
- )
-
-*/
- blx ASM_PFX(CommonCExceptionHandler) @ Call exception handler
-
- mov SP, R4 @ Restore SP
-
-#if (FixedPcdGet32(PcdVFPEnabled))
- vpop {d0-d15}
-#endif
-
- ldr R1, [SP, #0x4c] @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR
- mcr p15, 0, R1, c5, c0, 1 @ Write IFSR
-
- ldr R1, [SP, #0x44] @ Restore EFI_SYSTEM_CONTEXT_ARM.DFSR
- mcr p15, 0, R1, c5, c0, 0 @ Write DFSR
-
- ldr R1,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC
- str R1,[SP,#0x58] @ Store it back to srsfd stack slot so it can be restored
-
- ldr R1,[SP,#0x40] @ EFI_SYSTEM_CONTEXT_ARM.CPSR
- str R1,[SP,#0x5c] @ Store it back to srsfd stack slot so it can be restored
-
- add R3, SP, #0x54 @ Make R3 point to SVC LR saved on entry
- add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
- and R1, R1, #0x1f @ Check to see if User or System Mode
- cmp R1, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))
- cmpne R1, #0x10 @
- ldmibeq R2, {lr}^ @ restore unbanked lr
- @ else
- ldmibne R3, {lr} @ restore SVC lr, via ldmfd SP!, {LR}
-
- ldmfd SP!,{R0-R12} @ Restore general purpose registers
- @ Exception handler can not change SP
-
- add SP,SP,#0x20 @ Clear out the remaining stack space
- ldmfd SP!,{LR} @ restore the link register for this context
- rfefd SP! @ return from exception via srsfd stack slot
-
diff --git a/ArmPkg/Drivers/CpuDxe/Arm/ExceptionSupport.asm b/ArmPkg/Drivers/CpuDxe/Arm/ExceptionSupport.asm deleted file mode 100644 index b28ff9f7ee..0000000000 --- a/ArmPkg/Drivers/CpuDxe/Arm/ExceptionSupport.asm +++ /dev/null @@ -1,301 +0,0 @@ -//------------------------------------------------------------------------------
-//
-// Use ARMv6 instruction to operate on a single stack
-//
-// Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
-// Copyright (c) 2014, ARM Limited. All rights reserved.<BR>
-//
-// This program and the accompanying materials
-// are licensed and made available under the terms and conditions of the BSD License
-// which accompanies this distribution. The full text of the license may be found at
-// http://opensource.org/licenses/bsd-license.php
-//
-// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-//
-//------------------------------------------------------------------------------
-
-#include <Library/PcdLib.h>
-
-/*
-
-This is the stack constructed by the exception handler (low address to high address)
- # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM
- Reg Offset
- === ======
- R0 0x00 # stmfd SP!,{R0-R12}
- R1 0x04
- R2 0x08
- R3 0x0c
- R4 0x10
- R5 0x14
- R6 0x18
- R7 0x1c
- R8 0x20
- R9 0x24
- R10 0x28
- R11 0x2c
- R12 0x30
- SP 0x34 # reserved via subtraction 0x20 (32) from SP
- LR 0x38
- PC 0x3c
- CPSR 0x40
- DFSR 0x44
- DFAR 0x48
- IFSR 0x4c
- IFAR 0x50
-
- LR 0x54 # SVC Link register (we need to restore it)
-
- LR 0x58 # pushed by srsfd
- CPSR 0x5c
-
- */
-
-
- EXPORT ExceptionHandlersStart
- EXPORT ExceptionHandlersEnd
- EXPORT CommonExceptionEntry
- EXPORT AsmCommonExceptionEntry
- IMPORT CommonCExceptionHandler
-
- PRESERVE8
- AREA DxeExceptionHandlers, CODE, READONLY, CODEALIGN, ALIGN=5
-
-//
-// This code gets copied to the ARM vector table
-// ExceptionHandlersStart - ExceptionHandlersEnd gets copied
-//
-ExceptionHandlersStart
-
-Reset
- b ResetEntry
-
-UndefinedInstruction
- b UndefinedInstructionEntry
-
-SoftwareInterrupt
- b SoftwareInterruptEntry
-
-PrefetchAbort
- b PrefetchAbortEntry
-
-DataAbort
- b DataAbortEntry
-
-ReservedException
- b ReservedExceptionEntry
-
-Irq
- b IrqEntry
-
-Fiq
- b FiqEntry
-
-ResetEntry
- srsfd #0x13! ; Store return state on SVC stack
- ; We are already in SVC mode
- stmfd SP!,{LR} ; Store the link register for the current mode
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
- stmfd SP!,{R0-R12} ; Store the register state
-
- mov R0,#0 ; ExceptionType
- ldr R1,CommonExceptionEntry
- bx R1
-
-UndefinedInstructionEntry
- sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry
- srsfd #0x13! ; Store return state on SVC stack
- cps #0x13 ; Switch to SVC for common stack
- stmfd SP!,{LR} ; Store the link register for the current mode
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
- stmfd SP!,{R0-R12} ; Store the register state
-
- mov R0,#1 ; ExceptionType
- ldr R1,CommonExceptionEntry;
- bx R1
-
-SoftwareInterruptEntry
- srsfd #0x13! ; Store return state on SVC stack
- ; We are already in SVC mode
- stmfd SP!,{LR} ; Store the link register for the current mode
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
- stmfd SP!,{R0-R12} ; Store the register state
-
- mov R0,#2 ; ExceptionType
- ldr R1,CommonExceptionEntry
- bx R1
-
-PrefetchAbortEntry
- sub LR,LR,#4
- srsfd #0x13! ; Store return state on SVC stack
- cps #0x13 ; Switch to SVC for common stack
- stmfd SP!,{LR} ; Store the link register for the current mode
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
- stmfd SP!,{R0-R12} ; Store the register state
-
- mov R0,#3 ; ExceptionType
- ldr R1,CommonExceptionEntry
- bx R1
-
-DataAbortEntry
- sub LR,LR,#8
- srsfd #0x13! ; Store return state on SVC stack
- cps #0x13 ; Switch to SVC for common stack
- stmfd SP!,{LR} ; Store the link register for the current mode
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
- stmfd SP!,{R0-R12} ; Store the register state
-
- mov R0,#4 ; ExceptionType
- ldr R1,CommonExceptionEntry
- bx R1
-
-ReservedExceptionEntry
- srsfd #0x13! ; Store return state on SVC stack
- cps #0x13 ; Switch to SVC for common stack
- stmfd SP!,{LR} ; Store the link register for the current mode
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
- stmfd SP!,{R0-R12} ; Store the register state
-
- mov R0,#5 ; ExceptionType
- ldr R1,CommonExceptionEntry
- bx R1
-
-IrqEntry
- sub LR,LR,#4
- srsfd #0x13! ; Store return state on SVC stack
- cps #0x13 ; Switch to SVC for common stack
- stmfd SP!,{LR} ; Store the link register for the current mode
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
- stmfd SP!,{R0-R12} ; Store the register state
-
- mov R0,#6 ; ExceptionType
- ldr R1,CommonExceptionEntry
- bx R1
-
-FiqEntry
- sub LR,LR,#4
- srsfd #0x13! ; Store return state on SVC stack
- cps #0x13 ; Switch to SVC for common stack
- stmfd SP!,{LR} ; Store the link register for the current mode
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
- stmfd SP!,{R0-R12} ; Store the register state
- ; Since we have already switch to SVC R8_fiq - R12_fiq
- ; never get used or saved
- mov R0,#7 ; ExceptionType
- ldr R1,CommonExceptionEntry
- bx R1
-
-//
-// This gets patched by the C code that patches in the vector table
-//
-CommonExceptionEntry
- dcd AsmCommonExceptionEntry
-
-ExceptionHandlersEnd
-
-//
-// This code runs from CpuDxe driver loaded address. It is patched into
-// CommonExceptionEntry.
-//
-AsmCommonExceptionEntry
- mrc p15, 0, R1, c6, c0, 2 ; Read IFAR
- str R1, [SP, #0x50] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR
-
- mrc p15, 0, R1, c5, c0, 1 ; Read IFSR
- str R1, [SP, #0x4c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR
-
- mrc p15, 0, R1, c6, c0, 0 ; Read DFAR
- str R1, [SP, #0x48] ; Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR
-
- mrc p15, 0, R1, c5, c0, 0 ; Read DFSR
- str R1, [SP, #0x44] ; Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR
-
- ldr R1, [SP, #0x5c] ; srsfd saved pre-exception CPSR on the stack
- str R1, [SP, #0x40] ; Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR
-
- add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
- and R3, R1, #0x1f ; Check CPSR to see if User or System Mode
- cmp R3, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1f))
- cmpne R3, #0x10 ;
- stmeqed R2, {lr}^ ; save unbanked lr
- ; else
- stmneed R2, {lr} ; save SVC lr
-
-
- ldr R5, [SP, #0x58] ; PC is the LR pushed by srsfd
- ; Check to see if we have to adjust for Thumb entry
- sub r4, r0, #1 ; if (ExceptionType == 1 || ExceptionType == 2)) {
- cmp r4, #1 ; // UND & SVC have differnt LR adjust for Thumb
- bhi NoAdjustNeeded
-
- tst r1, #0x20 ; if ((CPSR & T)) == T) { // Thumb Mode on entry
- addne R5, R5, #2 ; PC += 2;
- strne R5,[SP,#0x58] ; Update LR value pushed by srsfd
-
-NoAdjustNeeded
-
- str R5, [SP, #0x3c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.PC
-
- add R1, SP, #0x60 ; We pushed 0x60 bytes on the stack
- str R1, [SP, #0x34] ; Store it in EFI_SYSTEM_CONTEXT_ARM.SP
-
- ; R0 is ExceptionType
- mov R1,SP ; R1 is SystemContext
-
-#if (FixedPcdGet32(PcdVFPEnabled))
- vpush {d0-d15} ; save vstm registers in case they are used in optimizations
-#endif
-
- mov R4, SP ; Save current SP
- tst R4, #4
- subne SP, SP, #4 ; Adjust SP if not 8-byte aligned
-
-/*
-VOID
-EFIAPI
-CommonCExceptionHandler (
- IN EFI_EXCEPTION_TYPE ExceptionType, R0
- IN OUT EFI_SYSTEM_CONTEXT SystemContext R1
- )
-
-*/
- blx CommonCExceptionHandler ; Call exception handler
-
- mov SP, R4 ; Restore SP
-
-#if (FixedPcdGet32(PcdVFPEnabled))
- vpop {d0-d15}
-#endif
-
- ldr R1, [SP, #0x4c] ; Restore EFI_SYSTEM_CONTEXT_ARM.IFSR
- mcr p15, 0, R1, c5, c0, 1 ; Write IFSR
-
- ldr R1, [SP, #0x44] ; Restore EFI_SYSTEM_CONTEXT_ARM.DFSR
- mcr p15, 0, R1, c5, c0, 0 ; Write DFSR
-
- ldr R1,[SP,#0x3c] ; EFI_SYSTEM_CONTEXT_ARM.PC
- str R1,[SP,#0x58] ; Store it back to srsfd stack slot so it can be restored
-
- ldr R1,[SP,#0x40] ; EFI_SYSTEM_CONTEXT_ARM.CPSR
- str R1,[SP,#0x5c] ; Store it back to srsfd stack slot so it can be restored
-
- add R3, SP, #0x54 ; Make R3 point to SVC LR saved on entry
- add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
- and R1, R1, #0x1f ; Check to see if User or System Mode
- cmp R1, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1f))
- cmpne R1, #0x10 ;
- ldmeqed R2, {lr}^ ; restore unbanked lr
- ; else
- ldmneed R3, {lr} ; restore SVC lr, via ldmfd SP!, {LR}
-
- ldmfd SP!,{R0-R12} ; Restore general purpose registers
- ; Exception handler can not change SP
-
- add SP,SP,#0x20 ; Clear out the remaining stack space
- ldmfd SP!,{LR} ; restore the link register for this context
- rfefd SP! ; return from exception via srsfd stack slot
-
- END
-
-
diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf index 9ad242a42e..21cdf319d4 100644 --- a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf @@ -29,17 +29,13 @@ CpuDxe.h
CpuMpCore.c
CpuMmuCommon.c
+ Exception.c
[Sources.ARM]
Arm/Mmu.c
- Arm/Exception.c
- Arm/ExceptionSupport.asm | RVCT
- Arm/ExceptionSupport.S | GCC
[Sources.AARCH64]
AArch64/Mmu.c
- AArch64/Exception.c
- AArch64/ExceptionSupport.S
[Packages]
ArmPkg/ArmPkg.dec
@@ -52,6 +48,7 @@ BaseMemoryLib
CacheMaintenanceLib
CpuLib
+ CpuExceptionHandlerLib
DebugLib
DefaultExceptionHandlerLib
DxeServicesTableLib
@@ -69,14 +66,13 @@ gEfiDebugImageInfoTableGuid
gArmMpCoreInfoGuid
gIdleLoopEventGuid
+ gEfiVectorHandoffTableGuid
[Pcd.common]
gArmTokenSpaceGuid.PcdVFPEnabled
- gArmTokenSpaceGuid.PcdCpuVectorBaseAddress
[FeaturePcd.common]
gArmTokenSpaceGuid.PcdCpuDxeProduceDebugSupport
- gArmTokenSpaceGuid.PcdRelocateVectorTable
gArmTokenSpaceGuid.PcdDebuggerExceptionSupport
[Depex]
diff --git a/ArmPkg/Drivers/CpuDxe/Exception.c b/ArmPkg/Drivers/CpuDxe/Exception.c new file mode 100644 index 0000000000..c3107cd4a6 --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/Exception.c @@ -0,0 +1,95 @@ +/** @file
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+ Portions Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "CpuDxe.h"
+#include <Library/CpuExceptionHandlerLib.h>
+#include <Guid/VectorHandoffTable.h>
+
+EFI_STATUS
+InitializeExceptions (
+ IN EFI_CPU_ARCH_PROTOCOL *Cpu
+ ) {
+ EFI_STATUS Status;
+ EFI_VECTOR_HANDOFF_INFO *VectorInfoList;
+ EFI_VECTOR_HANDOFF_INFO *VectorInfo;
+ BOOLEAN IrqEnabled;
+ BOOLEAN FiqEnabled;
+
+ VectorInfo = (EFI_VECTOR_HANDOFF_INFO *)NULL;
+ Status = EfiGetSystemConfigurationTable(&gEfiVectorHandoffTableGuid, (VOID **)&VectorInfoList);
+ if (Status == EFI_SUCCESS && VectorInfoList != NULL) {
+ VectorInfo = VectorInfoList;
+ }
+
+ // intialize the CpuExceptionHandlerLib so we take over the exception vector table from the DXE Core
+ InitializeCpuExceptionHandlers(VectorInfo);
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Disable interrupts
+ //
+ Cpu->GetInterruptState (Cpu, &IrqEnabled);
+ Cpu->DisableInterrupt (Cpu);
+
+ //
+ // EFI does not use the FIQ, but a debugger might so we must disable
+ // as we take over the exception vectors.
+ //
+ FiqEnabled = ArmGetFiqState ();
+ ArmDisableFiq ();
+
+ if (FiqEnabled) {
+ ArmEnableFiq ();
+ }
+
+ if (IrqEnabled) {
+ //
+ // Restore interrupt state
+ //
+ Status = Cpu->EnableInterrupt (Cpu);
+ }
+
+ return Status;
+}
+
+/**
+This function registers and enables the handler specified by InterruptHandler for a processor
+interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
+handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
+The installed handler is called once for each processor interrupt or exception.
+
+@param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
+are enabled and FALSE if interrupts are disabled.
+@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+when a processor interrupt occurs. If this parameter is NULL, then the handler
+will be uninstalled.
+
+@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+previously installed.
+@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+previously installed.
+@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
+
+**/
+EFI_STATUS
+RegisterInterruptHandler(
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ ) {
+ // pass down to CpuExceptionHandlerLib
+ return (EFI_STATUS)RegisterCpuInterruptHandler(InterruptType, InterruptHandler);
+}
|