From mboxrd@z Thu Jan  1 00:00:00 1970
Received: from mail-pg1-f195.google.com (mail-pg1-f195.google.com [209.85.215.195])
 by mx.groups.io with SMTP id smtpd.web10.8997.1598340254841944377
 for <devel@edk2.groups.io>;
 Tue, 25 Aug 2020 00:24:14 -0700
Authentication-Results: mx.groups.io;
 dkim=pass header.i=@linaro.org header.s=google header.b=zLhjm7t4;
 spf=pass (domain: linaro.org, ip: 209.85.215.195, mailfrom: tanmay.jagdale@linaro.org)
Received: by mail-pg1-f195.google.com with SMTP id v15so6199374pgh.6
        for <devel@edk2.groups.io>; Tue, 25 Aug 2020 00:24:14 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=linaro.org; s=google;
        h=from:to:cc:subject:date:message-id:in-reply-to:references
         :mime-version:content-transfer-encoding;
        bh=OKFl3ztsSKnxBsNMdpsfv488EBiBnaHiZ9tmLkU9isE=;
        b=zLhjm7t4mqEObDpg66EHhkS64ca0keQU8bpAbK+wMqoWmLkDxvHm5gNdQTHwajDksg
         F+n6xabO5x+n3rfKxNOv2eqVFL1pHE1xMCYKMBI0vQ4/cQL/NUDnH64ZFxp7G6E19pVO
         Znmy9aFzs2xGOMt8QOXaoH1W+mh9SwCrGR6J4NFMlmMOp6KOCGag6wneeM3QMdx0RUTu
         B2pZfjI1PZdelGTtCjB/X5vadqg39gYrePLCeIOWmJ3ZVjcEbad0BAmwgWIgNWh+xWlp
         NKVBs/0ZxP3oAVszS29/SfGmIveDxPv3vO8Lhc5mOPxSQaRIdEP7VzfjWYtjWaTbEDW6
         PLYg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to
         :references:mime-version:content-transfer-encoding;
        bh=OKFl3ztsSKnxBsNMdpsfv488EBiBnaHiZ9tmLkU9isE=;
        b=P91c9FTeNkcATKBRgfKbop+/k8E8lizNgg8OG7pSEkv2v5eyXVHDJsPxdpJN9FP8Kr
         Qn6DEU9hxZHtL8BoW4zEcloDOi8dpNXtCGpymQA57Xvaukvjlme445hfjfkxctNXEd4k
         R4AXlMm/dEvnDvZsd7fT4KeDMk3gfoU8DN2dptuI+++ajsXq57eQH1NabvGH2AScIS+b
         l/4Ti7mrXtUznF+nIHcsbcTnaZhh+uxmu2pVWOIqE4IoQfBJ9u83p3snLzLpPOx3fS3/
         zr9qWhB5xnw1dw/UYZ+LADZFucqukw19iaOgeytGv6IZMlz6BGYwRvoY45qa5l7eL0Xi
         3CjA==
X-Gm-Message-State: AOAM532C28RqiEXPlEaHdBgc6VmVgEyzWjaQjYREBXeZdyGYZAm6BZFy
	MHEi2AjvCweAmawHiONMSR3LCA==
X-Google-Smtp-Source: ABdhPJwlfnG6ouFA8RzMXjHTjJVjuWE+cI1iyMuSqToagTwr0vKNPBy4EEguFlk8zQjtS+msyliJyw==
X-Received: by 2002:aa7:8514:: with SMTP id v20mr7126285pfn.18.1598340254359;
        Tue, 25 Aug 2020 00:24:14 -0700 (PDT)
