[PATCH RFC 1/7] hw/riscv: Add support for ACPI RQSC table

Drew Fustini posted 7 patches 3 days, 22 hours ago
[PATCH RFC 1/7] hw/riscv: Add support for ACPI RQSC table
Posted by Drew Fustini 3 days, 22 hours ago
From: Vasudevan Srinivasan <vasu@rivosinc.com>

In build_rqsc(), set Res ID 1 for each cache controller in RQSC table.
The AML code that generates that PPTT table uses the cache controller
mmio_base address as the Cache ID.

TODO: Similar plumbing still needs to be done to correlate bandwitch
controllers to the Proximity Domain for Memory Affinity Structures in
the SRAT table.

Signed-off-by: Vasudevan Srinivasan <vasu@rivosinc.com>
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 hw/core/sysbus-fdt.c       |   3 ++
 hw/riscv/cbqri_bandwidth.c |  11 +++++
 hw/riscv/cbqri_capacity.c  |  11 +++++
 hw/riscv/virt-acpi-build.c | 121 +++++++++++++++++++++++++++++++++++++++++++++
 include/hw/riscv/cbqri.h   |  12 +++++
 5 files changed, 158 insertions(+)

diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
index 89d0c464454a..d7967cde51be 100644
--- a/hw/core/sysbus-fdt.c
+++ b/hw/core/sysbus-fdt.c
@@ -36,6 +36,7 @@
 #include "hw/display/ramfb.h"
 #include "hw/uefi/var-service-api.h"
 #include "hw/arm/fdt.h"
+#include "hw/riscv/cbqri.h"
 
 /*
  * internal struct that contains the information to create dynamic
@@ -140,6 +141,8 @@ static const BindingEntry bindings[] = {
     TYPE_BINDING(TYPE_ARM_SMMUV3, no_fdt_node),
     TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
     TYPE_BINDING(TYPE_UEFI_VARS_SYSBUS, add_uefi_vars_node),
+    TYPE_BINDING(TYPE_RISCV_CBQRI_BC, no_fdt_node),
+    TYPE_BINDING(TYPE_RISCV_CBQRI_CC, no_fdt_node),
     TYPE_BINDING("", NULL), /* last element */
 };
 
diff --git a/hw/riscv/cbqri_bandwidth.c b/hw/riscv/cbqri_bandwidth.c
index f86b3bf75027..01f03d790410 100644
--- a/hw/riscv/cbqri_bandwidth.c
+++ b/hw/riscv/cbqri_bandwidth.c
@@ -635,4 +635,15 @@ DeviceState *riscv_cbqri_bc_create(hwaddr addr,
     return dev;
 }
 
+void get_bc_details(DeviceState *ds, const char *type, RQSC *rqsc)
+{
+    if (strcmp(type, TYPE_RISCV_CBQRI_BC) == 0) {
+        RiscvCbqriBandwidthState *bcs = RISCV_CBQRI_BC(ds);
+        (rqsc)->controllerType = 1;
+        (rqsc)->mmio_base = bcs->mmio_base;
+        (rqsc)->rcidCount = bcs->nb_rcids;
+        (rqsc)->mcidCount = bcs->nb_mcids;
+    }
+}
+
 type_init(riscv_cbqri_bc_register_types)
diff --git a/hw/riscv/cbqri_capacity.c b/hw/riscv/cbqri_capacity.c
index 1c3570262a36..8d830c278e00 100644
--- a/hw/riscv/cbqri_capacity.c
+++ b/hw/riscv/cbqri_capacity.c
@@ -730,4 +730,15 @@ DeviceState *riscv_cbqri_cc_create(hwaddr addr,
     return dev;
 }
 
+void get_cc_details(DeviceState *ds, const char *type, RQSC *rqsc)
+{
+    if (strcmp(type, TYPE_RISCV_CBQRI_CC) == 0) {
+        RiscvCbqriCapacityState *ccs = RISCV_CBQRI_CC(ds);
+        rqsc->controllerType = 0;
+        rqsc->mmio_base = ccs->mmio_base;
+        rqsc->rcidCount = ccs->nb_rcids;
+        rqsc->mcidCount = ccs->nb_mcids;
+    }
+}
+
 type_init(riscv_cbqri_cc_register_types)
diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c
index f1406cb68339..210b3f5fff98 100644
--- a/hw/riscv/virt-acpi-build.c
+++ b/hw/riscv/virt-acpi-build.c
@@ -34,6 +34,7 @@
 #include "hw/pci-host/gpex.h"
 #include "hw/riscv/virt.h"
 #include "hw/riscv/numa.h"
+#include "hw/riscv/cbqri.h"
 #include "hw/virtio/virtio-acpi.h"
 #include "migration/vmstate.h"
 #include "qapi/error.h"
@@ -269,6 +270,123 @@ spcr_setup(GArray *table_data, BIOSLinker *linker, RISCVVirtState *s)
 /* RHCT Node[N] starts at offset 56 */
 #define RHCT_NODE_ARRAY_OFFSET 56
 
