mirror of
https://github.com/clearlinux/kvmtool.git
synced 2026-06-16 02:15:47 +00:00
kvm tools: virtio: move fdt node generation into core mmio code
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@arm.com> Signed-off-by: Pekka Enberg <penberg@kernel.org>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+37
-1
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user