ArmPkg/ArmGic: Move GICv3 sysreg check into ArmGicDxe

ArmGicArchLib implements a check on the accessibility of the GIC system
register interface, which is a prerequisite for using the GIC in v3
mode. It might be possible to use GICv2 compatibility mode on poorly
configured platforms where the GIC is v3 capable but not accessible, but
in most cases, the GIC is driven in its native mode.

This check is now only carried out in a single place, and there is not
really any reason to keep this in a separate library. Even though
ArmVirtPkg implements its own version, the basic check (and enablement
of the sysreg interface) is still needed.

So move this check into the DXE driver itself, and drop the dependency
on ArmGicArchLib. This allows it to be retired in a subsequent patch.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
This commit is contained in:
Ard Biesheuvel 2025-01-16 18:11:21 +01:00 committed by mergify[bot]
parent 84eed1ef2a
commit 8edd5fd6d3
2 changed files with 39 additions and 10 deletions

View File

@ -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;

View File

@ -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