From 22c6dbcbf42c16ab63752de5ae64b0cded558d48 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 1 Sep 2026 18:20:54 +0200 Subject: [PATCH 1/4] 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 diff --git a/ArmVirtPkg/ArmVirtPkg.dec b/ArmVirtPkg/ArmVirtPkg.dec index fd9a31a916d4..e91c70c95e95 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 000000000000..81d9d2ff8797 --- /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.
+ Copyright (c) 2026, Arm Ltd. All rights reserved.
+ Copyright (c) 2026, Google LLC. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +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 000000000000..2321d2cf353c --- /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.
+# Copyright (c) 2026, Arm Ltd. All rights reserved.
+# Copyright (c) 2026, Google LLC. All rights reserved.
+# +# 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 From 81e0b6361b401264c359e9eacf93e953e3c10bd0 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 1 Sep 2026 18:41:02 +0200 Subject: [PATCH 2/4] ArmVirtPkg: Implement stub DEPEX libraries for GIC v2/v3 presence Allow the unified ArmGicDxe driver to be replaced with either the v2 or the v3 one, depending on what the platform actually implements. This involves injecting a DEPEX on the ArmVirtPkg specific GUID that conveys whether the GIC is a revision 2 or a newer one. This DEPEX injection is done by adding a NULL library class resolution to each driver when incorporating it into the platform build. So add a library for GICv2 and one for GICv3 or newer. Signed-off-by: Ard Biesheuvel diff --git a/ArmVirtPkg/Library/ArmGicDepexLib/ArmGicDepexLib.c b/ArmVirtPkg/Library/ArmGicDepexLib/ArmGicDepexLib.c new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/ArmVirtPkg/Library/ArmGicDepexLib/ArmGicV2DepexLib.inf b/ArmVirtPkg/Library/ArmGicDepexLib/ArmGicV2DepexLib.inf new file mode 100644 index 000000000000..bd06dcf452af --- /dev/null +++ b/ArmVirtPkg/Library/ArmGicDepexLib/ArmGicV2DepexLib.inf @@ -0,0 +1,27 @@ +#/** @file +# +# Component description file for ArmGicDepexLib module +# +# Copyright (c) 2026, Google LLC. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#**/ + +[Defines] + INF_VERSION = 1.30 + BASE_NAME = ArmGicV2DepexLib + FILE_GUID = 7daabe90-e7a7-4b8a-8b28-1a4532afb691 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL + +[Sources] + ArmGicDepexLib.c + +[Packages] + ArmVirtPkg/ArmVirtPkg.dec + MdePkg/MdePkg.dec + +[Depex] + gArmVirtPlatformHasGicV2 diff --git a/ArmVirtPkg/Library/ArmGicDepexLib/ArmGicV3DepexLib.inf b/ArmVirtPkg/Library/ArmGicDepexLib/ArmGicV3DepexLib.inf new file mode 100644 index 000000000000..02ef5193f357 --- /dev/null +++ b/ArmVirtPkg/Library/ArmGicDepexLib/ArmGicV3DepexLib.inf @@ -0,0 +1,27 @@ +#/** @file +# +# Component description file for ArmGicDepexLib module +# +# Copyright (c) 2026, Google LLC. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#**/ + +[Defines] + INF_VERSION = 1.30 + BASE_NAME = ArmGicV3DepexLib + FILE_GUID = 12849212-ea40-4cd4-be97-de7636f05539 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL + +[Sources] + ArmGicDepexLib.c + +[Packages] + ArmVirtPkg/ArmVirtPkg.dec + MdePkg/MdePkg.dec + +[Depex] + gArmVirtPlatformHasGicV3 From d43a446baa384796b2c9897be5f86aa268e53d32 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 1 Sep 2026 18:50:49 +0200 Subject: [PATCH 3/4] ArmVirtPkg: Switch all platforms to split v2/v3 GIC drivers Use the separate v2 and v3 versions of the GIC driver, rather than the unified one, which is a bit odd because a platform never implements both, and GICv2 is obsolete by now. The only reason the unified driver is being kept alive is for virtual platforms that could decide to expose either. Let's refactor this a bit so that the version detection is separated from the driver dispatch itself, so that ordinary DEPEX resolution can be used to load either the v2 or the v3 driver. Signed-off-by: Ard Biesheuvel diff --git a/ArmVirtPkg/ArmVirt.dsc.inc b/ArmVirtPkg/ArmVirt.dsc.inc index fb1edceafcd2..73723fab8922 100644 --- a/ArmVirtPkg/ArmVirt.dsc.inc +++ b/ArmVirtPkg/ArmVirt.dsc.inc @@ -517,9 +517,14 @@ DEFINE FD_SIZE_IN_MB = 3 !include OvmfPkg/Include/Dsc/ShellComponents.dsc.inc - ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.inf { + ArmVirtPkg/Library/ArmVirtGicPlatformDxe/ArmVirtGicPlatformDxe.inf + ArmPkg/Drivers/ArmGicDxe/ArmGicV2Dxe.inf { - NULL|ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.inf + NULL|ArmVirtPkg/Library/ArmGicDepexLib/ArmGicV2DepexLib.inf + } + ArmPkg/Drivers/ArmGicDxe/ArmGicV3Dxe.inf { + + NULL|ArmVirtPkg/Library/ArmGicDepexLib/ArmGicV3DepexLib.inf } ArmPkg/Drivers/TimerDxe/TimerDxe.inf { diff --git a/ArmVirtPkg/ArmVirtCloudHv.fdf b/ArmVirtPkg/ArmVirtCloudHv.fdf index c7d212429a03..8a92843abf71 100644 --- a/ArmVirtPkg/ArmVirtCloudHv.fdf +++ b/ArmVirtPkg/ArmVirtCloudHv.fdf @@ -132,7 +132,9 @@ READ_LOCK_STATUS = TRUE INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf INF MdeModulePkg/Universal/SerialDxe/SerialDxe.inf - INF ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.inf + INF ArmVirtPkg/Library/ArmVirtGicPlatformDxe/ArmVirtGicPlatformDxe.inf + INF ArmPkg/Drivers/ArmGicDxe/ArmGicV2Dxe.inf + INF ArmPkg/Drivers/ArmGicDxe/ArmGicV3Dxe.inf INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf diff --git a/ArmVirtPkg/ArmVirtKvmTool.fdf b/ArmVirtPkg/ArmVirtKvmTool.fdf index ede74c08a8ff..fa22491d7aba 100644 --- a/ArmVirtPkg/ArmVirtKvmTool.fdf +++ b/ArmVirtPkg/ArmVirtKvmTool.fdf @@ -134,7 +134,9 @@ READ_LOCK_STATUS = TRUE INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf INF MdeModulePkg/Universal/SerialDxe/SerialDxe.inf - INF ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.inf + INF ArmVirtPkg/Library/ArmVirtGicPlatformDxe/ArmVirtGicPlatformDxe.inf + INF ArmPkg/Drivers/ArmGicDxe/ArmGicV2Dxe.inf + INF ArmPkg/Drivers/ArmGicDxe/ArmGicV3Dxe.inf INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf INF OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf diff --git a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc index ad158f57f127..f2bef9d1dda7 100644 --- a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc +++ b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc @@ -76,7 +76,9 @@ READ_LOCK_STATUS = TRUE INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf INF MdeModulePkg/Universal/SerialDxe/SerialDxe.inf - INF ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.inf + INF ArmVirtPkg/Library/ArmVirtGicPlatformDxe/ArmVirtGicPlatformDxe.inf + INF ArmPkg/Drivers/ArmGicDxe/ArmGicV2Dxe.inf + INF ArmPkg/Drivers/ArmGicDxe/ArmGicV3Dxe.inf INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf INF OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf diff --git a/ArmVirtPkg/ArmVirtXen.fdf b/ArmVirtPkg/ArmVirtXen.fdf index b7ddc5f9daf3..9d8ff900492e 100644 --- a/ArmVirtPkg/ArmVirtXen.fdf +++ b/ArmVirtPkg/ArmVirtXen.fdf @@ -142,7 +142,9 @@ READ_LOCK_STATUS = TRUE INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf INF MdeModulePkg/Universal/SerialDxe/SerialDxe.inf - INF ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.inf + INF ArmVirtPkg/Library/ArmVirtGicPlatformDxe/ArmVirtGicPlatformDxe.inf + INF ArmPkg/Drivers/ArmGicDxe/ArmGicV2Dxe.inf + INF ArmPkg/Drivers/ArmGicDxe/ArmGicV3Dxe.inf INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf