summaryrefslogtreecommitdiffstats
path: root/ArmPkg
diff options
context:
space:
mode:
Diffstat (limited to 'ArmPkg')
-rw-r--r--ArmPkg/Drivers/ArmGic/ArmGicDxe.c47
-rw-r--r--ArmPkg/Include/Library/ArmGicLib.h2
2 files changed, 39 insertions, 10 deletions
diff --git a/ArmPkg/Drivers/ArmGic/ArmGicDxe.c b/ArmPkg/Drivers/ArmGic/ArmGicDxe.c
index 1b40d8f942..b0da48e3a3 100644
--- a/ArmPkg/Drivers/ArmGic/ArmGicDxe.c
+++ b/ArmPkg/Drivers/ArmGic/ArmGicDxe.c
@@ -18,6 +18,42 @@ Abstract:
#include "ArmGicDxe.h"
+STATIC
+BOOLEAN
+GicV3Supported (
+ VOID
+ )
+{
+ UINT32 IccSre;
+
+ // Ideally we would like to use the GICC IIDR Architecture version here, but
+ // this does not seem to be very reliable as the implementation could easily
+ // get it wrong. It is more reliable to check if the GICv3 System Register
+ // feature is implemented on the CPU. This is also convenient as our GICv3
+ // driver requires SRE. If only Memory mapped access is available we try to
+ // drive the GIC as a v2.
+ if (ArmHasGicSystemRegisters ()) {
+ // Make sure System Register access is enabled (SRE). This depends on the
+ // higher privilege level giving us permission, otherwise we will either
+ // cause an exception here, or the write doesn't stick in which case we need
+ // to fall back to the GICv2 MMIO interface.
+ // Note: We do not need to set ICC_SRE_EL2.Enable because the OS is started
+ // at the same exception level.
+ // It is the OS responsibility to set this bit.
+ IccSre = ArmGicV3GetControlSystemRegisterEnable ();
+ if (!(IccSre & ICC_SRE_EL2_SRE)) {
+ ArmGicV3SetControlSystemRegisterEnable (IccSre | ICC_SRE_EL2_SRE);
+ IccSre = ArmGicV3GetControlSystemRegisterEnable ();
+ }
+
+ if (IccSre & ICC_SRE_EL2_SRE) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
/**
Initialize the state information for the CPU Architectural Protocol
@@ -36,17 +72,12 @@ InterruptDxeInitialize (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
- EFI_STATUS Status;
- ARM_GIC_ARCH_REVISION Revision;
-
- Revision = ArmGicGetSupportedArchRevision ();
+ EFI_STATUS Status;
- if (Revision == ARM_GIC_ARCH_REVISION_2) {
+ if (!GicV3Supported ()) {
Status = GicV2DxeInitialize (ImageHandle, SystemTable);
- } else if (Revision == ARM_GIC_ARCH_REVISION_3) {
- Status = GicV3DxeInitialize (ImageHandle, SystemTable);
} else {
- Status = EFI_UNSUPPORTED;
+ Status = GicV3DxeInitialize (ImageHandle, SystemTable);
}
return Status;
diff --git a/ArmPkg/Include/Library/ArmGicLib.h b/ArmPkg/Include/Library/ArmGicLib.h
index df32f47d86..57711ed9df 100644
--- a/ArmPkg/Include/Library/ArmGicLib.h
+++ b/ArmPkg/Include/Library/ArmGicLib.h
@@ -9,8 +9,6 @@
#ifndef ARMGIC_H_
#define ARMGIC_H_
-#include <Library/ArmGicArchLib.h>
-
// GIC Distributor
#define ARM_GIC_ICDDCR 0x000 // Distributor Control Register
#define ARM_GIC_ICDICTR 0x004 // Interrupt Controller Type Register