Re: [PATCH v3 04/10] hw/riscv/virt: add opt-in RPMI base support
Subrahmanya Lingappa <[email protected]> Mon, 20 Jul 2026 16:41:27 +0530
| Newsgroups | org.nongnu.qemu-riscv,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <CAPxK-6f9UG8C8avzthiRc3=hj=K9_=wDqEUa1t9KxVND7Gi93w@mail.gmail.com> |
Daniel, On Fri, Jul 17, 2026 at 6:47 PM Daniel Henrique Barboza <[email protected]> wrote: > > > > On 7/14/2026 4:56 AM, Subrahmanya Lingappa wrote: > > Add the virt machine rpmi=on/off option and wire the initial RPMI Base > > transport into machine realization. > > > > The option remains disabled by default and requires TCG plus librpmi. > > Invalid accelerator/build combinations fail during machine > > initialization. When enabled, virt allocates the RPMI shared-memory > > transport, creates the RPMI device, configures Base service metadata, > > and emits the corresponding device-tree nodes for firmware discovery. > > > > Signed-off-by: Subrahmanya Lingappa <[email protected]> > > --- > > hw/riscv/Kconfig | 1 + > > hw/riscv/virt.c | 96 ++++++++++++++++++++++++++++++++++++ > > include/hw/misc/riscv_rpmi.h | 10 ++++ > > include/hw/riscv/virt.h | 3 ++ > > 4 files changed, 110 insertions(+) > > > > diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig > > index 54e41a6afc..4e25be113a 100644 > > --- a/hw/riscv/Kconfig > > +++ b/hw/riscv/Kconfig > > @@ -49,6 +49,7 @@ config RISCV_VIRT > > imply VIRTIO_VGA > > imply TEST_DEVICES > > imply TPM_TIS_SYSBUS > > + imply RISCV_RPMI > > select DEVICE_TREE > > select RISCV_NUMA > > select GOLDFISH_RTC > > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c > > index 33775a61fd..e52ccfae1f 100644 > > --- a/hw/riscv/virt.c > > +++ b/hw/riscv/virt.c > > @@ -45,6 +45,8 @@ > > #include "hw/intc/riscv_aplic.h" > > #include "hw/intc/sifive_plic.h" > > #include "hw/misc/sifive_test.h" > > +#include "hw/misc/riscv_rpmi.h" > > +#include "hw/riscv/rpmi-fdt.h" > > #include "hw/core/platform-bus.h" > > #include "chardev/char.h" > > #include "system/device_tree.h" > > @@ -97,6 +99,8 @@ static const MemMapEntry virt_memmap[] = { > > [VIRT_UART0] = { 0x10000000, 0x100 }, > > [VIRT_VIRTIO] = { 0x10001000, 0x1000 }, > > [VIRT_FW_CFG] = { 0x10100000, 0x18 }, > > + [VIRT_RPMI_SHMEM] = { 0x10200000, 0x20000 }, > > + [VIRT_RPMI_DOORBELL] = { 0x10230000, 0x1000 }, > > [VIRT_FLASH] = { 0x20000000, 0x4000000 }, > > [VIRT_IMSIC_M] = { 0x24000000, VIRT_IMSIC_MAX_SIZE }, > > [VIRT_IMSIC_S] = { 0x28000000, VIRT_IMSIC_MAX_SIZE }, > > @@ -1002,6 +1006,40 @@ static void create_fdt_iommu(RISCVVirtState *s, uint16_t bdf) > > s->pci_iommu_bdf = bdf; > > } > > > > + > > +static RiscvRpmiConfig virt_rpmi_config(RISCVVirtState *s, > > + const uint32_t *hart_ids, > > + uint32_t hart_count) > > +{ > > + return (RiscvRpmiConfig) { > > + .doorbell_base = s->memmap[VIRT_RPMI_DOORBELL].base, > > + .shmem_base = s->memmap[VIRT_RPMI_SHMEM].base, > > + .shmem_size = s->memmap[VIRT_RPMI_SHMEM].size, > > + .a2p_req_size = VIRT_RPMI_A2P_REQ_SIZE, > > + .p2a_req_size = VIRT_RPMI_P2A_REQ_SIZE, > > + .platform_info = "QEMU RISC-V virt RPMI", > > + .hart_ids = hart_ids, > > + .hart_count = hart_count, > > + }; > > +} > > + > > +static void create_fdt_rpmi(RISCVVirtState *s, uint32_t *phandle, > > + uint32_t msi_phandle) > > +{ > > + RiscvRpmiConfig rpmi_cfg = virt_rpmi_config(s, NULL, 0); > > + uint32_t rpmi_mbox_handle; > > + RiscvRpmiFdtMboxConfig cfg = { > > + .shmem_base = rpmi_cfg.shmem_base, > > + .doorbell_base = rpmi_cfg.doorbell_base, > > + .a2p_req_size = rpmi_cfg.a2p_req_size, > > + .p2a_req_size = rpmi_cfg.p2a_req_size, > > + .doorbell_size = s->memmap[VIRT_RPMI_DOORBELL].size, > > + }; > > + > > + riscv_rpmi_fdt_add_mbox(MACHINE(s)->fdt, &cfg, phandle, > > + &rpmi_mbox_handle); > > +} > > + > > static void finalize_fdt(RISCVVirtState *s) > > { > > uint32_t phandle = 1, irq_mmio_phandle = 1, msi_pcie_phandle = 1; > > @@ -1021,6 +1059,10 @@ static void finalize_fdt(RISCVVirtState *s) > > create_fdt_pcie(s, irq_pcie_phandle, msi_pcie_phandle, > > iommu_sys_phandle); > > > > + if (s->have_rpmi) { > > + create_fdt_rpmi(s, &phandle, msi_pcie_phandle); > > + } > > + > > create_fdt_reset(s, &phandle); > > > > create_fdt_uart(s, irq_mmio_phandle); > > @@ -1410,6 +1452,18 @@ static void virt_machine_init(MachineState *machine) > > exit(1); > > } > > > > + > > + if (s->have_rpmi) { > > +#ifndef CONFIG_LIBRPMI > > + error_report("RISC-V RPMI support is not compiled in"); > > + exit(1); > > +#else > > + if (kvm_enabled()) { > > + error_report("RISC-V RPMI support is not available with KVM"); > > + exit(1); > > + } > > +#endif > > + } > > /* Initialize sockets */ > > mmio_irqchip = virtio_irqchip = pcie_irqchip = NULL; > > for (i = 0; i < socket_count; i++) { > > @@ -1552,6 +1606,25 @@ static void virt_machine_init(MachineState *machine) > > /* SiFive Test MMIO device */ > > sifive_test_create(s->memmap[VIRT_TEST].base); > > > > + if (s->have_rpmi) { > > + MachineClass *mc = MACHINE_GET_CLASS(machine); > > + const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(machine); > > + g_autofree uint32_t *rpmi_hart_ids = > > + g_new0(uint32_t, machine->smp.cpus); > > + RiscvRpmiConfig rpmi_cfg; > > + Error *local_err = NULL; > > + > > + for (i = 0; i < machine->smp.cpus; i++) { > > + rpmi_hart_ids[i] = possible_cpus->cpus[i].arch_id; > > + } > > + > > + rpmi_cfg = virt_rpmi_config(s, rpmi_hart_ids, machine->smp.cpus); > > + if (!riscv_rpmi_create(&rpmi_cfg, &local_err)) { > > + error_report_err(local_err); > > + exit(1); > > + } > > + } > > + > > /* VirtIO MMIO devices */ > > for (i = 0; i < VIRTIO_COUNT; i++) { > > sysbus_create_simple("virtio-mmio", > > @@ -1636,6 +1709,7 @@ static void virt_machine_instance_init(Object *obj) > > > > s->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6); > > s->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8); > > + s->have_rpmi = false; > > s->acpi = ON_OFF_AUTO_AUTO; > > s->iommu_sys = ON_OFF_AUTO_AUTO; > > } > > @@ -1710,6 +1784,21 @@ static void virt_set_aclint(Object *obj, bool value, Error **errp) > > s->have_aclint = value; > > } > > > > + > > +static bool virt_get_rpmi(Object *obj, Error **errp) > > +{ > > + RISCVVirtState *s = RISCV_VIRT_MACHINE(obj); > > + > > + return s->have_rpmi; > > +} > > + > > +static void virt_set_rpmi(Object *obj, bool value, Error **errp) > > +{ > > + RISCVVirtState *s = RISCV_VIRT_MACHINE(obj); > > + > > + s->have_rpmi = value; > > +} > > + > > bool virt_is_iommu_sys_enabled(RISCVVirtState *s) > > { > > return s->iommu_sys == ON_OFF_AUTO_ON; > > @@ -1831,6 +1920,13 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data) > > "enable/disable emulating " > > "ACLINT devices"); > > > > + > > + object_class_property_add_bool(oc, "rpmi", virt_get_rpmi, > > + virt_set_rpmi); > > + object_class_property_set_description(oc, "rpmi", > > + "Set on/off to enable/disable " > > + "RISC-V RPMI devices"); > > + > > object_class_property_add_str(oc, "aia", virt_get_aia, > > virt_set_aia); > > object_class_property_set_description(oc, "aia", > > diff --git a/include/hw/misc/riscv_rpmi.h b/include/hw/misc/riscv_rpmi.h > > index cb2658e57e..b5d8a32f9b 100644 > > --- a/include/hw/misc/riscv_rpmi.h > > +++ b/include/hw/misc/riscv_rpmi.h > > @@ -85,6 +85,16 @@ struct RiscvRpmiState { > > bool has_shmem; > > }; > > > > +#ifdef CONFIG_LIBRPMI > > DeviceState *riscv_rpmi_create(const RiscvRpmiConfig *cfg, Error **errp); > > +#else > > +static inline DeviceState *riscv_rpmi_create(const RiscvRpmiConfig *cfg, > > + Error **errp) > > +{ > > + (void)cfg; > > + (void)errp; > > + return NULL; > > +} > > I think you can do: > > static inline DeviceState *riscv_rpmi_create(const RiscvRpmiConfig *cfg G_GNUC_UNUSED, > Error **errp G_GNUC_UNUSED) > { > return NULL; > } > > Instead of using the args as void to not get warnings. > > > Everything else LGTM. Thanks, > Daniel > Fixed in v4. I replaced the explicit unused-parameter casts in the no-librpmi inline stub with G_GNUC_UNUSED. Thanks, Subbu > > > +#endif > > > > #endif > > diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h > > index 18a2a323a3..f7c48613bf 100644 > > --- a/include/hw/riscv/virt.h > > +++ b/include/hw/riscv/virt.h > > @@ -55,6 +55,7 @@ struct RISCVVirtState { > > > > int fdt_size; > > bool have_aclint; > > + bool have_rpmi; > > RISCVVirtAIAType aia_type; > > int aia_guests; > > char *oem_id; > > @@ -79,6 +80,8 @@ enum { > > VIRT_UART0, > > VIRT_VIRTIO, > > VIRT_FW_CFG, > > + VIRT_RPMI_SHMEM, > > + VIRT_RPMI_DOORBELL, > > VIRT_IMSIC_M, > > VIRT_IMSIC_S, > > VIRT_FLASH, >