diff --git a/ArmPkg/Drivers/ArmGic/ArmGicLib.c b/ArmPkg/Drivers/ArmGic/ArmGicLib.c index 9e6dacdc4f..61d5dacba2 100644 --- a/ArmPkg/Drivers/ArmGic/ArmGicLib.c +++ b/ArmPkg/Drivers/ArmGic/ArmGicLib.c @@ -13,97 +13,6 @@ #include #include -// In GICv3, there are 2 x 64KB frames: -// Redistributor control frame + SGI Control & Generation frame -#define GIC_V3_REDISTRIBUTOR_GRANULARITY (ARM_GICR_CTLR_FRAME_SIZE \ - + ARM_GICR_SGI_PPI_FRAME_SIZE) - -// In GICv4, there are 2 additional 64KB frames: -// VLPI frame + Reserved page frame -#define GIC_V4_REDISTRIBUTOR_GRANULARITY (GIC_V3_REDISTRIBUTOR_GRANULARITY \ - + ARM_GICR_SGI_VLPI_FRAME_SIZE \ - + ARM_GICR_SGI_RESERVED_FRAME_SIZE) - -#define ISENABLER_ADDRESS(base, offset) ((base) +\ - ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ISENABLER + 4 * (offset)) - -#define ICENABLER_ADDRESS(base, offset) ((base) +\ - ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ICENABLER + 4 * (offset)) - -#define IPRIORITY_ADDRESS(base, offset) ((base) +\ - ARM_GICR_CTLR_FRAME_SIZE + ARM_GIC_ICDIPR + 4 * (offset)) - -/** - * - * Return whether the Source interrupt index refers to a shared interrupt (SPI) - */ -STATIC -BOOLEAN -SourceIsSpi ( - IN UINTN Source - ) -{ - return Source >= 32 && Source < 1020; -} - -/** - * Return the base address of the GIC redistributor for the current CPU - * - * @param Revision GIC Revision. The GIC redistributor might have a different - * granularity following the GIC revision. - * - * @retval Base address of the associated GIC Redistributor - */ -STATIC -UINTN -GicGetCpuRedistributorBase ( - IN UINTN GicRedistributorBase, - IN ARM_GIC_ARCH_REVISION Revision - ) -{ - UINTN MpId; - UINTN CpuAffinity; - UINTN Affinity; - UINTN GicCpuRedistributorBase; - UINT64 TypeRegister; - - MpId = ArmReadMpidr (); - // Define CPU affinity as: - // Affinity0[0:8], Affinity1[9:15], Affinity2[16:23], Affinity3[24:32] - // whereas Affinity3 is defined at [32:39] in MPIDR - CpuAffinity = (MpId & (ARM_CORE_AFF0 | ARM_CORE_AFF1 | ARM_CORE_AFF2)) | - ((MpId & ARM_CORE_AFF3) >> 8); - - if (Revision < ARM_GIC_ARCH_REVISION_3) { - ASSERT_EFI_ERROR (EFI_UNSUPPORTED); - return 0; - } - - GicCpuRedistributorBase = GicRedistributorBase; - - do { - TypeRegister = MmioRead64 (GicCpuRedistributorBase + ARM_GICR_TYPER); - Affinity = ARM_GICR_TYPER_GET_AFFINITY (TypeRegister); - if (Affinity == CpuAffinity) { - return GicCpuRedistributorBase; - } - - // Move to the next GIC Redistributor frame. - // The GIC specification does not forbid a mixture of redistributors - // with or without support for virtual LPIs, so we test Virtual LPIs - // Support (VLPIS) bit for each frame to decide the granularity. - // Note: The assumption here is that the redistributors are adjacent - // for all CPUs. However this may not be the case for NUMA systems. - GicCpuRedistributorBase += (((ARM_GICR_TYPER_VLPIS & TypeRegister) != 0) - ? GIC_V4_REDISTRIBUTOR_GRANULARITY - : GIC_V3_REDISTRIBUTOR_GRANULARITY); - } while ((TypeRegister & ARM_GICR_TYPER_LAST) == 0); - - // The Redistributor has not been found for the current CPU - ASSERT_EFI_ERROR (EFI_NOT_FOUND); - return 0; -} - /** Return the GIC CPU Interrupt Interface ID. @@ -137,180 +46,6 @@ ArmGicGetMaxNumInterrupts ( return (ItLines == 0x1f) ? 1020 : 32 * (ItLines + 1); } -VOID -EFIAPI -ArmGicSetInterruptPriority ( - IN UINTN GicDistributorBase, - IN UINTN GicRedistributorBase, - IN UINTN Source, - IN UINT32 Priority - ) -{ - UINT32 RegOffset; - UINT8 RegShift; - ARM_GIC_ARCH_REVISION Revision; - UINTN GicCpuRedistributorBase; - - // Calculate register offset and bit position - RegOffset = (UINT32)(Source / 4); - RegShift = (UINT8)((Source % 4) * 8); - - Revision = ArmGicGetSupportedArchRevision (); - if ((Revision == ARM_GIC_ARCH_REVISION_2) || - SourceIsSpi (Source)) - { - MmioAndThenOr32 ( - GicDistributorBase + ARM_GIC_ICDIPR + (4 * RegOffset), - ~(0xff << RegShift), - Priority << RegShift - ); - } else { - GicCpuRedistributorBase = GicGetCpuRedistributorBase ( - GicRedistributorBase, - Revision - ); - if (GicCpuRedistributorBase == 0) { - return; - } - - MmioAndThenOr32 ( - IPRIORITY_ADDRESS (GicCpuRedistributorBase, RegOffset), - ~(0xff << RegShift), - Priority << RegShift - ); - } -} - -VOID -EFIAPI -ArmGicEnableInterrupt ( - IN UINTN GicDistributorBase, - IN UINTN GicRedistributorBase, - IN UINTN Source - ) -{ - UINT32 RegOffset; - UINT8 RegShift; - ARM_GIC_ARCH_REVISION Revision; - UINTN GicCpuRedistributorBase; - - // Calculate enable register offset and bit position - RegOffset = (UINT32)(Source / 32); - RegShift = (UINT8)(Source % 32); - - Revision = ArmGicGetSupportedArchRevision (); - if ((Revision == ARM_GIC_ARCH_REVISION_2) || - SourceIsSpi (Source)) - { - // Write set-enable register - MmioWrite32 ( - GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset), - 1 << RegShift - ); - } else { - GicCpuRedistributorBase = GicGetCpuRedistributorBase ( - GicRedistributorBase, - Revision - ); - if (GicCpuRedistributorBase == 0) { - ASSERT_EFI_ERROR (EFI_NOT_FOUND); - return; - } - - // Write set-enable register - MmioWrite32 ( - ISENABLER_ADDRESS (GicCpuRedistributorBase, RegOffset), - 1 << RegShift - ); - } -} - -VOID -EFIAPI -ArmGicDisableInterrupt ( - IN UINTN GicDistributorBase, - IN UINTN GicRedistributorBase, - IN UINTN Source - ) -{ - UINT32 RegOffset; - UINT8 RegShift; - ARM_GIC_ARCH_REVISION Revision; - UINTN GicCpuRedistributorBase; - - // Calculate enable register offset and bit position - RegOffset = (UINT32)(Source / 32); - RegShift = (UINT8)(Source % 32); - - Revision = ArmGicGetSupportedArchRevision (); - if ((Revision == ARM_GIC_ARCH_REVISION_2) || - SourceIsSpi (Source)) - { - // Write clear-enable register - MmioWrite32 ( - GicDistributorBase + ARM_GIC_ICDICER + (4 * RegOffset), - 1 << RegShift - ); - } else { - GicCpuRedistributorBase = GicGetCpuRedistributorBase ( - GicRedistributorBase, - Revision - ); - if (GicCpuRedistributorBase == 0) { - return; - } - - // Write clear-enable register - MmioWrite32 ( - ICENABLER_ADDRESS (GicCpuRedistributorBase, RegOffset), - 1 << RegShift - ); - } -} - -BOOLEAN -EFIAPI -ArmGicIsInterruptEnabled ( - IN UINTN GicDistributorBase, - IN UINTN GicRedistributorBase, - IN UINTN Source - ) -{ - UINT32 RegOffset; - UINT8 RegShift; - ARM_GIC_ARCH_REVISION Revision; - UINTN GicCpuRedistributorBase; - UINT32 Interrupts; - - // Calculate enable register offset and bit position - RegOffset = (UINT32)(Source / 32); - RegShift = (UINT8)(Source % 32); - - Revision = ArmGicGetSupportedArchRevision (); - if ((Revision == ARM_GIC_ARCH_REVISION_2) || - SourceIsSpi (Source)) - { - Interrupts = MmioRead32 ( - GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset) - ); - } else { - GicCpuRedistributorBase = GicGetCpuRedistributorBase ( - GicRedistributorBase, - Revision - ); - if (GicCpuRedistributorBase == 0) { - return 0; - } - - // Read set-enable register - Interrupts = MmioRead32 ( - ISENABLER_ADDRESS (GicCpuRedistributorBase, RegOffset) - ); - } - - return ((Interrupts & (1 << RegShift)) != 0); -} - VOID EFIAPI ArmGicDisableDistributor ( diff --git a/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c index ef48177ee5..9906f1c987 100644 --- a/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c +++ b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c @@ -28,6 +28,73 @@ extern EFI_HARDWARE_INTERRUPT2_PROTOCOL gHardwareInterrupt2V2Protocol; STATIC UINTN mGicInterruptInterfaceBase; STATIC UINTN mGicDistributorBase; +STATIC +VOID +ArmGicEnableInterrupt ( + IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, + IN UINTN Source + ) +{ + UINT32 RegOffset; + UINT8 RegShift; + + // Calculate enable register offset and bit position + RegOffset = (UINT32)(Source / 32); + RegShift = (UINT8)(Source % 32); + + // Write set-enable register + MmioWrite32 ( + GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset), + 1 << RegShift + ); +} + +STATIC +VOID +ArmGicDisableInterrupt ( + IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, + IN UINTN Source + ) +{ + UINT32 RegOffset; + UINT8 RegShift; + + // Calculate enable register offset and bit position + RegOffset = (UINT32)(Source / 32); + RegShift = (UINT8)(Source % 32); + + // Write clear-enable register + MmioWrite32 ( + GicDistributorBase + ARM_GIC_ICDICER + (4 * RegOffset), + 1 << RegShift + ); +} + +STATIC +BOOLEAN +ArmGicIsInterruptEnabled ( + IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, + IN UINTN Source + ) +{ + UINT32 RegOffset; + UINT8 RegShift; + UINT32 Interrupts; + + // Calculate enable register offset and bit position + RegOffset = (UINT32)(Source / 32); + RegShift = (UINT8)(Source % 32); + + Interrupts = MmioRead32 ( + GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset) + ); + + return ((Interrupts & (1 << RegShift)) != 0); +} + /** Enable interrupt source Source. diff --git a/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2NonSecLib.c b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2NonSecLib.c deleted file mode 100644 index 781645e8ea..0000000000 --- a/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2NonSecLib.c +++ /dev/null @@ -1,35 +0,0 @@ -/** @file -* -* Copyright (c) 2011-2023, Arm Limited. All rights reserved. -* -* SPDX-License-Identifier: BSD-2-Clause-Patent -* -**/ - -#include -#include -#include - -VOID -EFIAPI -ArmGicV2EnableInterruptInterface ( - IN UINTN GicInterruptInterfaceBase - ) -{ - /* - * Enable the CPU interface in Non-Secure world - * Note: The ICCICR register is banked when Security extensions are implemented - */ - MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR, 0x1); -} - -VOID -EFIAPI -ArmGicV2DisableInterruptInterface ( - IN UINTN GicInterruptInterfaceBase - ) -{ - // Disable Gic Interface - MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR, 0x0); - MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0x0); -} diff --git a/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c b/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c index 2bcd3f2154..fb168c5c4b 100644 --- a/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c +++ b/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c @@ -12,12 +12,248 @@ #define ARM_GIC_DEFAULT_PRIORITY 0x80 +// In GICv3, there are 2 x 64KB frames: +// Redistributor control frame + SGI Control & Generation frame +#define GIC_V3_REDISTRIBUTOR_GRANULARITY (ARM_GICR_CTLR_FRAME_SIZE \ + + ARM_GICR_SGI_PPI_FRAME_SIZE) + +// In GICv4, there are 2 additional 64KB frames: +// VLPI frame + Reserved page frame +#define GIC_V4_REDISTRIBUTOR_GRANULARITY (GIC_V3_REDISTRIBUTOR_GRANULARITY \ + + ARM_GICR_SGI_VLPI_FRAME_SIZE \ + + ARM_GICR_SGI_RESERVED_FRAME_SIZE) + +#define ISENABLER_ADDRESS(base, offset) ((base) +\ + ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ISENABLER + 4 * (offset)) + +#define ICENABLER_ADDRESS(base, offset) ((base) +\ + ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ICENABLER + 4 * (offset)) + +#define IPRIORITY_ADDRESS(base, offset) ((base) +\ + ARM_GICR_CTLR_FRAME_SIZE + ARM_GIC_ICDIPR + 4 * (offset)) + extern EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptV3Protocol; extern EFI_HARDWARE_INTERRUPT2_PROTOCOL gHardwareInterrupt2V3Protocol; STATIC UINTN mGicDistributorBase; STATIC UINTN mGicRedistributorsBase; +/** + * + * Return whether the Source interrupt index refers to a shared interrupt (SPI) + */ +STATIC +BOOLEAN +SourceIsSpi ( + IN UINTN Source + ) +{ + return Source >= 32 && Source < 1020; +} + +/** + * Return the base address of the GIC redistributor for the current CPU + * + * @retval Base address of the associated GIC Redistributor + */ +STATIC +UINTN +GicGetCpuRedistributorBase ( + IN UINTN GicRedistributorBase + ) +{ + UINTN MpId; + UINTN CpuAffinity; + UINTN Affinity; + UINTN GicCpuRedistributorBase; + UINT64 TypeRegister; + + MpId = ArmReadMpidr (); + // Define CPU affinity as: + // Affinity0[0:8], Affinity1[9:15], Affinity2[16:23], Affinity3[24:32] + // whereas Affinity3 is defined at [32:39] in MPIDR + CpuAffinity = (MpId & (ARM_CORE_AFF0 | ARM_CORE_AFF1 | ARM_CORE_AFF2)) | + ((MpId & ARM_CORE_AFF3) >> 8); + + GicCpuRedistributorBase = GicRedistributorBase; + + do { + TypeRegister = MmioRead64 (GicCpuRedistributorBase + ARM_GICR_TYPER); + Affinity = ARM_GICR_TYPER_GET_AFFINITY (TypeRegister); + if (Affinity == CpuAffinity) { + return GicCpuRedistributorBase; + } + + // Move to the next GIC Redistributor frame. + // The GIC specification does not forbid a mixture of redistributors + // with or without support for virtual LPIs, so we test Virtual LPIs + // Support (VLPIS) bit for each frame to decide the granularity. + // Note: The assumption here is that the redistributors are adjacent + // for all CPUs. However this may not be the case for NUMA systems. + GicCpuRedistributorBase += (((ARM_GICR_TYPER_VLPIS & TypeRegister) != 0) + ? GIC_V4_REDISTRIBUTOR_GRANULARITY + : GIC_V3_REDISTRIBUTOR_GRANULARITY); + } while ((TypeRegister & ARM_GICR_TYPER_LAST) == 0); + + // The Redistributor has not been found for the current CPU + ASSERT_EFI_ERROR (EFI_NOT_FOUND); + return 0; +} + +STATIC +VOID +ArmGicSetInterruptPriority ( + IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, + IN UINTN Source, + IN UINT32 Priority + ) +{ + UINT32 RegOffset; + UINT8 RegShift; + UINTN GicCpuRedistributorBase; + + // Calculate register offset and bit position + RegOffset = (UINT32)(Source / 4); + RegShift = (UINT8)((Source % 4) * 8); + + if (SourceIsSpi (Source)) { + MmioAndThenOr32 ( + GicDistributorBase + ARM_GIC_ICDIPR + (4 * RegOffset), + ~(0xff << RegShift), + Priority << RegShift + ); + } else { + GicCpuRedistributorBase = GicGetCpuRedistributorBase ( + GicRedistributorBase + ); + if (GicCpuRedistributorBase == 0) { + return; + } + + MmioAndThenOr32 ( + IPRIORITY_ADDRESS (GicCpuRedistributorBase, RegOffset), + ~(0xff << RegShift), + Priority << RegShift + ); + } +} + +STATIC +VOID +ArmGicEnableInterrupt ( + IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, + IN UINTN Source + ) +{ + UINT32 RegOffset; + UINT8 RegShift; + UINTN GicCpuRedistributorBase; + + // Calculate enable register offset and bit position + RegOffset = (UINT32)(Source / 32); + RegShift = (UINT8)(Source % 32); + + if (SourceIsSpi (Source)) { + // Write set-enable register + MmioWrite32 ( + GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset), + 1 << RegShift + ); + } else { + GicCpuRedistributorBase = GicGetCpuRedistributorBase ( + GicRedistributorBase + ); + if (GicCpuRedistributorBase == 0) { + ASSERT_EFI_ERROR (EFI_NOT_FOUND); + return; + } + + // Write set-enable register + MmioWrite32 ( + ISENABLER_ADDRESS (GicCpuRedistributorBase, RegOffset), + 1 << RegShift + ); + } +} + +STATIC +VOID +ArmGicDisableInterrupt ( + IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, + IN UINTN Source + ) +{ + UINT32 RegOffset; + UINT8 RegShift; + UINTN GicCpuRedistributorBase; + + // Calculate enable register offset and bit position + RegOffset = (UINT32)(Source / 32); + RegShift = (UINT8)(Source % 32); + + if (SourceIsSpi (Source)) { + // Write clear-enable register + MmioWrite32 ( + GicDistributorBase + ARM_GIC_ICDICER + (4 * RegOffset), + 1 << RegShift + ); + } else { + GicCpuRedistributorBase = GicGetCpuRedistributorBase ( + GicRedistributorBase + ); + if (GicCpuRedistributorBase == 0) { + return; + } + + // Write clear-enable register + MmioWrite32 ( + ICENABLER_ADDRESS (GicCpuRedistributorBase, RegOffset), + 1 << RegShift + ); + } +} + +STATIC +BOOLEAN +ArmGicIsInterruptEnabled ( + IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, + IN UINTN Source + ) +{ + UINT32 RegOffset; + UINT8 RegShift; + UINTN GicCpuRedistributorBase; + UINT32 Interrupts; + + // Calculate enable register offset and bit position + RegOffset = (UINT32)(Source / 32); + RegShift = (UINT8)(Source % 32); + + if (SourceIsSpi (Source)) { + Interrupts = MmioRead32 ( + GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset) + ); + } else { + GicCpuRedistributorBase = GicGetCpuRedistributorBase ( + GicRedistributorBase + ); + if (GicCpuRedistributorBase == 0) { + return 0; + } + + // Read set-enable register + Interrupts = MmioRead32 ( + ISENABLER_ADDRESS (GicCpuRedistributorBase, RegOffset) + ); + } + + return ((Interrupts & (1 << RegShift)) != 0); +} + /** Enable interrupt source Source. diff --git a/ArmPkg/Include/Library/ArmGicLib.h b/ArmPkg/Include/Library/ArmGicLib.h index 725ee268af..6f69aeb926 100644 --- a/ArmPkg/Include/Library/ArmGicLib.h +++ b/ArmPkg/Include/Library/ArmGicLib.h @@ -158,39 +158,6 @@ ArmGicSetPriorityMask ( IN INTN PriorityMask ); -VOID -EFIAPI -ArmGicSetInterruptPriority ( - IN UINTN GicDistributorBase, - IN UINTN GicRedistributorBase, - IN UINTN Source, - IN UINT32 Priority - ); - -VOID -EFIAPI -ArmGicEnableInterrupt ( - IN UINTN GicDistributorBase, - IN UINTN GicRedistributorBase, - IN UINTN Source - ); - -VOID -EFIAPI -ArmGicDisableInterrupt ( - IN UINTN GicDistributorBase, - IN UINTN GicRedistributorBase, - IN UINTN Source - ); - -BOOLEAN -EFIAPI -ArmGicIsInterruptEnabled ( - IN UINTN GicDistributorBase, - IN UINTN GicRedistributorBase, - IN UINTN Source - ); - // GIC revision 2 specific declarations // Interrupts from 1020 to 1023 are considered as special interrupts