On 04/06/16 18:15, Ard Biesheuvel wrote:
> Instead of relying on VirtFdtDxe to populate the GIC related PCDs, move
> this handling to our implementation of ArmGicArchLib, and retrieve the
> required DT info using the new FDT client protocol.
>
> This removes one of the reasons we need to load VirtFdtDxe first using
> an 'A PRIORI' declaration in the platform FDF.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <[email protected]>
> ---
> ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.c | 84
> ++++++++++++++++++--
> ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.inf | 15 +++-
> 2 files changed, 92 insertions(+), 7 deletions(-)
Urgh.
I guess the conversion (together with the next patch) should be
"straightforward". However, before I try to validate the code movement,
I have a small and a big question.
(21) small one: what do you need <libfdt.h>, FdtLib, and (consequently)
EmbeddedPkg/EmbeddedPkg.dec for?
... Nevermind, coming back from the source code below, I understand.
I'll make a suggestion down there. Consider (21) a no-op.
(22) The big question is this: how can I determine where this library
instance is used?
Namely, before the conversion, PcdGic*Base would be set only once (in
VirtFdtDxe). That means two things: (a) it is set *for sure*, for any
DXE driver that might want to look at the PCDs, plus (b) the PCDs are
not set more than once.
I can't see how this conversion guarantees either.
Let's start with question (b). (Breaking (b) is not a catastrophe, but
it's ugly.)
I tried to round up users of the lib class ArmGicArchLib. I found two
client INF files:
- ArmPkg/Drivers/ArmGic/ArmGicLib.inf
- ArmPkg/Drivers/ArmGic/ArmGicSecLib.inf
These are themselves library instances (with MODULE_TYPE=SEC, WTF?) So,
I guess I have to find the clients of the lib class ArmGicLib. They are:
- ArmPkg/Application/LinuxLoader/LinuxLoader.inf
We use this in our ARM (32-bit) builds. It means whenever this app is
run, it will re-set the PCDs. :/ ... Although, it looks like the
application only depends on ArmGicLib in the AARCH64 case, precisely
which architecture we don't build the application for. Okay,
ultimately, but confusing...
- ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
I guess this is our main target. This one is therefore certainly
correct to set the PCDs.
- ArmPlatformPkg/ArmVExpressPkg/ArmVExpressDxe/ArmFvpDxe.inf
We never include this driver. Okay.
- ArmPkg/Library/ArmGicArchLib/ArmGicArchLib.inf
- ArmPkg/Library/ArmGicArchSecLib/ArmGicArchSecLib.inf
- ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.inf
What the heck, all of these library instances are for class
ArmGicArchLib, which is what I started out with! We actually use the
last one (this patch modifies exactly it); it creates a circular
library dependency between ArmGicLib and ArmGicArchLib. Sweet $DEITY.
Anyway, since I started out tracking down ArmGicArchLib, and we don't
use the first two of the above, they don't add new things to follow.
- ArmPlatformPkg/Library/DebugSecExtraActionLib/DebugSecExtraActionLib.inf
We have a library class resolution to this, in "ArmVirt.dsc.inc", for
ArmPlatformSecExtraActionLib. That's a dead-end, thankfully; grepping
for the lib class, only
"ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressSecLibCTA9x4/ArmVExpressSecLib.inf"
depends on it, which I can't imagine we use. The resolution should be
dropped from "ArmVirtPkg/ArmVirt.dsc.inc", probably.
- ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf
- ArmPlatformPkg/PrePi/PeiMPCore.inf
These are SEC modules, and we don't use them. Okay.
So, ultimately, the only user of this library instance is
"ArmPkg/Drivers/ArmGic/ArmGicDxe.inf". ... Indeed, checking the build
report file for ArmVirtQemu (AARCH64), I find ArmVirtGicArchLib (and
ArmGicLib too) only under "ArmPkg/Drivers/ArmGic/ArmGicDxe.inf".
Question (22)(b) is therefore cleared; the PCDs in question will only be
set once, when "ArmPkg/Drivers/ArmGic/ArmGicDxe.inf" is dispatched.
Let's see (22)(a): can anything consume these PCDs before
"ArmPkg/Drivers/ArmGic/ArmGicDxe.inf" sets them?
- ArmPkg/Application/LinuxLoader/LinuxLoader.inf
Same as above: uses the PCDs only on AARCH64, when we don't build it.
- ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
The library sets the PCDs for it in time.
-
ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressSecLibRTSM/ArmVExpressSecLib.inf
We don't use this (it wants the PCDs as Fixed, anyway).
- ArmPlatformPkg/Library/DebugSecExtraActionLib/DebugSecExtraActionLib.inf
- ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf
- ArmPlatformPkg/PrePi/PeiMPCore.inf
Ditto for these three.
Alright! It was exhausting to verify it (you could have written it up
too... :)), but the conversion seems safe. Ultimately, as (22), I'll
make this request:
(22) please document in the commit message, that in all our builds, only
"ArmPkg/Drivers/ArmGic/ArmGicDxe.inf" links against this library, and
only "ArmPkg/Drivers/ArmGic/ArmGicDxe.inf" consumes the PCDs.
... This is actually a "standard requirement" for the rest of the
plugin-like patches, more or less. Do you think (knowing the rest of the
series) that it might make sense for you to post a v2 after my comments
thus far? Mainly, this "usage analysis" is exhausting, and for the rest
of the series, I'd prefer to validate yours, not construct mine. :)
Anyway, let's see the rest of this patch (INF file moved to the top --
can you perhaps adopt a diff-order file, for formatting the patches?):
> 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
(23) I don't think it's necessary. You use neither ImageHandle nor
SystemTable below. The client type restriction (on the LIBRARY_CLASS
line below) suffices.
> 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
>
Looks okay (modulo (21) above).
> 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.<BR>
> + Copyright (c) 2015 - 2016, Linaro 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
> @@ -19,21 +19,83 @@
> #include <Library/ArmGicArchLib.h>
> #include <Library/PcdLib.h>
> #include <Library/DebugLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <libfdt.h>
> +
> +#include <Protocol/FdtClient.h>
>
> 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);
(24) This line is too long.
Can you double-check the series that added lines don't exceed 79
characters? (I think "BaseTools/Scripts/PatchCheck.py" might help you
verify this -- see a7e173b07a1e.) I guess I shouldn't obsess about code
that is moved, but code you write genuinely for this work shouldn't be
too wide.
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
(25) Given the DepEx, you might want to replace this with an
ASSERT_EFI_ERROR(). Up to you.
> +
> + GicRevision = 2;
> + Status = FdtClient->FindCompatibleNodeReg (FdtClient,
> + "arm,cortex-a15-gic",
> + &Reg,
> + &RegElemSize,
> + &RegSize);
(26) The indentation of the arguments is not correct; they should be
aligned with "FindCompatibleNodeReg", plus one or two spaces.
Can you re-check the series for such indentation problems?
> + 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]);
Sigh. So this is the answer to (21). Here's another proposal then:
(27) can we perhaps dispense with the byte order conversion helpers from
libfdt? I mean, it is annoying to include the FDT library *just* for
this, when we have our shiny new protocol ready, for the rest of the
device tree massaging. So the idea is:
- If (knowing the rest of the series) you deem that libfdt is frequently
needed in addition to the new protocol *because* we frequently
manipulate the DTB beyond the capabilities of the new protocol (and in
a way that is hard to extract into the protocol), then sure, libfdt
and the protocol should co-exist in client code, and I have nothing
against fdt64_to_cpu()
- OTOH, if we mostly (only?) include LibFdt on top of the new protocol,
in the rest of the series too, because we can't live without
fdt64_to_cpu() and friends, then I suggest to remove the LibFdt
dependency, and exploit that FDT internals are always big-endian,
while UEFI is always little-endian. Therefore, use the SwapBytes64()
function (and friends) directly, from BaseLib.
What do you think?
> + 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;
>
This looks good to me (with the above remarks in mind).
Thanks!
Laszlo
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel