* RISC-V: Add CVA6 machine
@ 2025-06-09 13:17 Ben Dooks
2025-06-09 13:17 ` [PATCH v3 1/3] hw/riscv: add " Ben Dooks
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Ben Dooks @ 2025-06-09 13:17 UTC (permalink / raw)
To: nazar.kazakov, joseph.baker, fran.redondo, lawrence.hunter,
liwei1518, dbarboza, zhiwei_liu, alistair.francis, qemu-riscv
Cc: ben.dooks, qemu-devel
Add the CVA6 (the corev_apu from the fpga) model from
https://github.com/openhwgroup/cva6
Tree at:
https://gitlab.com/CodethinkLabs/qemu/-/tree/bjdooks/cva6-send-8jun2025?ref_type=heads
Fixes:
v3:
- fix missing file source
- set 64bit only for now
v2:
- rebased and fixed whitespace issues
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH v3 1/3] hw/riscv: add CVA6 machine 2025-06-09 13:17 RISC-V: Add CVA6 machine Ben Dooks @ 2025-06-09 13:17 ` Ben Dooks 2025-06-09 23:29 ` Alistair Francis 2025-06-09 13:17 ` [PATCH v3 2/3] target/riscv: add cva6 core type Ben Dooks 2025-06-09 13:17 ` [PATCH v3 3/3] hw/riscv: set cva6 to use TYPE_RISCV_CPU_CVA6 Ben Dooks 2 siblings, 1 reply; 7+ messages in thread From: Ben Dooks @ 2025-06-09 13:17 UTC (permalink / raw) To: nazar.kazakov, joseph.baker, fran.redondo, lawrence.hunter, liwei1518, dbarboza, zhiwei_liu, alistair.francis, qemu-riscv Cc: ben.dooks, qemu-devel Add a (currently Genesy2 based) CVA6 machine. Has SPI and UART, the GPIO and Ethernet are currently black-holed as there is no hardware model for them (lowRISC ethernet and Xilinx GPIO) Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> --- v3: - fix missed plic comment - made 64bit only for now v2: - whitespace fixes - use g_autofree on plic v1: - squashed in fixes for sd-card and new qemu init - move to spdx for cva6 machine - code cleanups missed in first review updated plic regmap make cva6 64bit for now --- hw/riscv/Kconfig | 11 ++ hw/riscv/cva6.c | 229 ++++++++++++++++++++++++++++++++++++++++ hw/riscv/meson.build | 1 + include/hw/riscv/cva6.h | 88 +++++++++++++++ 4 files changed, 329 insertions(+) create mode 100644 hw/riscv/cva6.c create mode 100644 include/hw/riscv/cva6.h diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index e6a0ac1fa1..033e29dab1 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -9,6 +9,17 @@ config IBEX # RISC-V machines in alphabetical order +# technically it might be possible to build cva6 32bit +config CVA6 + bool + default y + depends on RISCV64 + select DEVICE_TREE + select SIFIVE_PLIC + select XILINX_SPI + select RISCV_ACLINT + select UNIMP + config MICROCHIP_PFSOC bool default y diff --git a/hw/riscv/cva6.c b/hw/riscv/cva6.c new file mode 100644 index 0000000000..3adfa8b5cc --- /dev/null +++ b/hw/riscv/cva6.c @@ -0,0 +1,229 @@ +/* + * QEMU RISC-V Board for OpenHW CVA6 SoC + * + * Copyright (c) 2025 Codethink Ltd + * Ben Dooks <ben.dooks@codethink.co.uk> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "qapi/visitor.h" +#include "hw/boards.h" +#include "hw/irq.h" +#include "hw/loader.h" +#include "hw/sysbus.h" +#include "hw/misc/unimp.h" + +#include "hw/sd/sd.h" +#include "hw/ssi/ssi.h" + +#include "hw/riscv/cva6.h" +#include "hw/riscv/boot.h" +#include "hw/intc/riscv_aclint.h" + +#include "system/system.h" + +#include <libfdt.h> + +#define CVA6_ROM_BASE 0x10000 + +static const MemMapEntry cva6_memmap[] = { + [CVA6_DEBUG] = { 0x0000000, 0x1000 }, + [CVA6_ROM] = { CVA6_ROM_BASE, 0x10000 }, + [CVA6_CLINT] = { 0x2000000, 0xC0000 }, + [CVA6_PLIC] = { 0xC000000, 0x4000000 }, + [CVA6_UART] = { 0x10000000, 0x1000 }, + [CVA6_TIMER] = { 0x18000000, 0x10000 }, + [CVA6_SPI] = { 0x20000000, 0x800000 }, + [CVA6_ETHERNET] = { 0x30000000, 0x10000 }, + [CVA6_GPIO] = { 0x40000000, 0x1000 }, + [CVA6_DRAM] = { 0x80000000, 0x40000000 }, +}; + +static void cva6_machine_init(MachineState *machine) +{ + MachineClass *mc = MACHINE_GET_CLASS(machine); + MemoryRegion *sys_mem = get_system_memory(); + hwaddr dram_addr = cva6_memmap[CVA6_DRAM].base; + CVA6State *s = CVA6_MACHINE(machine); + RISCVBootInfo boot_info; + + object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_CVA6); + qdev_realize(DEVICE(&s->soc), NULL, &error_fatal); + + if (machine->ram_size > mc->default_ram_size) { + error_report("RAM size is too big for DRAM area"); + exit(EXIT_FAILURE); + } + + memory_region_add_subregion(sys_mem, dram_addr, machine->ram); + riscv_boot_info_init(&boot_info, &s->soc.cpus); + + if (machine->firmware) { + hwaddr firmware_load_addr = cva6_memmap[CVA6_ROM].base; + riscv_load_firmware(machine->firmware, &firmware_load_addr, NULL); + } + + if (machine->kernel_filename) { + /* note - we've not tested just loading the kernel w/o uboot */ + riscv_load_kernel(machine, &boot_info, dram_addr, false, NULL); + } + +} + +static void cva6_machine_class_init(ObjectClass *oc, const void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "RISC-V board for CVA6"; + mc->init = cva6_machine_init; + mc->max_cpus = 1; + mc->default_ram_id = "cva6.ram"; + /* start with "max" cpu type until we sort out CVA6 type */ + mc->default_cpu_type = TYPE_RISCV_CPU_MAX; + mc->default_ram_size = cva6_memmap[CVA6_DRAM].size; +}; + +static void cva6_soc_init(Object *obj) +{ + CVA6SoCState *s = RISCV_CVA6(obj); + + object_initialize_child(obj, "cpus", &s->cpus, TYPE_RISCV_HART_ARRAY); +} + +static void cva6_add_spi(CVA6SoCState *s, const MemMapEntry *map) +{ + DriveInfo *dinfo; + BlockBackend *blk; + DeviceState *card_dev; + qemu_irq sd_cs; + DeviceState *sddev; + SysBusDevice *busdev; + DeviceState *spi_dev; + SSIBus *spi; + + spi_dev = qdev_new("xlnx.xps-spi"); + qdev_prop_set_uint8(spi_dev, "num-ss-bits", 1); + qdev_prop_set_string(spi_dev, "endianness", "little"); + + busdev = SYS_BUS_DEVICE(spi_dev); + sysbus_realize_and_unref(busdev, &error_fatal); + sysbus_mmio_map(busdev, 0, map->base); + sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(DEVICE(s->plic), CVA6_SPI_IRQ)); + + spi = (SSIBus *)qdev_get_child_bus(spi_dev, "spi"); + + sddev = ssi_create_peripheral(spi, "ssi-sd"); + sd_cs = qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0); + sysbus_connect_irq(busdev, 1, sd_cs); + + dinfo = drive_get(IF_SD, 0, 0); + blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; + card_dev = qdev_new(TYPE_SD_CARD_SPI); + qdev_prop_set_drive_err(card_dev, "drive", blk, &error_fatal); + + qdev_realize_and_unref(card_dev, qdev_get_child_bus(sddev, "sd-bus"), &error_fatal); +} + +static void not_implemented(const char *name, const MemMapEntry *map) +{ + create_unimplemented_device(name, map->base, map->size); +} + +static void cva6_soc_realize(DeviceState *dev_soc, Error **errp) +{ + MemoryRegion *system_memory = get_system_memory(); + MachineState *ms = MACHINE(qdev_get_machine()); + CVA6SoCState *s = RISCV_CVA6(dev_soc); + const MemMapEntry *memmap = cva6_memmap; + MemoryRegion *rom = g_new(MemoryRegion, 1); + g_autofree char *plic_hart_config; + + object_property_set_str(OBJECT(&s->cpus), "cpu-type", ms->cpu_type, + &error_abort); + object_property_set_int(OBJECT(&s->cpus), "num-harts", ms->smp.cpus, + &error_abort); + object_property_set_int(OBJECT(&s->cpus), "resetvec", CVA6_ROM_BASE, + &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_fatal); + + /* boot rom */ + memory_region_init_rom(rom, OBJECT(dev_soc), "riscv.cva6.bootrom", + memmap[CVA6_ROM].size, &error_fatal); + memory_region_add_subregion(system_memory, memmap[CVA6_ROM].base, + rom); + + /* create PLIC hart topology configuration string */ + plic_hart_config = riscv_plic_hart_config_string(ms->smp.cpus); + + /* MMIO */ + s->plic = sifive_plic_create(memmap[CVA6_PLIC].base, + plic_hart_config, ms->smp.cpus, 0, + CVA6_PLIC_NUM_SOURCES, + CVA6_PLIC_NUM_PRIORITIES, + CVA6_PLIC_PRIORITY_BASE, + CVA6_PLIC_PENDING_BASE, + CVA6_PLIC_ENABLE_BASE, + CVA6_PLIC_ENABLE_STRIDE, + CVA6_PLIC_CONTEXT_BASE, + CVA6_PLIC_CONTEXT_STRIDE, + memmap[CVA6_PLIC].size); + + riscv_aclint_swi_create(memmap[CVA6_CLINT].base, 0, + ms->smp.cpus, false); + + riscv_aclint_mtimer_create( + memmap[CVA6_CLINT].base + RISCV_ACLINT_SWI_SIZE, + RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus, + RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME, + CLINT_TIMEBASE_FREQ, true); + + /* something in cva6-sdk uboot seems to prod the debug + * unit by accident, so make it not implemented */ + not_implemented("debug", &memmap[CVA6_DEBUG]); + + /* 16550 uart, one 32bit register per 32bit word */ + + serial_mm_init(system_memory, memmap[CVA6_UART].base, 2, + qdev_get_gpio_in(DEVICE(s->plic), CVA6_UART_IRQ), + 50*1000*10000, + serial_hd(0), DEVICE_LITTLE_ENDIAN); + + /* just unimplement the timers, network and gpio here for now. + * no-one seems to be using the apb timer block anyway*/ + not_implemented("net", &memmap[CVA6_ETHERNET]); + not_implemented("gpio", &memmap[CVA6_GPIO]); + not_implemented("timer", &memmap[CVA6_TIMER]); + + /* connect xilinx spi block here */ + cva6_add_spi(s, &memmap[CVA6_SPI]); +} + +static void cva6_soc_class_init(ObjectClass *oc, const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = cva6_soc_realize; + dc->user_creatable = false; +}; + +static const TypeInfo cva6_types[] = { + { + .name = TYPE_RISCV_CVA6, + .parent = TYPE_DEVICE, + .instance_size = sizeof(CVA6SoCState), + .instance_init = cva6_soc_init, + .class_init = cva6_soc_class_init, + }, { + .name = TYPE_CVA6_MACHINE, + .parent = TYPE_MACHINE, + .instance_size = sizeof(CVA6State), + .class_init = cva6_machine_class_init, + } +}; + +DEFINE_TYPES(cva6_types) diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index c22f3a7216..a32fffab63 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -2,6 +2,7 @@ riscv_ss = ss.source_set() riscv_ss.add(files('boot.c')) riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: files('numa.c')) riscv_ss.add(files('riscv_hart.c')) +riscv_ss.add(when: 'CONFIG_CVA6', if_true: files('cva6.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_SHAKTI_C', if_true: files('shakti_c.c')) diff --git a/include/hw/riscv/cva6.h b/include/hw/riscv/cva6.h new file mode 100644 index 0000000000..48e0979a0a --- /dev/null +++ b/include/hw/riscv/cva6.h @@ -0,0 +1,88 @@ +/* + * QEMU RISC-V Board for OpenHW CVA6 SoC + * https://github.com/openhwgroup/cva6/tree/master/corev_apu + * + * Copyright (c) 2025 Codethink Ltd + * Ben Dooks <ben.dooks@codethink.co.uk> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_CVA6_H +#define HW_CVA6_H + +#include "hw/riscv/riscv_hart.h" +#include "hw/intc/sifive_plic.h" +#include "hw/char/serial-mm.h" + +#include "hw/boards.h" +#include "hw/sysbus.h" +#include "qom/object.h" + +#define TYPE_RISCV_CVA6 "riscv.cva6.soc" +OBJECT_DECLARE_SIMPLE_TYPE(CVA6SoCState, RISCV_CVA6) + +typedef struct CVA6SoCState { + /*< private >*/ + DeviceState parent_obj; + + /*< public >*/ + RISCVHartArrayState cpus; + DeviceState *plic; + MemoryRegion rom; + + uint32_t resetvec; +} CVA6SoCState; + +#define TYPE_CVA6_MACHINE MACHINE_TYPE_NAME("cva6") +OBJECT_DECLARE_SIMPLE_TYPE(CVA6State, CVA6_MACHINE) + +typedef struct CVA6State { + /*< private >*/ + MachineState parent_obj; + + /*< public >*/ + CVA6SoCState soc; +} +CVA6State; + +enum { + CVA6_DEBUG, + CVA6_ROM, + CVA6_CLINT, + CVA6_PLIC, + CVA6_UART, + CVA6_TIMER, + CVA6_SPI, + CVA6_ETHERNET, + CVA6_GPIO, + CVA6_DRAM, +}; + +enum { + CVA6_UART_IRQ = 1, + CVA6_SPI_IRQ = 2, + CVA6_ETH_IRQ = 3, + CVA6_TIMER0_OVF_IRQ = 4, + CVA6_TIMER0_CMP_IRQ = 5, + CVA6_TIMER1_OVF_IRQ = 6, + CVA6_TIMER1_CMP_IRQ = 7, +}; + +#define CLINT_TIMEBASE_FREQ 25000000 + +/* + * plic register interface in corev_apu/rv_plic/rtl/plic_regmap.sv + * https://github.com/pulp-platform/rv_plic/blob/master/rtl/plic_regmap.sv +*/ + +#define CVA6_PLIC_NUM_SOURCES 32 +#define CVA6_PLIC_NUM_PRIORITIES 7 +#define CVA6_PLIC_PRIORITY_BASE 0x0000 +#define CVA6_PLIC_PENDING_BASE 0x1000 +#define CVA6_PLIC_ENABLE_BASE 0x2000 +#define CVA6_PLIC_ENABLE_STRIDE 0x80 +#define CVA6_PLIC_CONTEXT_BASE 0x200000 +#define CVA6_PLIC_CONTEXT_STRIDE 0x1000 + +#endif /* HW_CVA6_H */ -- 2.37.2.352.g3c44437643 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v3 1/3] hw/riscv: add CVA6 machine 2025-06-09 13:17 ` [PATCH v3 1/3] hw/riscv: add " Ben Dooks @ 2025-06-09 23:29 ` Alistair Francis 0 siblings, 0 replies; 7+ messages in thread From: Alistair Francis @ 2025-06-09 23:29 UTC (permalink / raw) To: Ben Dooks Cc: nazar.kazakov, joseph.baker, fran.redondo, lawrence.hunter, liwei1518, dbarboza, zhiwei_liu, alistair.francis, qemu-riscv, qemu-devel On Mon, Jun 9, 2025 at 11:19 PM Ben Dooks <ben.dooks@codethink.co.uk> wrote: > > Add a (currently Genesy2 based) CVA6 machine. > > Has SPI and UART, the GPIO and Ethernet are currently black-holed > as there is no hardware model for them (lowRISC ethernet and Xilinx > GPIO) > > Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> > --- > v3: > - fix missed plic comment > - made 64bit only for now > v2: > - whitespace fixes > - use g_autofree on plic > v1: > - squashed in fixes for sd-card and new qemu init > - move to spdx for cva6 machine > - code cleanups missed in first review > > updated plic regmap > > make cva6 64bit for now > --- > hw/riscv/Kconfig | 11 ++ > hw/riscv/cva6.c | 229 ++++++++++++++++++++++++++++++++++++++++ > hw/riscv/meson.build | 1 + > include/hw/riscv/cva6.h | 88 +++++++++++++++ > 4 files changed, 329 insertions(+) > create mode 100644 hw/riscv/cva6.c > create mode 100644 include/hw/riscv/cva6.h > > diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig > index e6a0ac1fa1..033e29dab1 100644 > --- a/hw/riscv/Kconfig > +++ b/hw/riscv/Kconfig > @@ -9,6 +9,17 @@ config IBEX > > # RISC-V machines in alphabetical order > > +# technically it might be possible to build cva6 32bit > +config CVA6 > + bool > + default y > + depends on RISCV64 > + select DEVICE_TREE > + select SIFIVE_PLIC > + select XILINX_SPI > + select RISCV_ACLINT > + select UNIMP > + > config MICROCHIP_PFSOC > bool > default y > diff --git a/hw/riscv/cva6.c b/hw/riscv/cva6.c > new file mode 100644 > index 0000000000..3adfa8b5cc > --- /dev/null > +++ b/hw/riscv/cva6.c > @@ -0,0 +1,229 @@ > +/* > + * QEMU RISC-V Board for OpenHW CVA6 SoC > + * > + * Copyright (c) 2025 Codethink Ltd > + * Ben Dooks <ben.dooks@codethink.co.uk> > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > + > +#include "qemu/osdep.h" > +#include "qemu/error-report.h" > +#include "qemu/units.h" > +#include "qapi/error.h" > +#include "qapi/visitor.h" > +#include "hw/boards.h" > +#include "hw/irq.h" > +#include "hw/loader.h" > +#include "hw/sysbus.h" > +#include "hw/misc/unimp.h" > + > +#include "hw/sd/sd.h" > +#include "hw/ssi/ssi.h" > + > +#include "hw/riscv/cva6.h" > +#include "hw/riscv/boot.h" > +#include "hw/intc/riscv_aclint.h" > + > +#include "system/system.h" > + > +#include <libfdt.h> > + > +#define CVA6_ROM_BASE 0x10000 > + > +static const MemMapEntry cva6_memmap[] = { > + [CVA6_DEBUG] = { 0x0000000, 0x1000 }, > + [CVA6_ROM] = { CVA6_ROM_BASE, 0x10000 }, > + [CVA6_CLINT] = { 0x2000000, 0xC0000 }, > + [CVA6_PLIC] = { 0xC000000, 0x4000000 }, > + [CVA6_UART] = { 0x10000000, 0x1000 }, > + [CVA6_TIMER] = { 0x18000000, 0x10000 }, > + [CVA6_SPI] = { 0x20000000, 0x800000 }, > + [CVA6_ETHERNET] = { 0x30000000, 0x10000 }, > + [CVA6_GPIO] = { 0x40000000, 0x1000 }, > + [CVA6_DRAM] = { 0x80000000, 0x40000000 }, > +}; > + > +static void cva6_machine_init(MachineState *machine) > +{ > + MachineClass *mc = MACHINE_GET_CLASS(machine); > + MemoryRegion *sys_mem = get_system_memory(); > + hwaddr dram_addr = cva6_memmap[CVA6_DRAM].base; > + CVA6State *s = CVA6_MACHINE(machine); > + RISCVBootInfo boot_info; > + > + object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_CVA6); > + qdev_realize(DEVICE(&s->soc), NULL, &error_fatal); > + > + if (machine->ram_size > mc->default_ram_size) { This should compare against cva6_memmap[CVA6_DRAM].size instead > + error_report("RAM size is too big for DRAM area"); > + exit(EXIT_FAILURE); > + } > + > + memory_region_add_subregion(sys_mem, dram_addr, machine->ram); > + riscv_boot_info_init(&boot_info, &s->soc.cpus); > + > + if (machine->firmware) { > + hwaddr firmware_load_addr = cva6_memmap[CVA6_ROM].base; > + riscv_load_firmware(machine->firmware, &firmware_load_addr, NULL); > + } > + > + if (machine->kernel_filename) { > + /* note - we've not tested just loading the kernel w/o uboot */ I don't think this is a useful comment, users can't see it and it seems prone to becoming stale. If you want you can put something like this in the user documentation (or the wiki page) but it shouldn't be here > + riscv_load_kernel(machine, &boot_info, dram_addr, false, NULL); > + } > + > +} > + > +static void cva6_machine_class_init(ObjectClass *oc, const void *data) > +{ > + MachineClass *mc = MACHINE_CLASS(oc); > + > + mc->desc = "RISC-V board for CVA6"; > + mc->init = cva6_machine_init; > + mc->max_cpus = 1; > + mc->default_ram_id = "cva6.ram"; > + /* start with "max" cpu type until we sort out CVA6 type */ > + mc->default_cpu_type = TYPE_RISCV_CPU_MAX; > + mc->default_ram_size = cva6_memmap[CVA6_DRAM].size; > +}; > + > +static void cva6_soc_init(Object *obj) > +{ > + CVA6SoCState *s = RISCV_CVA6(obj); > + > + object_initialize_child(obj, "cpus", &s->cpus, TYPE_RISCV_HART_ARRAY); > +} > + > +static void cva6_add_spi(CVA6SoCState *s, const MemMapEntry *map) > +{ > + DriveInfo *dinfo; > + BlockBackend *blk; > + DeviceState *card_dev; > + qemu_irq sd_cs; > + DeviceState *sddev; > + SysBusDevice *busdev; > + DeviceState *spi_dev; > + SSIBus *spi; > + > + spi_dev = qdev_new("xlnx.xps-spi"); > + qdev_prop_set_uint8(spi_dev, "num-ss-bits", 1); > + qdev_prop_set_string(spi_dev, "endianness", "little"); > + > + busdev = SYS_BUS_DEVICE(spi_dev); > + sysbus_realize_and_unref(busdev, &error_fatal); > + sysbus_mmio_map(busdev, 0, map->base); > + sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(DEVICE(s->plic), CVA6_SPI_IRQ)); > + > + spi = (SSIBus *)qdev_get_child_bus(spi_dev, "spi"); > + > + sddev = ssi_create_peripheral(spi, "ssi-sd"); > + sd_cs = qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0); > + sysbus_connect_irq(busdev, 1, sd_cs); > + > + dinfo = drive_get(IF_SD, 0, 0); > + blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; > + card_dev = qdev_new(TYPE_SD_CARD_SPI); > + qdev_prop_set_drive_err(card_dev, "drive", blk, &error_fatal); > + > + qdev_realize_and_unref(card_dev, qdev_get_child_bus(sddev, "sd-bus"), &error_fatal); > +} > + > +static void not_implemented(const char *name, const MemMapEntry *map) > +{ > + create_unimplemented_device(name, map->base, map->size); > +} > + > +static void cva6_soc_realize(DeviceState *dev_soc, Error **errp) > +{ > + MemoryRegion *system_memory = get_system_memory(); > + MachineState *ms = MACHINE(qdev_get_machine()); > + CVA6SoCState *s = RISCV_CVA6(dev_soc); > + const MemMapEntry *memmap = cva6_memmap; > + MemoryRegion *rom = g_new(MemoryRegion, 1); > + g_autofree char *plic_hart_config; > + > + object_property_set_str(OBJECT(&s->cpus), "cpu-type", ms->cpu_type, > + &error_abort); > + object_property_set_int(OBJECT(&s->cpus), "num-harts", ms->smp.cpus, > + &error_abort); > + object_property_set_int(OBJECT(&s->cpus), "resetvec", CVA6_ROM_BASE, > + &error_abort); > + sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_fatal); > + > + /* boot rom */ > + memory_region_init_rom(rom, OBJECT(dev_soc), "riscv.cva6.bootrom", > + memmap[CVA6_ROM].size, &error_fatal); > + memory_region_add_subregion(system_memory, memmap[CVA6_ROM].base, > + rom); > + > + /* create PLIC hart topology configuration string */ > + plic_hart_config = riscv_plic_hart_config_string(ms->smp.cpus); > + > + /* MMIO */ > + s->plic = sifive_plic_create(memmap[CVA6_PLIC].base, > + plic_hart_config, ms->smp.cpus, 0, > + CVA6_PLIC_NUM_SOURCES, > + CVA6_PLIC_NUM_PRIORITIES, > + CVA6_PLIC_PRIORITY_BASE, > + CVA6_PLIC_PENDING_BASE, > + CVA6_PLIC_ENABLE_BASE, > + CVA6_PLIC_ENABLE_STRIDE, > + CVA6_PLIC_CONTEXT_BASE, > + CVA6_PLIC_CONTEXT_STRIDE, > + memmap[CVA6_PLIC].size); > + > + riscv_aclint_swi_create(memmap[CVA6_CLINT].base, 0, > + ms->smp.cpus, false); > + > + riscv_aclint_mtimer_create( > + memmap[CVA6_CLINT].base + RISCV_ACLINT_SWI_SIZE, > + RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus, > + RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME, > + CLINT_TIMEBASE_FREQ, true); > + > + /* something in cva6-sdk uboot seems to prod the debug > + * unit by accident, so make it not implemented */ The comment should follow the QEMU code style https://www.qemu.org/docs/master/devel/style.html#comment-style > + not_implemented("debug", &memmap[CVA6_DEBUG]); > + > + /* 16550 uart, one 32bit register per 32bit word */ > + > + serial_mm_init(system_memory, memmap[CVA6_UART].base, 2, > + qdev_get_gpio_in(DEVICE(s->plic), CVA6_UART_IRQ), > + 50*1000*10000, > + serial_hd(0), DEVICE_LITTLE_ENDIAN); > + > + /* just unimplement the timers, network and gpio here for now. > + * no-one seems to be using the apb timer block anyway*/ > + not_implemented("net", &memmap[CVA6_ETHERNET]); > + not_implemented("gpio", &memmap[CVA6_GPIO]); > + not_implemented("timer", &memmap[CVA6_TIMER]); > + > + /* connect xilinx spi block here */ > + cva6_add_spi(s, &memmap[CVA6_SPI]); Is the SPI really part of the SoC? Usually SPI blocks are part of the machine/board. Alistair > +} > + > +static void cva6_soc_class_init(ObjectClass *oc, const void *data) > +{ > + DeviceClass *dc = DEVICE_CLASS(oc); > + > + dc->realize = cva6_soc_realize; > + dc->user_creatable = false; > +}; > + > +static const TypeInfo cva6_types[] = { > + { > + .name = TYPE_RISCV_CVA6, > + .parent = TYPE_DEVICE, > + .instance_size = sizeof(CVA6SoCState), > + .instance_init = cva6_soc_init, > + .class_init = cva6_soc_class_init, > + }, { > + .name = TYPE_CVA6_MACHINE, > + .parent = TYPE_MACHINE, > + .instance_size = sizeof(CVA6State), > + .class_init = cva6_machine_class_init, > + } > +}; > + > +DEFINE_TYPES(cva6_types) > diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build > index c22f3a7216..a32fffab63 100644 > --- a/hw/riscv/meson.build > +++ b/hw/riscv/meson.build > @@ -2,6 +2,7 @@ riscv_ss = ss.source_set() > riscv_ss.add(files('boot.c')) > riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: files('numa.c')) > riscv_ss.add(files('riscv_hart.c')) > +riscv_ss.add(when: 'CONFIG_CVA6', if_true: files('cva6.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_SHAKTI_C', if_true: files('shakti_c.c')) > diff --git a/include/hw/riscv/cva6.h b/include/hw/riscv/cva6.h > new file mode 100644 > index 0000000000..48e0979a0a > --- /dev/null > +++ b/include/hw/riscv/cva6.h > @@ -0,0 +1,88 @@ > +/* > + * QEMU RISC-V Board for OpenHW CVA6 SoC > + * https://github.com/openhwgroup/cva6/tree/master/corev_apu > + * > + * Copyright (c) 2025 Codethink Ltd > + * Ben Dooks <ben.dooks@codethink.co.uk> > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > + > +#ifndef HW_CVA6_H > +#define HW_CVA6_H > + > +#include "hw/riscv/riscv_hart.h" > +#include "hw/intc/sifive_plic.h" > +#include "hw/char/serial-mm.h" > + > +#include "hw/boards.h" > +#include "hw/sysbus.h" > +#include "qom/object.h" > + > +#define TYPE_RISCV_CVA6 "riscv.cva6.soc" > +OBJECT_DECLARE_SIMPLE_TYPE(CVA6SoCState, RISCV_CVA6) > + > +typedef struct CVA6SoCState { > + /*< private >*/ > + DeviceState parent_obj; > + > + /*< public >*/ > + RISCVHartArrayState cpus; > + DeviceState *plic; > + MemoryRegion rom; > + > + uint32_t resetvec; > +} CVA6SoCState; > + > +#define TYPE_CVA6_MACHINE MACHINE_TYPE_NAME("cva6") > +OBJECT_DECLARE_SIMPLE_TYPE(CVA6State, CVA6_MACHINE) > + > +typedef struct CVA6State { > + /*< private >*/ > + MachineState parent_obj; > + > + /*< public >*/ > + CVA6SoCState soc; > +} > +CVA6State; > + > +enum { > + CVA6_DEBUG, > + CVA6_ROM, > + CVA6_CLINT, > + CVA6_PLIC, > + CVA6_UART, > + CVA6_TIMER, > + CVA6_SPI, > + CVA6_ETHERNET, > + CVA6_GPIO, > + CVA6_DRAM, > +}; > + > +enum { > + CVA6_UART_IRQ = 1, > + CVA6_SPI_IRQ = 2, > + CVA6_ETH_IRQ = 3, > + CVA6_TIMER0_OVF_IRQ = 4, > + CVA6_TIMER0_CMP_IRQ = 5, > + CVA6_TIMER1_OVF_IRQ = 6, > + CVA6_TIMER1_CMP_IRQ = 7, > +}; > + > +#define CLINT_TIMEBASE_FREQ 25000000 > + > +/* > + * plic register interface in corev_apu/rv_plic/rtl/plic_regmap.sv > + * https://github.com/pulp-platform/rv_plic/blob/master/rtl/plic_regmap.sv > +*/ > + > +#define CVA6_PLIC_NUM_SOURCES 32 > +#define CVA6_PLIC_NUM_PRIORITIES 7 > +#define CVA6_PLIC_PRIORITY_BASE 0x0000 > +#define CVA6_PLIC_PENDING_BASE 0x1000 > +#define CVA6_PLIC_ENABLE_BASE 0x2000 > +#define CVA6_PLIC_ENABLE_STRIDE 0x80 > +#define CVA6_PLIC_CONTEXT_BASE 0x200000 > +#define CVA6_PLIC_CONTEXT_STRIDE 0x1000 > + > +#endif /* HW_CVA6_H */ > -- > 2.37.2.352.g3c44437643 > > ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 2/3] target/riscv: add cva6 core type 2025-06-09 13:17 RISC-V: Add CVA6 machine Ben Dooks 2025-06-09 13:17 ` [PATCH v3 1/3] hw/riscv: add " Ben Dooks @ 2025-06-09 13:17 ` Ben Dooks 2025-06-09 23:30 ` Alistair Francis 2025-06-09 13:17 ` [PATCH v3 3/3] hw/riscv: set cva6 to use TYPE_RISCV_CPU_CVA6 Ben Dooks 2 siblings, 1 reply; 7+ messages in thread From: Ben Dooks @ 2025-06-09 13:17 UTC (permalink / raw) To: nazar.kazakov, joseph.baker, fran.redondo, lawrence.hunter, liwei1518, dbarboza, zhiwei_liu, alistair.francis, qemu-riscv Cc: ben.dooks, qemu-devel Add TYPE_RISCV_CPU_CVA6 for the CVA6 core Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> --- target/riscv/cpu-qom.h | 1 + target/riscv/cpu.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index 1ee05eb393..3daf75568c 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -34,6 +34,7 @@ #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32") #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64") #define TYPE_RISCV_CPU_BASE128 RISCV_CPU_TYPE_NAME("x-rv128") +#define TYPE_RISCV_CPU_CVA6 RISCV_CPU_TYPE_NAME("cva6") #define TYPE_RISCV_CPU_RV32I RISCV_CPU_TYPE_NAME("rv32i") #define TYPE_RISCV_CPU_RV32E RISCV_CPU_TYPE_NAME("rv32e") #define TYPE_RISCV_CPU_RV64I RISCV_CPU_TYPE_NAME("rv64i") diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 629ac37501..fca45dc9d9 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -3009,6 +3009,17 @@ static const TypeInfo riscv_cpu_type_infos[] = { .misa_mxl_max = MXL_RV64, ), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_CVA6, TYPE_RISCV_VENDOR_CPU, + .misa_ext = RVI | RVM | RVA | RVF | RVD | RVC | RVB | RVS | RVU, + .misa_mxl_max = MXL_RV64, + .cfg.max_satp_mode = VM_1_10_SV39, + .priv_spec = PRIV_VERSION_1_12_0, + .cfg.pmp = true, + .cfg.mmu = true, + .cfg.ext_zifencei = true, + .cfg.ext_zicsr = true, + ), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E51, TYPE_RISCV_CPU_SIFIVE_E, .misa_mxl_max = MXL_RV64 ), -- 2.37.2.352.g3c44437643 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v3 2/3] target/riscv: add cva6 core type 2025-06-09 13:17 ` [PATCH v3 2/3] target/riscv: add cva6 core type Ben Dooks @ 2025-06-09 23:30 ` Alistair Francis 0 siblings, 0 replies; 7+ messages in thread From: Alistair Francis @ 2025-06-09 23:30 UTC (permalink / raw) To: Ben Dooks Cc: nazar.kazakov, joseph.baker, fran.redondo, lawrence.hunter, liwei1518, dbarboza, zhiwei_liu, alistair.francis, qemu-riscv, qemu-devel On Mon, Jun 9, 2025 at 11:18 PM Ben Dooks <ben.dooks@codethink.co.uk> wrote: > > Add TYPE_RISCV_CPU_CVA6 for the CVA6 core > > Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> Acked-by: Alistair Francis <alistair.francis@wdc.com> Alistair > --- > target/riscv/cpu-qom.h | 1 + > target/riscv/cpu.c | 11 +++++++++++ > 2 files changed, 12 insertions(+) > > diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h > index 1ee05eb393..3daf75568c 100644 > --- a/target/riscv/cpu-qom.h > +++ b/target/riscv/cpu-qom.h > @@ -34,6 +34,7 @@ > #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32") > #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64") > #define TYPE_RISCV_CPU_BASE128 RISCV_CPU_TYPE_NAME("x-rv128") > +#define TYPE_RISCV_CPU_CVA6 RISCV_CPU_TYPE_NAME("cva6") > #define TYPE_RISCV_CPU_RV32I RISCV_CPU_TYPE_NAME("rv32i") > #define TYPE_RISCV_CPU_RV32E RISCV_CPU_TYPE_NAME("rv32e") > #define TYPE_RISCV_CPU_RV64I RISCV_CPU_TYPE_NAME("rv64i") > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > index 629ac37501..fca45dc9d9 100644 > --- a/target/riscv/cpu.c > +++ b/target/riscv/cpu.c > @@ -3009,6 +3009,17 @@ static const TypeInfo riscv_cpu_type_infos[] = { > .misa_mxl_max = MXL_RV64, > ), > > + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_CVA6, TYPE_RISCV_VENDOR_CPU, > + .misa_ext = RVI | RVM | RVA | RVF | RVD | RVC | RVB | RVS | RVU, > + .misa_mxl_max = MXL_RV64, > + .cfg.max_satp_mode = VM_1_10_SV39, > + .priv_spec = PRIV_VERSION_1_12_0, > + .cfg.pmp = true, > + .cfg.mmu = true, > + .cfg.ext_zifencei = true, > + .cfg.ext_zicsr = true, > + ), > + > DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E51, TYPE_RISCV_CPU_SIFIVE_E, > .misa_mxl_max = MXL_RV64 > ), > -- > 2.37.2.352.g3c44437643 > > ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 3/3] hw/riscv: set cva6 to use TYPE_RISCV_CPU_CVA6 2025-06-09 13:17 RISC-V: Add CVA6 machine Ben Dooks 2025-06-09 13:17 ` [PATCH v3 1/3] hw/riscv: add " Ben Dooks 2025-06-09 13:17 ` [PATCH v3 2/3] target/riscv: add cva6 core type Ben Dooks @ 2025-06-09 13:17 ` Ben Dooks 2025-06-09 23:30 ` Alistair Francis 2 siblings, 1 reply; 7+ messages in thread From: Ben Dooks @ 2025-06-09 13:17 UTC (permalink / raw) To: nazar.kazakov, joseph.baker, fran.redondo, lawrence.hunter, liwei1518, dbarboza, zhiwei_liu, alistair.francis, qemu-riscv Cc: ben.dooks, qemu-devel Change to using TYPE_RISCV_CPU_CVA6 once this is merged. Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> --- hw/riscv/cva6.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/riscv/cva6.c b/hw/riscv/cva6.c index 3adfa8b5cc..e6fd0ebafc 100644 --- a/hw/riscv/cva6.c +++ b/hw/riscv/cva6.c @@ -83,8 +83,7 @@ static void cva6_machine_class_init(ObjectClass *oc, const void *data) mc->init = cva6_machine_init; mc->max_cpus = 1; mc->default_ram_id = "cva6.ram"; - /* start with "max" cpu type until we sort out CVA6 type */ - mc->default_cpu_type = TYPE_RISCV_CPU_MAX; + mc->default_cpu_type = TYPE_RISCV_CPU_CVA6; mc->default_ram_size = cva6_memmap[CVA6_DRAM].size; }; -- 2.37.2.352.g3c44437643 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v3 3/3] hw/riscv: set cva6 to use TYPE_RISCV_CPU_CVA6 2025-06-09 13:17 ` [PATCH v3 3/3] hw/riscv: set cva6 to use TYPE_RISCV_CPU_CVA6 Ben Dooks @ 2025-06-09 23:30 ` Alistair Francis 0 siblings, 0 replies; 7+ messages in thread From: Alistair Francis @ 2025-06-09 23:30 UTC (permalink / raw) To: Ben Dooks Cc: nazar.kazakov, joseph.baker, fran.redondo, lawrence.hunter, liwei1518, dbarboza, zhiwei_liu, alistair.francis, qemu-riscv, qemu-devel On Mon, Jun 9, 2025 at 11:20 PM Ben Dooks <ben.dooks@codethink.co.uk> wrote: > > Change to using TYPE_RISCV_CPU_CVA6 once this is merged. You can also just change the patch order to not require this patch > > Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Alistair > --- > hw/riscv/cva6.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > diff --git a/hw/riscv/cva6.c b/hw/riscv/cva6.c > index 3adfa8b5cc..e6fd0ebafc 100644 > --- a/hw/riscv/cva6.c > +++ b/hw/riscv/cva6.c > @@ -83,8 +83,7 @@ static void cva6_machine_class_init(ObjectClass *oc, const void *data) > mc->init = cva6_machine_init; > mc->max_cpus = 1; > mc->default_ram_id = "cva6.ram"; > - /* start with "max" cpu type until we sort out CVA6 type */ > - mc->default_cpu_type = TYPE_RISCV_CPU_MAX; > + mc->default_cpu_type = TYPE_RISCV_CPU_CVA6; > mc->default_ram_size = cva6_memmap[CVA6_DRAM].size; > }; > > -- > 2.37.2.352.g3c44437643 > > ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-06-09 23:31 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-06-09 13:17 RISC-V: Add CVA6 machine Ben Dooks 2025-06-09 13:17 ` [PATCH v3 1/3] hw/riscv: add " Ben Dooks 2025-06-09 23:29 ` Alistair Francis 2025-06-09 13:17 ` [PATCH v3 2/3] target/riscv: add cva6 core type Ben Dooks 2025-06-09 23:30 ` Alistair Francis 2025-06-09 13:17 ` [PATCH v3 3/3] hw/riscv: set cva6 to use TYPE_RISCV_CPU_CVA6 Ben Dooks 2025-06-09 23:30 ` Alistair Francis
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).