diff options
| -rw-r--r-- | ArmVirtPkg/ArmVirtPkg.dec | 3 | ||||
| -rw-r--r-- | ArmVirtPkg/Library/ArmVirtGicPlatformDxe/ArmVirtGicPlatformDxe.c | 201 | ||||
| -rw-r--r-- | ArmVirtPkg/Library/ArmVirtGicPlatformDxe/ArmVirtGicPlatformDxe.inf | 52 |
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
|
