Message ID | 20210724122407.2486558-5-anup.patel@wdc.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | QEMU RISC-V ACLINT Support | expand |
On Sat, Jul 24, 2021 at 10:27 PM Anup Patel <anup.patel@wdc.com> wrote: > > We extend virt machine to emulate ACLINT devices only when "aclint=on" > parameter is passed along with machine name in QEMU command-line. > > Signed-off-by: Anup Patel <anup.patel@wdc.com> > --- > hw/riscv/virt.c | 113 +++++++++++++++++++++++++++++++++++++++- > include/hw/riscv/virt.h | 2 + > 2 files changed, 114 insertions(+), 1 deletion(-) > > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c > index 48c8b4aeb2..7259057a74 100644 > --- a/hw/riscv/virt.c > +++ b/hw/riscv/virt.c > @@ -49,6 +49,7 @@ static const MemMapEntry virt_memmap[] = { > [VIRT_TEST] = { 0x100000, 0x1000 }, > [VIRT_RTC] = { 0x101000, 0x1000 }, > [VIRT_CLINT] = { 0x2000000, 0x10000 }, > + [VIRT_ACLINT_SSWI] = { 0x2F00000, 0x4000 }, Couldn't we use the same address as the current CLINT? Alistair > [VIRT_PCIE_PIO] = { 0x3000000, 0x10000 }, > [VIRT_PLIC] = { 0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) }, > [VIRT_UART0] = { 0x10000000, 0x100 }, > @@ -282,6 +283,82 @@ static void create_fdt_socket_clint(RISCVVirtState *s, > g_free(clint_cells); > } > > +static void create_fdt_socket_aclint(RISCVVirtState *s, > + const MemMapEntry *memmap, int socket, > + uint32_t *intc_phandles) > +{ > + int cpu; > + char *name; > + unsigned long addr; > + uint32_t aclint_cells_size; > + uint32_t *aclint_mswi_cells; > + uint32_t *aclint_sswi_cells; > + uint32_t *aclint_mtimer_cells; > + MachineState *mc = MACHINE(s); > + > + aclint_mswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2); > + aclint_mtimer_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2); > + aclint_sswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2); > + > + for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) { > + aclint_mswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]); > + aclint_mswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_SOFT); > + aclint_mtimer_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]); > + aclint_mtimer_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_TIMER); > + aclint_sswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]); > + aclint_sswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_SOFT); > + } > + aclint_cells_size = s->soc[socket].num_harts * sizeof(uint32_t) * 2; > + > + addr = memmap[VIRT_CLINT].base + (memmap[VIRT_CLINT].size * socket); > + name = g_strdup_printf("/soc/mswi@%lx", addr); > + qemu_fdt_add_subnode(mc->fdt, name); > + qemu_fdt_setprop_string(mc->fdt, name, "compatible", "riscv,aclint-mswi"); > + qemu_fdt_setprop_cells(mc->fdt, name, "reg", > + 0x0, addr, 0x0, RISCV_ACLINT_SWI_SIZE); > + qemu_fdt_setprop(mc->fdt, name, "interrupts-extended", > + aclint_mswi_cells, aclint_cells_size); > + qemu_fdt_setprop(mc->fdt, name, "interrupt-controller", NULL, 0); > + qemu_fdt_setprop_cell(mc->fdt, name, "#interrupt-cells", 0); > + riscv_socket_fdt_write_id(mc, mc->fdt, name, socket); > + g_free(name); > + > + addr = memmap[VIRT_CLINT].base + RISCV_ACLINT_SWI_SIZE + > + (memmap[VIRT_CLINT].size * socket); > + name = g_strdup_printf("/soc/mtimer@%lx", addr); > + qemu_fdt_add_subnode(mc->fdt, name); > + qemu_fdt_setprop_string(mc->fdt, name, "compatible", > + "riscv,aclint-mtimer"); > + qemu_fdt_setprop_cells(mc->fdt, name, "reg", > + 0x0, addr + RISCV_ACLINT_DEFAULT_MTIME, > + 0x0, memmap[VIRT_CLINT].size - RISCV_ACLINT_SWI_SIZE - > + RISCV_ACLINT_DEFAULT_MTIME, > + 0x0, addr + RISCV_ACLINT_DEFAULT_MTIMECMP, > + 0x0, RISCV_ACLINT_DEFAULT_MTIME); > + qemu_fdt_setprop(mc->fdt, name, "interrupts-extended", > + aclint_mtimer_cells, aclint_cells_size); > + riscv_socket_fdt_write_id(mc, mc->fdt, name, socket); > + g_free(name); > + > + addr = memmap[VIRT_ACLINT_SSWI].base + > + (memmap[VIRT_ACLINT_SSWI].size * socket); > + name = g_strdup_printf("/soc/sswi@%lx", addr); > + qemu_fdt_add_subnode(mc->fdt, name); > + qemu_fdt_setprop_string(mc->fdt, name, "compatible", "riscv,aclint-sswi"); > + qemu_fdt_setprop_cells(mc->fdt, name, "reg", > + 0x0, addr, 0x0, memmap[VIRT_ACLINT_SSWI].size); > + qemu_fdt_setprop(mc->fdt, name, "interrupts-extended", > + aclint_sswi_cells, aclint_cells_size); > + qemu_fdt_setprop(mc->fdt, name, "interrupt-controller", NULL, 0); > + qemu_fdt_setprop_cell(mc->fdt, name, "#interrupt-cells", 0); > + riscv_socket_fdt_write_id(mc, mc->fdt, name, socket); > + g_free(name); > + > + g_free(aclint_mswi_cells); > + g_free(aclint_mtimer_cells); > + g_free(aclint_sswi_cells); > +} > + > static void create_fdt_socket_plic(RISCVVirtState *s, > const MemMapEntry *memmap, int socket, > uint32_t *phandle, uint32_t *intc_phandles, > @@ -360,7 +437,11 @@ static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap, > > create_fdt_socket_memory(s, memmap, socket); > > - create_fdt_socket_clint(s, memmap, socket, intc_phandles); > + if (s->have_aclint) { > + create_fdt_socket_aclint(s, memmap, socket, intc_phandles); > + } else { > + create_fdt_socket_clint(s, memmap, socket, intc_phandles); > + } > > create_fdt_socket_plic(s, memmap, socket, phandle, > intc_phandles, xplic_phandles); > @@ -734,6 +815,14 @@ static void virt_machine_init(MachineState *machine) > RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME, > RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true); > > + /* Per-socket ACLINT SSWI */ > + if (s->have_aclint) { > + riscv_aclint_swi_create( > + memmap[VIRT_ACLINT_SSWI].base + > + i * memmap[VIRT_ACLINT_SSWI].size, > + base_hartid, hart_count, true); > + } > + > /* Per-socket PLIC hart topology configuration string */ > plic_hart_config_len = > (strlen(VIRT_PLIC_HART_CONFIG) + 1) * hart_count; > @@ -908,6 +997,22 @@ static void virt_machine_instance_init(Object *obj) > { > } > > +static bool virt_get_aclint(Object *obj, Error **errp) > +{ > + MachineState *ms = MACHINE(obj); > + RISCVVirtState *s = RISCV_VIRT_MACHINE(ms); > + > + return s->have_aclint; > +} > + > +static void virt_set_aclint(Object *obj, bool value, Error **errp) > +{ > + MachineState *ms = MACHINE(obj); > + RISCVVirtState *s = RISCV_VIRT_MACHINE(ms); > + > + s->have_aclint = value; > +} > + > static void virt_machine_class_init(ObjectClass *oc, void *data) > { > MachineClass *mc = MACHINE_CLASS(oc); > @@ -923,6 +1028,12 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) > mc->numa_mem_supported = true; > > machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE); > + > + object_class_property_add_bool(oc, "aclint", virt_get_aclint, > + virt_set_aclint); > + object_class_property_set_description(oc, "aclint", > + "Set on/off to enable/disable " > + "emulating ACLINT devices"); > } > > static const TypeInfo virt_machine_typeinfo = { > diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h > index 349fee1f89..d9105c1886 100644 > --- a/include/hw/riscv/virt.h > +++ b/include/hw/riscv/virt.h > @@ -43,6 +43,7 @@ struct RISCVVirtState { > FWCfgState *fw_cfg; > > int fdt_size; > + bool have_aclint; > }; > > enum { > @@ -51,6 +52,7 @@ enum { > VIRT_TEST, > VIRT_RTC, > VIRT_CLINT, > + VIRT_ACLINT_SSWI, > VIRT_PLIC, > VIRT_UART0, > VIRT_VIRTIO, > -- > 2.25.1 > >
On Thu, Aug 5, 2021 at 4:09 PM Alistair Francis <alistair23@gmail.com> wrote: > > On Sat, Jul 24, 2021 at 10:27 PM Anup Patel <anup.patel@wdc.com> wrote: > > > > We extend virt machine to emulate ACLINT devices only when "aclint=on" > > parameter is passed along with machine name in QEMU command-line. > > > > Signed-off-by: Anup Patel <anup.patel@wdc.com> > > --- > > hw/riscv/virt.c | 113 +++++++++++++++++++++++++++++++++++++++- > > include/hw/riscv/virt.h | 2 + > > 2 files changed, 114 insertions(+), 1 deletion(-) > > > > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c > > index 48c8b4aeb2..7259057a74 100644 > > --- a/hw/riscv/virt.c > > +++ b/hw/riscv/virt.c > > @@ -49,6 +49,7 @@ static const MemMapEntry virt_memmap[] = { > > [VIRT_TEST] = { 0x100000, 0x1000 }, > > [VIRT_RTC] = { 0x101000, 0x1000 }, > > [VIRT_CLINT] = { 0x2000000, 0x10000 }, > > + [VIRT_ACLINT_SSWI] = { 0x2F00000, 0x4000 }, > > Couldn't we use the same address as the current CLINT? Whoops, nevermind. Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Alistair
On Sat, Jul 24, 2021 at 8:27 PM Anup Patel <anup.patel@wdc.com> wrote: > > We extend virt machine to emulate ACLINT devices only when "aclint=on" > parameter is passed along with machine name in QEMU command-line. > > Signed-off-by: Anup Patel <anup.patel@wdc.com> > --- > hw/riscv/virt.c | 113 +++++++++++++++++++++++++++++++++++++++- > include/hw/riscv/virt.h | 2 + > 2 files changed, 114 insertions(+), 1 deletion(-) > Reviewed-by: Bin Meng <bmeng.cn@gmail.com> Please add a "Machine-specific options" in the Virt documentation. See sifive_u example @ https://qemu.readthedocs.io/en/latest/system/riscv/sifive_u.html#machine-specific-options Regards, Bin
On Fri, Aug 6, 2021 at 8:00 AM Bin Meng <bmeng.cn@gmail.com> wrote: > > On Sat, Jul 24, 2021 at 8:27 PM Anup Patel <anup.patel@wdc.com> wrote: > > > > We extend virt machine to emulate ACLINT devices only when "aclint=on" > > parameter is passed along with machine name in QEMU command-line. > > > > Signed-off-by: Anup Patel <anup.patel@wdc.com> > > --- > > hw/riscv/virt.c | 113 +++++++++++++++++++++++++++++++++++++++- > > include/hw/riscv/virt.h | 2 + > > 2 files changed, 114 insertions(+), 1 deletion(-) > > > > Reviewed-by: Bin Meng <bmeng.cn@gmail.com> > > Please add a "Machine-specific options" in the Virt documentation. > > See sifive_u example @ > https://qemu.readthedocs.io/en/latest/system/riscv/sifive_u.html#machine-specific-options Okay, I will update the documentation in the next revision. Regards, Anup > > Regards, > Bin
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 48c8b4aeb2..7259057a74 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -49,6 +49,7 @@ static const MemMapEntry virt_memmap[] = { [VIRT_TEST] = { 0x100000, 0x1000 }, [VIRT_RTC] = { 0x101000, 0x1000 }, [VIRT_CLINT] = { 0x2000000, 0x10000 }, + [VIRT_ACLINT_SSWI] = { 0x2F00000, 0x4000 }, [VIRT_PCIE_PIO] = { 0x3000000, 0x10000 }, [VIRT_PLIC] = { 0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) }, [VIRT_UART0] = { 0x10000000, 0x100 }, @@ -282,6 +283,82 @@ static void create_fdt_socket_clint(RISCVVirtState *s, g_free(clint_cells); } +static void create_fdt_socket_aclint(RISCVVirtState *s, + const MemMapEntry *memmap, int socket, + uint32_t *intc_phandles) +{ + int cpu; + char *name; + unsigned long addr; + uint32_t aclint_cells_size; + uint32_t *aclint_mswi_cells; + uint32_t *aclint_sswi_cells; + uint32_t *aclint_mtimer_cells; + MachineState *mc = MACHINE(s); + + aclint_mswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2); + aclint_mtimer_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2); + aclint_sswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2); + + for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) { + aclint_mswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]); + aclint_mswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_SOFT); + aclint_mtimer_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]); + aclint_mtimer_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_TIMER); + aclint_sswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]); + aclint_sswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_SOFT); + } + aclint_cells_size = s->soc[socket].num_harts * sizeof(uint32_t) * 2; + + addr = memmap[VIRT_CLINT].base + (memmap[VIRT_CLINT].size * socket); + name = g_strdup_printf("/soc/mswi@%lx", addr); + qemu_fdt_add_subnode(mc->fdt, name); + qemu_fdt_setprop_string(mc->fdt, name, "compatible", "riscv,aclint-mswi"); + qemu_fdt_setprop_cells(mc->fdt, name, "reg", + 0x0, addr, 0x0, RISCV_ACLINT_SWI_SIZE); + qemu_fdt_setprop(mc->fdt, name, "interrupts-extended", + aclint_mswi_cells, aclint_cells_size); + qemu_fdt_setprop(mc->fdt, name, "interrupt-controller", NULL, 0); + qemu_fdt_setprop_cell(mc->fdt, name, "#interrupt-cells", 0); + riscv_socket_fdt_write_id(mc, mc->fdt, name, socket); + g_free(name); + + addr = memmap[VIRT_CLINT].base + RISCV_ACLINT_SWI_SIZE + + (memmap[VIRT_CLINT].size * socket); + name = g_strdup_printf("/soc/mtimer@%lx", addr); + qemu_fdt_add_subnode(mc->fdt, name); + qemu_fdt_setprop_string(mc->fdt, name, "compatible", + "riscv,aclint-mtimer"); + qemu_fdt_setprop_cells(mc->fdt, name, "reg", + 0x0, addr + RISCV_ACLINT_DEFAULT_MTIME, + 0x0, memmap[VIRT_CLINT].size - RISCV_ACLINT_SWI_SIZE - + RISCV_ACLINT_DEFAULT_MTIME, + 0x0, addr + RISCV_ACLINT_DEFAULT_MTIMECMP, + 0x0, RISCV_ACLINT_DEFAULT_MTIME); + qemu_fdt_setprop(mc->fdt, name, "interrupts-extended", + aclint_mtimer_cells, aclint_cells_size); + riscv_socket_fdt_write_id(mc, mc->fdt, name, socket); + g_free(name); + + addr = memmap[VIRT_ACLINT_SSWI].base + + (memmap[VIRT_ACLINT_SSWI].size * socket); + name = g_strdup_printf("/soc/sswi@%lx", addr); + qemu_fdt_add_subnode(mc->fdt, name); + qemu_fdt_setprop_string(mc->fdt, name, "compatible", "riscv,aclint-sswi"); + qemu_fdt_setprop_cells(mc->fdt, name, "reg", + 0x0, addr, 0x0, memmap[VIRT_ACLINT_SSWI].size); + qemu_fdt_setprop(mc->fdt, name, "interrupts-extended", + aclint_sswi_cells, aclint_cells_size); + qemu_fdt_setprop(mc->fdt, name, "interrupt-controller", NULL, 0); + qemu_fdt_setprop_cell(mc->fdt, name, "#interrupt-cells", 0); + riscv_socket_fdt_write_id(mc, mc->fdt, name, socket); + g_free(name); + + g_free(aclint_mswi_cells); + g_free(aclint_mtimer_cells); + g_free(aclint_sswi_cells); +} + static void create_fdt_socket_plic(RISCVVirtState *s, const MemMapEntry *memmap, int socket, uint32_t *phandle, uint32_t *intc_phandles, @@ -360,7 +437,11 @@ static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap, create_fdt_socket_memory(s, memmap, socket); - create_fdt_socket_clint(s, memmap, socket, intc_phandles); + if (s->have_aclint) { + create_fdt_socket_aclint(s, memmap, socket, intc_phandles); + } else { + create_fdt_socket_clint(s, memmap, socket, intc_phandles); + } create_fdt_socket_plic(s, memmap, socket, phandle, intc_phandles, xplic_phandles); @@ -734,6 +815,14 @@ static void virt_machine_init(MachineState *machine) RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME, RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true); + /* Per-socket ACLINT SSWI */ + if (s->have_aclint) { + riscv_aclint_swi_create( + memmap[VIRT_ACLINT_SSWI].base + + i * memmap[VIRT_ACLINT_SSWI].size, + base_hartid, hart_count, true); + } + /* Per-socket PLIC hart topology configuration string */ plic_hart_config_len = (strlen(VIRT_PLIC_HART_CONFIG) + 1) * hart_count; @@ -908,6 +997,22 @@ static void virt_machine_instance_init(Object *obj) { } +static bool virt_get_aclint(Object *obj, Error **errp) +{ + MachineState *ms = MACHINE(obj); + RISCVVirtState *s = RISCV_VIRT_MACHINE(ms); + + return s->have_aclint; +} + +static void virt_set_aclint(Object *obj, bool value, Error **errp) +{ + MachineState *ms = MACHINE(obj); + RISCVVirtState *s = RISCV_VIRT_MACHINE(ms); + + s->have_aclint = value; +} + static void virt_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -923,6 +1028,12 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) mc->numa_mem_supported = true; machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE); + + object_class_property_add_bool(oc, "aclint", virt_get_aclint, + virt_set_aclint); + object_class_property_set_description(oc, "aclint", + "Set on/off to enable/disable " + "emulating ACLINT devices"); } static const TypeInfo virt_machine_typeinfo = { diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h index 349fee1f89..d9105c1886 100644 --- a/include/hw/riscv/virt.h +++ b/include/hw/riscv/virt.h @@ -43,6 +43,7 @@ struct RISCVVirtState { FWCfgState *fw_cfg; int fdt_size; + bool have_aclint; }; enum { @@ -51,6 +52,7 @@ enum { VIRT_TEST, VIRT_RTC, VIRT_CLINT, + VIRT_ACLINT_SSWI, VIRT_PLIC, VIRT_UART0, VIRT_VIRTIO,
We extend virt machine to emulate ACLINT devices only when "aclint=on" parameter is passed along with machine name in QEMU command-line. Signed-off-by: Anup Patel <anup.patel@wdc.com> --- hw/riscv/virt.c | 113 +++++++++++++++++++++++++++++++++++++++- include/hw/riscv/virt.h | 2 + 2 files changed, 114 insertions(+), 1 deletion(-)