From 87a8a9148cd5acbeb31c6668f55d6c31865a524a Mon Sep 17 00:00:00 2001
From: eeshanl <eeshanlondhe@microsoft.com>
Date: Wed, 11 Dec 2024 00:32:59 +0000
Subject: [PATCH] Add SMMU Sbsa support - Configure SMMU config HOB in
 SbsaPlatformPeiLib - Update SbsaQemuAcpiDxe to use ArmMonitor calls to work
 with updated qemu version 9.1.50 - Relies on cherry-pick
 42925c15bee09162c6dfc8c2204843ffac6201c1 in Silicon/Arm/TFA

---
 .../SbsaPlatformPeiLib/PlatformPeiLib.c       | 140 ++++++++++++++++++
 .../SbsaPlatformPeiLib/PlatformPeiLib.inf     |  52 +++++++
 Platforms/QemuSbsaPkg/QemuSbsaPkg.dsc         |   5 +-
 Platforms/QemuSbsaPkg/QemuSbsaPkg.fdf         |   1 +
 .../SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c         |  63 +++++++-
 .../SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf       |   2 +
 6 files changed, 259 insertions(+), 4 deletions(-)
 create mode 100644 Platforms/QemuSbsaPkg/Library/SbsaPlatformPeiLib/PlatformPeiLib.c
 create mode 100644 Platforms/QemuSbsaPkg/Library/SbsaPlatformPeiLib/PlatformPeiLib.inf

