]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Drivers/CpuDxe/Exception.c
ArmPkg: Introduce ArmSetLowVectors/ArmSetHighVectors functions
[mirror_edk2.git] / ArmPkg / Drivers / CpuDxe / Exception.c
index 90a0045e825ddcfbe69e64bb31b0056cb42a05a6..659b7137e16b5f46ecfacdbab41638be201a70f2 100644 (file)
@@ -1,8 +1,8 @@
 /** @file\r
 \r
-  Copyright (c) 2008-2009, Apple Inc. All rights reserved.\r
+  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
   \r
-  All rights reserved. This program and the accompanying materials\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
@@ -14,6 +14,8 @@
 \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
@@ -127,6 +129,7 @@ InitializeExceptions (
   EFI_PHYSICAL_ADDRESS Base;\r
   UINT32               *VectorBase;\r
 \r
+  Status = EFI_SUCCESS;\r
   //\r
   // Disable interrupts\r
   //\r
@@ -140,53 +143,73 @@ InitializeExceptions (
   FiqEnabled = ArmGetFiqState ();\r
   ArmDisableFiq ();\r
 \r
-  //\r
-  // Copy an implementation of the ARM exception vectors to PcdCpuVectorBaseAddress.\r
-  //\r
-  Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;\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
-  //\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
+    // 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
-  // Save existing vector table, in case debugger is already hooked in\r
-  CopyMem ((VOID *)gDebuggerExceptionHandlers, (VOID *)VectorBase, sizeof (gDebuggerExceptionHandlers));\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
-  // Copy our assembly code into the page that contains the exception vectors. \r
-  CopyMem ((VOID *)VectorBase, (VOID *)ExceptionHandlersStart, Length);\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
-  //\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
+    // Copy our assembly code into the page that contains the exception vectors.\r
+    CopyMem ((VOID *)VectorBase, (VOID *)ExceptionHandlersStart, Length);\r
 \r
-  //\r
-  // Initialize the C entry points for interrupts\r
-  //\r
-  for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) {\r
-    if ((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 alread hooked put its vector back\r
-      VectorBase[Index] = (UINT32)(UINTN)gDebuggerExceptionHandlers[Index];\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
 \r
-  // Flush Caches since we updated executable stuff\r
-  InvalidateInstructionCacheRange ((VOID *)PcdGet32(PcdCpuVectorBaseAddress), Length);\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
+    // 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