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
© 2016 - 2026 Red Hat, Inc.