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.dea...@arm.com>
---
 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to