[PATCH 07/13] hw/riscv/fdt-common, virt.c: add create_fdt_socket_aclint()
Daniel Henrique Barboza <[email protected]>
| Newsgroups | org.nongnu.qemu-riscv,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
Yet another FDT that we want to move to a helper to avoid copy/pasting code to other boards that will use a mtimer. In particular the future 'riscv-server-ref' board. No FDT changes made. Signed-off-by: Daniel Henrique Barboza <[email protected]> --- hw/riscv/fdt-common.c | 96 +++++++++++++++++++++++++++++++++ hw/riscv/virt.c | 99 ++++------------------------------- include/hw/riscv/fdt-common.h | 11 ++++ 3 files changed, 118 insertions(+), 88 deletions(-) diff --git a/hw/riscv/fdt-common.c b/hw/riscv/fdt-common.c index 77168f5c4f..f31cc9d3cc 100644 --- a/hw/riscv/fdt-common.c +++ b/hw/riscv/fdt-common.c @@ -16,6 +16,7 @@ #include "target/riscv/cpu_bits.h" #include "hw/riscv/riscv-iommu-bits.h" #include "hw/riscv/iommu.h" +#include "hw/intc/riscv_aclint.h" #include "hw/intc/riscv_imsic.h" #include "hw/pci/pci.h" #include "hw/pci/pcie_host.h" @@ -695,3 +696,98 @@ void create_fdt_socket_aplic(void *fdt, APLICFdtProps *props, aplic_phandles[props->socket] = aplic_s_phandle; } + +void create_fdt_socket_aclint(void *fdt, ACLINTFdtProps *props, + uint32_t *intc_phandles) +{ + uint32_t aclint_cells_size = props->num_harts * sizeof(uint32_t) * 2; + g_autofree uint32_t *aclint_mswi_cells = NULL; + g_autofree uint32_t *aclint_sswi_cells = NULL; + g_autofree uint32_t *aclint_mtimer_cells = NULL; + hwaddr addr, size; + char *name; + int cpu; + + aclint_mswi_cells = g_new0(uint32_t, props->num_harts * 2); + aclint_mtimer_cells = g_new0(uint32_t, props->num_harts * 2); + aclint_sswi_cells = g_new0(uint32_t, props->num_harts * 2); + + for (cpu = 0; cpu < props->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); + } + + if (props->aia_type != AIA_TYPE_APLIC_IMSIC) { + addr = props->clint->base + (props->clint->size * props->socket); + name = g_strdup_printf("/soc/mswi@%"HWADDR_PRIx, addr); + + qemu_fdt_add_subnode(fdt, name); + qemu_fdt_setprop_string(fdt, name, "compatible", "riscv,aclint-mswi"); + qemu_fdt_setprop_sized_cells(fdt, name, "reg", + 2, addr, 2, RISCV_ACLINT_SWI_SIZE); + qemu_fdt_setprop(fdt, name, "interrupts-extended", + aclint_mswi_cells, aclint_cells_size); + qemu_fdt_setprop(fdt, name, "interrupt-controller", NULL, 0); + qemu_fdt_setprop_cell(fdt, name, "#interrupt-cells", 0); + + if (props->numa_enabled) { + qemu_fdt_setprop_cell(fdt, name, "numa-node-id", props->socket); + } + + g_free(name); + } + + if (props->aia_type == AIA_TYPE_APLIC_IMSIC) { + addr = props->clint->base + + (RISCV_ACLINT_DEFAULT_MTIMER_SIZE * props->socket); + size = RISCV_ACLINT_DEFAULT_MTIMER_SIZE; + } else { + addr = props->clint->base + RISCV_ACLINT_SWI_SIZE + + (props->clint->size * props->socket); + size = props->clint->size - RISCV_ACLINT_SWI_SIZE; + } + + name = g_strdup_printf("/soc/mtimer@%"HWADDR_PRIx, addr); + qemu_fdt_add_subnode(fdt, name); + qemu_fdt_setprop_string(fdt, name, "compatible", + "riscv,aclint-mtimer"); + qemu_fdt_setprop_sized_cells(fdt, name, "reg", + 2, addr, + 2, size - RISCV_ACLINT_DEFAULT_MTIME, + 2, addr + RISCV_ACLINT_DEFAULT_MTIMECMP, + 2, RISCV_ACLINT_DEFAULT_MTIME); + qemu_fdt_setprop(fdt, name, "interrupts-extended", + aclint_mtimer_cells, aclint_cells_size); + + if (props->numa_enabled) { + qemu_fdt_setprop_cell(fdt, name, "numa-node-id", props->socket); + } + + g_free(name); + + if (props->aia_type != AIA_TYPE_APLIC_IMSIC) { + addr = props->aclint_sswi->base + + (props->aclint_sswi->size * props->socket); + + name = g_strdup_printf("/soc/sswi@%"HWADDR_PRIx, addr); + qemu_fdt_add_subnode(fdt, name); + qemu_fdt_setprop_string(fdt, name, "compatible", + "riscv,aclint-sswi"); + qemu_fdt_setprop_sized_cells(fdt, name, "reg", + 2, addr, 2, props->aclint_sswi->size); + qemu_fdt_setprop(fdt, name, "interrupts-extended", + aclint_sswi_cells, aclint_cells_size); + qemu_fdt_setprop(fdt, name, "interrupt-controller", NULL, 0); + qemu_fdt_setprop_cell(fdt, name, "#interrupt-cells", 0); + + if (props->numa_enabled) { + qemu_fdt_setprop_cell(fdt, name, "numa-node-id", props->socket); + } + + g_free(name); + } +} diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index dd8f5d9d75..ef2670f20e 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -180,93 +180,6 @@ static void virt_flash_map(RISCVVirtState *s, sysmem); } -static void create_fdt_socket_aclint(RISCVVirtState *s, - int socket, - uint32_t *intc_phandles) -{ - int cpu; - char *name; - unsigned long addr, size; - uint32_t aclint_cells_size; - g_autofree uint32_t *aclint_mswi_cells = NULL; - g_autofree uint32_t *aclint_sswi_cells = NULL; - g_autofree uint32_t *aclint_mtimer_cells = NULL; - MachineState *ms = 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; - - if (s->aia_type != VIRT_AIA_TYPE_APLIC_IMSIC) { - addr = s->memmap[VIRT_CLINT].base + - (s->memmap[VIRT_CLINT].size * socket); - name = g_strdup_printf("/soc/mswi@%lx", addr); - - qemu_fdt_add_subnode(ms->fdt, name); - qemu_fdt_setprop_string(ms->fdt, name, "compatible", - "riscv,aclint-mswi"); - qemu_fdt_setprop_sized_cells(ms->fdt, name, "reg", - 2, addr, 2, RISCV_ACLINT_SWI_SIZE); - qemu_fdt_setprop(ms->fdt, name, "interrupts-extended", - aclint_mswi_cells, aclint_cells_size); - qemu_fdt_setprop(ms->fdt, name, "interrupt-controller", NULL, 0); - qemu_fdt_setprop_cell(ms->fdt, name, "#interrupt-cells", 0); - riscv_socket_fdt_write_id(ms, name, socket); - g_free(name); - } - - if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) { - addr = s->memmap[VIRT_CLINT].base + - (RISCV_ACLINT_DEFAULT_MTIMER_SIZE * socket); - size = RISCV_ACLINT_DEFAULT_MTIMER_SIZE; - } else { - addr = s->memmap[VIRT_CLINT].base + RISCV_ACLINT_SWI_SIZE + - (s->memmap[VIRT_CLINT].size * socket); - size = s->memmap[VIRT_CLINT].size - RISCV_ACLINT_SWI_SIZE; - } - name = g_strdup_printf("/soc/mtimer@%lx", addr); - qemu_fdt_add_subnode(ms->fdt, name); - qemu_fdt_setprop_string(ms->fdt, name, "compatible", - "riscv,aclint-mtimer"); - qemu_fdt_setprop_sized_cells(ms->fdt, name, "reg", - 2, addr + RISCV_ACLINT_DEFAULT_MTIME, - 2, size - RISCV_ACLINT_DEFAULT_MTIME, - 2, addr + RISCV_ACLINT_DEFAULT_MTIMECMP, - 2, RISCV_ACLINT_DEFAULT_MTIME); - qemu_fdt_setprop(ms->fdt, name, "interrupts-extended", - aclint_mtimer_cells, aclint_cells_size); - riscv_socket_fdt_write_id(ms, name, socket); - g_free(name); - - if (s->aia_type != VIRT_AIA_TYPE_APLIC_IMSIC) { - addr = s->memmap[VIRT_ACLINT_SSWI].base + - (s->memmap[VIRT_ACLINT_SSWI].size * socket); - - name = g_strdup_printf("/soc/sswi@%lx", addr); - qemu_fdt_add_subnode(ms->fdt, name); - qemu_fdt_setprop_string(ms->fdt, name, "compatible", - "riscv,aclint-sswi"); - qemu_fdt_setprop_sized_cells(ms->fdt, name, "reg", - 2, addr, 2, s->memmap[VIRT_ACLINT_SSWI].size); - qemu_fdt_setprop(ms->fdt, name, "interrupts-extended", - aclint_sswi_cells, aclint_cells_size); - qemu_fdt_setprop(ms->fdt, name, "interrupt-controller", NULL, 0); - qemu_fdt_setprop_cell(ms->fdt, name, "#interrupt-cells", 0); - riscv_socket_fdt_write_id(ms, name, socket); - g_free(name); - } -} - static void create_fdt_socket_plic(RISCVVirtState *s, int socket, uint32_t *phandle, uint32_t *intc_phandles, @@ -347,6 +260,7 @@ static void create_fdt_sockets(RISCVVirtState *s, bool numa_enabled = riscv_numa_enabled(ms); bool is_32_bit = riscv_is_32bit(&s->soc[0]); APLICFdtProps aplic_props; + ACLINTFdtProps aclint_props; fdt_create_cpu_socket_subnode(ms->fdt, kvm_enabled() ? kvm_riscv_get_timebase_frequency(&s->soc->harts[0]) : @@ -354,6 +268,13 @@ static void create_fdt_sockets(RISCVVirtState *s, intc_phandles = g_new0(uint32_t, ms->smp.cpus); + if (virt_aclint_allowed() && s->have_aclint) { + aclint_props.clint = &s->memmap[VIRT_CLINT]; + aclint_props.aclint_sswi = &s->memmap[VIRT_ACLINT_SSWI]; + aclint_props.aia_type = s->aia_type; + aclint_props.numa_enabled = numa_enabled; + } + phandle_pos = ms->smp.cpus; for (socket = (socket_count - 1); socket >= 0; socket--) { hwaddr memaddr = s->memmap[VIRT_DRAM].base + @@ -372,7 +293,9 @@ static void create_fdt_sockets(RISCVVirtState *s, socket, riscv_numa_enabled(ms)); if (virt_aclint_allowed() && s->have_aclint) { - create_fdt_socket_aclint(s, socket, + aclint_props.socket = socket; + aclint_props.num_harts = s->soc[socket].num_harts; + create_fdt_socket_aclint(ms->fdt, &aclint_props, &intc_phandles[phandle_pos]); } else if (tcg_enabled()) { hwaddr clintaddr = s->memmap[VIRT_CLINT].base + diff --git a/include/hw/riscv/fdt-common.h b/include/hw/riscv/fdt-common.h index 7a7e3ad7af..fbcf9aaffb 100644 --- a/include/hw/riscv/fdt-common.h +++ b/include/hw/riscv/fdt-common.h @@ -63,6 +63,15 @@ typedef struct APLICFdtProps { int aia_type; } APLICFdtProps; +typedef struct ACLINTFdtProps { + const MemMapEntry *clint; + const MemMapEntry *aclint_sswi; + int socket; + int num_harts; + int aia_type; + bool numa_enabled; +} ACLINTFdtProps; + void *create_board_device_tree(const char *model, const char *compatible, int *fdt_size); void create_fdt_socket_memory(void *fdt, hwaddr addr, uint64_t size, @@ -112,4 +121,6 @@ void create_fdt_socket_aplic(void *fdt, APLICFdtProps *props, uint32_t *phandle, uint32_t *intc_phandles, uint32_t *aplic_phandles); +void create_fdt_socket_aclint(void *fdt, ACLINTFdtProps *props, + uint32_t *intc_phandles); #endif -- 2.43.0