diff --git a/Platforms/QemuSbsaPkg/Library/SbsaPlatformPeiLib/PlatformPeiLib.c b/Platforms/QemuSbsaPkg/Library/SbsaPlatformPeiLib/PlatformPeiLib.c
new file mode 100644
index 0000000000..057805b8c9
--- /dev/null
+++ b/Platforms/QemuSbsaPkg/Library/SbsaPlatformPeiLib/PlatformPeiLib.c
@@ -0,0 +1,140 @@
+/** @file
+
+  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Guid/SmmuConfig.h>
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <PiPei.h>
+
+#define SBSAQEMU_ACPI_HEADER(Signature, Type, Revision)                                        \
+  {                                                                                            \
+    Signature,                                    /* UINT32  Signature */                      \
+    sizeof (Type),                                /* UINT32  Length */                         \
+    Revision,                                     /* UINT8   Revision */                       \
+    0,                                            /* UINT8   Checksum */                       \
+    { 'L', 'I', 'N', 'A', 'R', 'O' },             /* UINT8   OemId[6] */                       \
+    FixedPcdGet64 (PcdAcpiDefaultOemTableId),     /* UINT64  OemTableId */                     \
+    FixedPcdGet32 (PcdAcpiDefaultOemRevision),    /* UINT32  OemRevision */                    \
+    FixedPcdGet32 (PcdAcpiDefaultCreatorId),      /* UINT32  CreatorId */                      \
+    FixedPcdGet32 (PcdAcpiDefaultCreatorRevision) /* UINT32  CreatorRevision */                \
+  }
+
+EFI_STATUS
+EFIAPI
+PlatformPeim (
+  VOID
+  )
+{
+
+  BuildFvHob(PcdGet64(PcdFvBaseAddress), PcdGet32(PcdFvSize));
+
+  // Create SMMU Config Hob struct. Same as IORT we want to publish as it is platform dependent.
+  SMMU_CONFIG SmmuConfig = {
+    .VersionMajor = CURRENT_SMMU_CONFIG_VERSION_MAJOR,
+    .VersionMinor = CURRENT_SMMU_CONFIG_VERSION_MINOR,
+
+    // Initialize IORT Table Header
+    .Config.Iort = {
+      SBSAQEMU_ACPI_HEADER(EFI_ACPI_6_0_IO_REMAPPING_TABLE_SIGNATURE,
+        PLATFORM_IO_REMAPPING_STRUCTURE,
+        EFI_ACPI_IO_REMAPPING_TABLE_REVISION_00),
+      3,
+      sizeof(EFI_ACPI_6_0_IO_REMAPPING_TABLE), // NodeOffset
+      0
+    },
+
+    // Initialize SMMU3 Structure
+    .Config.SmmuNode = {
+      {
+        {
+          EFI_ACPI_IORT_TYPE_SMMUv3,
+          sizeof(PLATFORM_ACPI_6_0_IO_REMAPPING_SMMU3_NODE),
+          2, // Revision
+          0, // Reserved
+          1, // NumIdMapping
+          OFFSET_OF(PLATFORM_ACPI_6_0_IO_REMAPPING_SMMU3_NODE,
+            SmmuIdMap) // IdReference
+        },
+        0x60050000, // Base address
+        EFI_ACPI_IORT_SMMUv3_FLAG_COHAC_OVERRIDE, // Flags
+        0, // Reserved
+        0, // VATOS address
+        EFI_ACPI_IORT_SMMUv3_MODEL_GENERIC, // SMMUv3 Model
+        74, // Event
+        75, // Pri
+        77, // Gerror
+        76, // Sync
+        0,  // Proximity domain
+        1   // DevIDMappingIndex
+      },
+      {
+        0x0000, // InputBase
+        0xffff, // NumIds
+        0x0000, // OutputBase
+        OFFSET_OF(PLATFORM_IO_REMAPPING_STRUCTURE, ItsNode), // OutputReference
+        0 // Flags
+      }
+    },
+
+    // Initialize RC Node
+    .Config.RcNode = {
+      {
+        {
+          EFI_ACPI_IORT_TYPE_ROOT_COMPLEX, // Type
+          sizeof(PLATFORM_ACPI_6_0_IO_REMAPPING_RC_NODE), // Length
+          0, // Revision
+          0, // Reserved
+          1, // NumIdMappings
+          OFFSET_OF(PLATFORM_ACPI_6_0_IO_REMAPPING_RC_NODE,
+            RcIdMap) // IdReference
+        },
+        1, // CacheCoherent
+        0, // AllocationHints
+        0, // Reserved
+        1, // MemoryAccessFlags
+        EFI_ACPI_IORT_ROOT_COMPLEX_ATS_UNSUPPORTED, // AtsAttribute
+        0x0,  // PciSegmentNumber
+        // 0, //MemoryAddressSizeLimit
+      },
+      {
+        0x0000, // InputBase
+        0xffff, // NumIds
+        0x0000, // OutputBase
+        OFFSET_OF(PLATFORM_IO_REMAPPING_STRUCTURE,
+          SmmuNode), // OutputReference
+        0, // Flags
+      }
+    },
+
+    // Initialize ITS Node
+    .Config.ItsNode = {
+      // EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE
+      {
+        // EFI_ACPI_6_0_IO_REMAPPING_NODE
+        {
+          EFI_ACPI_IORT_TYPE_ITS_GROUP, // Type
+          sizeof(PLATFORM_ACPI_6_0_IO_REMAPPING_ITS_NODE), // Length
+          0, // Revision
+          0, // Identifier
+          0, // NumIdMappings
+          0, // IdReference
+        },
+        1, // ITS count
+      },
+      0 // GIC ITS Identifiers
+    }
+  };
+
+  BuildGuidDataHob( & gSmmuConfigHobGuid, & SmmuConfig, sizeof(SMMU_CONFIG));
+
+  DEBUG((DEBUG_INFO, "Configured SmmuConfig Hob.\n"));
+
+  return EFI_SUCCESS;
+}
diff --git a/Platforms/QemuSbsaPkg/Library/SbsaPlatformPeiLib/PlatformPeiLib.inf b/Platforms/QemuSbsaPkg/Library/SbsaPlatformPeiLib/PlatformPeiLib.inf
new file mode 100644
index 0000000000..43a626198a
--- /dev/null
+++ b/Platforms/QemuSbsaPkg/Library/SbsaPlatformPeiLib/PlatformPeiLib.inf
@@ -0,0 +1,52 @@
+#/** @file
+#
+#  Copyright (c) 2011-2012, ARM Limited. All rights reserved.
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = ArmPlatformPeiLib
+  FILE_GUID                      = aa2c31d7-9029-4071-8a6b-9ca3f55c9bb0
+  MODULE_TYPE                    = SEC
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformPeiLib
+
+[Sources]
+  PlatformPeiLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+  DebugLib
+  HobLib
+  ArmPlatformLib
+
+[Guids]
+  gSmmuConfigHobGuid
+
+[Ppis]
+  gEfiPeiMasterBootModePpiGuid                  # PPI ALWAYS_PRODUCED
+  gEfiPeiBootInRecoveryModePpiGuid              # PPI SOMETIMES_PRODUCED
+
+[FixedPcd]
+  gArmTokenSpaceGuid.PcdFdBaseAddress
+  gArmTokenSpaceGuid.PcdFdSize
+
+  gArmTokenSpaceGuid.PcdFvBaseAddress
+  gArmTokenSpaceGuid.PcdFvSize
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision
+
+[depex]
+  TRUE
diff --git a/Platforms/QemuSbsaPkg/QemuSbsaPkg.dsc b/Platforms/QemuSbsaPkg/QemuSbsaPkg.dsc
index d6272c190c..50f3b559fe 100644
--- a/Platforms/QemuSbsaPkg/QemuSbsaPkg.dsc
+++ b/Platforms/QemuSbsaPkg/QemuSbsaPkg.dsc
@@ -163,7 +163,7 @@
   ArmHvcLib|ArmPkg/Library/ArmHvcLib/ArmHvcLib.inf
   ArmGenericTimerCounterLib|ArmPkg/Library/ArmGenericTimerVirtCounterLib/ArmGenericTimerVirtCounterLib.inf
 