Return-Path: <tanmay.jagdale@linaro.org>
Received: from bean-canyon.localdomain ([106.51.140.68])
        by smtp.googlemail.com with ESMTPSA id d5sm1722417pjw.18.2020.08.25.00.24.12
        (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
        Tue, 25 Aug 2020 00:24:13 -0700 (PDT)
From: "Tanmay Jagdale" <tanmay.jagdale@linaro.org>
To: leif@nuviainc.com,
	graeme@nuviainc.com,
	shashi.mallela@linaro.org,
	devel@edk2.groups.io
Cc: paul.isaacs@linaro.org,
	tanmay@marvell.com,
	Tanmay Jagdale <tanmay.jagdale@linaro.org>
Subject: [PATCH v2 edk2-platforms 5/8] SbsaQemu: AcpiDxe: Create MADT table at runtime
Date: Tue, 25 Aug 2020 12:53:19 +0530
Message-Id: <20200825072322.10848-6-tanmay.jagdale@linaro.org>
X-Mailer: git-send-email 2.28.0
In-Reply-To: <20200825072322.10848-1-tanmay.jagdale@linaro.org>
References: <20200825072322.10848-1-tanmay.jagdale@linaro.org>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit

- Add support to create MADT table at runtime.
- Included a macro for GIC Redistributor structure initialisation.

Signed-off-by: Tanmay Jagdale <tanmay.jagdale@linaro.org>
---
 Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf |  20 ++-
 Silicon/Qemu/SbsaQemu/Include/IndustryStandard/SbsaQemuAcpi.h     |  15 ++
 Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c   | 156 ++++++++++++++++++++
 3 files changed, 190 insertions(+), 1 deletion(-)

diff --git a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf
index 3795a7e11639..8125e8ba7553 100644
--- a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf
+++ b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf
@@ -41,9 +41,27 @@ [LibraryClasses]
   UefiRuntimeServicesTableLib
 
 [Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile
   gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdCoreCount
   gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdClusterCount
   gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdDeviceTreeBaseAddress
 
 [Depex]
-  TRUE
+  gEfiAcpiTableProtocolGuid                       ## CONSUMES
+
+[Guids]
+  gEdkiiPlatformHasAcpiGuid
+
+[Protocols]
+  gEfiAcpiTableProtocolGuid                       ## CONSUMES
+
+[FixedPcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision
+  gArmTokenSpaceGuid.PcdGicDistributorBase
+  gArmTokenSpaceGuid.PcdGicRedistributorsBase
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision
diff --git a/Silicon/Qemu/SbsaQemu/Include/IndustryStandard/SbsaQemuAcpi.h b/Silicon/Qemu/SbsaQemu/Include/IndustryStandard/SbsaQemuAcpi.h
index eac195b0585c..7a9a0061675f 100644
--- a/Silicon/Qemu/SbsaQemu/Include/IndustryStandard/SbsaQemuAcpi.h
+++ b/Silicon/Qemu/SbsaQemu/Include/IndustryStandard/SbsaQemuAcpi.h
@@ -22,6 +22,21 @@
     FixedPcdGet32 (PcdAcpiDefaultCreatorRevision)/* UINT32  CreatorRevision */ \
   }
 
+// Defines for MADT
+#define SBSAQEMU_MADT_GIC_VBASE          0x2c020000
+#define SBSAQEMU_MADT_GIC_HBASE          0x2c010000
+#define SBSAQEMU_MADT_GIC_PMU_IRQ        23
+#define SBSAQEMU_MADT_GICR_SIZE          0x4000000
+
+// Macro for MADT GIC Redistributor Structure
+#define SBSAQEMU_MADT_GICR_INIT() {                                            \
+   EFI_ACPI_6_0_GICR,                        /* Type */                        \
+   sizeof (EFI_ACPI_6_0_GICR_STRUCTURE),     /* Length */                      \
+   EFI_ACPI_RESERVED_WORD,                   /* Reserved */                    \
+   FixedPcdGet32 (PcdGicRedistributorsBase), /* DiscoveryRangeBaseAddress */   \
+   SBSAQEMU_MADT_GICR_SIZE                   /* DiscoveryRangeLength */        \
+   }
+
 #define SBSAQEMU_UART0_BASE              0x60000000
 
 #define SBSAQEMU_PCI_SEG0_CONFIG_BASE    0xf0000000
diff --git a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c
index d0d413891e81..1a8cfb8b0a2e 100644
--- a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c
+++ b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c
@@ -6,11 +6,17 @@
 *  SPDX-License-Identifier: BSD-2-Clause-Patent
 *
 **/
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/SbsaQemuAcpi.h>
+#include <Library/AcpiLib.h>
+#include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
 #include <Library/PcdLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiDriverEntryPoint.h>
 #include <Library/UefiLib.h>
+#include <Protocol/AcpiTable.h>
 #include <Protocol/FdtClient.h>
 #include <libfdt.h>
 
@@ -62,6 +68,137 @@ CountCpusFromFdt (
   ASSERT_RETURN_ERROR (PcdStatus);
 }
 
+/*
+ * A Function to Compute the ACPI Table Checksum
+ */
+VOID
+AcpiPlatformChecksum (
+  IN UINT8      *Buffer,
+  IN UINTN      Size
+  )
+{
+  UINTN ChecksumOffset;
+
+  ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum);
+
+  // Set checksum field to 0 since it is used as part of the calculation
+  Buffer[ChecksumOffset] = 0;
+
+  Buffer[ChecksumOffset] = CalculateCheckSum8(Buffer, Size);
+}
+
+/*
+ * A function that add the MADT ACPI table.
+  IN EFI_ACPI_COMMON_HEADER    *CurrentTable
+ */
+EFI_STATUS
+AddMadtTable (
+  IN EFI_ACPI_TABLE_PROTOCOL   *AcpiTable
+  )
+{
+  EFI_STATUS            Status;
+  UINTN                 TableHandle;
+  UINT32                TableSize;
+  EFI_PHYSICAL_ADDRESS  PageAddress;
+  UINT8                 *New;
+  UINT32                NumCores;
+
+  // Initialize MADT ACPI Header
+  EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER Header = {
+     SBSAQEMU_ACPI_HEADER (EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
+                           EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER,
+                           EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION),
+      0, 0 };
+
+  // Initialize GICC Structure
+  EFI_ACPI_6_0_GIC_STRUCTURE Gicc = EFI_ACPI_6_0_GICC_STRUCTURE_INIT (
+    0,                                     /* GicID */
+    0,                                     /* AcpiCpuUid */
+    0,                                     /* Mpidr */
+    EFI_ACPI_6_0_GIC_ENABLED,              /* Flags */
+    SBSAQEMU_MADT_GIC_PMU_IRQ,             /* PMU Irq */
+    FixedPcdGet32 (PcdGicDistributorBase), /* PhysicalBaseAddress */
+    SBSAQEMU_MADT_GIC_VBASE,               /* GicVBase */
+    SBSAQEMU_MADT_GIC_HBASE,               /* GicHBase */
+    25,                                    /* GsivId */
+    0,                                     /* GicRBase */
+    0                                      /* Efficiency */
+    );
+
+  // Initialize GIC Distributor Structure
+  EFI_ACPI_6_0_GIC_DISTRIBUTOR_STRUCTURE Gicd =
+    EFI_ACPI_6_0_GIC_DISTRIBUTOR_INIT (
+      0,
+      FixedPcdGet32 (PcdGicDistributorBase),
+      0,
+      3 /* GicVersion */
+    );
+
+ // Initialize GIC Redistributor Structure
+  EFI_ACPI_6_0_GICR_STRUCTURE Gicr = SBSAQEMU_MADT_GICR_INIT();
+
+  // Get CoreCount which was determined eariler after parsing device tree
+  NumCores = PcdGet32 (PcdCoreCount);
+
+  // Calculate the new table size based on the number of cores
+  TableSize = sizeof (EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER) +
+               (sizeof (EFI_ACPI_6_0_GIC_STRUCTURE) * NumCores) +
+               sizeof (EFI_ACPI_6_0_GIC_DISTRIBUTOR_STRUCTURE) +
+               sizeof (EFI_ACPI_6_0_GICR_STRUCTURE);
+
+  Status = gBS->AllocatePages (
+                  AllocateAnyPages,
+                  EfiACPIReclaimMemory,
+                  EFI_SIZE_TO_PAGES (TableSize),
+                  &PageAddress
+                  );
+  if (EFI_ERROR(Status)) {
+    DEBUG ((EFI_D_ERROR, "Failed to allocate pages for MADT table\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  New = (UINT8 *)(UINTN) PageAddress;
+  ZeroMem (New, TableSize);
+
+  // Add the  ACPI Description table header
+  CopyMem (New, &Header, sizeof (EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER));
+  ((EFI_ACPI_DESCRIPTION_HEADER*) New)->Length = TableSize;
+  New += sizeof (EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER);
+
+  // Add new GICC structures for the Cores
+  for (NumCores = 0; NumCores < PcdGet32 (PcdCoreCount); NumCores++) {
+    EFI_ACPI_6_0_GIC_STRUCTURE *GiccPtr;
+
+    CopyMem (New, &Gicc, sizeof (EFI_ACPI_6_0_GIC_STRUCTURE));
+    GiccPtr = (EFI_ACPI_6_0_GIC_STRUCTURE *) New;
+    GiccPtr->AcpiProcessorUid = NumCores;
+    GiccPtr->MPIDR = NumCores;
+    New += sizeof (EFI_ACPI_6_0_GIC_STRUCTURE);
+  }
+
+  // GIC Distributor Structure
+  CopyMem (New, &Gicd, sizeof (EFI_ACPI_6_0_GIC_DISTRIBUTOR_STRUCTURE));
+  New += sizeof (EFI_ACPI_6_0_GIC_DISTRIBUTOR_STRUCTURE);
+
+  // GIC ReDistributor Structure
+  CopyMem (New, &Gicr, sizeof (EFI_ACPI_6_0_GICR_STRUCTURE));
+  New += sizeof (EFI_ACPI_6_0_GICR_STRUCTURE);
+
+  AcpiPlatformChecksum ((UINT8*) PageAddress, TableSize);
+
+  Status = AcpiTable->InstallAcpiTable (
+                        AcpiTable,
+                        (EFI_ACPI_COMMON_HEADER *)PageAddress,
+                        TableSize,
+                        &TableHandle
+                        );
+  if (EFI_ERROR(Status)) {
+    DEBUG ((EFI_D_ERROR, "Failed to install MADT table\n"));
+  }
+
+  return Status;
+}
+
 EFI_STATUS
 EFIAPI
 InitializeSbsaQemuAcpiDxe (
@@ -69,8 +206,27 @@ InitializeSbsaQemuAcpiDxe (
   IN EFI_SYSTEM_TABLE     *SystemTable
   )
 {
+  EFI_STATUS                     Status;
+  EFI_ACPI_TABLE_PROTOCOL        *AcpiTable;
+
   // Parse the device tree and get the number of CPUs
   CountCpusFromFdt ();
 
+  // Check if ACPI Table Protocol has been installed
+  Status = gBS->LocateProtocol (
+                  &gEfiAcpiTableProtocolGuid,
+                  NULL,
+                  (VOID **)&AcpiTable
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "Failed to locate ACPI Table Protocol\n"));
+    return Status;
+  }
+
+  Status = AddMadtTable (AcpiTable);
+  if (EFI_ERROR(Status)) {
+     DEBUG((EFI_D_ERROR, "Failed to add MADT table\n"));
+  }
+
   return EFI_SUCCESS;
 }
-- 
2.28.0