[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v2 4/4] hw/riscv: virt: Add optional ACLINT support to virt m
From: |
Alistair Francis |
Subject: |
Re: [PATCH v2 4/4] hw/riscv: virt: Add optional ACLINT support to virt machine |
Date: |
Thu, 5 Aug 2021 16:09:37 +1000 |
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
>
>
- Re: [PATCH v2 4/4] hw/riscv: virt: Add optional ACLINT support to virt machine,
Alistair Francis <=