From c558a3b18b45348670e00bc3e7644d39c701fce3 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 28 Jan 2025 17:15:11 +0100 Subject: ArmPkg/ArmGicDxe: Map GIC MMIO regions before use The GIC driver itself has intimate knowledge of the hardware, and so it is the best suited to create the mappings of the MMIO control regions, in case they have not been mapped yet by the platform code. So call in the the CPU arch protocol to map the CPU interface, distributor and redistributor regions as they are discovered by the GIC driver startup code. Note that creating these mappings has no effect if the regions in question have already been mapped with the correct attributes. Signed-off-by: Ard Biesheuvel --- ArmPkg/Drivers/ArmGicDxe/ArmGicCommonDxe.c | 4 --- ArmPkg/Drivers/ArmGicDxe/GicV2/ArmGicV2Dxe.c | 24 ++++++++++++++- ArmPkg/Drivers/ArmGicDxe/GicV3/ArmGicV3Dxe.c | 45 ++++++++++++++++++++++++---- 3 files changed, 62 insertions(+), 11 deletions(-) diff --git a/ArmPkg/Drivers/ArmGicDxe/ArmGicCommonDxe.c b/ArmPkg/Drivers/ArmGicDxe/ArmGicCommonDxe.c index e777aee468..f40797b734 100644 --- a/ArmPkg/Drivers/ArmGicDxe/ArmGicCommonDxe.c +++ b/ArmPkg/Drivers/ArmGicDxe/ArmGicCommonDxe.c @@ -111,10 +111,6 @@ InstallAndRegisterInterruptService ( CONST UINTN RihArraySize = (sizeof (HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts); - // Locate the CPU arch protocol - cannot fail because of DEPEX - Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpuArch); - ASSERT_EFI_ERROR (Status); - // Initialize the array for the Interrupt Handlers gRegisteredInterruptHandlers = AllocateZeroPool (RihArraySize); if (gRegisteredInterruptHandlers == NULL) { diff --git a/ArmPkg/Drivers/ArmGicDxe/GicV2/ArmGicV2Dxe.c b/ArmPkg/Drivers/ArmGicDxe/GicV2/ArmGicV2Dxe.c index 258869b2c7..6dabece1da 100644 --- a/ArmPkg/Drivers/ArmGicDxe/GicV2/ArmGicV2Dxe.c +++ b/ArmPkg/Drivers/ArmGicDxe/GicV2/ArmGicV2Dxe.c @@ -22,6 +22,9 @@ Abstract: #define ARM_GIC_DEFAULT_PRIORITY 0x80 +#define GICD_V2_SIZE SIZE_4KB +#define GICC_V2_SIZE SIZE_8KB + // Interrupts from 1020 to 1023 are considered as special interrupts // (eg: spurious interrupts) #define ARM_GIC_IS_SPECIAL_INTERRUPTS(Interrupt) \ @@ -529,9 +532,28 @@ GicV2DxeInitialize ( ASSERT (PcdGet64 (PcdGicInterruptInterfaceBase) <= MAX_UINTN); ASSERT (PcdGet64 (PcdGicDistributorBase) <= MAX_UINTN); + // Locate the CPU arch protocol - cannot fail because of DEPEX + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpuArch); + ASSERT_EFI_ERROR (Status); + mGicInterruptInterfaceBase = (UINTN)PcdGet64 (PcdGicInterruptInterfaceBase); mGicDistributorBase = (UINTN)PcdGet64 (PcdGicDistributorBase); - mGicNumInterrupts = ArmGicGetMaxNumInterrupts (mGicDistributorBase); + + Status = gCpuArch->SetMemoryAttributes (gCpuArch, mGicDistributorBase, GICD_V2_SIZE, EFI_MEMORY_UC | EFI_MEMORY_XP); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to map GICv2 distributor MMIO interface: %r\n", __func__, Status)); + ASSERT_EFI_ERROR (Status); + return Status; + } + + mGicNumInterrupts = ArmGicGetMaxNumInterrupts (mGicDistributorBase); + + Status = gCpuArch->SetMemoryAttributes (gCpuArch, mGicInterruptInterfaceBase, GICC_V2_SIZE, EFI_MEMORY_UC | EFI_MEMORY_XP); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to map GICv2 CPU MMIO interface: %r\n", __func__, Status)); + ASSERT_EFI_ERROR (Status); + return Status; + } for (Index = 0; Index < mGicNumInterrupts; Index++) { GicV2DisableInterruptSource (&gHardwareInterruptV2Protocol, Index); diff --git a/ArmPkg/Drivers/ArmGicDxe/GicV3/ArmGicV3Dxe.c b/ArmPkg/Drivers/ArmGicDxe/GicV3/ArmGicV3Dxe.c index 34fe8d295c..798b01d0d6 100644 --- a/ArmPkg/Drivers/ArmGicDxe/GicV3/ArmGicV3Dxe.c +++ b/ArmPkg/Drivers/ArmGicDxe/GicV3/ArmGicV3Dxe.c @@ -23,6 +23,8 @@ + ARM_GICR_SGI_VLPI_FRAME_SIZE \ + ARM_GICR_SGI_RESERVED_FRAME_SIZE) +#define GICD_V3_SIZE SIZE_64KB + #define ISENABLER_ADDRESS(base, offset) ((base) +\ ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ISENABLER + 4 * (offset)) @@ -62,11 +64,12 @@ GicGetCpuRedistributorBase ( IN UINTN GicRedistributorBase ) { - UINTN MpId; - UINTN CpuAffinity; - UINTN Affinity; - UINTN GicCpuRedistributorBase; - UINT64 TypeRegister; + UINTN MpId; + UINTN CpuAffinity; + UINTN Affinity; + UINTN GicCpuRedistributorBase; + UINT64 TypeRegister; + EFI_STATUS Status; MpId = ArmReadMpidr (); // Define CPU affinity as: @@ -78,6 +81,24 @@ GicGetCpuRedistributorBase ( GicCpuRedistributorBase = GicRedistributorBase; do { + Status = gCpuArch->SetMemoryAttributes ( + gCpuArch, + GicCpuRedistributorBase, + GIC_V3_REDISTRIBUTOR_GRANULARITY, + EFI_MEMORY_UC | EFI_MEMORY_XP + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: Failed to map GICv3 redistributor MMIO interface at 0x%lx: %r\n", + __func__, + GicCpuRedistributorBase, + Status + )); + ASSERT_EFI_ERROR (Status); + return 0; + } + TypeRegister = MmioRead64 (GicCpuRedistributorBase + ARM_GICR_TYPER); Affinity = ARM_GICR_TYPER_GET_AFFINITY (TypeRegister); if (Affinity == CpuAffinity) { @@ -589,7 +610,19 @@ GicV3DxeInitialize ( // the system. ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid); - mGicDistributorBase = (UINTN)PcdGet64 (PcdGicDistributorBase); + // Locate the CPU arch protocol - cannot fail because of DEPEX + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpuArch); + ASSERT_EFI_ERROR (Status); + + mGicDistributorBase = (UINTN)PcdGet64 (PcdGicDistributorBase); + + Status = gCpuArch->SetMemoryAttributes (gCpuArch, mGicDistributorBase, GICD_V3_SIZE, EFI_MEMORY_UC | EFI_MEMORY_XP); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to map GICv3 distributor MMIO interface: %r\n", __func__, Status)); + ASSERT_EFI_ERROR (Status); + return Status; + } + mGicRedistributorBase = GicGetCpuRedistributorBase (PcdGet64 (PcdGicRedistributorsBase)); mGicNumInterrupts = ArmGicGetMaxNumInterrupts (mGicDistributorBase); -- cgit