On Wed, Sep 09, 2026 at 06:07:53PM -0300, Daniel Henrique Barboza wrote:
> 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

This needs to select SERIAL_MM rather than SERIAL, since the machine calls
serial_mm_init(). It also directly uses the platform bus, so it needs

    select PLATFORM_BUS

The machine also creates an ICH9 AHCI controller, so keeping it would require
selecting AHCI_ICH9.

However, SATA is optional for Server Platform v1.0, so I suggest dropping the
default ICH9 AHCI controller instead. That would also remove the IDE/AHCI
includes, NUM_SATA_PORTS, the AHCI-specific state, and its initialization.
The base machine would then have no default storage controller, and users
could add NVMe explicitly when needed.

Likewise, networking hardware is optional, so I suggest dropping the e1000e
default NIC. pci_init_nic_devices() may remain for explicit -nic requests.

To make suitable optional devices such as NVMe available, I suggest

    imply PCIE_DEVICES

rather than the broader PCI_DEVICES set.

> +#include "system/kvm.h"
> +#include "system/qtest.h"
> +#include "system/tcg.h"
> +#include "kvm/kvm_riscv.h"
> +#include "system/tpm.h"
> +#include "system/qtest.h"

Duplicate system/qtest.h include.

> +#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)
> +#define RVSERVER_IRQCHIP_DEFAULT_AIA_GUESTS 5

nit: Please align these definitions with the related definitions above.
Also, the two nearby #error strings have "accomodate" rather than
"accommodate".

> +enum {
> +    RVSERVER_UART0_IRQ = 10,
> +    RVSERVER_RTC_IRQ = 11,
> +    RVSERVER_PCIE_IRQ = 32, /* 32 to 35 */
> +    IOMMU_SYS_IRQ = 36, /* 36 to 39 */
> +    RVSERVER_PLATFORM_BUS_IRQ = 40, /* 40 to 48 */
> +};

RVSERVER_PLATFORM_BUS_NUM_IRQS is 8, so this should say 40 to 47. Please
also align the assignments.

> +static const MemMapEntry rvserver_ref_memmap[] = {
> +    [RVSERVER_DEBUG] =          {        0x0,         0x100 },

RVSERVER_DEBUG does not appear to be used.

> +        riscv_aclint_mtimer_create(memmap[RVSERVER_ACLINT].base +
> +                i * RISCV_ACLINT_DEFAULT_MTIMER_SIZE,
> +                RISCV_ACLINT_DEFAULT_MTIMER_SIZE,
> +                base_hartid, hart_count,
> +                RISCV_ACLINT_DEFAULT_MTIMECMP,
> +                RISCV_ACLINT_DEFAULT_MTIME,
> +                RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true);

Server SoC v1.0 CTI_010 requires the time CSR to count in units of 1 ns,
so we should define a machine-specific 1 GHz timebase rather than using
the 10 MHz virt default, for example

    #define RVSERVER_ACLINT_TIMEBASE_FREQ 1000000000

and use RVSERVER_ACLINT_TIMEBASE_FREQ in this call. The CPU FDT
timebase-frequency property should use

    kvm_enabled() ? kvm_riscv_get_timebase_frequency(&s->soc->harts[0]) :
                    RVSERVER_ACLINT_TIMEBASE_FREQ

> +    if (!rvserver_aclint_allowed()) {
> +        error_report("'aclint' is only available with TCG acceleration");
> +        exit(1);
> +    }

This makes the machine TCG/qtest only. We can follow virt's support of KVM
to enable it. The documentation can state that a conformant guest requires
a conformant host, while allowing nonconformant hosts to be used for
functional KVM testing.

> +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);

virt has an instance finalizer which unreferences either flash device when
initialization fails before realization. This machine should have the same
cleanup and set instance_finalize in its TypeInfo.

> +    static const char * const valid_cpu_types[] = {
> +        TYPE_RISCV_CPU_RVSERVER_REF,
> +    };

This needs a NULL terminator. MachineClass.valid_cpu_types is walked until
NULL. For example, testing this with "-cpu max" printed:

    The valid models are: riscv-server-ref, (null), (null)

KVM also needs TYPE_RISCV_CPU_HOST in the valid CPU types.

Thanks,
drew

Reply via email to