summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArd Biesheuvel <ardb@kernel.org>2026-09-01 18:20:54 +0200
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2026-09-02 11:29:05 +0000
commitaefdbf91f46e63ee862a869737c1b9549d8024be (patch)
tree83c33767d4f9350bac0f6a6b3fbb2b5758896074
parent046b1471e1688e6c756a17fbe9c4057701a0c383 (diff)
downloadedk2-aefdbf91f46e63ee862a869737c1b9549d8024be.tar.gz
edk2-aefdbf91f46e63ee862a869737c1b9549d8024be.zip
ArmVirtPkg: Create platform DXE driver to detect the GIC version
Take the code from ArmVirtGicArchLib, which is injected into the unified GIC driver by NULL library class resolution to set the associated PCDs as the driver loads, and implement a DXE driver that performs the same DT based detection. However, in this case, the driver installs a NULL protocol under a GUID that indicates the presence of either a V2 or a V3 (or later) GIC, in a way that allows the DXE driver dispatcher to take this into account. This will allow the unified GIC driver to be replaced with the split V2 and V3 versions, which is all we care to support going forward. Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
-rw-r--r--ArmVirtPkg/ArmVirtPkg.dec3
-rw-r--r--ArmVirtPkg/Library/ArmVirtGicPlatformDxe/ArmVirtGicPlatformDxe.c201
-rw-r--r--ArmVirtPkg/Library/ArmVirtGicPlatformDxe/ArmVirtGicPlatformDxe.inf52
3 files changed, 256 insertions, 0 deletions
diff --git a/ArmVirtPkg/ArmVirtPkg.dec b/ArmVirtPkg/ArmVirtPkg.dec
index fd9a31a916..e91c70c95e 100644
--- a/ArmVirtPkg/ArmVirtPkg.dec
+++ b/ArmVirtPkg/ArmVirtPkg.dec
@@ -40,6 +40,9 @@
gArmCcaIpaWidthGuid = { 0xbdb66787, 0xfc8a, 0x412e, { 0xa0, 0x9b, 0x84, 0x96, 0x61, 0x81, 0x72, 0xc0 } }
gArmCcaIsRealmGuid = { 0x45e4546d, 0x26ea, 0x449d, { 0xa4, 0xa6, 0xcb, 0x5a, 0x54, 0xe3, 0x03, 0x7c } }
+ gArmVirtPlatformHasGicV2 = { 0x5f69e3c5, 0x9cd4, 0x47cf, { 0xa5, 0x31, 0x56, 0x15, 0xcb, 0x80, 0xf5, 0x8b } }
+ gArmVirtPlatformHasGicV3 = { 0xa74128a8, 0xb243, 0x4157, { 0x9c, 0xa4, 0x47, 0x63, 0x29, 0x3a, 0x68, 0x45 } }
+
[PcdsFeatureFlag]
#
# Feature Flag PCD that defines whether TPM2 support is enabled
diff --git a/ArmVirtPkg/Library/ArmVirtGicPlatformDxe/ArmVirtGicPlatformDxe.c b/ArmVirtPkg/Library/ArmVirtGicPlatformDxe/ArmVirtGicPlatformDxe.c
new file mode 100644
index 0000000000..81d9d2ff87
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmVirtGicPlatformDxe/ArmVirtGicPlatformDxe.c
@@ -0,0 +1,201 @@
+/** @file
+ NULL library class implementation to discover the GIC for DT based virt platforms
+
+ Copyright (c) 2015 - 2016, Linaro Ltd. All rights reserved.<BR>
+ Copyright (c) 2026, Arm Ltd. All rights reserved.<BR>
+ Copyright (c) 2026, Google LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/ArmGicLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MapMmioLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/FdtClient.h>
+
+EFI_STATUS
+EFIAPI
+ArmVirtGicPlatformDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ FDT_CLIENT_PROTOCOL *FdtClient;
+ CONST UINT64 *Reg;
+ UINT32 RegSize;
+ UINTN AddressCells, SizeCells;
+ UINTN GicRevision;
+ EFI_STATUS Status;
+ UINT64 DistBase, CpuBase, RedistBase;
+ UINT64 DistSize, CpuSize, RedistSize;
+ RETURN_STATUS PcdStatus;
+ EFI_HANDLE Handle;
+ CONST EFI_GUID *DepexGuid;
+
+ Status = gBS->LocateProtocol (
+ &gFdtClientProtocolGuid,
+ NULL,
+ (VOID **)&FdtClient
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ GicRevision = 2;
+ Status = FdtClient->FindCompatibleNodeReg (
+ FdtClient,
+ "arm,cortex-a15-gic",
+ (CONST VOID **)&Reg,
+ &AddressCells,
+ &SizeCells,
+ &RegSize
+ );
+ if (Status == EFI_NOT_FOUND) {
+ GicRevision = 3;
+ Status = FdtClient->FindCompatibleNodeReg (
+ FdtClient,
+ "arm,gic-v3",
+ (CONST VOID **)&Reg,
+ &AddressCells,
+ &SizeCells,
+ &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_UINTN);
+ DistSize = SwapBytes64 (Reg[1]);
+ ASSERT (DistSize < MAX_UINTN);
+
+ // RegProp[2..3] == { GICR base, GICR size }
+ RedistBase = SwapBytes64 (Reg[2]);
+ ASSERT (RedistBase < MAX_UINTN);
+ RedistSize = SwapBytes64 (Reg[3]);
+ ASSERT (RedistSize < MAX_UINTN);
+
+ PcdStatus = PcdSet64S (PcdGicDistributorBase, DistBase);
+ ASSERT_RETURN_ERROR (PcdStatus);
+ PcdStatus = PcdSet64S (PcdGicRedistributorsBase, RedistBase);
+ ASSERT_RETURN_ERROR (PcdStatus);
+
+ DEBUG ((
+ DEBUG_INFO,
+ "Found GIC v3 Distributor @ 0x%Lx, Len 0x%Lx\n",
+ DistBase,
+ DistSize
+ ));
+
+ DEBUG ((
+ DEBUG_INFO,
+ "Found GIC v3 Redistributor @ 0x%Lx, Len 0x%Lx\n",
+ RedistBase,
+ RedistSize
+ ));
+
+ Status = MapMmioMemory (
+ DistBase,
+ DistSize,
+ (EFI_MEMORY_UC | EFI_MEMORY_XP)
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = MapMmioMemory (
+ RedistBase,
+ RedistSize,
+ (EFI_MEMORY_UC | EFI_MEMORY_XP)
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ DepexGuid = &gArmVirtPlatformHasGicV3;
+ break;
+
+ case 2:
+ //
+ // When the GICv2 is emulated with virtualization=on, it adds a virtual
+ // set of control registers. This means the register property can be
+ // either 32 or 64 bytes in size.
+ //
+ ASSERT ((RegSize == 32) || (RegSize == 64));
+
+ DistBase = SwapBytes64 (Reg[0]);
+ DistSize = SwapBytes64 (Reg[1]);
+ CpuBase = SwapBytes64 (Reg[2]);
+ CpuSize = SwapBytes64 (Reg[3]);
+ ASSERT (DistBase < MAX_UINTN);
+ ASSERT (CpuBase < MAX_UINTN);
+ ASSERT (DistSize < MAX_UINTN);
+ ASSERT (CpuSize < MAX_UINTN);
+
+ PcdStatus = PcdSet64S (PcdGicDistributorBase, DistBase);
+ ASSERT_RETURN_ERROR (PcdStatus);
+ PcdStatus = PcdSet64S (PcdGicInterruptInterfaceBase, CpuBase);
+ ASSERT_RETURN_ERROR (PcdStatus);
+
+ DEBUG ((DEBUG_INFO, "Found GICv2 @ 0x%Lx/0x%Lx\n", DistBase, CpuBase));
+
+ Status = MapMmioMemory (
+ DistBase,
+ DistSize,
+ (EFI_MEMORY_UC | EFI_MEMORY_XP)
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = MapMmioMemory (
+ CpuBase,
+ CpuSize,
+ (EFI_MEMORY_UC | EFI_MEMORY_XP)
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ DepexGuid = &gArmVirtPlatformHasGicV2;
+ break;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "%a: No GIC revision specified!\n", __func__));
+ return EFI_NOT_FOUND;
+ }
+
+ Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (&Handle, DepexGuid, NULL, NULL);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_REQUEST_UNLOAD_IMAGE;
+}
diff --git a/ArmVirtPkg/Library/ArmVirtGicPlatformDxe/ArmVirtGicPlatformDxe.inf b/ArmVirtPkg/Library/ArmVirtGicPlatformDxe/ArmVirtGicPlatformDxe.inf
new file mode 100644
index 0000000000..2321d2cf35
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmVirtGicPlatformDxe/ArmVirtGicPlatformDxe.inf
@@ -0,0 +1,52 @@
+#/** @file
+#
+# Component description file for ArmVirtGicPlatformDxe module
+#
+# Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
+# Copyright (c) 2026, Arm Ltd. All rights reserved.<BR>
+# Copyright (c) 2026, Google LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 1.30
+ BASE_NAME = ArmVirtGicPlatformDxe
+ FILE_GUID = b8de02d5-3164-448f-879c-62f695d6cca8
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = ArmVirtGicPlatformDxeInitialize
+
+[Sources]
+ ArmVirtGicPlatformDxe.c
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ PcdLib
+ MapMmioLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ ArmVirtPkg/ArmVirtPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[Protocols]
+ gFdtClientProtocolGuid ## CONSUMES
+
+[Pcd]
+ gArmTokenSpaceGuid.PcdGicDistributorBase
+ gArmTokenSpaceGuid.PcdGicRedistributorsBase
+ gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
+
+[Guids]
+ gArmVirtPlatformHasGicV2
+ gArmVirtPlatformHasGicV3
+
+[Depex]
+ gFdtClientProtocolGuid