diff --git a/ArmPkg/ArmPkg.ci.yaml b/ArmPkg/ArmPkg.ci.yaml index d64b915262..4da5882900 100644 --- a/ArmPkg/ArmPkg.ci.yaml +++ b/ArmPkg/ArmPkg.ci.yaml @@ -162,11 +162,13 @@ "icdsgir", "icdspr", "icenabler", + "icpendr", # MU_CHANGE: Fix spell check error "intid", "ipriority", "irouter", "isenabler", "ishst", # MU_CHANGE: Fix spell check error + "ispendr", # MU_CHANGE: Fix spell check error "istatus", "itargets", "lable", diff --git a/ArmPkg/Drivers/ArmGic/ArmGicLib.c b/ArmPkg/Drivers/ArmGic/ArmGicLib.c index 01d6f38bed..db52ac41d2 100644 --- a/ArmPkg/Drivers/ArmGic/ArmGicLib.c +++ b/ArmPkg/Drivers/ArmGic/ArmGicLib.c @@ -33,6 +33,14 @@ #define IPRIORITY_ADDRESS(base, offset) ((base) +\ ARM_GICR_CTLR_FRAME_SIZE + ARM_GIC_ICDIPR + 4 * (offset)) +// MU_CHANGE Starts: Added pending interrupts definitions +#define ISPENDR_ADDRESS(base, offset) ((base) +\ + ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ISPENDR + 4 * (offset)) + +#define ICPENDR_ADDRESS(base, offset) ((base) +\ + ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ICPENDR + 4 * (offset)) +// MU_CHANGE Ends + /** * * Return whether the Source interrupt index refers to a shared interrupt (SPI) @@ -439,6 +447,142 @@ ArmGicIsInterruptEnabled ( return ((Interrupts & (1 << RegShift)) != 0); } +// MU_CHANGE Starts: Added new interfaces to support pending interrupt manipulation +VOID +EFIAPI +ArmGicSetPendingInterrupt ( + IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, + IN UINTN Source + ) +{ + UINT32 RegOffset; + UINTN RegShift; + ARM_GIC_ARCH_REVISION Revision; + UINTN GicCpuRedistributorBase; + + // Calculate enable register offset and bit position + RegOffset = (UINT32)(Source / 32); // MS_CHANGE + RegShift = Source % 32; + + Revision = ArmGicGetSupportedArchRevision (); + if ((Revision == ARM_GIC_ARCH_REVISION_2) || + FeaturePcdGet (PcdArmGicV3WithV2Legacy) || + SourceIsSpi (Source)) + { + // Write set-pending register + MmioWrite32 ( + GicDistributorBase + ARM_GIC_ICDSPR + (4 * RegOffset), + 1 << RegShift + ); + } else { + GicCpuRedistributorBase = GicGetCpuRedistributorBase ( + GicRedistributorBase, + Revision + ); + if (GicCpuRedistributorBase == 0) { + ASSERT_EFI_ERROR (EFI_NOT_FOUND); + return; + } + + // Write set-enable register + MmioWrite32 ( + ISPENDR_ADDRESS (GicCpuRedistributorBase, RegOffset), + 1 << RegShift + ); + } +} + +VOID +EFIAPI +ArmGicClearPendingInterrupt ( + IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, + IN UINTN Source + ) +{ + UINT32 RegOffset; + UINTN RegShift; + ARM_GIC_ARCH_REVISION Revision; + UINTN GicCpuRedistributorBase; + + // Calculate enable register offset and bit position + RegOffset = (UINT32)(Source / 32); // MS_CHANGE + RegShift = Source % 32; + + Revision = ArmGicGetSupportedArchRevision (); + if ((Revision == ARM_GIC_ARCH_REVISION_2) || + FeaturePcdGet (PcdArmGicV3WithV2Legacy) || + SourceIsSpi (Source)) + { + // Write clear-enable register + MmioWrite32 ( + GicDistributorBase + ARM_GIC_ICDICPR + (4 * RegOffset), + 1 << RegShift + ); + } else { + GicCpuRedistributorBase = GicGetCpuRedistributorBase ( + GicRedistributorBase, + Revision + ); + if (GicCpuRedistributorBase == 0) { + return; + } + + // Write clear-enable register + MmioWrite32 ( + ICPENDR_ADDRESS (GicCpuRedistributorBase, RegOffset), + 1 << RegShift + ); + } +} + +BOOLEAN +EFIAPI +ArmGicIsInterruptPending ( + IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, + IN UINTN Source + ) +{ + UINT32 RegOffset; + UINTN RegShift; + ARM_GIC_ARCH_REVISION Revision; + UINTN GicCpuRedistributorBase; + UINT32 Interrupts; + + // Calculate enable register offset and bit position + RegOffset = (UINT32)(Source / 32); // MS_CHANGE + RegShift = Source % 32; + + Revision = ArmGicGetSupportedArchRevision (); + if ((Revision == ARM_GIC_ARCH_REVISION_2) || + FeaturePcdGet (PcdArmGicV3WithV2Legacy) || + SourceIsSpi (Source)) + { + Interrupts = MmioRead32 ( + GicDistributorBase + ARM_GIC_ICDSPR + (4 * RegOffset) + ); + } else { + GicCpuRedistributorBase = GicGetCpuRedistributorBase ( + GicRedistributorBase, + Revision + ); + if (GicCpuRedistributorBase == 0) { + return 0; + } + + // Read set-enable register + Interrupts = MmioRead32 ( + ISPENDR_ADDRESS (GicCpuRedistributorBase, RegOffset) + ); + } + + return ((Interrupts & (1 << RegShift)) != 0); +} + +// MU_CHANGE Ends + VOID EFIAPI ArmGicDisableDistributor ( diff --git a/ArmPkg/Include/Library/ArmGicLib.h b/ArmPkg/Include/Library/ArmGicLib.h index dd0266bc67..4e5c256c6d 100644 --- a/ArmPkg/Include/Library/ArmGicLib.h +++ b/ArmPkg/Include/Library/ArmGicLib.h @@ -82,6 +82,8 @@ // GIC SGI & PPI Redistributor frame #define ARM_GICR_ISENABLER 0x0100 // Interrupt Set-Enable Registers #define ARM_GICR_ICENABLER 0x0180 // Interrupt Clear-Enable Registers +#define ARM_GICR_ISPENDR 0x0200 // MU_CHANGE: Interrupt Set-Pending Registers +#define ARM_GICR_ICPENDR 0x0280 // MU_CHANGE: Interrupt Clear-Pending Registers // GIC Cpu interface #define ARM_GIC_ICCICR 0x00 // CPU Interface Control Register @@ -173,6 +175,33 @@ ArmGicDisableInterruptInterface ( IN INTN GicInterruptInterfaceBase ); +// MU_CHANGE Starts: Added new interfaces to support pending interrupt manipulation +VOID +EFIAPI +ArmGicSetPendingInterrupt ( + IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, + IN UINTN Source + ); + +VOID +EFIAPI +ArmGicClearPendingInterrupt ( + IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, + IN UINTN Source + ); + +BOOLEAN +EFIAPI +ArmGicIsInterruptPending ( + IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, + IN UINTN Source + ); + +// MU_CHANGE Ends + VOID EFIAPI ArmGicEnableDistributor (