diff --git a/ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.c b/ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.c
index 732860cadfe6..686622228831 100644
--- a/ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.c
+++ b/ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.c
@@ -1,7 +1,7 @@
/** @file
ArmGicArchLib library class implementation for DT based virt platforms
- Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ Copyright (c) 2015 - 2016, Linaro Ltd. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -19,21 +19,83 @@
#include
#include
#include
+#include
+#include
+
+#include
STATIC ARM_GIC_ARCH_REVISION mGicArchRevision;
-RETURN_STATUS
+EFI_STATUS
EFIAPI
ArmVirtGicArchLibConstructor (
- VOID
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
)
{
- UINT32 IccSre;
+ UINT32 IccSre;
+ FDT_CLIENT_PROTOCOL *FdtClient;
+ CONST VOID *Reg;
+ UINTN RegElemSize, RegSize;
+ UINTN GicRevision;
+ EFI_STATUS Status;
+ UINT64 DistBase, CpuBase, RedistBase;
- switch (PcdGet32 (PcdArmGicRevision)) {
+ Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL, (VOID **)&FdtClient);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ GicRevision = 2;
+ Status = FdtClient->FindCompatibleNodeReg (FdtClient,
+ "arm,cortex-a15-gic",
+ &Reg,
+ &RegElemSize,
+ &RegSize);
+ if (Status == EFI_NOT_FOUND) {
+ GicRevision = 3;
+ Status = FdtClient->FindCompatibleNodeReg (FdtClient,
+ "arm,gic-v3",
+ &Reg,
+ &RegElemSize,
+ &RegSize);
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ switch (GicRevision) {
case 3:
//
+ // The GIC v3 DT binding describes a series of at least 3 physical (base
+ // addresses, size) pairs: the distributor interface (GICD), at least one
+ // redistributor region (GICR) containing dedicated redistributor
+ // interfaces for all individual CPUs, and the CPU interface (GICC).
+ // Under virtualization, we assume that the first redistributor region
+ // listed covers the boot CPU. Also, our GICv3 driver only supports the
+ // system register CPU interface, so we can safely ignore the MMIO version
+ // which is listed after the sequence of redistributor interfaces.
+ // This means we are only interested in the first two memory regions
+ // supplied, and ignore everything else.
+ //
+ ASSERT (RegSize >= 32);
+
+ // RegProp[0..1] == { GICD base, GICD size }
+ DistBase = fdt64_to_cpu (((UINT64 *)Reg)[0]);
+ ASSERT (DistBase < MAX_UINT32);
+
+ // RegProp[2..3] == { GICR base, GICR size }
+ RedistBase = fdt64_to_cpu (((UINT64 *)Reg)[2]);
+ ASSERT (RedistBase < MAX_UINT32);
+
+ PcdSet32 (PcdGicDistributorBase, (UINT32)DistBase);
+ PcdSet32 (PcdGicRedistributorsBase, (UINT32)RedistBase);
+
+ DEBUG ((EFI_D_INFO, "Found GIC v3 (re)distributor @ 0x%Lx (0x%Lx)\n",
+ DistBase, RedistBase));
+
+ //
// The default implementation of ArmGicArchLib is responsible for enabling
// the system register interface on the GICv3 if one is found. So let's do
// the same here.
@@ -55,6 +117,18 @@ ArmVirtGicArchLibConstructor (
break;
case 2:
+ ASSERT (RegSize == 32);
+
+ DistBase = fdt64_to_cpu (((UINT64 *)Reg)[0]);
+ CpuBase = fdt64_to_cpu (((UINT64 *)Reg)[2]);
+ ASSERT (DistBase < MAX_UINT32);
+ ASSERT (CpuBase < MAX_UINT32);
+
+ PcdSet32 (PcdGicDistributorBase, (UINT32)DistBase);
+ PcdSet32 (PcdGicInterruptInterfaceBase, (UINT32)CpuBase);
+
+ DEBUG ((EFI_D_INFO, "Found GIC @ 0x%Lx/0x%Lx\n", DistBase, CpuBase));
+
mGicArchRevision = ARM_GIC_ARCH_REVISION_2;
break;
diff --git a/ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.inf b/ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.inf
index c85b2d44d856..57086242de1f 100644
--- a/ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.inf
+++ b/ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.inf
@@ -18,7 +18,7 @@ [Defines]
INF_VERSION = 0x00010005
BASE_NAME = ArmVirtGicArchLib
FILE_GUID = 87b0dc84-4661-4deb-a789-97977ff636ed
- MODULE_TYPE = BASE
+ MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = ArmGicArchLib|DXE_DRIVER UEFI_DRIVER UEFI_APPLICATION
CONSTRUCTOR = ArmVirtGicArchLibConstructor
@@ -30,11 +30,22 @@ [LibraryClasses]
PcdLib
DebugLib
ArmGicLib
+ UefiBootServicesTableLib
+ FdtLib
[Packages]
MdePkg/MdePkg.dec
ArmPkg/ArmPkg.dec
ArmVirtPkg/ArmVirtPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[Protocols]
+ gFdtClientProtocolGuid
[Pcd]
- gArmVirtTokenSpaceGuid.PcdArmGicRevision
+ gArmTokenSpaceGuid.PcdGicDistributorBase
+ gArmTokenSpaceGuid.PcdGicRedistributorsBase
+ gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
+
+[Depex]
+ gFdtClientProtocolGuid