]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c
ArmPkg: Tidy GIC code before changes.
[mirror_edk2.git] / ArmPkg / Drivers / ArmGic / GicV3 / ArmGicV3Dxe.c
index f756d308038617cbf659137f942b8abcafef806d..50b51ffcf57b23b110899c7c55237cf85b61d196 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 *\r
-*  Copyright (c) 2011-2014, ARM Limited. All rights reserved.\r
+*  Copyright (c) 2011-2017, ARM Limited. All rights reserved.\r
 *\r
 *  This program and the accompanying materials\r
 *  are licensed and made available under the terms and conditions of the BSD License\r
 *\r
 **/\r
 \r
+#include <Library/ArmGicLib.h>\r
+\r
 #include "ArmGicDxe.h"\r
-#include "GicV3/ArmGicV3Lib.h"\r
 \r
 #define ARM_GIC_DEFAULT_PRIORITY  0x80\r
 \r
 extern EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptV3Protocol;\r
 \r
 STATIC UINTN mGicDistributorBase;\r
+STATIC UINTN mGicRedistributorsBase;\r
 \r
 /**\r
   Enable interrupt source Source.\r
@@ -31,6 +33,7 @@ STATIC UINTN mGicDistributorBase;
   @retval EFI_DEVICE_ERROR  Hardware could not be programmed.\r
 \r
 **/\r
+STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 GicV3EnableInterruptSource (\r
@@ -38,12 +41,12 @@ GicV3EnableInterruptSource (
   IN HARDWARE_INTERRUPT_SOURCE          Source\r
   )\r
 {\r
-  if (Source > mGicNumInterrupts) {\r
+  if (Source >= mGicNumInterrupts) {\r
     ASSERT(FALSE);\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  ArmGicEnableInterrupt (mGicDistributorBase, Source);\r
+  ArmGicEnableInterrupt (mGicDistributorBase, mGicRedistributorsBase, Source);\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -58,6 +61,7 @@ GicV3EnableInterruptSource (
   @retval EFI_DEVICE_ERROR  Hardware could not be programmed.\r
 \r
 **/\r
+STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 GicV3DisableInterruptSource (\r
@@ -65,12 +69,12 @@ GicV3DisableInterruptSource (
   IN HARDWARE_INTERRUPT_SOURCE          Source\r
   )\r
 {\r
-  if (Source > mGicNumInterrupts) {\r
+  if (Source >= mGicNumInterrupts) {\r
     ASSERT(FALSE);\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  ArmGicDisableInterrupt (mGicDistributorBase, Source);\r
+  ArmGicDisableInterrupt (mGicDistributorBase, mGicRedistributorsBase, Source);\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -86,6 +90,7 @@ GicV3DisableInterruptSource (
   @retval EFI_DEVICE_ERROR  InterruptState is not valid\r
 \r
 **/\r
+STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 GicV3GetInterruptSourceState (\r
@@ -94,12 +99,16 @@ GicV3GetInterruptSourceState (
   IN BOOLEAN                            *InterruptState\r
   )\r
 {\r
-  if (Source > mGicNumInterrupts) {\r
+  if (Source >= mGicNumInterrupts) {\r
     ASSERT(FALSE);\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  *InterruptState = ArmGicIsInterruptEnabled (mGicDistributorBase, Source);\r
+  *InterruptState = ArmGicIsInterruptEnabled (\r
+                      mGicDistributorBase,\r
+                      mGicRedistributorsBase,\r
+                      Source\r
+                      );\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -115,6 +124,7 @@ GicV3GetInterruptSourceState (
   @retval EFI_DEVICE_ERROR  Hardware could not be programmed.\r
 \r
 **/\r
+STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 GicV3EndOfInterrupt (\r
@@ -122,7 +132,7 @@ GicV3EndOfInterrupt (
   IN HARDWARE_INTERRUPT_SOURCE          Source\r
   )\r
 {\r
-  if (Source > mGicNumInterrupts) {\r
+  if (Source >= mGicNumInterrupts) {\r
     ASSERT(FALSE);\r
     return EFI_UNSUPPORTED;\r
   }\r
@@ -135,13 +145,15 @@ GicV3EndOfInterrupt (
   EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.\r
 \r
   @param  InterruptType    Defines the type of interrupt or exception that\r
-                           occurred on the processor.This parameter is processor architecture specific.\r
+                           occurred on the processor. This parameter is\r
+                           processor architecture specific.\r
   @param  SystemContext    A pointer to the processor context when\r
                            the interrupt occurred on the processor.\r
 \r
   @return None\r
 \r
 **/\r
+STATIC\r
 VOID\r
 EFIAPI\r
 GicV3IrqInterruptHandler (\r
@@ -166,15 +178,12 @@ GicV3IrqInterruptHandler (
     // Call the registered interrupt handler.\r
     InterruptHandler (GicInterrupt, SystemContext);\r
   } else {\r
-    DEBUG ((EFI_D_ERROR, "Spurious GIC interrupt: 0x%x\n", GicInterrupt));\r
+    DEBUG ((DEBUG_ERROR, "Spurious GIC interrupt: 0x%x\n", GicInterrupt));\r
+    GicV3EndOfInterrupt (&gHardwareInterruptV3Protocol, GicInterrupt);\r
   }\r
-\r
-  GicV3EndOfInterrupt (&gHardwareInterruptV3Protocol, GicInterrupt);\r
 }\r
 \r
-//\r
 // The protocol instance produced by this driver\r
-//\r
 EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptV3Protocol = {\r
   RegisterInterruptSource,\r
   GicV3EnableInterruptSource,\r
@@ -238,13 +247,22 @@ GicV3DxeInitialize (
   UINTN                   Index;\r
   UINT32                  RegOffset;\r
   UINTN                   RegShift;\r
-  UINT32                  CpuTarget;\r
+  UINT64                  CpuTarget;\r
+  UINT64                  MpId;\r
 \r
-  // Make sure the Interrupt Controller Protocol is not already installed in the system.\r
+  // Make sure the Interrupt Controller Protocol is not already installed in\r
+  // the system.\r
   ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);\r
 \r
-  mGicDistributorBase = PcdGet32 (PcdGicDistributorBase);\r
-  mGicNumInterrupts = ArmGicGetMaxNumInterrupts (mGicDistributorBase);\r
+  mGicDistributorBase    = PcdGet64 (PcdGicDistributorBase);\r
+  mGicRedistributorsBase = PcdGet64 (PcdGicRedistributorsBase);\r
+  mGicNumInterrupts      = ArmGicGetMaxNumInterrupts (mGicDistributorBase);\r
+\r
+  // We will be driving this GIC in native v3 mode, i.e., with Affinity\r
+  // Routing enabled. So ensure that the ARE bit is set.\r
+  if (!FeaturePcdGet (PcdArmGicV3WithV2Legacy)) {\r
+    MmioOr32 (mGicDistributorBase + ARM_GIC_ICDDCR, ARM_GIC_ICDDCR_ARE);\r
+  }\r
 \r
   for (Index = 0; Index < mGicNumInterrupts; Index++) {\r
     GicV3DisableInterruptSource (&gHardwareInterruptV3Protocol, Index);\r
@@ -259,25 +277,65 @@ GicV3DxeInitialize (
       );\r
   }\r
 \r
-  //\r
   // Targets the interrupts to the Primary Cpu\r
-  //\r
-\r
-  // Only Primary CPU will run this code. We can identify our GIC CPU ID by reading\r
-  // the GIC Distributor Target register. The 8 first GICD_ITARGETSRn are banked to each\r
-  // connected CPU. These 8 registers hold the CPU targets fields for interrupts 0-31.\r
-  // More Info in the GIC Specification about "Interrupt Processor Targets Registers"\r
-  //\r
-  // Read the first Interrupt Processor Targets Register (that corresponds to the 4\r
-  // first SGIs)\r
-  CpuTarget = MmioRead32 (mGicDistributorBase + ARM_GIC_ICDIPTR);\r
-\r
-  // The CPU target is a bit field mapping each CPU to a GIC CPU Interface. This value\r
-  // is 0 when we run on a uniprocessor platform.\r
-  if (CpuTarget != 0) {\r
-    // The 8 first Interrupt Processor Targets Registers are read-only\r
-    for (Index = 8; Index < (mGicNumInterrupts / 4); Index++) {\r
-      MmioWrite32 (mGicDistributorBase + ARM_GIC_ICDIPTR + (Index * 4), CpuTarget);\r
+\r
+  if (FeaturePcdGet (PcdArmGicV3WithV2Legacy)) {\r
+    // Only Primary CPU will run this code. We can identify our GIC CPU ID by\r
+    // reading the GIC Distributor Target register. The 8 first\r
+    // GICD_ITARGETSRn are banked to each connected CPU. These 8 registers\r
+    // hold the CPU targets fields for interrupts 0-31. More Info in the GIC\r
+    // Specification about "Interrupt Processor Targets Registers"\r
+\r
+    // Read the first Interrupt Processor Targets Register (that corresponds\r
+    // to the 4 first SGIs)\r
+    CpuTarget = MmioRead32 (mGicDistributorBase + ARM_GIC_ICDIPTR);\r
+\r
+    // The CPU target is a bit field mapping each CPU to a GIC CPU Interface.\r
+    // This value is 0 when we run on a uniprocessor platform.\r
+    if (CpuTarget != 0) {\r
+      // The 8 first Interrupt Processor Targets Registers are read-only\r
+      for (Index = 8; Index < (mGicNumInterrupts / 4); Index++) {\r
+        MmioWrite32 (\r
+          mGicDistributorBase + ARM_GIC_ICDIPTR + (Index * 4),\r
+          CpuTarget\r
+          );\r
+      }\r
+    }\r
+  } else {\r
+    MpId = ArmReadMpidr ();\r
+    CpuTarget = MpId &\r
+      (ARM_CORE_AFF0 | ARM_CORE_AFF1 | ARM_CORE_AFF2 | ARM_CORE_AFF3);\r
+\r
+    if ((MmioRead32 (\r
+           mGicDistributorBase + ARM_GIC_ICDDCR\r
+         ) & ARM_GIC_ICDDCR_DS) != 0) {\r
+\r
+      // If the Disable Security (DS) control bit is set, we are dealing with a\r
+      // GIC that has only one security state. In this case, let's assume we are\r
+      // executing in non-secure state (which is appropriate for DXE modules)\r
+      // and that no other firmware has performed any configuration on the GIC.\r
+      // This means we need to reconfigure all interrupts to non-secure Group 1\r
+      // first.\r
+\r
+      MmioWrite32 (\r
+        mGicRedistributorsBase + ARM_GICR_CTLR_FRAME_SIZE + ARM_GIC_ICDISR,\r
+        0xffffffff\r
+        );\r
+\r
+      for (Index = 32; Index < mGicNumInterrupts; Index += 32) {\r
+        MmioWrite32 (\r
+          mGicDistributorBase + ARM_GIC_ICDISR + Index / 8,\r
+          0xffffffff\r
+          );\r
+      }\r
+    }\r
+\r
+    // Route the SPIs to the primary CPU. SPIs start at the INTID 32\r
+    for (Index = 0; Index < (mGicNumInterrupts - 32); Index++) {\r
+      MmioWrite32 (\r
+        mGicDistributorBase + ARM_GICD_IROUTER + (Index * 8),\r
+        CpuTarget | ARM_GICD_IROUTER_IRM\r
+        );\r
     }\r
   }\r
 \r
@@ -294,7 +352,10 @@ GicV3DxeInitialize (
   ArmGicEnableDistributor (mGicDistributorBase);\r
 \r
   Status = InstallAndRegisterInterruptService (\r
-          &gHardwareInterruptV3Protocol, GicV3IrqInterruptHandler, GicV3ExitBootServicesEvent);\r
+             &gHardwareInterruptV3Protocol,\r
+             GicV3IrqInterruptHandler,\r
+             GicV3ExitBootServicesEvent\r
+             );\r
 \r
   return Status;\r
 }\r