On 9/8/2026 7:40 AM, Andrew Jones wrote:
On Fri, Sep 04, 2026 at 04:56:08PM -0300, Daniel Henrique Barboza wrote:
The RISC-V Server Platform specification [1] defines a standardized set
of hardware and software capabilities, that portable system software,
such as OS and hypervisors can rely on being present in a RISC-V server
platform.

The main features included in this emulation are:

- Based on riscv virt machine type;
- A new memory map as close as virt machine as possible;
- An always present IOMMU platform device (riscv-iommu-sys) that uses
   IRQs 36 to 39, one IRQ for queue, similar to the 'virt' board;
- AIA;
- PCIe AHCI;
- PCIe NIC;
- No virtio device;
- No fw_cfg device;
- No ACPI table provided;
- Only minimal device tree nodes;
- a platform bus for TPM support.

A note about TPM support:  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 [2].  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:

- 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://github.com/riscv-non-isa/riscv-server-platform
[2] https://qemu-project.gitlab.io/qemu/specs/tpm.html

Signed-off-by: Daniel Henrique Barboza <[email protected]>
Reviewed-by: Nutty Liu <[email protected]>
Reviewed-by: Chao Liu <[email protected]>
---
  configs/devices/riscv64-softmmu/default.mak |   1 +
  hw/riscv/Kconfig                            |  16 +
  hw/riscv/meson.build                        |   1 +
  hw/riscv/server_platform_ref.c              | 769 ++++++++++++++++++++
  4 files changed, 787 insertions(+)
  create mode 100644 hw/riscv/server_platform_ref.c

diff --git a/configs/devices/riscv64-softmmu/default.mak 
b/configs/devices/riscv64-softmmu/default.mak
index a8e4d0ab33..ae3f62e2d4 100644
--- a/configs/devices/riscv64-softmmu/default.mak
+++ b/configs/devices/riscv64-softmmu/default.mak
@@ -9,6 +9,7 @@
  # CONFIG_SIFIVE_E=n
  # CONFIG_SIFIVE_U=n
  # CONFIG_RISCV_VIRT=n
+# CONFIG_RISCV_SERVER_PLATFORM_REF=n
  # CONFIG_MICROCHIP_PFSOC=n
  # CONFIG_SHAKTI_C=n
  # CONFIG_XIANGSHAN_KUNMINGHU=n
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index d06ac26648..da59eb2155 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -69,6 +69,22 @@ config RISCV_VIRT
      select ACPI
      select ACPI_PCI
+config RISCV_SERVER_PLATFORM_REF
+    bool
+    default y
+    depends on RISCV64
+    imply TPM_TIS_SYSBUS
+    select RISCV_NUMA
+    select GOLDFISH_RTC
+    select PCI
+    select PCI_EXPRESS_GENERIC_BRIDGE
+    select PFLASH_CFI01
+    select SERIAL
+    select RISCV_ACLINT
+    select RISCV_APLIC
+    select RISCV_IMSIC
+    select RISCV_IOMMU
+
  config SHAKTI_C
      bool
      default y
diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build
index 7aa3c1578d..cc5a019f7c 100644
--- a/hw/riscv/meson.build
+++ b/hw/riscv/meson.build
@@ -7,6 +7,7 @@ riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: 
files('numa.c'))
  riscv_ss.add(files('riscv_hart.c'))
  riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c'))
  riscv_ss.add(when: 'CONFIG_RISCV_VIRT', if_true: files('virt.c'))
+riscv_ss.add(when: 'CONFIG_RISCV_SERVER_PLATFORM_REF', if_true: 
files('server_platform_ref.c'))
  riscv_ss.add(when: 'CONFIG_SHAKTI_C', if_true: files('shakti_c.c'))
  riscv_ss.add(when: 'CONFIG_SIFIVE_E', if_true: files('sifive_e.c'))
  riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u.c'))
