Generating fdt nodes for virtio-mmio devices should be in the core code, not hidden inside the architecture code for ARM. This patch reworks the .data field of struct device_header for virtio-mmio devices, so that it contains a function pointer which can be called to generate the FDT node for each device. Signed-off-by: Will Deacon <will.deacon@xxxxxxx> --- tools/kvm/arm/fdt.c | 30 ++++++++++-------------------- tools/kvm/virtio/mmio.c | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 21 deletions(-) diff --git a/tools/kvm/arm/fdt.c b/tools/kvm/arm/fdt.c index c61bf58..7198fe8 100644 --- a/tools/kvm/arm/fdt.c +++ b/tools/kvm/arm/fdt.c @@ -69,28 +69,15 @@ static void generate_cpu_nodes(void *fdt, struct kvm *kvm) _FDT(fdt_end_node(fdt)); } -#define DEVICE_NAME_MAX_LEN 32 -static void generate_virtio_mmio_node(void *fdt, struct virtio_mmio *vmmio) +static void generate_irq_prop(void *fdt, u8 irq) { - char dev_name[DEVICE_NAME_MAX_LEN]; - u64 addr = vmmio->addr; - u64 reg_prop[] = { - cpu_to_fdt64(addr), - cpu_to_fdt64(VIRTIO_MMIO_IO_SIZE) - }; u32 irq_prop[] = { cpu_to_fdt32(GIC_FDT_IRQ_TYPE_SPI), - cpu_to_fdt32(vmmio->irq - GIC_SPI_IRQ_BASE), + cpu_to_fdt32(irq - GIC_SPI_IRQ_BASE), cpu_to_fdt32(GIC_FDT_IRQ_FLAGS_EDGE_LO_HI), }; - snprintf(dev_name, DEVICE_NAME_MAX_LEN, "virtio@%llx", addr); - - _FDT(fdt_begin_node(fdt, dev_name)); - _FDT(fdt_property_string(fdt, "compatible", "virtio,mmio")); - _FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop))); _FDT(fdt_property(fdt, "interrupts", irq_prop, sizeof(irq_prop))); - _FDT(fdt_end_node(fdt)); } static int setup_fdt(struct kvm *kvm) @@ -105,8 +92,10 @@ static int setup_fdt(struct kvm *kvm) void *fdt = staging_fdt; void *fdt_dest = guest_flat_to_host(kvm, kvm->arch.dtb_guest_start); - void (*generate_fdt_nodes)(void *, struct kvm *, u32) - = kvm->cpus[0]->generate_fdt_nodes; + void (*generate_mmio_fdt_nodes)(void *, struct device_header *, + void (*)(void *, u8)); + void (*generate_cpu_peripheral_fdt_nodes)(void *, struct kvm *, u32) + = kvm->cpus[0]->generate_fdt_nodes; /* Create new tree without a reserve map */ _FDT(fdt_create(fdt, FDT_MAX_SIZE)); @@ -144,13 +133,14 @@ static int setup_fdt(struct kvm *kvm) /* CPU and peripherals (interrupt controller, timers, etc) */ generate_cpu_nodes(fdt, kvm); - if (generate_fdt_nodes) - generate_fdt_nodes(fdt, kvm, gic_phandle); + if (generate_cpu_peripheral_fdt_nodes) + generate_cpu_peripheral_fdt_nodes(fdt, kvm, gic_phandle); /* Virtio MMIO devices */ dev_hdr = device__first_dev(DEVICE_BUS_MMIO); while (dev_hdr) { - generate_virtio_mmio_node(fdt, dev_hdr->data); + generate_mmio_fdt_nodes = dev_hdr->data; + generate_mmio_fdt_nodes(fdt, dev_hdr, generate_irq_prop); dev_hdr = device__next_dev(dev_hdr); } diff --git a/tools/kvm/virtio/mmio.c b/tools/kvm/virtio/mmio.c index bd30f37..a4e4855 100644 --- a/tools/kvm/virtio/mmio.c +++ b/tools/kvm/virtio/mmio.c @@ -5,6 +5,7 @@ #include "kvm/virtio.h" #include "kvm/kvm.h" #include "kvm/irq.h" +#include "kvm/fdt.h" #include <linux/virtio_mmio.h> #include <string.h> @@ -215,6 +216,41 @@ static void virtio_mmio_mmio_callback(u64 addr, u8 *data, u32 len, virtio_mmio_config_in(offset, data, len, ptr); } +#ifdef CONFIG_HAS_LIBFDT +#define DEVICE_NAME_MAX_LEN 32 +static void generate_virtio_mmio_fdt_node(void *fdt, + struct device_header *dev_hdr, + void (*generate_irq_prop)(void *fdt, + u8 irq)) +{ + char dev_name[DEVICE_NAME_MAX_LEN]; + struct virtio_mmio *vmmio = container_of(dev_hdr, + struct virtio_mmio, + dev_hdr); + u64 addr = vmmio->addr; + u64 reg_prop[] = { + cpu_to_fdt64(addr), + cpu_to_fdt64(VIRTIO_MMIO_IO_SIZE), + }; + + snprintf(dev_name, DEVICE_NAME_MAX_LEN, "virtio@%llx", addr); + + _FDT(fdt_begin_node(fdt, dev_name)); + _FDT(fdt_property_string(fdt, "compatible", "virtio,mmio")); + _FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop))); + generate_irq_prop(fdt, vmmio->irq); + _FDT(fdt_end_node(fdt)); +} +#else +static void generate_virtio_mmio_fdt_node(void *fdt, + struct device_header *dev_hdr, + void (*generate_irq_prop)(void *fdt, + u8 irq)) +{ + die("Unable to generate device tree nodes without libfdt\n"); +} +#endif + int virtio_mmio_init(struct kvm *kvm, void *dev, struct virtio_device *vdev, int device_id, int subsys_id, int class) { @@ -241,7 +277,7 @@ int virtio_mmio_init(struct kvm *kvm, void *dev, struct virtio_device *vdev, vmmio->irq = line; vmmio->dev_hdr = (struct device_header) { .bus_type = DEVICE_BUS_MMIO, - .data = vmmio, + .data = generate_virtio_mmio_fdt_node, }; device__register(&vmmio->dev_hdr); -- 1.8.0 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html