]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmPkg/ArmExceptionLib: use EL0 stack for synchronous exceptions
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Wed, 15 Mar 2017 16:26:41 +0000 (16:26 +0000)
committerArd Biesheuvel <ard.biesheuvel@linaro.org>
Mon, 27 Mar 2017 12:54:26 +0000 (13:54 +0100)
In order to be able to produce meaningful diagnostic output when taking
synchronous exceptions that have been caused by corruption of the stack
pointer, prepare the EL0 stack pointer and switch to it when handling the
'Sync exception using SPx' exception class.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
ArmPkg/Library/ArmExceptionLib/AArch64/AArch64Exception.c
ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S
ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf

index 3d6eb4974d7469f780b5daebced8d2e220a2aaea..bd307628af87a1531071a3feaa2009a060974d5f 100644 (file)
@@ -16,7 +16,7 @@
 #include <Uefi.h>\r
 \r
 #include <Chipset/AArch64.h>\r
-\r
+#include <Library/MemoryAllocationLib.h>\r
 #include <Protocol/DebugSupport.h> // for MAX_AARCH64_EXCEPTION\r
 \r
 UINTN                   gMaxExceptionNumber = MAX_AARCH64_EXCEPTION;\r
@@ -25,11 +25,26 @@ EFI_EXCEPTION_CALLBACK  gDebuggerExceptionHandlers[MAX_AARCH64_EXCEPTION + 1] =
 PHYSICAL_ADDRESS        gExceptionVectorAlignmentMask = ARM_VECTOR_TABLE_ALIGNMENT;\r
 UINTN                   gDebuggerNoHandlerValue = 0; // todo: define for AArch64\r
 \r
