summaryrefslogtreecommitdiffstats
path: root/ArmPkg
diff options
context:
space:
mode:
authorArd Biesheuvel <ardb@kernel.org>2025-01-17 12:08:51 +0100
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2025-01-17 18:37:27 +0000
commit2d2642f4832ebc45cb7d5ba9430b933d953b94f2 (patch)
tree9843f1120620aacda591befa6159a8a9624694f6 /ArmPkg
parent81e2cd329efc0ed240234f475426cb81bf5d9c84 (diff)
downloadedk2-2d2642f4832ebc45cb7d5ba9430b933d953b94f2.tar.gz
ArmPkg/ArmGicDxe: Use EOImode 0x0 on GICv3
When re-entering EDK2 from a high level OS such as Linux, the GICv3 may be configured to use split priority drop and deactivate (EOImode == 1), whereas EDK2's GICv3 driver assumes the default setting of EOImode == 0. So clear the EOImode bit explicitly when taking control of the GIC. Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Diffstat (limited to 'ArmPkg')
-rw-r--r--ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.h10
-rw-r--r--ArmPkg/Drivers/ArmGicDxe/GicV3/AArch64/ArmGicV3.S17
-rw-r--r--ArmPkg/Drivers/ArmGicDxe/GicV3/Arm/ArmGicV3.S16
-rw-r--r--ArmPkg/Drivers/ArmGicDxe/GicV3/ArmGicV3Dxe.c5
-rw-r--r--ArmPkg/Include/Library/ArmGicLib.h3
5 files changed, 50 insertions, 1 deletions
diff --git a/ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.h b/ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.h
index 733984265b..57732661d2 100644
--- a/ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.h
+++ b/ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.h
@@ -139,4 +139,14 @@ ArmGicV3SetPriorityMask (
IN UINTN Priority
);
+UINTN
+ArmGicV3GetControlRegister (
+ VOID
+ );
+
+VOID
+ArmGicV3SetControlRegister (
+ IN UINTN Value
+ );
+
#endif // ARM_GIC_DXE_H_
diff --git a/ArmPkg/Drivers/ArmGicDxe/GicV3/AArch64/ArmGicV3.S b/ArmPkg/Drivers/ArmGicDxe/GicV3/AArch64/ArmGicV3.S
index 504f026a1d..81aaeefa56 100644
--- a/ArmPkg/Drivers/ArmGicDxe/GicV3/AArch64/ArmGicV3.S
+++ b/ArmPkg/Drivers/ArmGicDxe/GicV3/AArch64/ArmGicV3.S
@@ -22,6 +22,7 @@
#define ICC_IAR1_EL1 S3_0_C12_C12_0
#define ICC_PMR_EL1 S3_0_C4_C6_0
#define ICC_BPR1_EL1 S3_0_C12_C12_3
+#define ICC_CTLR_EL1 S3_0_C12_C12_4
#endif
@@ -99,3 +100,19 @@ ASM_FUNC(ArmGicV3SetPriorityMask)
ASM_FUNC(ArmGicV3SetBinaryPointer)
msr ICC_BPR1_EL1, x0
ret
+
+//UINTN
+//ArmGicV3GetControlRegister(
+// VOID
+// );
+ASM_FUNC(ArmGicV3GetControlRegister)
+ mrs x0, ICC_CTLR_EL1
+ ret
+
+//VOID
+//ArmGicV3SetControlRegister(
+// IN UINTN Value
+// );
+ASM_FUNC(ArmGicV3SetControlRegister)
+ msr ICC_CTLR_EL1, x0
+ ret
diff --git a/ArmPkg/Drivers/ArmGicDxe/GicV3/Arm/ArmGicV3.S b/ArmPkg/Drivers/ArmGicDxe/GicV3/Arm/ArmGicV3.S
index 33c0a58464..d57e17b901 100644
--- a/ArmPkg/Drivers/ArmGicDxe/GicV3/Arm/ArmGicV3.S
+++ b/ArmPkg/Drivers/ArmGicDxe/GicV3/Arm/ArmGicV3.S
@@ -78,3 +78,19 @@ ASM_FUNC(ArmGicV3SetPriorityMask)
ASM_FUNC(ArmGicV3SetBinaryPointer)
mcr p15, 0, r0, c12, c12, 3 //ICC_BPR1
bx lr
+
+//UINTN
+//ArmGicV3GetControlRegister(
+// VOID
+// );
+ASM_FUNC(ArmGicV3GetControlRegister)
+ mrc p15, 0, r0, c12, c12, 4 //ICC_CTLR
+ bx lr
+
+//VOID
+//ArmGicV3SetControlRegister(
+// IN UINTN Value
+// );
+ASM_FUNC(ArmGicV3SetControlRegister)
+ mcr p15, 0, r0, c12, c12, 4 //ICC_CTLR
+ bx lr
diff --git a/ArmPkg/Drivers/ArmGicDxe/GicV3/ArmGicV3Dxe.c b/ArmPkg/Drivers/ArmGicDxe/GicV3/ArmGicV3Dxe.c
index 2b6c0fc9f1..d456e6cb83 100644
--- a/ArmPkg/Drivers/ArmGicDxe/GicV3/ArmGicV3Dxe.c
+++ b/ArmPkg/Drivers/ArmGicDxe/GicV3/ArmGicV3Dxe.c
@@ -704,6 +704,11 @@ GicV3DxeInitialize (
// Set priority mask reg to 0xff to allow all priorities through
ArmGicV3SetPriorityMask (0xff);
+ // Use combined priority drop and deactivate (EOImode == 0)
+ RegValue = ArmGicV3GetControlRegister ();
+ RegValue &= ~(UINT64)ICC_CTLR_EOImode;
+ ArmGicV3SetControlRegister (RegValue);
+
// Enable gic cpu interface
ArmGicV3EnableInterruptInterface ();
diff --git a/ArmPkg/Include/Library/ArmGicLib.h b/ArmPkg/Include/Library/ArmGicLib.h
index 02112ebf07..de49c59437 100644
--- a/ArmPkg/Include/Library/ArmGicLib.h
+++ b/ArmPkg/Include/Library/ArmGicLib.h
@@ -118,7 +118,8 @@
// GIC revision 3 specific declarations
-#define ICC_SRE_EL2_SRE (1 << 0)
+#define ICC_SRE_EL2_SRE (1 << 0)
+#define ICC_CTLR_EOImode (1 << 1)
#define ARM_GICD_IROUTER_IRM BIT31