diff --git a/ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.c b/ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.c index 732860cadf..7ef829ff2d 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 @@ -14,11 +14,16 @@ **/ #include +#include #include #include -#include +#include #include +#include +#include + +#include STATIC ARM_GIC_ARCH_REVISION mGicArchRevision; @@ -28,11 +33,61 @@ ArmVirtGicArchLibConstructor ( VOID ) { - UINT32 IccSre; + UINT32 IccSre; + FDT_CLIENT_PROTOCOL *FdtClient; + CONST UINT64 *Reg; + UINT32 RegElemSize, RegSize; + UINTN GicRevision; + EFI_STATUS Status; + UINT64 DistBase, CpuBase, RedistBase; - switch (PcdGet32 (PcdArmGicRevision)) { + Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL, + (VOID **)&FdtClient); + ASSERT_EFI_ERROR (Status); + + GicRevision = 2; + Status = FdtClient->FindCompatibleNodeReg (FdtClient, "arm,cortex-a15-gic", + (CONST VOID **)&Reg, &RegElemSize, &RegSize); + if (Status == EFI_NOT_FOUND) { + GicRevision = 3; + Status = FdtClient->FindCompatibleNodeReg (FdtClient, "arm,gic-v3", + (CONST VOID **)&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 = SwapBytes64 (Reg[0]); + ASSERT (DistBase < MAX_UINT32); + + // RegProp[2..3] == { GICR base, GICR size } + RedistBase = SwapBytes64 (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 @@ -55,6 +110,18 @@ ArmVirtGicArchLibConstructor ( break; case 2: + ASSERT (RegSize == 32); + + DistBase = SwapBytes64 (Reg[0]); + CpuBase = SwapBytes64 (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 c85b2d44d8..a25c191bc9 100644 --- a/ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.inf +++ b/ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.inf @@ -27,14 +27,24 @@ ArmVirtGicArchLib.c [LibraryClasses] - PcdLib - DebugLib ArmGicLib + BaseLib + DebugLib + PcdLib + UefiBootServicesTableLib [Packages] - MdePkg/MdePkg.dec ArmPkg/ArmPkg.dec ArmVirtPkg/ArmVirtPkg.dec + MdePkg/MdePkg.dec + +[Protocols] + gFdtClientProtocolGuid ## CONSUMES [Pcd] - gArmVirtTokenSpaceGuid.PcdArmGicRevision + gArmTokenSpaceGuid.PcdGicDistributorBase + gArmTokenSpaceGuid.PcdGicRedistributorsBase + gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase + +[Depex] + gFdtClientProtocolGuid