-  PlatformPeiLib|ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf
+  PlatformPeiLib|QemuSbsaPkg/Library/SbsaPlatformPeiLib/PlatformPeiLib.inf
   MemoryInitPeiLib|ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf
 
   # ARM PL031 RTC Driver
@@ -571,7 +571,7 @@
 
   gEfiMdeModulePkgTokenSpaceGuid.PcdTurnOffUsbLegacySupport|TRUE
 
-  gEfiMdeModulePkgTokenSpaceGuid.PcdRequireIommu|FALSE # don't require IOMMU
+  gEfiMdeModulePkgTokenSpaceGuid.PcdRequireIommu|TRUE # require IOMMU
   gEfiMdeModulePkgTokenSpaceGuid.PcdHiiOsRuntimeSupport|FALSE
   gEfiMdeModulePkgTokenSpaceGuid.PcdEnableVariableRuntimeCache|FALSE
 
@@ -1363,6 +1363,7 @@
   MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
   QemuSbsaPkg/AcpiTables/AcpiTables.inf
   QemuSbsaPkg/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf
+  ArmPkg/Drivers/SmmuDxe/SmmuDxe.inf
 
   #
   # Standalone MM drivers in non-secure world
diff --git a/Platforms/QemuSbsaPkg/QemuSbsaPkg.fdf b/Platforms/QemuSbsaPkg/QemuSbsaPkg.fdf
index 5af2edc4e8..7a42b3f11a 100644
--- a/Platforms/QemuSbsaPkg/QemuSbsaPkg.fdf
+++ b/Platforms/QemuSbsaPkg/QemuSbsaPkg.fdf
@@ -343,6 +343,7 @@ READ_LOCK_STATUS   = TRUE
   INF MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
   INF QemuSbsaPkg/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf
   INF RuleOverride = ACPITABLE QemuSbsaPkg/AcpiTables/AcpiTables.inf
+  INF ArmPkg/Drivers/SmmuDxe/SmmuDxe.inf
 
   #
   # EBC support
diff --git a/Platforms/QemuSbsaPkg/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c b/Platforms/QemuSbsaPkg/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c
index fcbac5d491..52c1005a7e 100644
--- a/Platforms/QemuSbsaPkg/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c
+++ b/Platforms/QemuSbsaPkg/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c
@@ -9,6 +9,8 @@
 #include <IndustryStandard/Acpi.h>
 #include <IndustryStandard/AcpiAml.h>
 #include <IndustryStandard/SbsaQemuAcpi.h>
+#include <IndustryStandard/ArmStdSmc.h>
+#include <Library/ArmMonitorLib.h>
 #include <Library/AcpiLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
@@ -16,11 +18,68 @@
 #include <Library/MemoryAllocationLib.h>
 #include <Library/PcdLib.h>
 #include <Library/PrintLib.h>