+#define EL0_STACK_PAGES   2\r
+\r
+VOID\r
+RegisterEl0Stack (\r
+  IN  VOID    *Stack\r
+  );\r
+\r
 RETURN_STATUS ArchVectorConfig(\r
   IN  UINTN       VectorBaseAddress\r
   )\r
 {\r
   UINTN             HcrReg;\r
+  UINT8             *Stack;\r
+\r
+  Stack = AllocatePages (EL0_STACK_PAGES);\r
+  if (Stack == NULL) {\r
+    return RETURN_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  RegisterEl0Stack ((UINT8 *)Stack + EFI_PAGES_TO_SIZE (EL0_STACK_PAGES));\r
 \r
   if (ArmReadCurrentEL() == AARCH64_EL2) {\r
     HcrReg = ArmReadHcr();\r
index ff1f5fc813165ac2853f1b4520e64ea6ec6b2850..1879e9871ae9c8d6c16a8f12dd1a9e900a11e621 100644 (file)
 \r
 GCC_ASM_EXPORT(ExceptionHandlersEnd)\r
 GCC_ASM_EXPORT(CommonCExceptionHandler)\r
+GCC_ASM_EXPORT(RegisterEl0Stack)\r
 \r
 .text\r
 \r
@@ -122,35 +123,53 @@ ASM_PFX(ExceptionHandlersStart):
 VECTOR_BASE(ExceptionHandlersStart)\r
 #endif\r
 \r
-  .macro  ExceptionEntry, val\r
+  .macro  ExceptionEntry, val, sp=SPx\r
+  //\r
+  // Our backtrace and register dump code is written in C and so it requires\r
+  // a stack. This makes it difficult to produce meaningful diagnostics when\r
+  // the stack pointer has been corrupted. So in such cases (i.e., when taking\r
+  // synchronous exceptions), this macro is expanded with \sp set to SP0, in\r
+  // which case we switch to the SP_EL0 stack pointer, which has been\r
+  // initialized to point to a buffer that has been set aside for this purpose.\r
+  //\r
+  // Since 'sp' may no longer refer to the stack frame that was active when\r
+  // the exception was taken, we may have to switch back and forth between\r
+  // SP_EL0 and SP_ELx to record the correct value for SP in the context struct.\r
+  //\r
+  .ifnc   \sp, SPx\r
+  msr     SPsel, xzr\r
+  .endif\r
+\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
-  // Push some GP registers so we can record the exception context\r
+  // Push the GP registers so we can record the exception context\r
   stp      x0, x1, [sp, #-GP_CONTEXT_SIZE]!\r
   stp      x2, x3, [sp, #0x10]\r
   stp      x4, x5, [sp, #0x20]\r
   stp      x6, x7, [sp, #0x30]\r
+  stp      x8,  x9,  [sp, #0x40]\r
+  stp      x10, x11, [sp, #0x50]\r
+  stp      x12, x13, [sp, #0x60]\r
+  stp      x14, x15, [sp, #0x70]\r
+  stp      x16, x17, [sp, #0x80]\r
+  stp      x18, x19, [sp, #0x90]\r
+  stp      x20, x21, [sp, #0xa0]\r
+  stp      x22, x23, [sp, #0xb0]\r
+  stp      x24, x25, [sp, #0xc0]\r
+  stp      x26, x27, [sp, #0xd0]\r
+  stp      x28, x29, [sp, #0xe0]\r
+  add      x28, sp, #(GP_CONTEXT_SIZE + FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)\r
 \r
-  EL1_OR_EL2_OR_EL3(x1)\r
-1:mrs      x2, elr_el1   // Exception Link Register\r
-  mrs      x3, spsr_el1  // Saved Processor Status Register 32bit\r
-  mrs      x5, esr_el1   // EL1 Exception syndrome register 32bit\r
-  mrs      x6, far_el1   // EL1 Fault Address Register\r
-  b        4f\r
-\r
-2:mrs      x2, elr_el2   // Exception Link Register\r
-  mrs      x3, spsr_el2  // Saved Processor Status Register 32bit\r
-  mrs      x5, esr_el2   // EL2 Exception syndrome register 32bit\r
-  mrs      x6, far_el2   // EL2 Fault Address Register\r
-  b        4f\r
-\r
-3:mrs      x2, elr_el3   // Exception Link Register\r
-  mrs      x3, spsr_el3  // Saved Processor Status Register 32bit\r
-  mrs      x5, esr_el3   // EL3 Exception syndrome register 32bit\r
-  mrs      x6, far_el3   // EL3 Fault Address Register\r
+  .ifnc    \sp, SPx\r
+  msr      SPsel, #1\r
+  mov      x7, sp\r
+  msr      SPsel, xzr\r
+  .else\r
+  mov      x7, x28\r
+  .endif\r
 \r
-4:mrs      x4, fpsr      // Floating point Status Register  32bit\r
+  stp      x30,  x7, [sp, #0xf0]\r
 \r
   // Record the type of exception that occurred.\r
   mov       x0, #\val\r
@@ -189,7 +208,7 @@ ASM_PFX(SErrorSP0):
 //\r
 VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPx_SYNC)\r
 ASM_PFX(SynchronousExceptionSPx):\r
-  ExceptionEntry  EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS\r
+  ExceptionEntry  EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS, SP0\r
 \r
 VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPx_IRQ)\r
 ASM_PFX(IrqSPx):\r
@@ -248,20 +267,25 @@ ASM_PFX(ExceptionHandlersEnd):
 \r
 ASM_PFX(CommonExceptionEntry):\r
 \r
-  // Stack the remaining GP registers\r
-  stp      x8,  x9,  [sp, #0x40]\r
-  stp      x10, x11, [sp, #0x50]\r
-  stp      x12, x13, [sp, #0x60]\r
-  stp      x14, x15, [sp, #0x70]\r
-  stp      x16, x17, [sp, #0x80]\r
-  stp      x18, x19, [sp, #0x90]\r
-  stp      x20, x21, [sp, #0xa0]\r
-  stp      x22, x23, [sp, #0xb0]\r
-  stp      x24, x25, [sp, #0xc0]\r
-  stp      x26, x27, [sp, #0xd0]\r
-  stp      x28, x29, [sp, #0xe0]\r
-  add      x28, sp, #GP_CONTEXT_SIZE + FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE\r
-  stp      x30, x28, [sp, #0xf0]\r
+  EL1_OR_EL2_OR_EL3(x1)\r
+1:mrs      x2, elr_el1   // Exception Link Register\r
+  mrs      x3, spsr_el1  // Saved Processor Status Register 32bit\r
+  mrs      x5, esr_el1   // EL1 Exception syndrome register 32bit\r
+  mrs      x6, far_el1   // EL1 Fault Address Register\r
+  b        4f\r
+\r
+2:mrs      x2, elr_el2   // Exception Link Register\r
+  mrs      x3, spsr_el2  // Saved Processor Status Register 32bit\r
+  mrs      x5, esr_el2   // EL2 Exception syndrome register 32bit\r
+  mrs      x6, far_el2   // EL2 Fault Address Register\r
+  b        4f\r
+\r
+3:mrs      x2, elr_el3   // Exception Link Register\r
+  mrs      x3, spsr_el3  // Saved Processor Status Register 32bit\r
+  mrs      x5, esr_el3   // EL3 Exception syndrome register 32bit\r
+  mrs      x6, far_el3   // EL3 Fault Address Register\r
+\r
+4:mrs      x4, fpsr      // Floating point Status Register  32bit\r
 \r
   // Save the SYS regs\r
   stp      x2,  x3,  [x28, #-SYS_CONTEXT_SIZE]!\r
@@ -368,3 +392,7 @@ ASM_PFX(CommonExceptionEntry):
   add      sp, sp, #FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE\r
 \r
   eret\r
+\r
+ASM_PFX(RegisterEl0Stack):\r
+  msr     sp_el0, x0\r
+  ret\r
index 10d9ae0f4afc30405606d761d9f8e1f6d29544d2..cd9149cf76c62dd9e5f71440dc51bb941e8c13d1 100644 (file)
 \r
 [LibraryClasses]\r
   ArmLib\r
-  DebugLib\r
-  DefaultExceptionHandlerLib\r
   BaseMemoryLib\r
   CacheMaintenanceLib\r
+  DebugLib\r
+  DefaultExceptionHandlerLib\r
+  MemoryAllocationLib\r
 \r
 [Pcd]\r
   gArmTokenSpaceGuid.PcdDebuggerExceptionSupport\r