Skip to content

Commit

Permalink
Added functionalities to manipulate pending interrupts (#42)
Browse files Browse the repository at this point in the history
# Preface

Please ensure you have read the [contribution
docs](https://github.com/microsoft/mu/blob/master/CONTRIBUTING.md) prior
to submitting the pull request. In particular,
[pull request
guidelines](https://github.com/microsoft/mu/blob/master/CONTRIBUTING.md#pull-request-best-practices).

## Description

This change provides additional functionalities to `ArmGicLib` to
manipulate
pending interrupt related status. The added functions include:

- `ArmGicSetPendingInterrupt`
- `ArmGicClearPendingInterrupt`
- `ArmGicIsInterruptPending`

For each item, place an "x" in between `[` and `]` if true. Example:
`[x]`.
_(you can also check items in the GitHub UI)_

- [x] Impacts functionality?
- [ ] Impacts security?
- [ ] Breaking change?
- [ ] Includes tests?
- [ ] Includes documentation?

## How This Was Tested

This change was tested on QEMU and FVP virtual platforms, as well as
proprietary physical
devices.

## Integration Instructions

N/A
  • Loading branch information
kuqin12 authored and kenlautner committed May 12, 2023
1 parent a45d968 commit 9aae937
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 0 deletions.
2 changes: 2 additions & 0 deletions ArmPkg/ArmPkg.ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
144 changes: 144 additions & 0 deletions ArmPkg/Drivers/ArmGic/ArmGicLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 (
Expand Down
29 changes: 29 additions & 0 deletions ArmPkg/Include/Library/ArmGicLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 (
Expand Down

0 comments on commit 9aae937

Please sign in to comment.