The sifive_u board does not share the same CPU socket FDT bits from the other boards. In particular the riscv,isa creation is done using either CPU0 from soc.e_cpus.harts, and for all other CPUs soc.u_cups.harts is used.
It would be too cumbersome to add all these details in the common code so we're going to add a special sifive_u only helper that shares the common bits with the common helper used by the other boards. create_fdt_socket_cpu_internal() contains the common bits shared between the sifive_u board and the rest. Signed-off-by: Daniel Henrique Barboza <[email protected]> --- hw/riscv/fdt-common.c | 108 +++++++++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 43 deletions(-) diff --git a/hw/riscv/fdt-common.c b/hw/riscv/fdt-common.c index 6c795409a4..70168ad657 100644 --- a/hw/riscv/fdt-common.c +++ b/hw/riscv/fdt-common.c @@ -94,28 +94,29 @@ void fdt_create_cpu_socket_subnode(void *fdt, uint64_t timebase_frequency) qemu_fdt_add_subnode(fdt, "/cpus/cpu-map"); } -void create_fdt_socket_cpus(void *fdt, RISCVCPU *socket_harts, - int socket_id, int num_harts_socket, - int socket_hartid_base, uint32_t *phandle, - uint32_t *intc_phandles, bool numa_enabled, - bool is_32_bit) +static void +create_fdt_socket_cpu_internal(void *fdt, char *clust_name, RISCVCPU *cpu_ptr, + int cpu, int socket_id, int socket_hartid_base, + uint32_t *phandle, uint32_t *intc_phandles, + bool numa_enabled, bool is_32_bit) { - g_autofree char *clust_name = NULL; - uint32_t cpu_phandle; - - clust_name = g_strdup_printf("/cpus/cpu-map/cluster%d", socket_id); - qemu_fdt_add_subnode(fdt, clust_name); - - for (int cpu = num_harts_socket - 1; cpu >= 0; cpu--) { - RISCVCPU *cpu_ptr = &socket_harts[cpu]; + g_autofree char *cpu_name = NULL; + g_autofree char *core_name = NULL; + g_autofree char *intc_name = NULL; + uint32_t cpu_phandle = (*phandle)++; + bool is_sifive_u = cpu_ptr == NULL; + + cpu_name = g_strdup_printf("/cpus/cpu@%d", socket_hartid_base + cpu); + + /* + * The sifive_u board has an exclusive satp and riscv,isa + * schema that can't be shared with other boards, so part + * of the CPU FDT creation (i.e. the /cpus/cpu@N subnode) + * is still being done by the board. + */ + if (!is_sifive_u) { int8_t satp_mode_max = cpu_ptr->cfg.max_satp_mode; - g_autofree char *cpu_name = NULL; - g_autofree char *core_name = NULL; - g_autofree char *intc_name = NULL; - - cpu_phandle = (*phandle)++; - cpu_name = g_strdup_printf("/cpus/cpu@%d", socket_hartid_base + cpu); qemu_fdt_add_subnode(fdt, cpu_name); if (satp_mode_max != -1) { @@ -140,30 +141,51 @@ void create_fdt_socket_cpus(void *fdt, RISCVCPU *socket_harts, qemu_fdt_setprop_cell(fdt, cpu_name, "riscv,cbop-block-size", cpu_ptr->cfg.cbop_blocksize); } + } - qemu_fdt_setprop_string(fdt, cpu_name, "compatible", "riscv"); - qemu_fdt_setprop_string(fdt, cpu_name, "status", "okay"); - qemu_fdt_setprop_cell(fdt, cpu_name, "reg", - socket_hartid_base + cpu); - qemu_fdt_setprop_string(fdt, cpu_name, "device_type", "cpu"); - if (numa_enabled) { - qemu_fdt_setprop_cell(fdt, cpu_name, "numa-node-id", socket_id); - } - qemu_fdt_setprop_cell(fdt, cpu_name, "phandle", cpu_phandle); - - intc_phandles[cpu] = (*phandle)++; - - intc_name = g_strdup_printf("%s/interrupt-controller", cpu_name); - qemu_fdt_add_subnode(fdt, intc_name); - qemu_fdt_setprop_cell(fdt, intc_name, "phandle", - intc_phandles[cpu]); - qemu_fdt_setprop_string(fdt, intc_name, "compatible", - "riscv,cpu-intc"); - qemu_fdt_setprop(fdt, intc_name, "interrupt-controller", NULL, 0); - qemu_fdt_setprop_cell(fdt, intc_name, "#interrupt-cells", 1); - - core_name = g_strdup_printf("%s/core%d", clust_name, cpu); - qemu_fdt_add_subnode(fdt, core_name); - qemu_fdt_setprop_cell(fdt, core_name, "cpu", cpu_phandle); + qemu_fdt_setprop_string(fdt, cpu_name, "compatible", "riscv"); + qemu_fdt_setprop_string(fdt, cpu_name, "status", "okay"); + qemu_fdt_setprop_cell(fdt, cpu_name, "reg", + socket_hartid_base + cpu); + qemu_fdt_setprop_string(fdt, cpu_name, "device_type", "cpu"); + if (numa_enabled) { + qemu_fdt_setprop_cell(fdt, cpu_name, "numa-node-id", socket_id); + } + qemu_fdt_setprop_cell(fdt, cpu_name, "phandle", cpu_phandle); + + intc_phandles[cpu] = (*phandle)++; + + intc_name = g_strdup_printf("%s/interrupt-controller", cpu_name); + qemu_fdt_add_subnode(fdt, intc_name); + qemu_fdt_setprop_cell(fdt, intc_name, "phandle", + intc_phandles[cpu]); + qemu_fdt_setprop_string(fdt, intc_name, "compatible", + "riscv,cpu-intc"); + qemu_fdt_setprop(fdt, intc_name, "interrupt-controller", NULL, 0); + qemu_fdt_setprop_cell(fdt, intc_name, "#interrupt-cells", 1); + + core_name = g_strdup_printf("%s/core%d", clust_name, cpu); + qemu_fdt_add_subnode(fdt, core_name); + qemu_fdt_setprop_cell(fdt, core_name, "cpu", cpu_phandle); +} + +void create_fdt_socket_cpus(void *fdt, RISCVCPU *socket_harts, + int socket_id, int num_harts_socket, + int socket_hartid_base, uint32_t *phandle, + uint32_t *intc_phandles, bool numa_enabled, + bool is_32_bit) +{ + g_autofree char *clust_name = NULL; + + clust_name = g_strdup_printf("/cpus/cpu-map/cluster%d", socket_id); + qemu_fdt_add_subnode(fdt, clust_name); + + for (int cpu = num_harts_socket - 1; cpu >= 0; cpu--) { + RISCVCPU *cpu_ptr = &socket_harts[cpu]; + + create_fdt_socket_cpu_internal(fdt, clust_name, cpu_ptr, cpu, + socket_id, socket_hartid_base, + phandle, intc_phandles, numa_enabled, + is_32_bit); } } -- 2.43.0
