On 4 March 2016 at 00:05, Cohen, Eugene <[email protected]> wrote: > Introduce ARM and AArch64 instances of the CpuExceptionHandlerLib > which provides exception handling and registration of handlers > regardless of execution phase. > > Two variants of the ArmExceptionLib are provided: one where > exception handlers reside within the module (meeting appropriate > architectural alignment requirements for the vector table) and > another one that will relocate a copy of exception handlers to > an address specified by PcdCpuVectorBaseAddress. The > ArmRelocateExceptionLib is intended for use in cases where > ArmExceptionLib is too large for the application (uncompressed > XIP images) as driven by the vector table alignment padding. > > The AArch64 build of this library supports execution at > EL1, EL2, and EL3 exception levels. > > Tested on ARM, and AArch64 with SEC, DXE Core, and CpuDxe > modules. > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Eugene Cohen <[email protected]>
Hi Eugene, I have one comment below: > --- > ArmPkg/ArmPkg.dsc | 3 + > .../ArmExceptionLib/AArch64/AArch64Exception.c | 44 +++ > .../ArmExceptionLib/AArch64/ExceptionSupport.S | 425 > +++++++++++++++++++++ > ArmPkg/Library/ArmExceptionLib/Arm/ArmException.c | 50 +++ > .../Library/ArmExceptionLib/Arm/ExceptionSupport.S | 305 +++++++++++++++ > .../ArmExceptionLib/Arm/ExceptionSupport.asm | 302 +++++++++++++++ > ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.c | 340 +++++++++++++++++ > ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf | 63 +++ > .../ArmExceptionLib/ArmRelocateExceptionLib.inf | 65 ++++ > 9 files changed, 1597 insertions(+) > create mode 100644 ArmPkg/Library/ArmExceptionLib/AArch64/AArch64Exception.c > create mode 100644 ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S > create mode 100644 ArmPkg/Library/ArmExceptionLib/Arm/ArmException.c > create mode 100644 ArmPkg/Library/ArmExceptionLib/Arm/ExceptionSupport.S > create mode 100644 ArmPkg/Library/ArmExceptionLib/Arm/ExceptionSupport.asm > create mode 100644 ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.c > create mode 100644 ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf > create mode 100644 ArmPkg/Library/ArmExceptionLib/ArmRelocateExceptionLib.inf > [...] > diff --git a/ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.c > b/ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.c > new file mode 100644 > index 0000000..3a6f31a > --- /dev/null > +++ b/ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.c > @@ -0,0 +1,340 @@ > +/* @file > +* Main file supporting the SEC Phase for Versatile Express > +* > +* Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR> > +* Copyright (c) 2011-2014, ARM Limited. All rights reserved. > +* Copyright (c) 2016 HP Development Company, L.P. > +* > +* 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 <Uefi.h> > +#include <Library/CpuExceptionHandlerLib.h> > + > +#include <Library/ArmLib.h> > +#include <Library/PcdLib.h> > +#include <Library/CacheMaintenanceLib.h> > +#include <Library/BaseLib.h> > +#include <Library/BaseMemoryLib.h> > +#include <Library/DebugLib.h> > +#include <Library/DefaultExceptionHandlerLib.h> > + > +RETURN_STATUS > +CopyExceptionHandlers( > + IN PHYSICAL_ADDRESS BaseAddress > + ); > + > +EFI_STATUS > +EFIAPI > +RegisterExceptionHandler( > + IN EFI_EXCEPTION_TYPE ExceptionType, > + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler > + ); > + > +VOID > +ExceptionHandlersStart( > + VOID > + ); > + > +VOID > +ExceptionHandlersEnd( > + VOID > + ); > + > +VOID > +CommonExceptionEntry( > + VOID > + ); > + > +VOID > +AsmCommonExceptionEntry( > + VOID > + ); > + > +RETURN_STATUS ArchVectorConfig( > + IN UINTN VectorBaseAddress > + ); > + > +// these globals are provided by the architecture specific source (Arm or > AArch64) > +extern UINTN gMaxExceptionNumber; > +extern EFI_EXCEPTION_CALLBACK gExceptionHandlers[]; > +extern EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[]; > +extern PHYSICAL_ADDRESS gExceptionVectorAlignmentMask; > +extern UINTN gDebuggerNoHandlerValue; > + > +// A compiler flag adjusts the compilation of this library to a variant where > +// the vectors are relocated (copied) to another location versus using the > +// vectors in-place. Since this effects an assembly .align directive we must > +// address this at library build time. Since this affects the build of the > +// library we cannot represent this in a PCD since PCDs are evaluated on > +// a per-module basis. > +#if defined(ARM_RELOCATE_VECTORS) > +BOOLEAN gArmRelocateVectorTable = TRUE; > +#else > +BOOLEAN gArmRelocateVectorTable = FALSE; > +#endif > + > + > +/** > +Initializes all CPU exceptions entries and provides the default exception > handlers. > + > +Caller should try to get an array of interrupt and/or exception vectors that > are in use and need to > +persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification. > +If caller cannot get reserved vector list or it does not exists, set > VectorInfo to NULL. > +If VectorInfo is not NULL, the exception vectors will be initialized per > vector attribute accordingly. > + > +@param[in] VectorInfo Pointer to reserved vector list. > + > +@retval EFI_SUCCESS CPU Exception Entries have been successfully > initialized > +with default exception handlers. > +@retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if > VectorInfo is not NULL. > +@retval EFI_UNSUPPORTED This function is not supported. > + > +**/ > +EFI_STATUS > +EFIAPI > +InitializeCpuExceptionHandlers( > + IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL > + ) > +{ > + RETURN_STATUS Status; > + UINTN VectorBase; > + > + Status = EFI_SUCCESS; > + > + // if we are requested to copy exceptin handlers to another location > + if (gArmRelocateVectorTable) { > + > + VectorBase = PcdGet32(PcdCpuVectorBaseAddress); > + Status = CopyExceptionHandlers(VectorBase); > + > + } > + else { // use VBAR to point to where our exception handlers are > + > + // The vector table must be aligned for the architecture. If this > + // assertion fails ensure the appropriate FFS alignment is in effect, > + // which can be accomplished by ensuring the proper Align=X statement > + // in the platform packaging rules. For ARM Align=32 is required and > + // for AArch64 Align=4K is required. Align=Auto can be used but this > + // is known to cause an issue with populating the reset vector area > + // for encapsulated FVs. > + ASSERT(((UINTN)ExceptionHandlersStart & gExceptionVectorAlignmentMask) > == 0); > + > + // We do not copy the Exception Table at > PcdGet32(PcdCpuVectorBaseAddress). We just set Vector > + // Base Address to point into CpuDxe code. > + VectorBase = (UINTN)ExceptionHandlersStart; > + > + Status = RETURN_SUCCESS; > + } > + > + if (!RETURN_ERROR(Status)) { > + // call the architecture-specific routine to prepare for the new vector > + // configuration to take effect > + ArchVectorConfig(VectorBase); > + > + ArmWriteVBar(VectorBase); > + } > + > + return RETURN_SUCCESS; > +} > + > +/** > +Copies exception handlers to the speciifed address. > + > +Caller should try to get an array of interrupt and/or exception vectors that > are in use and need to > +persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification. > +If caller cannot get reserved vector list or it does not exists, set > VectorInfo to NULL. > +If VectorInfo is not NULL, the exception vectors will be initialized per > vector attribute accordingly. > + > +@param[in] VectorInfo Pointer to reserved vector list. > + > +@retval EFI_SUCCESS CPU Exception Entries have been successfully > initialized > +with default exception handlers. > +@retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if > VectorInfo is not NULL. > +@retval EFI_UNSUPPORTED This function is not supported. > + > +**/ > +RETURN_STATUS > +CopyExceptionHandlers( > + IN PHYSICAL_ADDRESS BaseAddress > + ) > +{ > + RETURN_STATUS Status; > + UINTN Offset; > + UINTN Length; > + UINTN Index; > + UINT32 *VectorBase; > + > + // ensure that the destination value specifies an address meeting the > vector alignment requirements > + ASSERT ((BaseAddress & gExceptionVectorAlignmentMask) == 0); > + > + // > + // Copy an implementation of the exception vectors to > PcdCpuVectorBaseAddress. > + // > + Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart; > + > + VectorBase = (UINT32 *)(UINTN)BaseAddress; > + > + if (FeaturePcdGet(PcdDebuggerExceptionSupport) == TRUE) { > + // Save existing vector table, in case debugger is already hooked in > + CopyMem((VOID *)gDebuggerExceptionHandlers, (VOID *)VectorBase, sizeof > (EFI_EXCEPTION_CALLBACK)* (gMaxExceptionNumber+1)); > + } > + > + // 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)(BaseAddress + Offset)) = > (UINTN)AsmCommonExceptionEntry; > + Why is this needed? CommonExceptionEntry should already contain the absolute address of AsmCommonExceptionEntry, this is taken care of by the linker and/or the PE/COFF relocation (exactly the same as how your reference here got its actual value) > + // > + // Initialize the C entry points for interrupts > + // > + for (Index = 0; Index <= gMaxExceptionNumber; Index++) { > + if (!FeaturePcdGet(PcdDebuggerExceptionSupport) || > + (gDebuggerExceptionHandlers[Index] == 0) || > (gDebuggerExceptionHandlers[Index] == (VOID *)gDebuggerNoHandlerValue)) { > + > + Status = RegisterExceptionHandler(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 *)(UINTN)BaseAddress, Length); > + > + // Update the vector base address register to activate the new exception > vectors > + ArmWriteVBar((UINTN)BaseAddress); > + > + return RETURN_SUCCESS; > +} > + > + > +/** > +Initializes all CPU interrupt/exceptions entries and provides the default > interrupt/exception handlers. > + > +Caller should try to get an array of interrupt and/or exception vectors that > are in use and need to > +persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification. > +If caller cannot get reserved vector list or it does not exists, set > VectorInfo to NULL. > +If VectorInfo is not NULL, the exception vectors will be initialized per > vector attribute accordingly. > + > +@param[in] VectorInfo Pointer to reserved vector list. > + > +@retval EFI_SUCCESS All CPU interrupt/exception entries have been > successfully initialized > +with default interrupt/exception handlers. > +@retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if > VectorInfo is not NULL. > +@retval EFI_UNSUPPORTED This function is not supported. > + > +**/ > +EFI_STATUS > +EFIAPI > +InitializeCpuInterruptHandlers( > +IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL > +) > +{ > + // not needed, this is what the CPU driver is for > + return EFI_UNSUPPORTED; > +} > + > +/** > +Registers a function to be called from the processor exception handler. (On > ARM/AArch64 this only > +provides exception handlers, not interrupt handling which is provided > through the Hardware Interrupt > +Protocol.) > + > +This function registers and enables the handler specified by > ExceptionHandler for a processor > +interrupt or exception type specified by ExceptionType. If ExceptionHandler > is NULL, then the > +handler for the processor interrupt or exception type specified by > ExceptionType is uninstalled. > +The installed handler is called once for each processor interrupt or > exception. > +NOTE: This function should be invoked after InitializeCpuExceptionHandlers() > or > +InitializeCpuInterruptHandlers() invoked, otherwise EFI_UNSUPPORTED returned. > + > +@param[in] ExceptionType Defines which interrupt or exception to hook. > +@param[in] ExceptionHandler 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 ExceptionHandler is not NULL, and a handler > for ExceptionType was > +previously installed. > +@retval EFI_INVALID_PARAMETER ExceptionHandler is NULL, and a handler for > ExceptionType was not > +previously installed. > +@retval EFI_UNSUPPORTED The interrupt specified by ExceptionType is > not supported, > +or this function is not supported. > +**/ > +RETURN_STATUS > +RegisterCpuInterruptHandler( > + IN EFI_EXCEPTION_TYPE ExceptionType, > + IN EFI_CPU_INTERRUPT_HANDLER ExceptionHandler > + ) { > + if (ExceptionType > gMaxExceptionNumber) { > + return RETURN_UNSUPPORTED; > + } > + > + if ((ExceptionHandler != NULL) && (gExceptionHandlers[ExceptionType] != > NULL)) { > + return RETURN_ALREADY_STARTED; > + } > + > + gExceptionHandlers[ExceptionType] = ExceptionHandler; > + > + return RETURN_SUCCESS; > +} > + > +/** > +Register exception handler. > + > +@param This A pointer to the SMM_CPU_SERVICE_PROTOCOL > instance. > +@param ExceptionType Defines which interrupt or exception to hook. > Type EFI_EXCEPTION_TYPE and > +the valid values for this parameter are defined in EFI_DEBUG_SUPPORT_PROTOCOL > +of the UEFI 2.0 specification. > +@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 > +EFIAPI > +RegisterExceptionHandler( > + IN EFI_EXCEPTION_TYPE ExceptionType, > + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler > + ) > +{ > + return RegisterCpuInterruptHandler(ExceptionType, InterruptHandler); > +} > + > +VOID > +EFIAPI > +CommonCExceptionHandler( > + IN EFI_EXCEPTION_TYPE ExceptionType, > + IN OUT EFI_SYSTEM_CONTEXT SystemContext > + ) > +{ > + if (ExceptionType <= gMaxExceptionNumber) { > + if (gExceptionHandlers[ExceptionType]) { > + gExceptionHandlers[ExceptionType](ExceptionType, SystemContext); > + return; > + } > + } > + else { > + DEBUG((EFI_D_ERROR, "Unknown exception type %d\n", ExceptionType)); > + ASSERT(FALSE); > + } > + > + DefaultExceptionHandler(ExceptionType, SystemContext); > +} > diff --git a/ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf > b/ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf > new file mode 100644 > index 0000000..5bad2a2 > --- /dev/null > +++ b/ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf > @@ -0,0 +1,63 @@ > +## @file > +# Instance of CpuExceptionHandlerLib Library for ARM/AArch64 architectures > +# > +# This library instance is used for modules that will implement exception > +# handlers in-place (by programming VBAR). The exception handlers will be > +# generated with alignment as required by the processor architecture. The > +# alignment must be propagated into the parent FFS/FV through FDF build rules > +# for the relevant module types (i.e. Align=Auto). > +# > +# Note that using this library instance can cause growth to the size of the > FV > +# due to the padding added by the build tools to meet the vector alignment > +# requirements and may not be desirable for space-sensitive FVs > (uncompressed / > +# XIP components). The alternative library instance, ArmRelocateExceptionLib > +# should be considered for these applications. > +# > +# Copyright (c) 2011-2012, ARM Limited. All rights reserved. > +# Copyright (c) 2016 HP Development Company, L.P. > +# > +# 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. > +# > +# > + > +[Defines] > + INF_VERSION = 0x00010005 > + BASE_NAME = ArmExceptionLib > + FILE_GUID = A9796991-4E88-47F0-87C5-D96A1D270539 > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = CpuExceptionHandlerLib > + > +[Sources.common] > + ArmExceptionLib.c > + > +[Sources.Arm] > + Arm/ArmException.c > + Arm/ExceptionSupport.asm | RVCT > + Arm/ExceptionSupport.S | GCC > + > +[Sources.AARCH64] > + AArch64/AArch64Exception.c > + AArch64/ExceptionSupport.S > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + ArmPkg/ArmPkg.dec > + > +[LibraryClasses] > + ArmLib > + DebugLib > + DefaultExceptionHandlerLib > + BaseMemoryLib > + CacheMaintenanceLib > + > +[Pcd] > + gArmTokenSpaceGuid.PcdDebuggerExceptionSupport > + gArmTokenSpaceGuid.PcdCpuVectorBaseAddress > diff --git a/ArmPkg/Library/ArmExceptionLib/ArmRelocateExceptionLib.inf > b/ArmPkg/Library/ArmExceptionLib/ArmRelocateExceptionLib.inf > new file mode 100644 > index 0000000..340812b > --- /dev/null > +++ b/ArmPkg/Library/ArmExceptionLib/ArmRelocateExceptionLib.inf > @@ -0,0 +1,65 @@ > +## @file > +# Instance of CpuExceptionHandlerLib Library for ARM/AArch64 architectures > +# > +# This library instance is used when exception vectors must be relocated to > +# a specific address. The address is specified by PcdCpuVectorBaseAddress. > +# Since the alignment requirement for in-place exception handlers causes > +# image size to increase, this instance is useful for modules that need to > +# minimize space used in their FV (like XIP modules). See > ArmExceptionLib.inf > +# for the in-place exception handler alternative. > +# > +# Copyright (c) 2011-2012, ARM Limited. All rights reserved. > +# Copyright (c) 2016 HP Development Company, L.P. > +# > +# 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. > +# > +# > + > +[Defines] > + INF_VERSION = 0x00010005 > + BASE_NAME = ArmRelocateExceptionLib > + FILE_GUID = 62AA447A-1FBA-429E-9E0D-CE0D2D8DCF58 > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = CpuExceptionHandlerLib > + > +[Sources.common] > + ArmExceptionLib.c > + > +[Sources.Arm] > + Arm/ArmException.c > + Arm/ExceptionSupport.asm | RVCT > + Arm/ExceptionSupport.S | GCC > + > +[Sources.AARCH64] > + AArch64/AArch64Exception.c > + AArch64/ExceptionSupport.S > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + ArmPkg/ArmPkg.dec > + > +[LibraryClasses] > + ArmLib > + DebugLib > + DefaultExceptionHandlerLib > + BaseMemoryLib > + CacheMaintenanceLib > + > +[Pcd] > + gArmTokenSpaceGuid.PcdDebuggerExceptionSupport > + gArmTokenSpaceGuid.PcdCpuVectorBaseAddress > + > +[BuildOptions] > + # We must pass a define to specify that we are relocating vectors so the > + # vector alignment is relaxed (space savings); note that this must be done > + # as a define and not a PCD since it affects assembly directives. > + *_*_*_PP_FLAGS = -DARM_RELOCATE_VECTORS > + *_*_*_CC_FLAGS = -DARM_RELOCATE_VECTORS > -- > 1.9.5.msysgit.0 > _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

