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; + EFI_STATUS Status; - Revision = ArmGicGetSupportedArchRevision (); - - 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 - // GIC Distributor #define ARM_GIC_ICDDCR 0x000 // Distributor Control Register #define ARM_GIC_ICDICTR 0x004 // Interrupt Controller Type Register