diff --git a/hw/riscv/server_platform_ref.c b/hw/riscv/server_platform_ref.c
new file mode 100644
index 0000000000..cc74bf06a1
--- /dev/null
+++ b/hw/riscv/server_platform_ref.c
@@ -0,0 +1,769 @@
+/*
+ * QEMU RISC-V Server Platform Reference Board (riscv-server-ref)
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qemu/error-report.h"
+#include "qemu/guest-random.h"
+#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"
+#include "hw/char/serial.h"
+#include "hw/block/flash.h"
+#include "hw/ide/pci.h"
+#include "hw/ide/ahci-pci.h"
+#include "hw/pci/pci.h"
+#include "hw/pci-host/gpex.h"
+#include "hw/core/sysbus-fdt.h"
+#include "hw/riscv/riscv_hart.h"
+#include "hw/riscv/boot.h"
+#include "hw/riscv/device-common.h"
+#include "hw/riscv/fdt-common.h"
+#include "hw/riscv/numa.h"
+#include "hw/riscv/iommu.h"
+#include "hw/riscv/riscv-iommu.h"
+#include "hw/riscv/riscv-iommu-bits.h"
+#include "hw/intc/riscv_aclint.h"
+#include "hw/intc/riscv_aplic.h"
+#include "hw/intc/riscv_imsic.h"
+#include "chardev/char.h"
+#include "hw/char/serial-mm.h"
+#include "system/device_tree.h"
+#include "system/runstate.h"
+#include "system/system.h"
+#include "system/kvm.h"
+#include "system/tcg.h"
+#include "kvm/kvm_riscv.h"
+#include "system/tpm.h"
+#include "system/qtest.h"
+#include "target/riscv/cpu.h"
+#include "net/net.h"
+
+#include "aia.h"
+
+#define RVSERVER_CPUS_MAX_BITS             9
+#define RVSERVER_CPUS_MAX                  (1 << RVSERVER_CPUS_MAX_BITS)
+#define RVSERVER_SOCKETS_MAX_BITS          2
+#define RVSERVER_SOCKETS_MAX               (1 << RVSERVER_SOCKETS_MAX_BITS)
+
+#define RVSERVER_IRQCHIP_NUM_MSIS 255
+#define RVSERVER_IRQCHIP_NUM_SOURCES 96
+#define RVSERVER_IRQCHIP_NUM_PRIO_BITS 3
+#define RVSERVER_IRQCHIP_MAX_GUESTS_BITS 3
+#define RVSERVER_IRQCHIP_MAX_GUESTS \
+    ((1U << RVSERVER_IRQCHIP_MAX_GUESTS_BITS) - 1U)

The server-soc spec (which the server platform spec depends on) says we
need a minimum of 5 VS-mode interrupt files (IIC_040). That does require
three bits, but we could set RVSERVER_IRQCHIP_MAX_GUESTS to 5 in order
to set the minimum (which is our usual approach). Doing that would both
keep our config minimized and allow testing of sparse imsic topologies
by default. And aia_guests is still configurable on the command line for
those that want to configure more.

Fair enough.  I'll set RVSERVER_IRQCHIP_MAX_GUESTS to 5.


+
+#define NUM_SATA_PORTS  6

[...]

+static void rvserver_ref_machine_instance_init(Object *obj)
+{
+    RISCVServerRefMachineState *s = RISCV_SERVER_REF_MACHINE(obj);
+
+    s->flash[0] = riscv_flash_create(OBJECT(s), "riscv-server-ref.flash0",
+                                        "pflash0", RVSERVER_FLASH_SECTOR_SIZE);
+    s->flash[1] = riscv_flash_create(OBJECT(s), "riscv-server-ref.flash1",
+                                        "pflash1", RVSERVER_FLASH_SECTOR_SIZE);

More whitespace issues here. Might want to double check whole file with
some tool.

I believe you caugh every single one of them.  Would be nice to have a 'lint' 
like
script to check for this kind of stuff though.


Thanks,
Daniel


Reply via email to