Hi Brian,

On 29/5/26 23:59, Brian Cain wrote:
From: Brian Cain <[email protected]>

Signed-off-by: Brian Cain <[email protected]>
---
  configs/devices/hexagon-softmmu/default.mak |   1 +
  configs/targets/hexagon-softmmu.mak         |   1 +
  include/hw/hexagon/virt.h                   |  31 ++
  hw/hexagon/virt.c                           | 463 ++++++++++++++++++++
  hw/hexagon/Kconfig                          |  10 +
  hw/hexagon/meson.build                      |   1 +
  tests/qemu-iotests/testenv.py               |   1 +
  7 files changed, 508 insertions(+)
  create mode 100644 include/hw/hexagon/virt.h
  create mode 100644 hw/hexagon/virt.c


+static int32_t fdt_add_hvm_pic_node(HexagonVirtMachineState *vms,
+                                     const struct hexagon_machine_config 
*m_cfg)
+{

[*] Dead code (see below)

+    MachineState *ms = MACHINE(vms);
+    int32_t irq_phandle = qemu_fdt_alloc_phandle(ms->fdt);
+
+    qemu_fdt_setprop_cell(ms->fdt, "/soc", "interrupt-parent",
+                          irq_phandle);
+
+    qemu_fdt_add_subnode(ms->fdt, "/soc/interrupt-controller");
+    qemu_fdt_setprop_cell(ms->fdt, "/soc/interrupt-controller",
+                          "#address-cells", 2);
+    qemu_fdt_setprop_cell(ms->fdt, "/soc/interrupt-controller",
+                          "#interrupt-cells", 2);
+    qemu_fdt_setprop_string(ms->fdt, "/soc/interrupt-controller", "compatible",
+                            "qcom,h2-pic,hvm-pic");
+    qemu_fdt_setprop(ms->fdt, "/soc/interrupt-controller",
+                     "interrupt-controller", NULL, 0);
+    qemu_fdt_setprop_cell(ms->fdt, "/soc/interrupt-controller", "phandle",
+                          irq_phandle);
+
+    sysbus_mmio_map(SYS_BUS_DEVICE(vms->l2vic), 1,
+                    m_cfg->cfgtable.fastl2vic_base << 16);
+
+    return irq_phandle;
+}


+static void fdt_add_uart(const HexagonVirtMachineState *vms, int uart,
+                         int32_t irq_phandle, int32_t clk_phandle)
+{
+    char *nodename;
+    hwaddr base = base_memmap[uart].base;
+    hwaddr size = base_memmap[uart].size;
+    assert(uart == 0);
+    int irq = irqmap[VIRT_UART0 + uart];
+    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);
+    if (vms->l2vic) {
+        sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->l2vic, irq));

[*] Dead code (see below)

+    }
+
+    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);
+    if (vms->l2vic) {

[*] Dead code (see below)

+        qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
+                               32 + irq, 0);
+        qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
+                              irq_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_virtio_devices(const HexagonVirtMachineState *vms,
+                                   int32_t irq_phandle)
+{
+    MachineState *ms = MACHINE(vms);
+    /* VirtIO MMIO devices */
+    for (int i = 0; i < VIRTIO_DEV_COUNT; i++) {
+        char *nodename;
+        int irq = irqmap[VIRT_MMIO] + i;
+        size_t size = base_memmap[VIRT_MMIO].size;
+        hwaddr base = base_memmap[VIRT_MMIO].base + i * size;
+
+        nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
+        qemu_fdt_add_subnode(ms->fdt, nodename);
+        qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", 
"virtio,mmio");
+        qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 2, base, 1,
+                                     size);
+        qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts", irq, 0);
+        qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
+                              irq_phandle);
+
+        sysbus_create_simple(
+            "virtio-mmio", base,
+            qdev_get_gpio_in(vms->l2vic, irqmap[VIRT_MMIO] + i));

[*] Unreachable otherwise that'd crash... Dead code.

+
+        g_free(nodename);
+    }
+}


