Customize device-tree with Gunyah specific properties. Some of these properties include specification of doorbells that need to be created and associated with various interrupts.
Signed-off-by: Srivatsa Vaddagiri <quic_svadd...@quicinc.com> --- accel/stubs/gunyah-stub.c | 5 +++ hw/arm/virt.c | 11 ++++++ include/sysemu/gunyah.h | 2 + target/arm/gunyah.c | 79 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+) diff --git a/accel/stubs/gunyah-stub.c b/accel/stubs/gunyah-stub.c index faeb2af915..e9a8752bb4 100644 --- a/accel/stubs/gunyah-stub.c +++ b/accel/stubs/gunyah-stub.c @@ -16,3 +16,8 @@ int gunyah_arm_set_dtb(__u64 dtb_start, __u64 dtb_size) { return -1; } + +void gunyah_arm_fdt_customize(void *fdt, uint64_t mem_base, + uint32_t gic_phandle) { + return; +} diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 60fbe2f7c4..1aaadc1e1d 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2005,6 +2005,14 @@ static void virt_cpu_post_init(VirtMachineState *vms, MemoryRegion *sysmem) } } +static void virt_modify_dtb(const struct arm_boot_info *binfo, void *fdt) +{ + const VirtMachineState *vms = container_of(binfo, VirtMachineState, + bootinfo); + + gunyah_arm_fdt_customize(fdt, vms->memmap[VIRT_MEM].base, vms->gic_phandle); +} + static void machvirt_init(MachineState *machine) { VirtMachineState *vms = VIRT_MACHINE(machine); @@ -2311,6 +2319,9 @@ static void machvirt_init(MachineState *machine) vms->bootinfo.skip_dtb_autoload = true; vms->bootinfo.firmware_loaded = firmware_loaded; vms->bootinfo.psci_conduit = vms->psci_conduit; + if (gunyah_enabled()) { + vms->bootinfo.modify_dtb = virt_modify_dtb; + } arm_load_kernel(ARM_CPU(first_cpu), machine, &vms->bootinfo); vms->machine_done.notify = virt_machine_done; diff --git a/include/sysemu/gunyah.h b/include/sysemu/gunyah.h index a73d17bfb9..d0c1d8564c 100644 --- a/include/sysemu/gunyah.h +++ b/include/sysemu/gunyah.h @@ -28,5 +28,7 @@ DECLARE_INSTANCE_CHECKER(GUNYAHState, GUNYAH_STATE, TYPE_GUNYAH_ACCEL) int gunyah_arm_set_dtb(__u64 dtb_start, __u64 dtb_size); +void gunyah_arm_fdt_customize(void *fdt, uint64_t mem_base, + uint32_t gic_phandle); #endif /* QEMU_GUNYAH_H */ diff --git a/target/arm/gunyah.c b/target/arm/gunyah.c index 73c1c2a88a..1521f2d414 100644 --- a/target/arm/gunyah.c +++ b/target/arm/gunyah.c @@ -11,6 +11,9 @@ #include "sysemu/gunyah.h" #include "sysemu/gunyah_int.h" #include "linux-headers/linux/gunyah.h" +#include "exec/memory.h" +#include "sysemu/device_tree.h" +#include "hw/arm/fdt.h" /* * Specify location of device-tree in guest address space. @@ -43,3 +46,79 @@ int gunyah_arm_set_dtb(__u64 dtb_start, __u64 dtb_size) return 0; } + +void gunyah_arm_fdt_customize(void *fdt, uint64_t mem_base, + uint32_t gic_phandle) +{ + char *nodename; + int i; + GUNYAHState *state = get_gunyah_state(); + + qemu_fdt_add_subnode(fdt, "/gunyah-vm-config"); + qemu_fdt_setprop_string(fdt, "/gunyah-vm-config", + "image-name", "qemu-vm"); + qemu_fdt_setprop_string(fdt, "/gunyah-vm-config", "os-type", "linux"); + + nodename = g_strdup_printf("/gunyah-vm-config/memory"); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", 2); + qemu_fdt_setprop_cell(fdt, nodename, "#size-cells", 2); + qemu_fdt_setprop_u64(fdt, nodename, "base-address", mem_base); + + g_free(nodename); + + nodename = g_strdup_printf("/gunyah-vm-config/interrupts"); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_cell(fdt, nodename, "config", gic_phandle); + g_free(nodename); + + nodename = g_strdup_printf("/gunyah-vm-config/vcpus"); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "affinity", "proxy"); + g_free(nodename); + + nodename = g_strdup_printf("/gunyah-vm-config/vdevices"); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "generate", "/hypervisor"); + g_free(nodename); + + for (i = 0; i < state->nr_slots; ++i) { + if (!state->slots[i].start || state->slots[i].lend || + state->slots[i].start == mem_base) { + continue; + } + + nodename = g_strdup_printf("/gunyah-vm-config/vdevices/shm-%x", i); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "vdevice-type", "shm"); + qemu_fdt_setprop_string(fdt, nodename, "push-compatible", "dma"); + qemu_fdt_setprop(fdt, nodename, "peer-default", NULL, 0); + qemu_fdt_setprop_u64(fdt, nodename, "dma_base", 0); + g_free(nodename); + + nodename = g_strdup_printf("/gunyah-vm-config/vdevices/shm-%x/memory", + i); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_cell(fdt, nodename, "label", i); + qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", 2); + qemu_fdt_setprop_u64(fdt, nodename, "base", state->slots[i].start); + g_free(nodename); + } + + for (i = 0; i < state->nr_irqs; ++i) { + nodename = g_strdup_printf("/gunyah-vm-config/vdevices/bell-%x", i); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "vdevice-type", "doorbell"); + char *p = g_strdup_printf("/hypervisor/bell-%x", i); + qemu_fdt_setprop_string(fdt, nodename, "generate", p); + g_free(p); + qemu_fdt_setprop_cell(fdt, nodename, "label", i); + qemu_fdt_setprop(fdt, nodename, "peer-default", NULL, 0); + qemu_fdt_setprop(fdt, nodename, "source-can-clear", NULL, 0); + + qemu_fdt_setprop_cells(fdt, nodename, "interrupts", + GIC_FDT_IRQ_TYPE_SPI, i, GIC_FDT_IRQ_FLAGS_LEVEL_HI); + + g_free(nodename); + } +} -- 2.25.1