On Thu, Jun 11, 2026 at 7:44 AM Daniel Henrique Barboza <[email protected]> wrote: > > The RISC-V Server Platform spec requires a TPM device. TPM devices in > QEMU comes usually in two flavors: emulated or passthrough. A > passthrough device requires a host TPM device that the QEMU process can > borrow and it's usually coupled with KVM acceleration. > > To use the TPM emulator we'll need help from an external TPM emulator > called swtpm. More info can be found in [1]. For our purposes this is > a process that, if running Ubuntu, can be installed via 'swtpm' package. > We'll go back to it shortly. > > For now, adding support for the emulated TPM device 'tpm-tis' (other TPM > flavors might work as well, 'tpm-tis' is the one tested with this work) > requires a platform bus. Adding a platform bus will open the door for > more devices to be added in the board. This is ok - a reference board > isn't a restricted board and users are free to add devices at their > leisure. > > Here's how to use tpm-tis with the riscv-server-ref board after applying > this patch: > > - in a separated shell/term run 'swtpm' (--log is optional): > > $ mkdir /tmp/mytpm1 > $ swtpm socket --tpmstate dir=/tmp/mytpm1 \ > --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ > --tpm2 \ > --log level=20 > > Then start QEMU with: > > $ qemu-system-riscv64 -M riscv-server-ref (...) \ > -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ > -tpmdev emulator,id=tpm0,chardev=chrtpm\ > -device tpm-tis-device,tpmdev=tpm0 > > [1] https://qemu-project.gitlab.io/qemu/specs/tpm.html > > Signed-off-by: Daniel Henrique Barboza <[email protected]>
Reviewed-by: Alistair Francis <[email protected]> Alistair > --- > hw/riscv/Kconfig | 1 + > hw/riscv/server_platform_ref.c | 92 +++++++++++++++++++++++++++++++++- > 2 files changed, 91 insertions(+), 2 deletions(-) > > diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig > index 1807c423ff..d3912cbb1e 100644 > --- a/hw/riscv/Kconfig > +++ b/hw/riscv/Kconfig > @@ -73,6 +73,7 @@ config RISCV_SERVER_PLATFORM_REF > bool > default y > depends on RISCV64 > + imply TPM_TIS_SYSBUS > select RISCV_NUMA > select GOLDFISH_RTC > select PCI > diff --git a/hw/riscv/server_platform_ref.c b/hw/riscv/server_platform_ref.c > index 7e626c6eb7..790d9861f3 100644 > --- a/hw/riscv/server_platform_ref.c > +++ b/hw/riscv/server_platform_ref.c > @@ -14,6 +14,7 @@ > #include "qapi/error.h" > #include "qapi/qapi-visit-common.h" > #include "hw/core/boards.h" > +#include "hw/core/platform-bus.h" > #include "hw/core/loader.h" > #include "hw/core/sysbus.h" > #include "hw/core/qdev-properties.h" > @@ -39,6 +40,7 @@ > #include "system/runstate.h" > #include "system/system.h" > #include "system/tcg.h" > +#include "system/tpm.h" > #include "system/qtest.h" > #include "target/riscv/cpu.h" > #include "target/riscv/pmu.h" > @@ -72,6 +74,8 @@ > #define SYSCON_RESET 0x1 > #define SYSCON_POWEROFF 0x2 > > +#define RVSERVER_PLATFORM_BUS_NUM_IRQS 8 > + > #define TYPE_RISCV_SERVER_REF_MACHINE MACHINE_TYPE_NAME("riscv-server-ref") > OBJECT_DECLARE_SIMPLE_TYPE(RISCVServerRefMachineState, > RISCV_SERVER_REF_MACHINE) > > @@ -88,6 +92,8 @@ struct RISCVServerRefMachineState { > int fdt_size; > int aia_guests; > const MemMapEntry *memmap; > + > + DeviceState *platform_bus_dev; > }; > > enum { > @@ -106,6 +112,7 @@ enum { > RVSERVER_DRAM, > RVSERVER_PCIE_MMIO, > RVSERVER_PCIE_PIO, > + RVSERVER_PLATFORM_BUS, > RVSERVER_PCIE_ECAM, > RVSERVER_PCIE_MMIO_HIGH > }; > @@ -114,7 +121,8 @@ enum { > RVSERVER_UART0_IRQ = 10, > RVSERVER_RTC_IRQ = 11, > RVSERVER_PCIE_IRQ = 0x20, /* 32 to 35 */ > - IOMMU_SYS_IRQ = 0x24 /* 36 to 39 */ > + IOMMU_SYS_IRQ = 0x24, /* 36 to 39 */ > + RVSERVER_PLATFORM_BUS_IRQ = 40, /* 40 to 48 */ > }; > > /* > @@ -147,6 +155,7 @@ static const MemMapEntry rvserver_ref_memmap[] = { > [RVSERVER_IOMMU_SYS] = { 0x102000, 0x1000 }, > [RVSERVER_ACLINT] = { 0x2000000, 0x10000 }, > [RVSERVER_PCIE_PIO] = { 0x3000000, 0x10000 }, > + [RVSERVER_PLATFORM_BUS] = { 0x4000000, 0x2000000 }, > [RVSERVER_APLIC_M] = { 0xc000000, APLIC_SIZE(RVSERVER_CPUS_MAX) > }, > [RVSERVER_APLIC_S] = { 0xd000000, APLIC_SIZE(RVSERVER_CPUS_MAX) > }, > [RVSERVER_UART0] = { 0x10000000, 0x100 }, > @@ -214,6 +223,34 @@ static void > rvserver_flash_maps(RISCVServerRefMachineState *s, > rvserver_flash_map(s->flash[1], flashbase + flashsize, flashsize, > sysmem); > } > > +static void create_platform_bus(RISCVServerRefMachineState *s, > + DeviceState *irqchip) > +{ > + DeviceState *dev; > + SysBusDevice *sysbus; > + int i; > + MemoryRegion *sysmem = get_system_memory(); > + > + dev = qdev_new(TYPE_PLATFORM_BUS_DEVICE); > + dev->id = g_strdup(TYPE_PLATFORM_BUS_DEVICE); > + qdev_prop_set_uint32(dev, "num_irqs", RVSERVER_PLATFORM_BUS_NUM_IRQS); > + qdev_prop_set_uint32(dev, "mmio_size", > + s->memmap[RVSERVER_PLATFORM_BUS].size); > + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); > + > + s->platform_bus_dev = dev; > + > + sysbus = SYS_BUS_DEVICE(dev); > + for (i = 0; i < RVSERVER_PLATFORM_BUS_NUM_IRQS; i++) { > + int irq = RVSERVER_PLATFORM_BUS_IRQ + i; > + sysbus_connect_irq(sysbus, i, qdev_get_gpio_in(irqchip, irq)); > + } > + > + memory_region_add_subregion(sysmem, > + s->memmap[RVSERVER_PLATFORM_BUS].base, > + sysbus_mmio_get_region(sysbus, 0)); > +} > + > static void create_pcie_irq_map(RISCVServerRefMachineState *s, > void *fdt, char *nodename, > uint32_t irqchip_phandle) > @@ -585,6 +622,16 @@ static void > create_fdt_socket_aplic(RISCVServerRefMachineState *s, > aplic_s_phandle, 0, > false, num_harts); > > + if (socket == 0) { > + g_autofree char *aplic_name = fdt_get_aplic_nodename(aplic_addr); > + MachineState *ms = MACHINE(s); > + > + platform_bus_add_all_fdt_nodes(ms->fdt, aplic_name, > + s->memmap[RVSERVER_PLATFORM_BUS].base, > + s->memmap[RVSERVER_PLATFORM_BUS].size, > + RVSERVER_PLATFORM_BUS_IRQ); > + } > + > aplic_phandles[socket] = aplic_s_phandle; > } > > @@ -1265,6 +1312,8 @@ static void rvserver_ref_machine_init(MachineState > *machine) > > gpex_pcie_init(system_memory, pcie_irqchip, s); > > + create_platform_bus(s, mmio_irqchip); > + > serial_mm_init(system_memory, memmap[RVSERVER_UART0].base, > 0, qdev_get_gpio_in(mmio_irqchip, RVSERVER_UART0_IRQ), 399193, > serial_hd(0), DEVICE_LITTLE_ENDIAN); > @@ -1341,10 +1390,38 @@ static void rvserver_ref_set_aia_guests(Object *obj, > const char *val, > } > } > > +static HotplugHandler *rvserver_machine_get_hotplug_handler(MachineState *ms, > + DeviceState *dev) > +{ > + MachineClass *mc = MACHINE_GET_CLASS(ms); > + > + if (device_is_dynamic_sysbus(mc, dev)) { > + return HOTPLUG_HANDLER(ms); > + } > + > + return NULL; > +} > + > +static void rvserver_machine_device_plug_cb(HotplugHandler *hotplug_dev, > + DeviceState *dev, Error **errp) > +{ > + RISCVServerRefMachineState *s = RISCV_SERVER_REF_MACHINE(hotplug_dev); > + > + if (s->platform_bus_dev) { > + MachineClass *mc = MACHINE_GET_CLASS(s); > + > + if (device_is_dynamic_sysbus(mc, dev)) { > + > platform_bus_link_device(PLATFORM_BUS_DEVICE(s->platform_bus_dev), > + SYS_BUS_DEVICE(dev)); > + } > + } > +} > + > static void rvserver_ref_machine_class_init(ObjectClass *oc, const void > *data) > { > char str[128]; > MachineClass *mc = MACHINE_CLASS(oc); > + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); > static const char * const valid_cpu_types[] = { > TYPE_RISCV_CPU_RVSERVER_REF, > }; > @@ -1370,6 +1447,13 @@ static void > rvserver_ref_machine_class_init(ObjectClass *oc, const void *data) > sprintf(str, "Set number of guest MMIO pages for AIA IMSIC. Valid value " > "should be between 0 and %d.", RVSERVER_IRQCHIP_MAX_GUESTS); > object_class_property_set_description(oc, "aia-guests", str); > + > + assert(!mc->get_hotplug_handler); > + mc->get_hotplug_handler = rvserver_machine_get_hotplug_handler; > + hc->plug = rvserver_machine_device_plug_cb; > +#ifdef CONFIG_TPM > + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS); > +#endif > } > > static const TypeInfo rvserver_ref_typeinfo = { > @@ -1378,7 +1462,11 @@ static const TypeInfo rvserver_ref_typeinfo = { > .class_init = rvserver_ref_machine_class_init, > .instance_init = rvserver_ref_machine_instance_init, > .instance_size = sizeof(RISCVServerRefMachineState), > - .interfaces = riscv64_machine_interfaces, > + .interfaces = (const InterfaceInfo[]) { > + { TYPE_HOTPLUG_HANDLER }, > + { TYPE_TARGET_RISCV64_MACHINE }, > + { } > + }, > }; > > static void rvserver_ref_init_register_types(void) > -- > 2.43.0 > >
