ArmPkg: Tidy GIC code before changes.
This change is purely cosmetic, to tidy some code before change. Mods involve: Re-order #includes Reformat comments. Use ns consistently (always "100ns" not sometimes "100 nS") Split overlength code lines. Make protocol functions STATIC. Remove "Horor vacui" comments. Rationalize GIC register address calculations Replace explicit test and assert with ASSERT_EFI_ERROR. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Girish Pathak <girish.pathak@arm.com> Signed-off-by: Alexei Fedorov <alexei.fedorov@arm.com> Signed-off-by: Evan Lloyd <evan.lloyd@arm.com> Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
This commit is contained in:
committed by
Leif Lindholm
parent
fe4049471b
commit
b0393756d6
@@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>
|
||||
Copyright (c) 2013-2017, ARM Ltd. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
@@ -28,14 +28,10 @@ ExitBootServicesEvent (
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
//
|
||||
// Making this global saves a few bytes in image size
|
||||
//
|
||||
EFI_HANDLE gHardwareInterruptHandle = NULL;
|
||||
|
||||
//
|
||||
// Notifications
|
||||
//
|
||||
EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
|
||||
|
||||
// Maximum Number of Interrupts
|
||||
@@ -94,48 +90,55 @@ InstallAndRegisterInterruptService (
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_CPU_ARCH_PROTOCOL *Cpu;
|
||||
CONST UINTN RihArraySize =
|
||||
(sizeof(HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);
|
||||
|
||||
// Initialize the array for the Interrupt Handlers
|
||||
gRegisteredInterruptHandlers = (HARDWARE_INTERRUPT_HANDLER*)AllocateZeroPool (sizeof(HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);
|
||||
gRegisteredInterruptHandlers = AllocateZeroPool (RihArraySize);
|
||||
if (gRegisteredInterruptHandlers == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&gHardwareInterruptHandle,
|
||||
&gHardwareInterruptProtocolGuid, InterruptProtocol,
|
||||
&gHardwareInterruptProtocolGuid,
|
||||
InterruptProtocol,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the CPU protocol that this driver requires.
|
||||
//
|
||||
Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Unregister the default exception handler.
|
||||
//
|
||||
Status = Cpu->RegisterInterruptHandler (Cpu, ARM_ARCH_EXCEPTION_IRQ, NULL);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Register to receive interrupts
|
||||
//
|
||||
Status = Cpu->RegisterInterruptHandler (Cpu, ARM_ARCH_EXCEPTION_IRQ, InterruptHandler);
|
||||
Status = Cpu->RegisterInterruptHandler (
|
||||
Cpu,
|
||||
ARM_ARCH_EXCEPTION_IRQ,
|
||||
InterruptHandler
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Register for an ExitBootServicesEvent
|
||||
Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_SIGNAL_EXIT_BOOT_SERVICES,
|
||||
TPL_NOTIFY,
|
||||
ExitBootServicesEvent,
|
||||
NULL,
|
||||
&EfiExitBootServicesEvent
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>
|
||||
Copyright (c) 2013-2017, ARM Ltd. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
@@ -28,9 +28,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
extern UINTN mGicNumInterrupts;
|
||||
extern HARDWARE_INTERRUPT_HANDLER *gRegisteredInterruptHandlers;
|
||||
|
||||
//
|
||||
// Common API
|
||||
//
|
||||
EFI_STATUS
|
||||
InstallAndRegisterInterruptService (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *InterruptProtocol,
|
||||
@@ -46,18 +44,14 @@ RegisterInterruptSource (
|
||||
IN HARDWARE_INTERRUPT_HANDLER Handler
|
||||
);
|
||||
|
||||
//
|
||||
// GicV2 API
|
||||
//
|
||||
EFI_STATUS
|
||||
GicV2DxeInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
);
|
||||
|
||||
//
|
||||
// GicV3 API
|
||||
//
|
||||
EFI_STATUS
|
||||
GicV3DxeInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011-2015, ARM Limited. All rights reserved.
|
||||
* Copyright (c) 2011-2017, ARM Limited. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are licensed and made available under the terms and conditions of the BSD License
|
||||
@@ -19,6 +19,13 @@
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
|
||||
|
||||
#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))
|
||||
|
||||
/**
|
||||
*
|
||||
* Return whether the Source interrupt index refers to a shared interrupt (SPI)
|
||||
@@ -55,13 +62,17 @@ GicGetCpuRedistributorBase (
|
||||
UINTN GicCpuRedistributorBase;
|
||||
|
||||
MpId = ArmReadMpidr ();
|
||||
// Define CPU affinity as Affinity0[0:8], Affinity1[9:15], Affinity2[16:23], Affinity3[24:32]
|
||||
// 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);
|
||||
CpuAffinity = (MpId & (ARM_CORE_AFF0 | ARM_CORE_AFF1 | ARM_CORE_AFF2)) |
|
||||
((MpId & ARM_CORE_AFF3) >> 8);
|
||||
|
||||
if (Revision == ARM_GIC_ARCH_REVISION_3) {
|
||||
// 2 x 64KB frame: Redistributor control frame + SGI Control & Generation frame
|
||||
GicRedistributorGranularity = ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_SGI_PPI_FRAME_SIZE;
|
||||
// 2 x 64KB frame:
|
||||
// Redistributor control frame + SGI Control & Generation frame
|
||||
GicRedistributorGranularity = ARM_GICR_CTLR_FRAME_SIZE
|
||||
+ ARM_GICR_SGI_PPI_FRAME_SIZE;
|
||||
} else {
|
||||
ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
|
||||
return 0;
|
||||
@@ -112,7 +123,10 @@ ArmGicSendSgiTo (
|
||||
IN INTN SgiId
|
||||
)
|
||||
{
|
||||
MmioWrite32 (GicDistributorBase + ARM_GIC_ICDSGIR, ((TargetListFilter & 0x3) << 24) | ((CPUTargetList & 0xFF) << 16) | SgiId);
|
||||
MmioWrite32 (
|
||||
GicDistributorBase + ARM_GIC_ICDSGIR,
|
||||
((TargetListFilter & 0x3) << 24) | ((CPUTargetList & 0xFF) << 16) | SgiId
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -123,7 +137,8 @@ ArmGicSendSgiTo (
|
||||
* in the GICv3 the register value is only the InterruptId.
|
||||
*
|
||||
* @param GicInterruptInterfaceBase Base Address of the GIC CPU Interface
|
||||
* @param InterruptId InterruptId read from the Interrupt Acknowledge Register
|
||||
* @param InterruptId InterruptId read from the Interrupt
|
||||
* Acknowledge Register
|
||||
*
|
||||
* @retval value returned by the Interrupt Acknowledge Register
|
||||
*
|
||||
@@ -200,16 +215,25 @@ ArmGicEnableInterrupt (
|
||||
FeaturePcdGet (PcdArmGicV3WithV2Legacy) ||
|
||||
SourceIsSpi (Source)) {
|
||||
// Write set-enable register
|
||||
MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset), 1 << RegShift);
|
||||
MmioWrite32 (
|
||||
GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset),
|
||||
1 << RegShift
|
||||
);
|
||||
} else {
|
||||
GicCpuRedistributorBase = GicGetCpuRedistributorBase (GicRedistributorBase, Revision);
|
||||
GicCpuRedistributorBase = GicGetCpuRedistributorBase (
|
||||
GicRedistributorBase,
|
||||
Revision
|
||||
);
|
||||
if (GicCpuRedistributorBase == 0) {
|
||||
ASSERT_EFI_ERROR (EFI_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
// Write set-enable register
|
||||
MmioWrite32 (GicCpuRedistributorBase + ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ISENABLER + (4 * RegOffset), 1 << RegShift);
|
||||
MmioWrite32 (
|
||||
ISENABLER_ADDRESS(GicCpuRedistributorBase, RegOffset),
|
||||
1 << RegShift
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,15 +259,24 @@ ArmGicDisableInterrupt (
|
||||
FeaturePcdGet (PcdArmGicV3WithV2Legacy) ||
|
||||
SourceIsSpi (Source)) {
|
||||
// Write clear-enable register
|
||||
MmioWrite32 (GicDistributorBase + ARM_GIC_ICDICER + (4 * RegOffset), 1 << RegShift);
|
||||
MmioWrite32 (
|
||||
GicDistributorBase + ARM_GIC_ICDICER + (4 * RegOffset),
|
||||
1 << RegShift
|
||||
);
|
||||
} else {
|
||||
GicCpuRedistributorBase = GicGetCpuRedistributorBase (GicRedistributorBase, Revision);
|
||||
GicCpuRedistributorBase = GicGetCpuRedistributorBase (
|
||||
GicRedistributorBase,
|
||||
Revision
|
||||
);
|
||||
if (GicCpuRedistributorBase == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Write clear-enable register
|
||||
MmioWrite32 (GicCpuRedistributorBase + ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ICENABLER + (4 * RegOffset), 1 << RegShift);
|
||||
MmioWrite32 (
|
||||
ICENABLER_ADDRESS(GicCpuRedistributorBase, RegOffset),
|
||||
1 << RegShift
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,15 +302,23 @@ ArmGicIsInterruptEnabled (
|
||||
if ((Revision == ARM_GIC_ARCH_REVISION_2) ||
|
||||
FeaturePcdGet (PcdArmGicV3WithV2Legacy) ||
|
||||
SourceIsSpi (Source)) {
|
||||
Interrupts = ((MmioRead32 (GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset)) & (1 << RegShift)) != 0);
|
||||
Interrupts = ((MmioRead32 (
|
||||
GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset)
|
||||
)
|
||||
& (1 << RegShift)) != 0);
|
||||
} else {
|
||||
GicCpuRedistributorBase = GicGetCpuRedistributorBase (GicRedistributorBase, Revision);
|
||||
GicCpuRedistributorBase = GicGetCpuRedistributorBase (
|
||||
GicRedistributorBase,
|
||||
Revision
|
||||
);
|
||||
if (GicCpuRedistributorBase == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read set-enable register
|
||||
Interrupts = MmioRead32 (GicCpuRedistributorBase + ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ISENABLER + (4 * RegOffset));
|
||||
Interrupts = MmioRead32 (
|
||||
ISENABLER_ADDRESS(GicCpuRedistributorBase, RegOffset)
|
||||
);
|
||||
}
|
||||
|
||||
return ((Interrupts & (1 << RegShift)) != 0);
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>
|
||||
Portions copyright (c) 2010, Apple Inc. All rights reserved.<BR>
|
||||
Portions copyright (c) 2011-2016, ARM Ltd. All rights reserved.<BR>
|
||||
Portions copyright (c) 2011-2017, ARM Ltd. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
@@ -43,6 +43,7 @@ STATIC UINT32 mGicDistributorBase;
|
||||
@retval EFI_UNSUPPORTED Source interrupt is not supported
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV2EnableInterruptSource (
|
||||
@@ -70,6 +71,7 @@ GicV2EnableInterruptSource (
|
||||
@retval EFI_UNSUPPORTED Source interrupt is not supported
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV2DisableInterruptSource (
|
||||
@@ -98,6 +100,7 @@ GicV2DisableInterruptSource (
|
||||
@retval EFI_UNSUPPORTED Source interrupt is not supported
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV2GetInterruptSourceState (
|
||||
@@ -127,6 +130,7 @@ GicV2GetInterruptSourceState (
|
||||
@retval EFI_UNSUPPORTED Source interrupt is not supported
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV2EndOfInterrupt (
|
||||
@@ -147,13 +151,15 @@ GicV2EndOfInterrupt (
|
||||
EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.
|
||||
|
||||
@param InterruptType Defines the type of interrupt or exception that
|
||||
occurred on the processor.This parameter is processor architecture specific.
|
||||
occurred on the processor.This parameter is
|
||||
processor architecture specific.
|
||||
@param SystemContext A pointer to the processor context when
|
||||
the interrupt occurred on the processor.
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
EFIAPI
|
||||
GicV2IrqInterruptHandler (
|
||||
@@ -166,9 +172,10 @@ GicV2IrqInterruptHandler (
|
||||
|
||||
GicInterrupt = ArmGicV2AcknowledgeInterrupt (mGicInterruptInterfaceBase);
|
||||
|
||||
// Special Interrupts (ID1020-ID1023) have an Interrupt ID greater than the number of interrupt (ie: Spurious interrupt).
|
||||
// Special Interrupts (ID1020-ID1023) have an Interrupt ID greater than the
|
||||
// number of interrupt (ie: Spurious interrupt).
|
||||
if ((GicInterrupt & ARM_GIC_ICCIAR_ACKINTID) >= mGicNumInterrupts) {
|
||||
// The special interrupt do not need to be acknowledge
|
||||
// The special interrupts do not need to be acknowledged
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -177,14 +184,12 @@ GicV2IrqInterruptHandler (
|
||||
// Call the registered interrupt handler.
|
||||
InterruptHandler (GicInterrupt, SystemContext);
|
||||
} else {
|
||||
DEBUG ((EFI_D_ERROR, "Spurious GIC interrupt: 0x%x\n", GicInterrupt));
|
||||
DEBUG ((DEBUG_ERROR, "Spurious GIC interrupt: 0x%x\n", GicInterrupt));
|
||||
GicV2EndOfInterrupt (&gHardwareInterruptV2Protocol, GicInterrupt);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The protocol instance produced by this driver
|
||||
//
|
||||
EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptV2Protocol = {
|
||||
RegisterInterruptSource,
|
||||
GicV2EnableInterruptSource,
|
||||
@@ -196,12 +201,13 @@ EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptV2Protocol = {
|
||||
/**
|
||||
Shutdown our hardware
|
||||
|
||||
DXE Core will disable interrupts and turn off the timer and disable interrupts
|
||||
after all the event handlers have run.
|
||||
DXE Core will disable interrupts and turn off the timer and disable
|
||||
interrupts after all the event handlers have run.
|
||||
|
||||
@param[in] Event The Event that is being processed
|
||||
@param[in] Context Event Context
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
EFIAPI
|
||||
GicV2ExitBootServicesEvent (
|
||||
@@ -256,7 +262,8 @@ GicV2DxeInitialize (
|
||||
UINTN RegShift;
|
||||
UINT32 CpuTarget;
|
||||
|
||||
// Make sure the Interrupt Controller Protocol is not already installed in the system.
|
||||
// Make sure the Interrupt Controller Protocol is not already installed in
|
||||
// the system.
|
||||
ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);
|
||||
|
||||
mGicInterruptInterfaceBase = PcdGet64 (PcdGicInterruptInterfaceBase);
|
||||
@@ -276,25 +283,27 @@ GicV2DxeInitialize (
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Targets the interrupts to the Primary Cpu
|
||||
//
|
||||
|
||||
// Only Primary CPU will run this code. We can identify our GIC CPU ID by reading
|
||||
// the GIC Distributor Target register. The 8 first GICD_ITARGETSRn are banked to each
|
||||
// connected CPU. These 8 registers hold the CPU targets fields for interrupts 0-31.
|
||||
// More Info in the GIC Specification about "Interrupt Processor Targets Registers"
|
||||
//
|
||||
// Read the first Interrupt Processor Targets Register (that corresponds to the 4
|
||||
// first SGIs)
|
||||
// Only Primary CPU will run this code. We can identify our GIC CPU ID by
|
||||
// reading the GIC Distributor Target register. The 8 first GICD_ITARGETSRn
|
||||
// are banked to each connected CPU. These 8 registers hold the CPU targets
|
||||
// fields for interrupts 0-31. More Info in the GIC Specification about
|
||||
// "Interrupt Processor Targets Registers"
|
||||
|
||||
// Read the first Interrupt Processor Targets Register (that corresponds to
|
||||
// the 4 first SGIs)
|
||||
CpuTarget = MmioRead32 (mGicDistributorBase + ARM_GIC_ICDIPTR);
|
||||
|
||||
// The CPU target is a bit field mapping each CPU to a GIC CPU Interface. This value
|
||||
// is 0 when we run on a uniprocessor platform.
|
||||
// The CPU target is a bit field mapping each CPU to a GIC CPU Interface.
|
||||
// This value is 0 when we run on a uniprocessor platform.
|
||||
if (CpuTarget != 0) {
|
||||
// The 8 first Interrupt Processor Targets Registers are read-only
|
||||
for (Index = 8; Index < (mGicNumInterrupts / 4); Index++) {
|
||||
MmioWrite32 (mGicDistributorBase + ARM_GIC_ICDIPTR + (Index * 4), CpuTarget);
|
||||
MmioWrite32 (
|
||||
mGicDistributorBase + ARM_GIC_ICDIPTR + (Index * 4),
|
||||
CpuTarget
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,7 +320,10 @@ GicV2DxeInitialize (
|
||||
ArmGicEnableDistributor (mGicDistributorBase);
|
||||
|
||||
Status = InstallAndRegisterInterruptService (
|
||||
&gHardwareInterruptV2Protocol, GicV2IrqInterruptHandler, GicV2ExitBootServicesEvent);
|
||||
&gHardwareInterruptV2Protocol,
|
||||
GicV2IrqInterruptHandler,
|
||||
GicV2ExitBootServicesEvent
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011-2016, ARM Limited. All rights reserved.
|
||||
* Copyright (c) 2011-2017, ARM Limited. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are licensed and made available under the terms and conditions of the BSD License
|
||||
@@ -33,6 +33,7 @@ STATIC UINTN mGicRedistributorsBase;
|
||||
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV3EnableInterruptSource (
|
||||
@@ -60,6 +61,7 @@ GicV3EnableInterruptSource (
|
||||
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV3DisableInterruptSource (
|
||||
@@ -88,6 +90,7 @@ GicV3DisableInterruptSource (
|
||||
@retval EFI_DEVICE_ERROR InterruptState is not valid
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV3GetInterruptSourceState (
|
||||
@@ -101,7 +104,11 @@ GicV3GetInterruptSourceState (
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
*InterruptState = ArmGicIsInterruptEnabled (mGicDistributorBase, mGicRedistributorsBase, Source);
|
||||
*InterruptState = ArmGicIsInterruptEnabled (
|
||||
mGicDistributorBase,
|
||||
mGicRedistributorsBase,
|
||||
Source
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
@@ -117,6 +124,7 @@ GicV3GetInterruptSourceState (
|
||||
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV3EndOfInterrupt (
|
||||
@@ -137,13 +145,15 @@ GicV3EndOfInterrupt (
|
||||
EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.
|
||||
|
||||
@param InterruptType Defines the type of interrupt or exception that
|
||||
occurred on the processor.This parameter is processor architecture specific.
|
||||
occurred on the processor. This parameter is
|
||||
processor architecture specific.
|
||||
@param SystemContext A pointer to the processor context when
|
||||
the interrupt occurred on the processor.
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
EFIAPI
|
||||
GicV3IrqInterruptHandler (
|
||||
@@ -168,14 +178,12 @@ GicV3IrqInterruptHandler (
|
||||
// Call the registered interrupt handler.
|
||||
InterruptHandler (GicInterrupt, SystemContext);
|
||||
} else {
|
||||
DEBUG ((EFI_D_ERROR, "Spurious GIC interrupt: 0x%x\n", GicInterrupt));
|
||||
DEBUG ((DEBUG_ERROR, "Spurious GIC interrupt: 0x%x\n", GicInterrupt));
|
||||
GicV3EndOfInterrupt (&gHardwareInterruptV3Protocol, GicInterrupt);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The protocol instance produced by this driver
|
||||
//
|
||||
EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptV3Protocol = {
|
||||
RegisterInterruptSource,
|
||||
GicV3EnableInterruptSource,
|
||||
@@ -242,17 +250,16 @@ GicV3DxeInitialize (
|
||||
UINT64 CpuTarget;
|
||||
UINT64 MpId;
|
||||
|
||||
// Make sure the Interrupt Controller Protocol is not already installed in the system.
|
||||
// Make sure the Interrupt Controller Protocol is not already installed in
|
||||
// the system.
|
||||
ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);
|
||||
|
||||
mGicDistributorBase = PcdGet64 (PcdGicDistributorBase);
|
||||
mGicRedistributorsBase = PcdGet64 (PcdGicRedistributorsBase);
|
||||
mGicNumInterrupts = ArmGicGetMaxNumInterrupts (mGicDistributorBase);
|
||||
|
||||
//
|
||||
// We will be driving this GIC in native v3 mode, i.e., with Affinity
|
||||
// Routing enabled. So ensure that the ARE bit is set.
|
||||
//
|
||||
if (!FeaturePcdGet (PcdArmGicV3WithV2Legacy)) {
|
||||
MmioOr32 (mGicDistributorBase + ARM_GIC_ICDDCR, ARM_GIC_ICDDCR_ARE);
|
||||
}
|
||||
@@ -270,51 +277,65 @@ GicV3DxeInitialize (
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Targets the interrupts to the Primary Cpu
|
||||
//
|
||||
|
||||
if (FeaturePcdGet (PcdArmGicV3WithV2Legacy)) {
|
||||
// Only Primary CPU will run this code. We can identify our GIC CPU ID by reading
|
||||
// the GIC Distributor Target register. The 8 first GICD_ITARGETSRn are banked to each
|
||||
// connected CPU. These 8 registers hold the CPU targets fields for interrupts 0-31.
|
||||
// More Info in the GIC Specification about "Interrupt Processor Targets Registers"
|
||||
//
|
||||
// Read the first Interrupt Processor Targets Register (that corresponds to the 4
|
||||
// first SGIs)
|
||||
// Only Primary CPU will run this code. We can identify our GIC CPU ID by
|
||||
// reading the GIC Distributor Target register. The 8 first
|
||||
// GICD_ITARGETSRn are banked to each connected CPU. These 8 registers
|
||||
// hold the CPU targets fields for interrupts 0-31. More Info in the GIC
|
||||
// Specification about "Interrupt Processor Targets Registers"
|
||||
|
||||
// Read the first Interrupt Processor Targets Register (that corresponds
|
||||
// to the 4 first SGIs)
|
||||
CpuTarget = MmioRead32 (mGicDistributorBase + ARM_GIC_ICDIPTR);
|
||||
|
||||
// The CPU target is a bit field mapping each CPU to a GIC CPU Interface. This value
|
||||
// is 0 when we run on a uniprocessor platform.
|
||||
// The CPU target is a bit field mapping each CPU to a GIC CPU Interface.
|
||||
// This value is 0 when we run on a uniprocessor platform.
|
||||
if (CpuTarget != 0) {
|
||||
// The 8 first Interrupt Processor Targets Registers are read-only
|
||||
for (Index = 8; Index < (mGicNumInterrupts / 4); Index++) {
|
||||
MmioWrite32 (mGicDistributorBase + ARM_GIC_ICDIPTR + (Index * 4), CpuTarget);
|
||||
MmioWrite32 (
|
||||
mGicDistributorBase + ARM_GIC_ICDIPTR + (Index * 4),
|
||||
CpuTarget
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MpId = ArmReadMpidr ();
|
||||
CpuTarget = MpId & (ARM_CORE_AFF0 | ARM_CORE_AFF1 | ARM_CORE_AFF2 | ARM_CORE_AFF3);
|
||||
CpuTarget = MpId &
|
||||
(ARM_CORE_AFF0 | ARM_CORE_AFF1 | ARM_CORE_AFF2 | ARM_CORE_AFF3);
|
||||
|
||||
if ((MmioRead32 (
|
||||
mGicDistributorBase + ARM_GIC_ICDDCR
|
||||
) & ARM_GIC_ICDDCR_DS) != 0) {
|
||||
|
||||
if ((MmioRead32 (mGicDistributorBase + ARM_GIC_ICDDCR) & ARM_GIC_ICDDCR_DS) != 0) {
|
||||
//
|
||||
// If the Disable Security (DS) control bit is set, we are dealing with a
|
||||
// GIC that has only one security state. In this case, let's assume we are
|
||||
// executing in non-secure state (which is appropriate for DXE modules)
|
||||
// and that no other firmware has performed any configuration on the GIC.
|
||||
// This means we need to reconfigure all interrupts to non-secure Group 1
|
||||
// first.
|
||||
//
|
||||
MmioWrite32 (mGicRedistributorsBase + ARM_GICR_CTLR_FRAME_SIZE + ARM_GIC_ICDISR, 0xffffffff);
|
||||
|
||||
MmioWrite32 (
|
||||
mGicRedistributorsBase + ARM_GICR_CTLR_FRAME_SIZE + ARM_GIC_ICDISR,
|
||||
0xffffffff
|
||||
);
|
||||
|
||||
for (Index = 32; Index < mGicNumInterrupts; Index += 32) {
|
||||
MmioWrite32 (mGicDistributorBase + ARM_GIC_ICDISR + Index / 8, 0xffffffff);
|
||||
MmioWrite32 (
|
||||
mGicDistributorBase + ARM_GIC_ICDISR + Index / 8,
|
||||
0xffffffff
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Route the SPIs to the primary CPU. SPIs start at the INTID 32
|
||||
for (Index = 0; Index < (mGicNumInterrupts - 32); Index++) {
|
||||
MmioWrite32 (mGicDistributorBase + ARM_GICD_IROUTER + (Index * 8), CpuTarget | ARM_GICD_IROUTER_IRM);
|
||||
MmioWrite32 (
|
||||
mGicDistributorBase + ARM_GICD_IROUTER + (Index * 8),
|
||||
CpuTarget | ARM_GICD_IROUTER_IRM
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,7 +352,10 @@ GicV3DxeInitialize (
|
||||
ArmGicEnableDistributor (mGicDistributorBase);
|
||||
|
||||
Status = InstallAndRegisterInterruptService (
|
||||
&gHardwareInterruptV3Protocol, GicV3IrqInterruptHandler, GicV3ExitBootServicesEvent);
|
||||
&gHardwareInterruptV3Protocol,
|
||||
GicV3IrqInterruptHandler,
|
||||
GicV3ExitBootServicesEvent
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
Reference in New Issue
Block a user