@@ -2024,6 +2024,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);
@@ -2335,6 +2343,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;
@@ -35,6 +35,8 @@ 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);
#else /* CONFIG_GUNYAH_IS_POSSIBLE */
@@ -45,6 +47,11 @@ static inline int gunyah_arm_set_dtb(__u64 dtb_start, __u64 dtb_size)
return -1;
}
+static inline void gunyah_arm_fdt_customize(void *fdt, uint64_t mem_base,
+ uint32_t gic_phandle)
+{
+}
+
#endif /* CONFIG_GUNYAH_IS_POSSIBLE */
#endif /* QEMU_GUNYAH_H */
@@ -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);
+ }
+}
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_svaddagi@quicinc.com> --- hw/arm/virt.c | 11 ++++++ include/sysemu/gunyah.h | 7 ++++ target/arm/gunyah.c | 79 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+)