From 2308092b2b78e6e083092bd3599cec6a0769319e Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 26 Apr 2018 11:15:24 -0700 Subject: [PATCH 1/7] hw/riscv/sifive_u: Create a SiFive U SoC object Create a SiFive Unleashed U54 SoC and use that in the sifive_u machine. We leave the SoC, RAM, device tree and reset/fdt loading as part of the machine. All the other device creation has been moved to the SoC. Signed-off-by: Alistair Francis Reviewed-by: Michael Clark --- hw/riscv/sifive_u.c | 87 +++++++++++++++++++++++++++---------- include/hw/riscv/sifive_u.h | 16 ++++++- 2 files changed, 79 insertions(+), 24 deletions(-) diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index c05dcbba95..e2b4f97b10 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -116,10 +116,10 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0); qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1); - for (cpu = s->soc.num_harts - 1; cpu >= 0; cpu--) { + for (cpu = s->soc.cpus.num_harts - 1; cpu >= 0; cpu--) { nodename = g_strdup_printf("/cpus/cpu@%d", cpu); char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu); - char *isa = riscv_isa_string(&s->soc.harts[cpu]); + char *isa = riscv_isa_string(&s->soc.cpus.harts[cpu]); qemu_fdt_add_subnode(fdt, nodename); qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", SIFIVE_U_CLOCK_FREQ); @@ -140,8 +140,8 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, g_free(nodename); } - cells = g_new0(uint32_t, s->soc.num_harts * 4); - for (cpu = 0; cpu < s->soc.num_harts; cpu++) { + cells = g_new0(uint32_t, s->soc.cpus.num_harts * 4); + for (cpu = 0; cpu < s->soc.cpus.num_harts; cpu++) { nodename = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu); uint32_t intc_phandle = qemu_fdt_get_phandle(fdt, nodename); @@ -159,12 +159,12 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, 0x0, memmap[SIFIVE_U_CLINT].base, 0x0, memmap[SIFIVE_U_CLINT].size); qemu_fdt_setprop(fdt, nodename, "interrupts-extended", - cells, s->soc.num_harts * sizeof(uint32_t) * 4); + cells, s->soc.cpus.num_harts * sizeof(uint32_t) * 4); g_free(cells); g_free(nodename); - cells = g_new0(uint32_t, s->soc.num_harts * 4); - for (cpu = 0; cpu < s->soc.num_harts; cpu++) { + cells = g_new0(uint32_t, s->soc.cpus.num_harts * 4); + for (cpu = 0; cpu < s->soc.cpus.num_harts; cpu++) { nodename = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu); uint32_t intc_phandle = qemu_fdt_get_phandle(fdt, nodename); @@ -181,7 +181,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv,plic0"); qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0); qemu_fdt_setprop(fdt, nodename, "interrupts-extended", - cells, s->soc.num_harts * sizeof(uint32_t) * 4); + cells, s->soc.cpus.num_harts * sizeof(uint32_t) * 4); qemu_fdt_setprop_cells(fdt, nodename, "reg", 0x0, memmap[SIFIVE_U_PLIC].base, 0x0, memmap[SIFIVE_U_PLIC].size); @@ -217,17 +217,12 @@ static void riscv_sifive_u_init(MachineState *machine) SiFiveUState *s = g_new0(SiFiveUState, 1); MemoryRegion *system_memory = get_system_memory(); MemoryRegion *main_mem = g_new(MemoryRegion, 1); - MemoryRegion *mask_rom = g_new(MemoryRegion, 1); int i; - /* Initialize SOC */ - object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY); + /* Initialize SoC */ + object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_U_SOC); object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc), &error_abort); - object_property_set_str(OBJECT(&s->soc), SIFIVE_U_CPU, "cpu-type", - &error_abort); - object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts", - &error_abort); object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_abort); @@ -235,17 +230,11 @@ static void riscv_sifive_u_init(MachineState *machine) memory_region_init_ram(main_mem, NULL, "riscv.sifive.u.ram", machine->ram_size, &error_fatal); memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DRAM].base, - main_mem); + main_mem); /* create device tree */ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline); - /* boot rom */ - memory_region_init_rom(mask_rom, NULL, "riscv.sifive.u.mrom", - memmap[SIFIVE_U_MROM].size, &error_fatal); - memory_region_add_subregion(system_memory, memmap[SIFIVE_U_MROM].base, - mask_rom); - if (machine->kernel_filename) { load_kernel(machine->kernel_filename); } @@ -284,6 +273,36 @@ static void riscv_sifive_u_init(MachineState *machine) rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt), memmap[SIFIVE_U_MROM].base + sizeof(reset_vec), &address_space_memory); +} + +static void riscv_sifive_u_soc_init(Object *obj) +{ + SiFiveUSoCState *s = RISCV_U_SOC(obj); + + object_initialize(&s->cpus, sizeof(s->cpus), TYPE_RISCV_HART_ARRAY); + object_property_add_child(obj, "cpus", OBJECT(&s->cpus), + &error_abort); + object_property_set_str(OBJECT(&s->cpus), SIFIVE_U_CPU, "cpu-type", + &error_abort); + object_property_set_int(OBJECT(&s->cpus), smp_cpus, "num-harts", + &error_abort); +} + +static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) +{ + SiFiveUSoCState *s = RISCV_U_SOC(dev); + const struct MemmapEntry *memmap = sifive_u_memmap; + MemoryRegion *system_memory = get_system_memory(); + MemoryRegion *mask_rom = g_new(MemoryRegion, 1); + + object_property_set_bool(OBJECT(&s->cpus), true, "realized", + &error_abort); + + /* boot rom */ + memory_region_init_rom(mask_rom, NULL, "riscv.sifive.u.mrom", + memmap[SIFIVE_U_MROM].size, &error_fatal); + memory_region_add_subregion(system_memory, memmap[SIFIVE_U_MROM].base, + mask_rom); /* MMIO */ s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base, @@ -314,3 +333,27 @@ static void riscv_sifive_u_machine_init(MachineClass *mc) } DEFINE_MACHINE("sifive_u", riscv_sifive_u_machine_init) + +static void riscv_sifive_u_soc_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = riscv_sifive_u_soc_realize; + /* Reason: Uses serial_hds in realize function, thus can't be used twice */ + dc->user_creatable = false; +} + +static const TypeInfo riscv_sifive_u_soc_type_info = { + .name = TYPE_RISCV_U_SOC, + .parent = TYPE_DEVICE, + .instance_size = sizeof(SiFiveUSoCState), + .instance_init = riscv_sifive_u_soc_init, + .class_init = riscv_sifive_u_soc_class_init, +}; + +static void riscv_sifive_u_soc_register_types(void) +{ + type_register_static(&riscv_sifive_u_soc_type_info); +} + +type_init(riscv_sifive_u_soc_register_types) diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h index 94a390566e..49f1946539 100644 --- a/include/hw/riscv/sifive_u.h +++ b/include/hw/riscv/sifive_u.h @@ -19,13 +19,25 @@ #ifndef HW_SIFIVE_U_H #define HW_SIFIVE_U_H +#define TYPE_RISCV_U_SOC "riscv.sifive.u.soc" +#define RISCV_U_SOC(obj) \ + OBJECT_CHECK(SiFiveUSoCState, (obj), TYPE_RISCV_U_SOC) + +typedef struct SiFiveUSoCState { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + RISCVHartArrayState cpus; + DeviceState *plic; +} SiFiveUSoCState; + typedef struct SiFiveUState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ - RISCVHartArrayState soc; - DeviceState *plic; + SiFiveUSoCState soc; void *fdt; int fdt_size; } SiFiveUState; From 651cd8b7e18eda46a36cf073428452d04bb354f2 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 3 May 2018 16:54:02 -0700 Subject: [PATCH 2/7] hw/riscv/sifive_e: Create a SiFive E SoC object Signed-off-by: Alistair Francis Reviewed-by: Michael Clark --- hw/riscv/sifive_e.c | 94 +++++++++++++++++++++++++++---------- include/hw/riscv/sifive_e.h | 16 ++++++- 2 files changed, 83 insertions(+), 27 deletions(-) diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index e4ecb7aa4b..cb1b6948bf 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -102,18 +102,12 @@ static void riscv_sifive_e_init(MachineState *machine) SiFiveEState *s = g_new0(SiFiveEState, 1); MemoryRegion *sys_mem = get_system_memory(); MemoryRegion *main_mem = g_new(MemoryRegion, 1); - MemoryRegion *mask_rom = g_new(MemoryRegion, 1); - MemoryRegion *xip_mem = g_new(MemoryRegion, 1); int i; - /* Initialize SOC */ - object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY); + /* Initialize SoC */ + object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_E_SOC); object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc), &error_abort); - object_property_set_str(OBJECT(&s->soc), SIFIVE_E_CPU, "cpu-type", - &error_abort); - object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts", - &error_abort); object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_abort); @@ -123,6 +117,49 @@ static void riscv_sifive_e_init(MachineState *machine) memory_region_add_subregion(sys_mem, memmap[SIFIVE_E_DTIM].base, main_mem); + /* Mask ROM reset vector */ + uint32_t reset_vec[2] = { + 0x204002b7, /* 0x1000: lui t0,0x20400 */ + 0x00028067, /* 0x1004: jr t0 */ + }; + + /* copy in the reset vector in little_endian byte order */ + for (i = 0; i < sizeof(reset_vec) >> 2; i++) { + reset_vec[i] = cpu_to_le32(reset_vec[i]); + } + rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec), + memmap[SIFIVE_E_MROM].base, &address_space_memory); + + if (machine->kernel_filename) { + load_kernel(machine->kernel_filename); + } +} + +static void riscv_sifive_e_soc_init(Object *obj) +{ + SiFiveESoCState *s = RISCV_E_SOC(obj); + + object_initialize(&s->cpus, sizeof(s->cpus), TYPE_RISCV_HART_ARRAY); + object_property_add_child(obj, "cpus", OBJECT(&s->cpus), + &error_abort); + object_property_set_str(OBJECT(&s->cpus), SIFIVE_E_CPU, "cpu-type", + &error_abort); + object_property_set_int(OBJECT(&s->cpus), smp_cpus, "num-harts", + &error_abort); +} + +static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) +{ + const struct MemmapEntry *memmap = sifive_e_memmap; + + SiFiveESoCState *s = RISCV_E_SOC(dev); + MemoryRegion *sys_mem = get_system_memory(); + MemoryRegion *xip_mem = g_new(MemoryRegion, 1); + MemoryRegion *mask_rom = g_new(MemoryRegion, 1); + + object_property_set_bool(OBJECT(&s->cpus), true, "realized", + &error_abort); + /* Mask ROM */ memory_region_init_rom(mask_rom, NULL, "riscv.sifive.e.mrom", memmap[SIFIVE_E_MROM].size, &error_fatal); @@ -171,23 +208,6 @@ static void riscv_sifive_e_init(MachineState *machine) memmap[SIFIVE_E_XIP].size, &error_fatal); memory_region_set_readonly(xip_mem, true); memory_region_add_subregion(sys_mem, memmap[SIFIVE_E_XIP].base, xip_mem); - - /* Mask ROM reset vector */ - uint32_t reset_vec[2] = { - 0x204002b7, /* 0x1000: lui t0,0x20400 */ - 0x00028067, /* 0x1004: jr t0 */ - }; - - /* copy in the reset vector in little_endian byte order */ - for (i = 0; i < sizeof(reset_vec) >> 2; i++) { - reset_vec[i] = cpu_to_le32(reset_vec[i]); - } - rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec), - memmap[SIFIVE_E_MROM].base, &address_space_memory); - - if (machine->kernel_filename) { - load_kernel(machine->kernel_filename); - } } static void riscv_sifive_e_machine_init(MachineClass *mc) @@ -198,3 +218,27 @@ static void riscv_sifive_e_machine_init(MachineClass *mc) } DEFINE_MACHINE("sifive_e", riscv_sifive_e_machine_init) + +static void riscv_sifive_e_soc_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = riscv_sifive_e_soc_realize; + /* Reason: Uses serial_hds in realize function, thus can't be used twice */ + dc->user_creatable = false; +} + +static const TypeInfo riscv_sifive_e_soc_type_info = { + .name = TYPE_RISCV_E_SOC, + .parent = TYPE_DEVICE, + .instance_size = sizeof(SiFiveESoCState), + .instance_init = riscv_sifive_e_soc_init, + .class_init = riscv_sifive_e_soc_class_init, +}; + +static void riscv_sifive_e_soc_register_types(void) +{ + type_register_static(&riscv_sifive_e_soc_type_info); +} + +type_init(riscv_sifive_e_soc_register_types) diff --git a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h index 12ad6d2ebb..7b6d8aed96 100644 --- a/include/hw/riscv/sifive_e.h +++ b/include/hw/riscv/sifive_e.h @@ -19,13 +19,25 @@ #ifndef HW_SIFIVE_E_H #define HW_SIFIVE_E_H +#define TYPE_RISCV_E_SOC "riscv.sifive.e.soc" +#define RISCV_E_SOC(obj) \ + OBJECT_CHECK(SiFiveESoCState, (obj), TYPE_RISCV_E_SOC) + +typedef struct SiFiveESoCState { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + RISCVHartArrayState cpus; + DeviceState *plic; +} SiFiveESoCState; + typedef struct SiFiveEState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ - RISCVHartArrayState soc; - DeviceState *plic; + SiFiveESoCState soc; } SiFiveEState; enum { From 647a70a10f257bdeba33ff5f1bcb2b26518a9f4c Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 26 Apr 2018 13:54:12 -0700 Subject: [PATCH 3/7] hw/riscv/sifive_plic: Use gpios instead of irqs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of creating the interrupt in lines with qemu_allocate_irq() use qdev_init_gpio_in() as this gives us the ability to use the qdev*gpio*() helpers later on. Signed-off-by: Alistair Francis Suggested-by: Philippe Mathieu-Daudé Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Michael Clark --- hw/riscv/sifive_e.c | 5 +++-- hw/riscv/sifive_plic.c | 6 +----- hw/riscv/sifive_u.c | 5 +++-- hw/riscv/virt.c | 4 ++-- include/hw/riscv/sifive_plic.h | 1 - 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index cb1b6948bf..8a8dbe1c00 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -187,13 +187,14 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) sifive_mmio_emulate(sys_mem, "riscv.sifive.e.gpio0", memmap[SIFIVE_E_GPIO0].base, memmap[SIFIVE_E_GPIO0].size); sifive_uart_create(sys_mem, memmap[SIFIVE_E_UART0].base, - serial_hd(0), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_E_UART0_IRQ]); + serial_hd(0), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_E_UART0_IRQ)); sifive_mmio_emulate(sys_mem, "riscv.sifive.e.qspi0", memmap[SIFIVE_E_QSPI0].base, memmap[SIFIVE_E_QSPI0].size); sifive_mmio_emulate(sys_mem, "riscv.sifive.e.pwm0", memmap[SIFIVE_E_PWM0].base, memmap[SIFIVE_E_PWM0].size); /* sifive_uart_create(sys_mem, memmap[SIFIVE_E_UART1].base, - serial_hd(1), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_E_UART1_IRQ]); */ + serial_hd(1), qdev_get_gpio_in(DEVICE(s->plic), + SIFIVE_E_UART1_IRQ)); */ sifive_mmio_emulate(sys_mem, "riscv.sifive.e.qspi1", memmap[SIFIVE_E_QSPI1].base, memmap[SIFIVE_E_QSPI1].size); sifive_mmio_emulate(sys_mem, "riscv.sifive.e.pwm1", diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c index 874de2ebaf..a91aeb97ab 100644 --- a/hw/riscv/sifive_plic.c +++ b/hw/riscv/sifive_plic.c @@ -435,7 +435,6 @@ static void sifive_plic_irq_request(void *opaque, int irq, int level) static void sifive_plic_realize(DeviceState *dev, Error **errp) { SiFivePLICState *plic = SIFIVE_PLIC(dev); - int i; memory_region_init_io(&plic->mmio, OBJECT(dev), &sifive_plic_ops, plic, TYPE_SIFIVE_PLIC, plic->aperture_size); @@ -448,10 +447,7 @@ static void sifive_plic_realize(DeviceState *dev, Error **errp) plic->claimed = g_new0(uint32_t, plic->bitfield_words); plic->enable = g_new0(uint32_t, plic->bitfield_words * plic->num_addrs); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &plic->mmio); - plic->irqs = g_new0(qemu_irq, plic->num_sources + 1); - for (i = 0; i <= plic->num_sources; i++) { - plic->irqs[i] = qemu_allocate_irq(sifive_plic_irq_request, plic, i); - } + qdev_init_gpio_in(dev, sifive_plic_irq_request, plic->num_sources); } static void sifive_plic_class_init(ObjectClass *klass, void *data) diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index e2b4f97b10..1a548b71e0 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -317,9 +317,10 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) SIFIVE_U_PLIC_CONTEXT_STRIDE, memmap[SIFIVE_U_PLIC].size); sifive_uart_create(system_memory, memmap[SIFIVE_U_UART0].base, - serial_hd(0), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART0_IRQ]); + serial_hd(0), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_UART0_IRQ)); /* sifive_uart_create(system_memory, memmap[SIFIVE_U_UART1].base, - serial_hd(1), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART1_IRQ]); */ + serial_hd(1), qdev_get_gpio_in(DEVICE(s->plic), + SIFIVE_U_UART1_IRQ)); */ sifive_clint_create(memmap[SIFIVE_U_CLINT].base, memmap[SIFIVE_U_CLINT].size, smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE); diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 34d48993a2..aeada2498d 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -380,11 +380,11 @@ static void riscv_virt_board_init(MachineState *machine) for (i = 0; i < VIRTIO_COUNT; i++) { sysbus_create_simple("virtio-mmio", memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size, - SIFIVE_PLIC(s->plic)->irqs[VIRTIO_IRQ + i]); + qdev_get_gpio_in(DEVICE(s->plic), VIRTIO_IRQ + i)); } serial_mm_init(system_memory, memmap[VIRT_UART0].base, - 0, SIFIVE_PLIC(s->plic)->irqs[UART0_IRQ], 399193, + 0, qdev_get_gpio_in(DEVICE(s->plic), UART0_IRQ), 399193, serial_hd(0), DEVICE_LITTLE_ENDIAN); } diff --git a/include/hw/riscv/sifive_plic.h b/include/hw/riscv/sifive_plic.h index 11a5a98df1..2f2af7e686 100644 --- a/include/hw/riscv/sifive_plic.h +++ b/include/hw/riscv/sifive_plic.h @@ -56,7 +56,6 @@ typedef struct SiFivePLICState { uint32_t *claimed; uint32_t *enable; QemuMutex lock; - qemu_irq *irqs; /* config */ char *hart_config; From 2a1a6f6d47f192a12a3765a3558a11d619d25237 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Fri, 11 May 2018 10:22:48 -0700 Subject: [PATCH 4/7] hw/riscv/sifive_u: Set the soc device tree node as a simple-bus To allow Linux to ennumerate devices on the /soc/ node set it as a "simple-bus". Signed-off-by: Alistair Francis Reviewed-by: Michael Clark --- hw/riscv/sifive_u.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 1a548b71e0..d3db8ab9f5 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -97,7 +97,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_add_subnode(fdt, "/soc"); qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0); - qemu_fdt_setprop_string(fdt, "/soc", "compatible", "ucbbar,spike-bare-soc"); + qemu_fdt_setprop_string(fdt, "/soc", "compatible", "simple-bus"); qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2); qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2); From 98ceee7fdc04526b7c264823a14ef5977b90040a Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Fri, 11 May 2018 10:24:00 -0700 Subject: [PATCH 5/7] hw/riscv/sifive_u: Set the interrupt controller number of interrupts Set the interrupt-controller ndev to the correct number taken from the HiFive Unleashed board. Signed-off-by: Alistair Francis Reviewed-by: Michael Clark --- hw/riscv/sifive_u.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index d3db8ab9f5..4d3ba4e624 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -187,7 +187,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, 0x0, memmap[SIFIVE_U_PLIC].size); qemu_fdt_setprop_string(fdt, nodename, "reg-names", "control"); qemu_fdt_setprop_cell(fdt, nodename, "riscv,max-priority", 7); - qemu_fdt_setprop_cell(fdt, nodename, "riscv,ndev", 4); + qemu_fdt_setprop_cell(fdt, nodename, "riscv,ndev", 0x35); qemu_fdt_setprop_cells(fdt, nodename, "phandle", 2); qemu_fdt_setprop_cells(fdt, nodename, "linux,phandle", 2); plic_phandle = qemu_fdt_get_phandle(fdt, nodename); From bde3ab9a9f2c2d08c7dabe77f19528b3f094b620 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Fri, 11 May 2018 10:26:23 -0700 Subject: [PATCH 6/7] hw/riscv/sifive_u: Move the uart device tree node under /soc/ Signed-off-by: Alistair Francis Reviewed-by: Michael Clark --- hw/riscv/sifive_u.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 4d3ba4e624..445fe4f7fb 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -194,7 +194,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, g_free(cells); g_free(nodename); - nodename = g_strdup_printf("/uart@%lx", + nodename = g_strdup_printf("/soc/uart@%lx", (long)memmap[SIFIVE_U_UART0].base); qemu_fdt_add_subnode(fdt, nodename); qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,uart0"); From 5a7f76a3d47a75290868968682c0585d380764a4 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 26 Apr 2018 13:59:08 -0700 Subject: [PATCH 7/7] hw/riscv/sifive_u: Connect the Cadence GEM Ethernet device Connect the Cadence GEM ethernet device. This also requires us to expose the plic interrupt lines. Signed-off-by: Alistair Francis Reviewed-by: Michael Clark --- default-configs/riscv32-softmmu.mak | 2 ++ default-configs/riscv64-softmmu.mak | 2 ++ hw/riscv/sifive_u.c | 50 +++++++++++++++++++++++++++++ include/hw/riscv/sifive_u.h | 9 ++++-- 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/default-configs/riscv32-softmmu.mak b/default-configs/riscv32-softmmu.mak index 20e670d99c..7937c69e22 100644 --- a/default-configs/riscv32-softmmu.mak +++ b/default-configs/riscv32-softmmu.mak @@ -3,3 +3,5 @@ CONFIG_SERIAL=y CONFIG_VIRTIO_MMIO=y include virtio.mak + +CONFIG_CADENCE=y diff --git a/default-configs/riscv64-softmmu.mak b/default-configs/riscv64-softmmu.mak index 20e670d99c..7937c69e22 100644 --- a/default-configs/riscv64-softmmu.mak +++ b/default-configs/riscv64-softmmu.mak @@ -3,3 +3,5 @@ CONFIG_SERIAL=y CONFIG_VIRTIO_MMIO=y include virtio.mak + +CONFIG_CADENCE=y diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 445fe4f7fb..3a6ffeb437 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -60,8 +60,11 @@ static const struct MemmapEntry { [SIFIVE_U_UART0] = { 0x10013000, 0x1000 }, [SIFIVE_U_UART1] = { 0x10023000, 0x1000 }, [SIFIVE_U_DRAM] = { 0x80000000, 0x0 }, + [SIFIVE_U_GEM] = { 0x100900FC, 0x2000 }, }; +#define GEM_REVISION 0x10070109 + static uint64_t load_kernel(const char *kernel_filename) { uint64_t kernel_entry, kernel_high; @@ -194,6 +197,27 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, g_free(cells); g_free(nodename); + nodename = g_strdup_printf("/soc/ethernet@%lx", + (long)memmap[SIFIVE_U_GEM].base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "cdns,macb"); + qemu_fdt_setprop_cells(fdt, nodename, "reg", + 0x0, memmap[SIFIVE_U_GEM].base, + 0x0, memmap[SIFIVE_U_GEM].size); + qemu_fdt_setprop_string(fdt, nodename, "reg-names", "control"); + qemu_fdt_setprop_string(fdt, nodename, "phy-mode", "gmii"); + qemu_fdt_setprop_cells(fdt, nodename, "interrupt-parent", plic_phandle); + qemu_fdt_setprop_cells(fdt, nodename, "interrupts", SIFIVE_U_GEM_IRQ); + qemu_fdt_setprop_cells(fdt, nodename, "#address-cells", 1); + qemu_fdt_setprop_cells(fdt, nodename, "#size-cells", 0); + g_free(nodename); + + nodename = g_strdup_printf("/soc/ethernet@%lx/ethernet-phy@0", + (long)memmap[SIFIVE_U_GEM].base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_cells(fdt, nodename, "reg", 0x0); + g_free(nodename); + nodename = g_strdup_printf("/soc/uart@%lx", (long)memmap[SIFIVE_U_UART0].base); qemu_fdt_add_subnode(fdt, nodename); @@ -286,6 +310,9 @@ static void riscv_sifive_u_soc_init(Object *obj) &error_abort); object_property_set_int(OBJECT(&s->cpus), smp_cpus, "num-harts", &error_abort); + + object_initialize(&s->gem, sizeof(s->gem), TYPE_CADENCE_GEM); + qdev_set_parent_bus(DEVICE(&s->gem), sysbus_get_default()); } static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) @@ -294,6 +321,10 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) const struct MemmapEntry *memmap = sifive_u_memmap; MemoryRegion *system_memory = get_system_memory(); MemoryRegion *mask_rom = g_new(MemoryRegion, 1); + qemu_irq plic_gpios[SIFIVE_U_PLIC_NUM_SOURCES]; + int i; + Error *err = NULL; + NICInfo *nd = &nd_table[0]; object_property_set_bool(OBJECT(&s->cpus), true, "realized", &error_abort); @@ -324,6 +355,25 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) sifive_clint_create(memmap[SIFIVE_U_CLINT].base, memmap[SIFIVE_U_CLINT].size, smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE); + + for (i = 0; i < SIFIVE_U_PLIC_NUM_SOURCES; i++) { + plic_gpios[i] = qdev_get_gpio_in(DEVICE(s->plic), i); + } + + if (nd->used) { + qemu_check_nic_model(nd, TYPE_CADENCE_GEM); + qdev_set_nic_properties(DEVICE(&s->gem), nd); + } + object_property_set_int(OBJECT(&s->gem), GEM_REVISION, "revision", + &error_abort); + object_property_set_bool(OBJECT(&s->gem), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gem), 0, memmap[SIFIVE_U_GEM].base); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gem), 0, + plic_gpios[SIFIVE_U_GEM_IRQ]); } static void riscv_sifive_u_machine_init(MachineClass *mc) diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h index 49f1946539..e8b4d9ffa3 100644 --- a/include/hw/riscv/sifive_u.h +++ b/include/hw/riscv/sifive_u.h @@ -19,6 +19,8 @@ #ifndef HW_SIFIVE_U_H #define HW_SIFIVE_U_H +#include "hw/net/cadence_gem.h" + #define TYPE_RISCV_U_SOC "riscv.sifive.u.soc" #define RISCV_U_SOC(obj) \ OBJECT_CHECK(SiFiveUSoCState, (obj), TYPE_RISCV_U_SOC) @@ -30,6 +32,7 @@ typedef struct SiFiveUSoCState { /*< public >*/ RISCVHartArrayState cpus; DeviceState *plic; + CadenceGEMState gem; } SiFiveUSoCState; typedef struct SiFiveUState { @@ -49,12 +52,14 @@ enum { SIFIVE_U_PLIC, SIFIVE_U_UART0, SIFIVE_U_UART1, - SIFIVE_U_DRAM + SIFIVE_U_DRAM, + SIFIVE_U_GEM }; enum { SIFIVE_U_UART0_IRQ = 3, - SIFIVE_U_UART1_IRQ = 4 + SIFIVE_U_UART1_IRQ = 4, + SIFIVE_U_GEM_IRQ = 0x35 }; enum {