+#include <Library/ResetSystemLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiDriverEntryPoint.h>
 #include <Library/UefiLib.h>
 #include <Protocol/AcpiTable.h>
 
+#define SIP_SVC_GET_CPU_COUNT  SMC_SIP_FUNCTION_ID(200)
+#define SIP_SVC_GET_CPU_NODE   SMC_SIP_FUNCTION_ID(201)
+#define SMC_SIP_CALL_SUCCESS   SMC_ARCH_CALL_SUCCESS
+
+/**
+  Get CPU count from information passed by TF-A.
+
+**/
+UINT32
+GetCpuCount (
+  VOID
+  )
+{
+  ARM_MONITOR_ARGS  SmcArgs;
+
+  SmcArgs.Arg0 = SIP_SVC_GET_CPU_COUNT;
+  ArmMonitorCall (&SmcArgs);
+
+  if (SmcArgs.Arg0 != SMC_SIP_CALL_SUCCESS) {
+    DEBUG ((DEBUG_ERROR, "%a: SIP_SVC_GET_CPU_COUNT call failed. We have no cpu information.\n", __func__));
+    ResetShutdown ();
+  }
+
+  DEBUG ((DEBUG_INFO, "%a: We have %d cpus.\n", __func__, SmcArgs.Arg1));
+
+  return SmcArgs.Arg1;
+}
+
+/**
+  Get MPIDR for a given cpu from TF-A.
+
+  @param [in]   CpuId    Index of cpu to retrieve MPIDR value for.
+
+  @retval                MPIDR value of CPU at index <CpuId>
+**/
+UINT64
+GetMpidr (
+  IN UINTN  CpuId
+  )
+{
+  ARM_MONITOR_ARGS  SmcArgs;
+
+  SmcArgs.Arg0 = SIP_SVC_GET_CPU_NODE;
+  SmcArgs.Arg1 = CpuId;
+  ArmMonitorCall (&SmcArgs);
+
+  if (SmcArgs.Arg0 != SMC_SIP_CALL_SUCCESS) {
+    DEBUG ((DEBUG_ERROR, "%a: SIP_SVC_GET_CPU_NODE call failed. We have no MPIDR for CPU%d.\n", __func__, CpuId));
+    ResetShutdown ();
+  }
+
+  DEBUG ((DEBUG_INFO, "%a: MPIDR for CPU%d: = %d\n", __func__, CpuId, SmcArgs.Arg2));
+
+  return SmcArgs.Arg2;
+}
+
 /*
  * A Function to Compute the ACPI Table Checksum
  */
@@ -129,7 +188,7 @@ AddMadtTable (
     CopyMem (New, &Gicc, sizeof (EFI_ACPI_6_0_GIC_STRUCTURE));
     GiccPtr                   = (EFI_ACPI_6_0_GIC_STRUCTURE *)New;
     GiccPtr->AcpiProcessorUid = CoreIndex;
-    GiccPtr->MPIDR            = FdtHelperGetMpidr (CoreIndex);
+    GiccPtr->MPIDR            = GetMpidr (CoreIndex);
     New                      += sizeof (EFI_ACPI_6_0_GIC_STRUCTURE);
   }
 
@@ -431,7 +490,7 @@ InitializeSbsaQemuAcpiDxe (
   UINT32                   NumCores;
 
   // Parse the device tree and get the number of CPUs
-  NumCores = FdtHelperCountCpus ();
+  NumCores = GetCpuCount ();
   ASSERT (PcdGet32 (PcdCoreCount) == NumCores);
 
   // Check if ACPI Table Protocol has been installed
diff --git a/Platforms/QemuSbsaPkg/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf b/Platforms/QemuSbsaPkg/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf
index 4b49551100..eadf8a53a9 100644
--- a/Platforms/QemuSbsaPkg/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf
+++ b/Platforms/QemuSbsaPkg/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf
@@ -29,6 +29,7 @@
 
 [LibraryClasses]
   ArmLib
+  ArmMonitorLib
   BaseMemoryLib
   BaseLib
   DebugLib
@@ -36,6 +37,7 @@
   FdtHelperLib
   PcdLib
   PrintLib
+  ResetSystemLib
   UefiDriverEntryPoint
   UefiLib
   UefiRuntimeServicesTableLib