]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c
OvmfPkg/QemuBootOrderLib: drop too strict "/HD(" suffix from vblk prefix
[mirror_edk2.git] / ArmPkg / Drivers / ArmGic / GicV3 / ArmGicV3Dxe.c
index f3bf1910c5070d30df3c0e7aaacfcd54261a8440..983936f3738a74bb5d5e08e012973df240958a8b 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 *\r
-*  Copyright (c) 2011-2015, ARM Limited. All rights reserved.\r
+*  Copyright (c) 2011-2016, 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
@@ -12,8 +12,9 @@
 *\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
@@ -39,7 +40,7 @@ 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
@@ -66,7 +67,7 @@ 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
@@ -95,7 +96,7 @@ GicV3GetInterruptSourceState (
   IN BOOLEAN                            *InterruptState\r
   )\r
 {\r
-  if (Source > mGicNumInterrupts) {\r
+  if (Source >= mGicNumInterrupts) {\r
     ASSERT(FALSE);\r
     return EFI_UNSUPPORTED;\r
   }\r
@@ -123,7 +124,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
@@ -168,9 +169,8 @@ GicV3IrqInterruptHandler (
     InterruptHandler (GicInterrupt, SystemContext);\r
   } else {\r
     DEBUG ((EFI_D_ERROR, "Spurious GIC interrupt: 0x%x\n", GicInterrupt));\r
+    GicV3EndOfInterrupt (&gHardwareInterruptV3Protocol, GicInterrupt);\r
   }\r
-\r
-  GicV3EndOfInterrupt (&gHardwareInterruptV3Protocol, GicInterrupt);\r
 }\r
 \r
 //\r
@@ -274,12 +274,48 @@ GicV3DxeInitialize (
   // Targets the interrupts to the Primary Cpu\r
   //\r
 \r
-  MpId = ArmReadMpidr ();\r
-  CpuTarget = MpId & (ARM_CORE_AFF0 | ARM_CORE_AFF1 | ARM_CORE_AFF2 | ARM_CORE_AFF3);\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 (mGicDistributorBase + ARM_GICD_IROUTER + (Index * 8), CpuTarget | ARM_GICD_IROUTER_IRM);\r
+  if (FeaturePcdGet (PcdArmGicV3WithV2Legacy)) {\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
+    }\r
+  } else {\r
+    MpId = ArmReadMpidr ();\r
+    CpuTarget = MpId & (ARM_CORE_AFF0 | ARM_CORE_AFF1 | ARM_CORE_AFF2 | ARM_CORE_AFF3);\r
+\r
+    if ((MmioRead32 (mGicDistributorBase + ARM_GIC_ICDDCR) & 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 (mGicRedistributorsBase + ARM_GICR_CTLR_FRAME_SIZE + ARM_GIC_ICDISR, 0xffffffff);\r
+\r
+      for (Index = 32; Index < mGicNumInterrupts; Index += 32) {\r
+        MmioWrite32 (mGicDistributorBase + ARM_GIC_ICDISR + Index / 8, 0xffffffff);\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 (mGicDistributorBase + ARM_GICD_IROUTER + (Index * 8), CpuTarget | ARM_GICD_IROUTER_IRM);\r
+    }\r
   }\r
 \r
   // Set binary point reg to 0x7 (no preemption)\r