diff --git a/ArmPkg/Drivers/ArmGic/ArmGicLib.c b/ArmPkg/Drivers/ArmGic/ArmGicLib.c index 666008638c..41e970bc49 100644 --- a/ArmPkg/Drivers/ArmGic/ArmGicLib.c +++ b/ArmPkg/Drivers/ArmGic/ArmGicLib.c @@ -14,6 +14,7 @@ #include #include +#include #include #include "GicV2/ArmGicV2Lib.h" @@ -49,13 +50,39 @@ ArmGicSendSgiTo ( MmioWrite32 (GicDistributorBase + ARM_GIC_ICDSGIR, ((TargetListFilter & 0x3) << 24) | ((CPUTargetList & 0xFF) << 16) | SgiId); } +/* + * Acknowledge and return the value of the Interrupt Acknowledge Register + * + * InterruptId is returned separately from the register value because in + * the GICv2 the register value contains the CpuId and InterruptId while + * 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 + * + * @retval value returned by the Interrupt Acknowledge Register + * + */ UINTN EFIAPI ArmGicAcknowledgeInterrupt ( - IN UINTN GicInterruptInterfaceBase + IN UINTN GicInterruptInterfaceBase, + OUT UINTN *InterruptId ) { - return ArmGicV2AcknowledgeInterrupt (GicInterruptInterfaceBase); + UINTN Value; + + Value = ArmGicV2AcknowledgeInterrupt (GicInterruptInterfaceBase); + + // InterruptId is required for the caller to know if a valid or spurious + // interrupt has been read + ASSERT (InterruptId != NULL); + + if (InterruptId != NULL) { + *InterruptId = Value & ARM_GIC_ICCIAR_ACKINTID; + } + + return Value; } VOID diff --git a/ArmPkg/Include/Library/ArmGicLib.h b/ArmPkg/Include/Library/ArmGicLib.h index f2d4c7b27c..e3ef228dba 100644 --- a/ArmPkg/Include/Library/ArmGicLib.h +++ b/ArmPkg/Include/Library/ArmGicLib.h @@ -140,10 +140,24 @@ ArmGicSendSgiTo ( IN INTN SgiId ); +/* + * Acknowledge and return the value of the Interrupt Acknowledge Register + * + * InterruptId is returned separately from the register value because in + * the GICv2 the register value contains the CpuId and InterruptId while + * 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 + * + * @retval value returned by the Interrupt Acknowledge Register + * + */ UINTN EFIAPI ArmGicAcknowledgeInterrupt ( - IN UINTN GicInterruptInterfaceBase + IN UINTN GicInterruptInterfaceBase, + OUT UINTN *InterruptId ); VOID diff --git a/ArmPlatformPkg/Library/DebugSecExtraActionLib/DebugSecExtraActionLib.c b/ArmPlatformPkg/Library/DebugSecExtraActionLib/DebugSecExtraActionLib.c index f42f518722..1e1b1ea64d 100755 --- a/ArmPlatformPkg/Library/DebugSecExtraActionLib/DebugSecExtraActionLib.c +++ b/ArmPlatformPkg/Library/DebugSecExtraActionLib/DebugSecExtraActionLib.c @@ -1,6 +1,6 @@ /** @file * -* Copyright (c) 2011-2012, ARM Limited. All rights reserved. +* Copyright (c) 2011-2014, 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 @@ -30,24 +30,25 @@ NonSecureWaitForFirmware ( VOID ) { - VOID (*secondary_start)(VOID); - UINTN Interrupt; + VOID (*SecondaryStart)(VOID); + UINTN AcknowledgeInterrupt; + UINTN InterruptId; // The secondary cores will execute the firmware once wake from WFI. - secondary_start = (VOID (*)())PcdGet32(PcdFvBaseAddress); + SecondaryStart = (VOID (*)())PcdGet32 (PcdFvBaseAddress); - ArmCallWFI(); + ArmCallWFI (); // Acknowledge the interrupt and send End of Interrupt signal. - Interrupt = ArmGicAcknowledgeInterrupt (PcdGet32 (PcdGicInterruptInterfaceBase)); + AcknowledgeInterrupt = ArmGicAcknowledgeInterrupt (PcdGet32 (PcdGicInterruptInterfaceBase), &InterruptId); // Check if it is a valid interrupt ID - if ((Interrupt & ARM_GIC_ICCIAR_ACKINTID) < ArmGicGetMaxNumInterrupts (PcdGet32 (PcdGicDistributorBase))) { + if (InterruptId < ArmGicGetMaxNumInterrupts (PcdGet32 (PcdGicDistributorBase))) { // Got a valid SGI number hence signal End of Interrupt - ArmGicEndOfInterrupt (PcdGet32 (PcdGicInterruptInterfaceBase), Interrupt); + ArmGicEndOfInterrupt (PcdGet32 (PcdGicInterruptInterfaceBase), AcknowledgeInterrupt); } // Jump to secondary core entry point. - secondary_start (); + SecondaryStart (); // PEI Core should always load and never return ASSERT (FALSE); diff --git a/ArmPlatformPkg/PrePeiCore/MainMPCore.c b/ArmPlatformPkg/PrePeiCore/MainMPCore.c index 69863de549..d40594f835 100644 --- a/ArmPlatformPkg/PrePeiCore/MainMPCore.c +++ b/ArmPlatformPkg/PrePeiCore/MainMPCore.c @@ -1,6 +1,6 @@ /** @file * -* Copyright (c) 2011-2012, ARM Limited. All rights reserved. +* Copyright (c) 2011-2014, 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 @@ -45,7 +45,8 @@ SecondaryMain ( UINT32 CoreId; VOID (*SecondaryStart)(VOID); UINTN SecondaryEntryAddr; - UINTN Interrupt; + UINTN AcknowledgeInterrupt; + UINTN InterruptId; ClusterId = GET_CLUSTER_ID(MpId); CoreId = GET_CORE_ID(MpId); @@ -88,11 +89,11 @@ SecondaryMain ( SecondaryEntryAddr = MmioRead32 (ArmCoreInfoTable[Index].MailboxGetAddress); // Acknowledge the interrupt and send End of Interrupt signal. - Interrupt = ArmGicAcknowledgeInterrupt (PcdGet32 (PcdGicInterruptInterfaceBase)); + AcknowledgeInterrupt = ArmGicAcknowledgeInterrupt (PcdGet32 (PcdGicInterruptInterfaceBase), &InterruptId); // Check if it is a valid interrupt ID - if ((Interrupt & ARM_GIC_ICCIAR_ACKINTID) < ArmGicGetMaxNumInterrupts (PcdGet32 (PcdGicDistributorBase))) { + if (InterruptId < ArmGicGetMaxNumInterrupts (PcdGet32 (PcdGicDistributorBase))) { // Got a valid SGI number hence signal End of Interrupt - ArmGicEndOfInterrupt (PcdGet32 (PcdGicInterruptInterfaceBase), Interrupt); + ArmGicEndOfInterrupt (PcdGet32 (PcdGicInterruptInterfaceBase), AcknowledgeInterrupt); } } while (SecondaryEntryAddr == 0); diff --git a/ArmPlatformPkg/PrePi/MainMPCore.c b/ArmPlatformPkg/PrePi/MainMPCore.c index 3db3ce6857..bf813730d3 100644 --- a/ArmPlatformPkg/PrePi/MainMPCore.c +++ b/ArmPlatformPkg/PrePi/MainMPCore.c @@ -1,6 +1,6 @@ /** @file * -* Copyright (c) 2011-2012, ARM Limited. All rights reserved. +* Copyright (c) 2011-2014, 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 @@ -55,7 +55,8 @@ SecondaryMain ( UINT32 CoreId; VOID (*SecondaryStart)(VOID); UINTN SecondaryEntryAddr; - UINTN Interrupt; + UINTN AcknowledgeInterrupt; + UINTN InterruptId; ClusterId = GET_CLUSTER_ID(MpId); CoreId = GET_CORE_ID(MpId); @@ -88,11 +89,11 @@ SecondaryMain ( SecondaryEntryAddr = MmioRead32 (ArmCoreInfoTable[Index].MailboxGetAddress); // Acknowledge the interrupt and send End of Interrupt signal. - Interrupt = ArmGicAcknowledgeInterrupt (PcdGet32 (PcdGicInterruptInterfaceBase)); + AcknowledgeInterrupt = ArmGicAcknowledgeInterrupt (PcdGet32 (PcdGicInterruptInterfaceBase), &InterruptId); // Check if it is a valid interrupt ID - if ((Interrupt & ARM_GIC_ICCIAR_ACKINTID) < ArmGicGetMaxNumInterrupts (PcdGet32 (PcdGicDistributorBase))) { + if (InterruptId < ArmGicGetMaxNumInterrupts (PcdGet32 (PcdGicDistributorBase))) { // Got a valid SGI number hence signal End of Interrupt - ArmGicEndOfInterrupt (PcdGet32 (PcdGicInterruptInterfaceBase), Interrupt); + ArmGicEndOfInterrupt (PcdGet32 (PcdGicInterruptInterfaceBase), AcknowledgeInterrupt); } } while (SecondaryEntryAddr == 0);