hw/arm/sysbus-fdt: enable vfio-calxeda-xgmac dynamic instantiation
This patch allows the instantiation of the vfio-calxeda-xgmac device from the QEMU command line (-device vfio-calxeda-xgmac,host="<device>"). A specialized device tree node is created for the guest, containing compat, dma-coherent, reg and interrupts properties. Signed-off-by: Eric Auger <eric.auger@linaro.org> Acked-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 1434455898-17895-1-git-send-email-eric.auger@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
							parent
							
								
									ba890a9b25
								
							
						
					
					
						commit
						decf4f807b
					
				| 
						 | 
				
			
			@ -26,6 +26,9 @@
 | 
			
		|||
#include "sysemu/device_tree.h"
 | 
			
		||||
#include "hw/platform-bus.h"
 | 
			
		||||
#include "sysemu/sysemu.h"
 | 
			
		||||
#include "hw/vfio/vfio-platform.h"
 | 
			
		||||
#include "hw/vfio/vfio-calxeda-xgmac.h"
 | 
			
		||||
#include "hw/arm/fdt.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * internal struct that contains the information to create dynamic
 | 
			
		||||
| 
						 | 
				
			
			@ -53,11 +56,81 @@ typedef struct NodeCreationPair {
 | 
			
		|||
    int (*add_fdt_node_fn)(SysBusDevice *sbdev, void *opaque);
 | 
			
		||||
} NodeCreationPair;
 | 
			
		||||
 | 
			
		||||
/* Device Specific Code */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * add_calxeda_midway_xgmac_fdt_node
 | 
			
		||||
 *
 | 
			
		||||
 * Generates a simple node with following properties:
 | 
			
		||||
 * compatible string, regs, interrupts, dma-coherent
 | 
			
		||||
 */
 | 
			
		||||
static int add_calxeda_midway_xgmac_fdt_node(SysBusDevice *sbdev, void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    PlatformBusFDTData *data = opaque;
 | 
			
		||||
    PlatformBusDevice *pbus = data->pbus;
 | 
			
		||||
    void *fdt = data->fdt;
 | 
			
		||||
    const char *parent_node = data->pbus_node_name;
 | 
			
		||||
    int compat_str_len, i, ret = -1;
 | 
			
		||||
    char *nodename;
 | 
			
		||||
    uint32_t *irq_attr, *reg_attr;
 | 
			
		||||
    uint64_t mmio_base, irq_number;
 | 
			
		||||
    VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
 | 
			
		||||
    VFIODevice *vbasedev = &vdev->vbasedev;
 | 
			
		||||
 | 
			
		||||
    mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
 | 
			
		||||
    nodename = g_strdup_printf("%s/%s@%" PRIx64, parent_node,
 | 
			
		||||
                               vbasedev->name, mmio_base);
 | 
			
		||||
    qemu_fdt_add_subnode(fdt, nodename);
 | 
			
		||||
 | 
			
		||||
    compat_str_len = strlen(vdev->compat) + 1;
 | 
			
		||||
    qemu_fdt_setprop(fdt, nodename, "compatible",
 | 
			
		||||
                          vdev->compat, compat_str_len);
 | 
			
		||||
 | 
			
		||||
    qemu_fdt_setprop(fdt, nodename, "dma-coherent", "", 0);
 | 
			
		||||
 | 
			
		||||
    reg_attr = g_new(uint32_t, vbasedev->num_regions * 2);
 | 
			
		||||
    for (i = 0; i < vbasedev->num_regions; i++) {
 | 
			
		||||
        mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, i);
 | 
			
		||||
        reg_attr[2 * i] = cpu_to_be32(mmio_base);
 | 
			
		||||
        reg_attr[2 * i + 1] = cpu_to_be32(
 | 
			
		||||
                                memory_region_size(&vdev->regions[i]->mem));
 | 
			
		||||
    }
 | 
			
		||||
    ret = qemu_fdt_setprop(fdt, nodename, "reg", reg_attr,
 | 
			
		||||
                           vbasedev->num_regions * 2 * sizeof(uint32_t));
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        error_report("could not set reg property of node %s", nodename);
 | 
			
		||||
        goto fail_reg;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    irq_attr = g_new(uint32_t, vbasedev->num_irqs * 3);
 | 
			
		||||
    for (i = 0; i < vbasedev->num_irqs; i++) {
 | 
			
		||||
        irq_number = platform_bus_get_irqn(pbus, sbdev , i)
 | 
			
		||||
                         + data->irq_start;
 | 
			
		||||
        irq_attr[3 * i] = cpu_to_be32(GIC_FDT_IRQ_TYPE_SPI);
 | 
			
		||||
        irq_attr[3 * i + 1] = cpu_to_be32(irq_number);
 | 
			
		||||
        irq_attr[3 * i + 2] = cpu_to_be32(GIC_FDT_IRQ_FLAGS_LEVEL_HI);
 | 
			
		||||
    }
 | 
			
		||||
    ret = qemu_fdt_setprop(fdt, nodename, "interrupts",
 | 
			
		||||
                     irq_attr, vbasedev->num_irqs * 3 * sizeof(uint32_t));
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        error_report("could not set interrupts property of node %s",
 | 
			
		||||
                     nodename);
 | 
			
		||||
    }
 | 
			
		||||
    g_free(irq_attr);
 | 
			
		||||
