Skip to content

Commit 2b7c65c

Browse files
ArmPkg/Drivers/ArmGicDxe: Add ESPI support for GICv3
- Add ESPI configuration to GICv3. - Remove mNumGicInterrupts and replace with GicIsValidSource(), GicGetGreatestIntid() APIs. mNumGicInterrupts is still used internally in GICv2. - Tested on qemu with the BSA test suite. Signed-off-by: Nick Graves <[email protected]>
1 parent 7711e8a commit 2b7c65c

File tree

5 files changed

+288
-75
lines changed

5 files changed

+288
-75
lines changed

ArmPkg/Drivers/ArmGicDxe/ArmGicCommonDxe.c

+34-13
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,23 @@ EFI_HANDLE gHardwareInterruptHandle = NULL;
1414
// Notifications
1515
EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
1616

17-
// Maximum Number of Interrupts
18-
UINTN mGicNumInterrupts = 0;
19-
2017
HARDWARE_INTERRUPT_HANDLER *gRegisteredInterruptHandlers = NULL;
2118
EFI_CPU_ARCH_PROTOCOL *gCpuArch;
2219

20+
/**
21+
*
22+
* Return whether the Source interrupt index refers to an extended shared
23+
* interrupt (ESPI)
24+
*/
25+
STATIC
26+
BOOLEAN
27+
SourceIsEspi (
28+
IN UINTN Source
29+
)
30+
{
31+
return Source >= ARM_GIC_ARCH_EXT_SPI_MIN && Source <= ARM_GIC_ARCH_EXT_SPI_MAX;
32+
}
33+
2334
/**
2435
Calculate GICD_ICFGRn base address and corresponding bit
2536
field Int_config[1] of the GIC distributor register.
@@ -38,18 +49,25 @@ GicGetDistributorIcfgBaseAndBit (
3849
OUT UINTN *Config1Bit
3950
)
4051
{
41-
UINTN RegIndex;
42-
UINTN Field;
52+
UINTN RegIndex;
53+
UINTN Field;
54+
UINTN RegOffset;
55+
HARDWARE_INTERRUPT_SOURCE AdjustedSource;
4356

44-
if (Source >= mGicNumInterrupts) {
45-
ASSERT (Source < mGicNumInterrupts);
57+
if (!GicIsValidSource (Source)) {
58+
ASSERT (FALSE);
4659
return EFI_UNSUPPORTED;
4760
}
4861

49-
RegIndex = Source / ARM_GIC_ICDICFR_F_STRIDE; // NOTE: truncation is significant
50-
Field = Source % ARM_GIC_ICDICFR_F_STRIDE;
62+
// Translate ESPI sources into the SPI range for indexing purposes.
63+
AdjustedSource = Source & ~(ARM_GIC_ARCH_EXT_SPI_MIN);
64+
65+
RegOffset = (SourceIsEspi (Source)) ? ARM_GIC_ICDICFR_E : ARM_GIC_ICDICFR;
66+
67+
RegIndex = AdjustedSource / ARM_GIC_ICDICFR_F_STRIDE; // NOTE: truncation is significant
68+
Field = AdjustedSource % ARM_GIC_ICDICFR_F_STRIDE;
5169
*RegAddress = (UINTN)PcdGet64 (PcdGicDistributorBase)
52-
+ ARM_GIC_ICDICFR
70+
+ RegOffset
5371
+ (ARM_GIC_ICDICFR_BYTES * RegIndex);
5472
*Config1Bit = ((Field * ARM_GIC_ICDICFR_F_WIDTH)
5573
+ ARM_GIC_ICDICFR_F_CONFIG1_BIT);
@@ -76,7 +94,7 @@ RegisterInterruptSource (
7694
IN HARDWARE_INTERRUPT_HANDLER Handler
7795
)
7896
{
79-
if (Source >= mGicNumInterrupts) {
97+
if (!GicIsValidSource (Source)) {
8098
ASSERT (FALSE);
8199
return EFI_UNSUPPORTED;
82100
}
@@ -107,9 +125,12 @@ InstallAndRegisterInterruptService (
107125
IN EFI_EVENT_NOTIFY ExitBootServicesEvent
108126
)
109127
{
110-
EFI_STATUS Status;
128+
EFI_STATUS Status;
129+
130+
UINTN NumIntids = GicGetGreatestIntid () + 1;
131+
111132
CONST UINTN RihArraySize =
112-
(sizeof (HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);
133+
(sizeof (HARDWARE_INTERRUPT_HANDLER) * NumIntids);
113134

114135
// Initialize the array for the Interrupt Handlers
115136
gRegisteredInterruptHandlers = AllocateZeroPool (RihArraySize);

ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.h

+24-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
2121
#include <Protocol/HardwareInterrupt.h>
2222
#include <Protocol/HardwareInterrupt2.h>
2323

24-
extern UINTN mGicNumInterrupts;
2524
extern HARDWARE_INTERRUPT_HANDLER *gRegisteredInterruptHandlers;
2625
extern EFI_CPU_ARCH_PROTOCOL *gCpuArch;
2726

@@ -76,6 +75,30 @@ GicGetDistributorIcfgBaseAndBit (
7675
OUT UINTN *Config1Bit
7776
);
7877

78+
/**
79+
Returns true if the Source is valid.
80+
81+
@param Source Hardware source of the interrupt.
82+
83+
@retval True if valid, false otherwise.
84+
*/
85+
BOOLEAN
86+
EFIAPI
87+
GicIsValidSource (
88+
IN HARDWARE_INTERRUPT_SOURCE Source
89+
);
90+
91+
/**
92+
Returns the greatest valid intid.
93+
94+
@retval The greatest valid intid.
95+
*/
96+
HARDWARE_INTERRUPT_SOURCE
97+
EFIAPI
98+
GicGetGreatestIntid (
99+
VOID
100+
);
101+
79102
UINT32
80103
EFIAPI
81104
ArmGicGetInterfaceIdentification (

ArmPkg/Drivers/ArmGicDxe/GicV2/ArmGicV2Dxe.c

+22
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Module Name:
1919
#include <Library/ArmGicLib.h>
2020

2121
#include "ArmGicDxe.h"
22+
#include "Protocol/HardwareInterrupt.h"
2223

2324
#define ARM_GIC_DEFAULT_PRIORITY 0x80
2425

@@ -36,6 +37,9 @@ extern EFI_HARDWARE_INTERRUPT2_PROTOCOL gHardwareInterrupt2V2Protocol;
3637
STATIC UINTN mGicInterruptInterfaceBase;
3738
STATIC UINTN mGicDistributorBase;
3839

40+
// Maximum Number of Interrupts
41+
STATIC UINTN mGicNumInterrupts;
42+
3943
STATIC
4044
VOID
4145
ArmGicEnableInterrupt (
@@ -613,3 +617,21 @@ GicV2DxeInitialize (
613617

614618
return Status;
615619
}
620+
621+
BOOLEAN
622+
EFIAPI
623+
GicIsValidSource (
624+
IN HARDWARE_INTERRUPT_SOURCE Source
625+
)
626+
{
627+
return Source < mGicNumInterrupts;
628+
}
629+
630+
HARDWARE_INTERRUPT_SOURCE
631+
EFIAPI
632+
GicGetGreatestIntid (
633+
VOID
634+
)
635+
{
636+
return mGicNumInterrupts - 1;
637+
}

0 commit comments

Comments
 (0)