+static u_int8_t gatherCbqriDetails(RISCVVirtState *vs, RQSC rqsc[])
+{
+    BusChild *bc = NULL;
+    DeviceState *ds = NULL;
+    u_int8_t controllerCount = 0;
+
+    if (vs == NULL) {
+        printf("RISCVVirtState is NULL\n");
+        return 0;
+    }
+
+    QTAILQ_FOREACH(bc, &vs->platform_bus_dev->parent_bus->children, sibling) {
+        if (strcmp(object_get_typename(OBJECT(bc->child)),
+                   TYPE_RISCV_CBQRI_BC) == 0)
+        {
+            ds = bc->child;
+            get_bc_details(ds, object_get_typename(OBJECT(bc->child)),
+                           &(rqsc[controllerCount]));
+            controllerCount++;
+        }
+        if (strcmp(object_get_typename(OBJECT(bc->child)),
+                   TYPE_RISCV_CBQRI_CC) == 0)
+        {
+            ds = bc->child;
+            get_cc_details(ds, object_get_typename(OBJECT(bc->child)),
+                           &(rqsc[controllerCount]));
+            controllerCount++;
+        }
+    }
+
+    return controllerCount;
+}
+
+/*
+ *
+ * RQSC Table
+ *
+ */
+static void build_rqsc(GArray *table_data,
+                       BIOSLinker *linker,
+                       RISCVVirtState *s)
+{
+    int numCbqriControllers = 0;
+    /* Support for upto 10 CBQRI controllers */
+    RQSC rqsc[10];
+    int i = 0;
+
+    AcpiTable table = { .sig = "RQSC", .rev = 0, .oem_id = s->oem_id,
+                        .oem_table_id = s->oem_table_id };
+
+    acpi_table_begin(&table, table_data);
+
+    numCbqriControllers = gatherCbqriDetails(s, rqsc);
+
+    fprintf(stderr, "[QEMU] %s(): numCbqriControllers = %d\n",
+            __func__, numCbqriControllers);
+    /* Number of QoS Controllers */
+    build_append_int_noprefix(table_data, numCbqriControllers, 4);
+
+    for (i = 0; i < numCbqriControllers; i++) {
+        fprintf(stderr, "[QEMU] %s(): Controller %d: Controller Type = %d\n",
+                __func__, i, rqsc[i].controllerType);
+        /* Controller Type */
+        build_append_int_noprefix(table_data, rqsc[i].controllerType, 1);
+        /* Reserved */
+        build_append_int_noprefix(table_data, 0, 1);
+        /* Length */
+        build_append_int_noprefix(table_data, 32, 2);
+        /* Controller register interface address */
+        build_append_gas(table_data,
+                AML_AS_SYSTEM_MEMORY,
+                0,
+                0,
+                4,
+                rqsc[i].mmio_base);
+        /* RCID Count */
+        build_append_int_noprefix(table_data, rqsc[i].rcidCount, 4);
+        /* MCID Count */
+        build_append_int_noprefix(table_data, rqsc[i].mcidCount, 4);
+        /* Controller Flags*/
+        build_append_int_noprefix(table_data, 0, 2);
+        /* Number of Resources hard coded to 1 for QEMU */
+        build_append_int_noprefix(table_data, 1, 2);
+
+        /* Resource Structure per Controller */
+        /* Resource Type  - Setting to the same as Controller Type for now */
+        build_append_int_noprefix(table_data, rqsc[i].controllerType, 1);
+        /* Reserved */
+        build_append_int_noprefix(table_data, 0, 1);
+        /* Length of Resource Structure */
+        build_append_int_noprefix(table_data, 20, 2);
+        /* Resource Flags */
+        build_append_int_noprefix(table_data, 0, 2);
+        /* Reserved */
+        build_append_int_noprefix(table_data, 0, 1);
+        /* Resource ID Type  - Setting to the same as Controller Type for now */
+        build_append_int_noprefix(table_data, rqsc[i].controllerType, 1);
+        /*
+         * The AML code that generates that PPTT table uses the cache
+         * controller mmio_base address as the Cache ID.
+         *
+         * TODO: Similar plumbing still needs to be done to correlate
+         * the memory controller to Proximity Domain in the SRAT table
+         */
+        fprintf(stderr, "[QEMU] %s(): Controller %d: Resource ID 1 = 0x%lx\n",
+                __func__, i, rqsc[i].mmio_base);
+        /* Resource ID 1 DWORD 1 CacheID or Proximity Domain */
+        build_append_int_noprefix(table_data, rqsc[i].mmio_base, 4);
+        /* Resource ID 1 DWORD 2 Reserved */
+        build_append_int_noprefix(table_data, 0, 4);
+        /* Resrouce ID 2 */
+        build_append_int_noprefix(table_data, 0, 4);
+    }
+
+    acpi_table_end(linker, &table);
+}
+
 /*
  * ACPI spec, Revision 6.6
  * 5.2.37 RISC-V Hart Capabilities Table (RHCT)
@@ -894,6 +1012,9 @@ static void virt_acpi_build(RISCVVirtState *s, AcpiBuildTables *tables)
         spcr_setup(tables_blob, tables->linker, s);
     }
 
+    acpi_add_table(table_offsets, tables_blob);
+    build_rqsc(tables_blob, tables->linker, s);
+
     acpi_add_table(table_offsets, tables_blob);
     {
         AcpiMcfgInfo mcfg = {
diff --git a/include/hw/riscv/cbqri.h b/include/hw/riscv/cbqri.h
index a07f1e3a2dde..227d4d2bd842 100644
--- a/include/hw/riscv/cbqri.h
+++ b/include/hw/riscv/cbqri.h
@@ -79,4 +79,16 @@ DeviceState *riscv_cbqri_cc_create(hwaddr addr,
 DeviceState *riscv_cbqri_bc_create(hwaddr addr,
                                    const RiscvCbqriBandwidthCaps *caps,
                                    const char *target_name);
+void example_soc_cbqri_init(void);
+
+typedef struct _RQSC {
+    u_int8_t controllerType;
+    u_int64_t mmio_base;
+    u_int16_t rcidCount;
+    u_int16_t mcidCount;
+} RQSC;
+
+void get_bc_details(DeviceState *ds, const char *type, RQSC *rqsc);
+void get_cc_details(DeviceState *ds, const char *type, RQSC *rqsc);
+
 #endif

-- 
2.43.0