fail_reg:
 | 
			
		||||
    g_free(reg_attr);
 | 
			
		||||
    g_free(nodename);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* list of supported dynamic sysbus devices */
 | 
			
		||||
static const NodeCreationPair add_fdt_node_functions[] = {
 | 
			
		||||
    {TYPE_VFIO_CALXEDA_XGMAC, add_calxeda_midway_xgmac_fdt_node},
 | 
			
		||||
    {"", NULL}, /* last element */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Generic Code */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * add_fdt_node - add the device tree node of a dynamic sysbus device
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,21 +47,11 @@
 | 
			
		|||
#include "hw/arm/virt-acpi-build.h"
 | 
			
		||||
#include "hw/arm/sysbus-fdt.h"
 | 
			
		||||
#include "hw/platform-bus.h"
 | 
			
		||||
#include "hw/arm/fdt.h"
 | 
			
		||||
 | 
			
		||||
/* Number of external interrupt lines to configure the GIC with */
 | 
			
		||||
#define NUM_IRQS 256
 | 
			
		||||
 | 
			
		||||
#define GIC_FDT_IRQ_TYPE_SPI 0
 | 
			
		||||
#define GIC_FDT_IRQ_TYPE_PPI 1
 | 
			
		||||
 | 
			
		||||
#define GIC_FDT_IRQ_FLAGS_EDGE_LO_HI 1
 | 
			
		||||
#define GIC_FDT_IRQ_FLAGS_EDGE_HI_LO 2
 | 
			
		||||
#define GIC_FDT_IRQ_FLAGS_LEVEL_HI 4
 | 
			
		||||
#define GIC_FDT_IRQ_FLAGS_LEVEL_LO 8
 | 
			
		||||
 | 
			
		||||
#define GIC_FDT_IRQ_PPI_CPU_START 8
 | 
			
		||||
#define GIC_FDT_IRQ_PPI_CPU_WIDTH 8
 | 
			
		||||
 | 
			
		||||
#define PLATFORM_BUS_NUM_IRQS 64
 | 
			
		||||
 | 
			
		||||
static ARMPlatformBusSystemParams platform_bus_params;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,34 @@
 | 
			
		|||
/*
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2015 Linaro Limited
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify it
 | 
			
		||||
 * under the terms and conditions of the GNU General Public License,
 | 
			
		||||
 * version 2 or later, as published by the Free Software Foundation.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
			
		||||
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
			
		||||
 * more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License along with
 | 
			
		||||
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 * Define macros useful when building ARM device tree nodes
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef QEMU_ARM_FDT_H
 | 
			
		||||
#define QEMU_ARM_FDT_H
 | 
			
		||||
 | 
			
		||||
#define GIC_FDT_IRQ_TYPE_SPI 0
 | 
			
		||||
#define GIC_FDT_IRQ_TYPE_PPI 1
 | 
			
		||||
 | 
			
		||||
#define GIC_FDT_IRQ_FLAGS_EDGE_LO_HI 1
 | 
			
		||||
#define GIC_FDT_IRQ_FLAGS_EDGE_HI_LO 2
 | 
			
		||||
#define GIC_FDT_IRQ_FLAGS_LEVEL_HI 4
 | 
			
		||||
#define GIC_FDT_IRQ_FLAGS_LEVEL_LO 8
 | 
			
		||||
 | 
			
		||||
#define GIC_FDT_IRQ_PPI_CPU_START 8
 | 
			
		||||
#define GIC_FDT_IRQ_PPI_CPU_WIDTH 8
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
		Loading…
	
		Reference in New Issue