Build the virt machine with the hex-board helpers instead of its own copies, and drop the machine state that nothing used. The machine, its device tree and its devices are unchanged; virt writes interrupts as the bare line number.
Reviewed-by: Pierrick Bouvier <[email protected]> Signed-off-by: Brian Cain <[email protected]> --- include/hw/hexagon/virt.h | 6 - hw/hexagon/virt.c | 309 ++++---------------------------------- 2 files changed, 26 insertions(+), 289 deletions(-) diff --git a/include/hw/hexagon/virt.h b/include/hw/hexagon/virt.h index 4ca2f1ef859..dc9f22a83c4 100644 --- a/include/hw/hexagon/virt.h +++ b/include/hw/hexagon/virt.h @@ -17,15 +17,9 @@ struct HexagonVirtMachineState { HexagonCommonMachineState parent_obj; int fdt_size; - MemoryRegion *sys; MemoryRegion tcm; - MemoryRegion bios; - Clock *apb_clk; - DeviceState *virtio_mmio[VIRTIO_DEV_COUNT]; }; -void hexagon_load_fdt(const struct HexagonVirtMachineState *vms); - #define TYPE_HEXAGON_VIRT_MACHINE MACHINE_TYPE_NAME("virt") OBJECT_DECLARE_SIMPLE_TYPE(HexagonVirtMachineState, HEXAGON_VIRT_MACHINE) diff --git a/hw/hexagon/virt.c b/hw/hexagon/virt.c index b601cd77a92..d8e91770595 100644 --- a/hw/hexagon/virt.c +++ b/hw/hexagon/virt.c @@ -8,26 +8,15 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/hexagon/virt.h" -#include "elf.h" -#include "hw/char/pl011.h" -#include "hw/core/clock.h" -#include "hw/core/sysbus-fdt.h" #include "hw/hexagon/hexagon.h" +#include "hw/hexagon/hex-board.h" #include "hw/hexagon/hex-subsys.h" #include "hw/core/loader.h" -#include "hw/core/qdev-properties.h" -#include "hw/core/qdev-clock.h" -#include "hw/core/register.h" #include "qemu/error-report.h" -#include "qemu/guest-random.h" #include "qemu/target-info.h" #include "qemu/units.h" #include "machine_cfg_v68n_1024.h.inc" -#include "system/address-spaces.h" #include "system/device_tree.h" -#include "system/reset.h" -#include "system/system.h" -#include <libfdt.h> enum { VIRT_UART0, @@ -49,222 +38,9 @@ static const MemMapEntry base_memmap[] = { }; -static void create_fdt(HexagonVirtMachineState *vms) -{ - MachineState *ms = MACHINE(vms); - void *fdt = create_device_tree(&vms->fdt_size); - uint8_t rng_seed[32]; - - if (!fdt) { - error_report("create_device_tree() failed"); - exit(1); - } - - ms->fdt = fdt; - - qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2); - qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x1); - qemu_fdt_setprop_string(fdt, "/", "model", "hexagon-virt,qemu"); - qemu_fdt_setprop_string(fdt, "/", "compatible", "qcom,sm8150"); - - qemu_fdt_add_subnode(fdt, "/soc"); - qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2); - qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x1); - qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0); - - qemu_fdt_add_subnode(fdt, "/chosen"); - qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed)); - qemu_fdt_setprop(fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed)); -} - -static int32_t fdt_add_l2vic(HexagonVirtMachineState *vms, - const struct hexagon_machine_config *m_cfg) -{ - MachineState *ms = MACHINE(vms); - int32_t l2vic_phandle = qemu_fdt_alloc_phandle(ms->fdt); - char *nodename = g_strdup_printf("/soc/interrupt-controller@%x", - m_cfg->l2vic_base); - const char compat[] = "qcom,h2-pic\0hvm-pic"; - - qemu_fdt_setprop_cell(ms->fdt, "/soc", "interrupt-parent", l2vic_phandle); - - qemu_fdt_add_subnode(ms->fdt, nodename); - qemu_fdt_setprop_cell(ms->fdt, nodename, "#address-cells", 0x0); - qemu_fdt_setprop_cell(ms->fdt, nodename, "#interrupt-cells", 0x1); - qemu_fdt_setprop(ms->fdt, nodename, "compatible", compat, sizeof(compat)); - qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0, - m_cfg->l2vic_base, m_cfg->l2vic_size); - qemu_fdt_setprop(ms->fdt, nodename, "interrupt-controller", NULL, 0); - qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", l2vic_phandle); - - g_free(nodename); - return l2vic_phandle; -} - -static void fdt_add_hvx(HexagonVirtMachineState *vms, - const struct hexagon_machine_config *m_cfg) -{ - const MachineState *ms = MACHINE(vms); - uint32_t vtcm_size_bytes = m_cfg->cfgtable.vtcm_size_kb * 1024; - if (vtcm_size_bytes > 0) { - qemu_fdt_add_subnode(ms->fdt, "/soc/vtcm"); - qemu_fdt_setprop_string(ms->fdt, "/soc/vtcm", "compatible", - "qcom,hexagon_vtcm"); - - assert(sizeof(m_cfg->cfgtable.vtcm_base) == sizeof(uint32_t)); - qemu_fdt_setprop_cells(ms->fdt, "/soc/vtcm", "reg", 0, - m_cfg->cfgtable.vtcm_base << 16, - vtcm_size_bytes); - } - - if (m_cfg->cfgtable.ext_contexts > 0) { - qemu_fdt_add_subnode(ms->fdt, "/soc/hvx"); - qemu_fdt_setprop_string(ms->fdt, "/soc/hvx", "compatible", - "qcom,hexagon-hvx"); - qemu_fdt_setprop_cells(ms->fdt, "/soc/hvx", "qcom,hvx-max-ctxts", - m_cfg->cfgtable.ext_contexts); - qemu_fdt_setprop_cells(ms->fdt, "/soc/hvx", "qcom,hvx-vlength", - m_cfg->cfgtable.hvx_vec_log_length); - } -} - -static int32_t fdt_add_clocks(const HexagonVirtMachineState *vms) -{ - MachineState *ms = MACHINE(vms); - int32_t clk_phandle = qemu_fdt_alloc_phandle(ms->fdt); - - qemu_fdt_add_subnode(ms->fdt, "/apb-pclk"); - qemu_fdt_setprop_string(ms->fdt, "/apb-pclk", "compatible", "fixed-clock"); - qemu_fdt_setprop_cell(ms->fdt, "/apb-pclk", "#clock-cells", 0x0); - qemu_fdt_setprop_cell(ms->fdt, "/apb-pclk", "clock-frequency", 24000000); - qemu_fdt_setprop_string(ms->fdt, "/apb-pclk", "clock-output-names", - "clk24mhz"); - qemu_fdt_setprop_cell(ms->fdt, "/apb-pclk", "phandle", clk_phandle); - - return clk_phandle; -} - -static void fdt_add_uart(const HexagonVirtMachineState *vms, int uart, - int32_t clk_phandle, int32_t l2vic_phandle) -{ - char *nodename; - hwaddr base = base_memmap[uart].base; - hwaddr size = base_memmap[uart].size; - assert(uart == 0); - const char compat[] = "arm,pl011\0arm,primecell"; - const char clocknames[] = "uartclk\0apb_pclk"; - MachineState *ms = MACHINE(vms); - DeviceState *dev; - SysBusDevice *s; - - dev = qdev_new(TYPE_PL011); - s = SYS_BUS_DEVICE(dev); - qdev_prop_set_chr(dev, "chardev", serial_hd(0)); - qdev_connect_clock_in(dev, "clk", vms->apb_clk); - sysbus_realize_and_unref(s, &error_fatal); - sysbus_mmio_map(s, 0, base); - sysbus_connect_irq(s, 0, - qdev_get_gpio_in(vms->parent_obj.l2vic, VIRT_UART0_IRQ)); - - nodename = g_strdup_printf("/pl011@%" PRIx64, base); - qemu_fdt_add_subnode(ms->fdt, nodename); - - /* Note that we can't use setprop_string because of the embedded NUL */ - qemu_fdt_setprop(ms->fdt, nodename, "compatible", compat, sizeof(compat)); - qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0, base, size); - qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupts", VIRT_UART0_IRQ); - qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent", - l2vic_phandle); - qemu_fdt_setprop_cells(ms->fdt, nodename, "clocks", clk_phandle, - clk_phandle); - qemu_fdt_setprop(ms->fdt, nodename, "clock-names", clocknames, - sizeof(clocknames)); - - qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", nodename); - qemu_fdt_add_subnode(ms->fdt, "/aliases"); - qemu_fdt_setprop_string(ms->fdt, "/aliases", "serial0", nodename); - - g_free(nodename); -} - -static void fdt_add_cpu_nodes(const HexagonVirtMachineState *vms) -{ - MachineState *ms = MACHINE(vms); - qemu_fdt_add_subnode(ms->fdt, "/cpus"); - qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#address-cells", 0x1); - qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#size-cells", 0x0); - - /* cpu nodes */ - for (int num = ms->smp.cpus - 1; num >= 0; num--) { - char *nodename = g_strdup_printf("/cpus/cpu@%d", num); - qemu_fdt_add_subnode(ms->fdt, nodename); - qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "cpu"); - qemu_fdt_setprop_cell(ms->fdt, nodename, "reg", num); - qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", - qemu_fdt_alloc_phandle(ms->fdt)); - g_free(nodename); - } -} - -static void create_virtio_devices(HexagonVirtMachineState *vms, - int32_t l2vic_phandle) -{ - MachineState *ms = MACHINE(vms); - hwaddr size = base_memmap[VIRT_MMIO].size; - - for (int i = 0; i < VIRTIO_DEV_COUNT; i++) { - int irq = VIRTIO_IRQ_BASE + i; - hwaddr base = base_memmap[VIRT_MMIO].base + i * size; - char *nodename = g_strdup_printf("/soc/virtio_mmio@%" PRIx64, base); - DeviceState *dev = qdev_new("virtio-mmio"); - SysBusDevice *s = SYS_BUS_DEVICE(dev); - - object_property_add_child(OBJECT(MACHINE(vms)), "virtio-mmio[*]", - OBJECT(dev)); - sysbus_realize_and_unref(s, &error_fatal); - sysbus_mmio_map(s, 0, base); - sysbus_connect_irq(s, 0, - qdev_get_gpio_in(vms->parent_obj.l2vic, irq)); - vms->virtio_mmio[i] = dev; - - qemu_fdt_add_subnode(ms->fdt, nodename); - qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", - "virtio,mmio"); - qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0, base, size); - qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupts", irq); - qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent", - l2vic_phandle); - - g_free(nodename); - } -} - -void hexagon_load_fdt(const HexagonVirtMachineState *vms) -{ - MachineState *ms = MACHINE(vms); - hwaddr fdt_addr = base_memmap[VIRT_FDT].base; - uint32_t fdtsize = vms->fdt_size; - - g_assert(fdtsize <= base_memmap[VIRT_FDT].size); - /* copy in the device tree */ - rom_add_blob_fixed_as("fdt", ms->fdt, fdtsize, fdt_addr, - &address_space_memory); - qemu_register_reset_nosnapshotload( - qemu_fdt_randomize_seeds, - rom_ptr_for_as(&address_space_memory, fdt_addr, fdtsize)); -} - static uint64_t load_kernel(const HexagonVirtMachineState *vms) { - MachineState *ms = MACHINE(vms); - uint64_t entry = 0; - if (load_elf_ram_sym(ms->kernel_filename, NULL, NULL, NULL, &entry, NULL, - NULL, NULL, 0, EM_HEXAGON, 0, 0, &address_space_memory, - false, NULL) > 0) { - return entry; - } - error_report("error loading '%s'", ms->kernel_filename); - exit(1); + return hex_board_load_elf(MACHINE(vms)->kernel_filename, NULL, NULL, NULL); } static uint64_t load_bios(HexagonVirtMachineState *vms) @@ -283,75 +59,42 @@ static uint64_t load_bios(HexagonVirtMachineState *vms) return bios_addr; /* Return entry point at address 0x0 */ } -static void do_cpu_reset(void *opaque) -{ - HexagonCPU *cpu = opaque; - CPUState *cs = CPU(cpu); - cpu_reset(cs); -} - static void virt_init(MachineState *ms) { HexagonVirtMachineState *vms = HEXAGON_VIRT_MACHINE(ms); const struct hexagon_machine_config *m_cfg = &v68n_1024; - int32_t clk_phandle; int32_t l2vic_phandle; + uint64_t start = 0; + bool have_start = false; - create_fdt(vms); + hex_board_create_fdt(ms, "hexagon-virt,qemu", "qcom,sm8150", + &vms->fdt_size); qemu_fdt_setprop_string(ms->fdt, "/chosen", "bootargs", ms->kernel_cmdline); - vms->sys = get_system_memory(); - - /* Create APB clock for peripherals */ - vms->apb_clk = clock_new(OBJECT(ms), "apb-pclk"); - clock_set_hz(vms->apb_clk, 24000000); - hex_subsys_create(&vms->parent_obj, m_cfg, v68_rev); - - if (m_cfg->l2tcm_size) { - memory_region_init_ram(&vms->tcm, NULL, "tcm.ram", m_cfg->l2tcm_size, - &error_fatal); - memory_region_add_subregion(vms->sys, m_cfg->cfgtable.l2tcm_base << 16, - &vms->tcm); - } - - fdt_add_hvx(vms, m_cfg); - - l2vic_phandle = fdt_add_l2vic(vms, m_cfg); - create_virtio_devices(vms, l2vic_phandle); - - g_autofree HexagonCPU **cpus = g_new(HexagonCPU *, ms->smp.cpus); - - for (int i = 0; i < ms->smp.cpus; i++) { - HexagonCPU *cpu = HEXAGON_CPU(object_new(ms->cpu_type)); - qemu_register_reset(do_cpu_reset, cpu); - - if (i == 0) { - if (ms->kernel_filename) { - uint64_t entry = load_kernel(vms); - qdev_prop_set_uint32(DEVICE(cpu), "exec-start-addr", entry); - } else if (ms->firmware) { - uint64_t entry = load_bios(vms); - qdev_prop_set_uint32(DEVICE(cpu), "exec-start-addr", entry); - } - } - qdev_prop_set_uint32(DEVICE(cpu), "htid", i); - qdev_prop_set_bit(DEVICE(cpu), "start-powered-off", (i != 0)); - hex_subsys_add_cpu(&vms->parent_obj, DEVICE(cpu)); - cpus[i] = cpu; - } - - hex_subsys_realize_cluster(&vms->parent_obj); - - for (int i = 0; i < ms->smp.cpus; i++) { - hex_subsys_realize_cpu(&vms->parent_obj, DEVICE(cpus[i]), (i == 0)); + hex_board_create_tcm(m_cfg, &vms->tcm); + hex_board_fdt_add_hvx(ms, m_cfg); + + l2vic_phandle = hex_board_fdt_add_l2vic(ms, m_cfg); + hex_board_create_virtio(ms, base_memmap[VIRT_MMIO].base, + base_memmap[VIRT_MMIO].size, VIRTIO_IRQ_BASE, + VIRTIO_DEV_COUNT, l2vic_phandle); + + if (ms->kernel_filename) { + start = load_kernel(vms); + have_start = true; + } else if (ms->firmware) { + start = load_bios(vms); + have_start = true; } + hex_board_create_cpus(ms, have_start, start); - fdt_add_cpu_nodes(vms); - clk_phandle = fdt_add_clocks(vms); - fdt_add_uart(vms, VIRT_UART0, clk_phandle, l2vic_phandle); + hex_board_fdt_add_cpus(ms); + hex_board_create_uart(ms, base_memmap[VIRT_UART0].base, + base_memmap[VIRT_UART0].size, VIRT_UART0_IRQ, + l2vic_phandle); - hexagon_load_fdt(vms); + hex_board_load_fdt(ms, vms->fdt_size, base_memmap[VIRT_FDT].base); } -- 2.34.1
