/** @file\r
*\r
-* Copyright (c) 2011-2017, ARM Limited. All rights reserved.\r
+* Copyright (c) 2011-2018, ARM Limited. All rights reserved.\r
*\r
* This program and the accompanying materials\r
* are licensed and made available under the terms and conditions of the BSD License\r
#include <Library/IoLib.h>\r
#include <Library/PcdLib.h>\r
\r
+// In GICv3, there are 2 x 64KB frames:\r
+// Redistributor control frame + SGI Control & Generation frame\r
+#define GIC_V3_REDISTRIBUTOR_GRANULARITY (ARM_GICR_CTLR_FRAME_SIZE \\r
+ + ARM_GICR_SGI_PPI_FRAME_SIZE)\r
+\r
+// In GICv4, there are 2 additional 64KB frames:\r
+// VLPI frame + Reserved page frame\r
+#define GIC_V4_REDISTRIBUTOR_GRANULARITY (GIC_V3_REDISTRIBUTOR_GRANULARITY \\r
+ + ARM_GICR_SGI_VLPI_FRAME_SIZE \\r
+ + ARM_GICR_SGI_RESERVED_FRAME_SIZE)\r
\r
#define ISENABLER_ADDRESS(base,offset) ((base) + \\r
ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ISENABLER + (4 * offset))\r
IN ARM_GIC_ARCH_REVISION Revision\r
)\r
{\r
- UINTN Index;\r
UINTN MpId;\r
UINTN CpuAffinity;\r
UINTN Affinity;\r
- UINTN GicRedistributorGranularity;\r
UINTN GicCpuRedistributorBase;\r
+ UINT64 TypeRegister;\r
\r
MpId = ArmReadMpidr ();\r
// Define CPU affinity as:\r
CpuAffinity = (MpId & (ARM_CORE_AFF0 | ARM_CORE_AFF1 | ARM_CORE_AFF2)) |\r
((MpId & ARM_CORE_AFF3) >> 8);\r
\r
- if (Revision == ARM_GIC_ARCH_REVISION_3) {\r
- // 2 x 64KB frame:\r
- // Redistributor control frame + SGI Control & Generation frame\r
- GicRedistributorGranularity = ARM_GICR_CTLR_FRAME_SIZE\r
- + ARM_GICR_SGI_PPI_FRAME_SIZE;\r
- } else {\r
+ if (Revision < ARM_GIC_ARCH_REVISION_3) {\r
ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
return 0;\r
}\r
\r
GicCpuRedistributorBase = GicRedistributorBase;\r
\r
- for (Index = 0; Index < PcdGet32 (PcdCoreCount); Index++) {\r
- Affinity = MmioRead64 (GicCpuRedistributorBase + ARM_GICR_TYPER) >> 32;\r
+ do {\r
+ TypeRegister = MmioRead64 (GicCpuRedistributorBase + ARM_GICR_TYPER);\r
+ Affinity = ARM_GICR_TYPER_GET_AFFINITY (TypeRegister);\r
if (Affinity == CpuAffinity) {\r
return GicCpuRedistributorBase;\r
}\r
\r
- // Move to the next GIC Redistributor frame\r
- GicCpuRedistributorBase += GicRedistributorGranularity;\r
- }\r
+ // Move to the next GIC Redistributor frame.\r
+ // The GIC specification does not forbid a mixture of redistributors\r
+ // with or without support for virtual LPIs, so we test Virtual LPIs\r
+ // Support (VLPIS) bit for each frame to decide the granularity.\r
+ // Note: The assumption here is that the redistributors are adjacent\r
+ // for all CPUs. However this may not be the case for NUMA systems.\r
+ GicCpuRedistributorBase += (((ARM_GICR_TYPER_VLPIS & TypeRegister) != 0)\r
+ ? GIC_V4_REDISTRIBUTOR_GRANULARITY\r
+ : GIC_V3_REDISTRIBUTOR_GRANULARITY);\r
+ } while ((TypeRegister & ARM_GICR_TYPER_LAST) == 0);\r
\r
// The Redistributor has not been found for the current CPU\r
ASSERT_EFI_ERROR (EFI_NOT_FOUND);\r