+static void virt_init(MachineState *ms)
+{
+    HexagonVirtMachineState *vms = HEXAGON_VIRT_MACHINE(ms);
+    const struct hexagon_machine_config *m_cfg = &v68n_1024;
+    DeviceState *gsregs_dev;
+    DeviceState *tlb_dev;
+    DeviceState *cpu0;
+    int32_t irq_phandle = -1;
+    int32_t clk_phandle;
+
+    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);
+
+    memory_region_init_ram(&vms->parent_obj.ram, NULL, "ddr.ram",
+                           ms->ram_size, &error_fatal);
+    memory_region_add_subregion(vms->sys, 0x0, &vms->parent_obj.ram);
+
+    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);
+    }
+
+    memory_region_init_rom(&vms->parent_obj.cfgtable_rom, NULL,
+                           "config_table.rom", sizeof(m_cfg->cfgtable),
+                           &error_fatal);
+    memory_region_add_subregion(vms->sys, m_cfg->cfgbase,
+                                &vms->parent_obj.cfgtable_rom);
+    fdt_add_hvx(vms, m_cfg);
+
+    gsregs_dev = qdev_new(TYPE_HEXAGON_GLOBALREG);
+    object_property_add_child(OBJECT(ms), "global-regs", OBJECT(gsregs_dev));
+    qdev_prop_set_uint64(gsregs_dev, "config-table-addr", m_cfg->cfgbase);
+    qdev_prop_set_uint32(gsregs_dev, "dsp-rev", v68_rev);
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(gsregs_dev), &error_fatal);
+
+    tlb_dev = qdev_new(TYPE_HEXAGON_TLB);
+    object_property_add_child(OBJECT(ms), "tlb", OBJECT(tlb_dev));
+    qdev_prop_set_uint32(tlb_dev, "num-entries",
+                         m_cfg->cfgtable.jtlb_size_entries);
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(tlb_dev), &error_fatal);
+
+    cpu0 = NULL;
+    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) {
+            cpu0 = DEVICE(cpu);
+            if (ms->kernel_filename) {
+                uint64_t entry = load_kernel(vms);
+                qdev_prop_set_uint32(cpu0, "exec-start-addr", entry);
+            } else if (ms->firmware) {
+                uint64_t entry = load_bios(vms);
+                qdev_prop_set_uint32(cpu0, "exec-start-addr", entry);
+            }
+        }
+        qdev_prop_set_uint32(DEVICE(cpu), "htid", i);
+        qdev_prop_set_bit(DEVICE(cpu), "start-powered-off", (i != 0));
+        object_property_set_link(OBJECT(cpu), "global-regs",
+                                 OBJECT(gsregs_dev), &error_fatal);
+        object_property_set_link(OBJECT(cpu), "tlb",
+                                 OBJECT(tlb_dev), &error_fatal);
+
+        qdev_realize_and_unref(DEVICE(cpu), NULL, &error_fatal);
+    }
+    /* TODO: enable l2vic when l2vic device arrives */
+    if (object_class_by_name("l2vic")) {
+        vms->l2vic = sysbus_create_varargs(
+            "l2vic", m_cfg->l2vic_base,

I'm really confused by this code, since no "l2vic" exist. Yet I suppose.
Can't we just remove this code and re-introduce once with the former
addition? I'd also remove the fdt_add_hvm_pic_node() and
fdt_add_virtio_devices() methods.
Normally all code should be used / tested, and IIUC [*] is dead code.

+            qdev_get_gpio_in(cpu0, 0),
+            qdev_get_gpio_in(cpu0, 1),
+            qdev_get_gpio_in(cpu0, 2),
+            qdev_get_gpio_in(cpu0, 3),
+            qdev_get_gpio_in(cpu0, 4),
+            qdev_get_gpio_in(cpu0, 5),
+            qdev_get_gpio_in(cpu0, 6),
+            qdev_get_gpio_in(cpu0, 7), NULL);
+
+        irq_phandle = fdt_add_hvm_pic_node(vms, m_cfg);
+        fdt_add_virtio_devices(vms, irq_phandle);
+        fdt_add_gpt_node(vms);
+    }
+
+    fdt_add_cpu_nodes(vms);
+    clk_phandle = fdt_add_clocks(vms);
+    fdt_add_uart(vms, VIRT_UART0, irq_phandle, clk_phandle);
+
+    rom_add_blob_fixed_as("config_table.rom", &m_cfg->cfgtable,
+                          sizeof(m_cfg->cfgtable), m_cfg->cfgbase,
+                          &address_space_memory);
+
+    hexagon_load_fdt(vms);
+}
Rest of the patch LGTM.

Regards,

Phil.



Reply via email to