diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2015-06-19 17:05:15 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-06-19 17:05:15 +0100 |
commit | 799810fb2810ec4cb82f12ec9b023e1bfe434d71 (patch) | |
tree | 6788be8c5ede10f11aefae993e88f494a634b22a /hw | |
parent | ffdb1409a79c9cc91afd9f58df625fdca16bf8b9 (diff) | |
parent | a59d31a1ebdce796a469242800db89bf09c94580 (diff) | |
download | qemu-799810fb2810ec4cb82f12ec9b023e1bfe434d71.zip qemu-799810fb2810ec4cb82f12ec9b023e1bfe434d71.tar.gz qemu-799810fb2810ec4cb82f12ec9b023e1bfe434d71.tar.bz2 |
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20150619' into staging
target-arm queue:
* support --semihosting-config,arg=value
* Cortex-R5 support (including implementing them on the Zynq board)
* Cortex-M4 support (without FPU)
* enable vfio-calxeda-xgmac
* don't reset ALIAS sysregs
# gpg: Signature made Fri Jun 19 14:41:54 2015 BST using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
* remotes/pmaydell/tags/pull-target-arm-20150619:
semihosting: add --semihosting-config arg sub-argument
semihosting: create SemihostingConfig structure and semihost.h
arm: xlnx-zynqmp: Add 2xCortexR5 CPUs
arm: xlnx-zynqmp: Add boot-cpu property
arm: xlnx-zynqmp: Preface CPU variables with "apu"
target-arm: Add support for Cortex-R5
target-arm: Implement PMSAv7 MPU
target-arm: Add registers for PMSAv7
target-arm/helper.c: define MPUIR register
target-arm: Do not reset sysregs marked as ALIAS
hw/arm/sysbus-fdt: enable vfio-calxeda-xgmac dynamic instantiation
target-arm: Add the Cortex-M4 CPU
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/arm/sysbus-fdt.c | 73 | ||||
-rw-r--r-- | hw/arm/virt.c | 12 | ||||
-rw-r--r-- | hw/arm/xlnx-ep108.c | 2 | ||||
-rw-r--r-- | hw/arm/xlnx-zynqmp.c | 79 |
4 files changed, 141 insertions, 25 deletions
diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c index 3038b94..9d28797 100644 --- a/hw/arm/sysbus-fdt.c +++ b/hw/arm/sysbus-fdt.c @@ -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 * diff --git a/hw/arm/virt.c b/hw/arm/virt.c index f1e85c8..4e78083a 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -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; diff --git a/hw/arm/xlnx-ep108.c b/hw/arm/xlnx-ep108.c index b924f5e..f94da86 100644 --- a/hw/arm/xlnx-ep108.c +++ b/hw/arm/xlnx-ep108.c @@ -65,7 +65,7 @@ static void xlnx_ep108_init(MachineState *machine) xlnx_ep108_binfo.kernel_cmdline = machine->kernel_cmdline; xlnx_ep108_binfo.initrd_filename = machine->initrd_filename; xlnx_ep108_binfo.loader_start = 0; - arm_load_kernel(&s->soc.cpu[0], &xlnx_ep108_binfo); + arm_load_kernel(s->soc.boot_cpu_ptr, &xlnx_ep108_binfo); } static QEMUMachine xlnx_ep108_machine = { diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index 6b01965..5e72078 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -64,10 +64,17 @@ static void xlnx_zynqmp_init(Object *obj) XlnxZynqMPState *s = XLNX_ZYNQMP(obj); int i; - for (i = 0; i < XLNX_ZYNQMP_NUM_CPUS; i++) { - object_initialize(&s->cpu[i], sizeof(s->cpu[i]), + for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) { + object_initialize(&s->apu_cpu[i], sizeof(s->apu_cpu[i]), "cortex-a53-" TYPE_ARM_CPU); - object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpu[i]), + object_property_add_child(obj, "apu-cpu[*]", OBJECT(&s->apu_cpu[i]), + &error_abort); + } + + for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) { + object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]), + "cortex-r5-" TYPE_ARM_CPU); + object_property_add_child(obj, "rpu-cpu[*]", OBJECT(&s->rpu_cpu[i]), &error_abort); } @@ -90,12 +97,13 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) XlnxZynqMPState *s = XLNX_ZYNQMP(dev); MemoryRegion *system_memory = get_system_memory(); uint8_t i; + const char *boot_cpu = s->boot_cpu ? s->boot_cpu : "apu-cpu[0]"; qemu_irq gic_spi[GIC_NUM_SPI_INTR]; Error *err = NULL; qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", GIC_NUM_SPI_INTR + 32); qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2); - qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", XLNX_ZYNQMP_NUM_CPUS); + qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", XLNX_ZYNQMP_NUM_APU_CPUS); object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); if (err) { error_propagate((errp), (err)); @@ -121,38 +129,77 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) } } - for (i = 0; i < XLNX_ZYNQMP_NUM_CPUS; i++) { + for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) { qemu_irq irq; + char *name; - object_property_set_int(OBJECT(&s->cpu[i]), QEMU_PSCI_CONDUIT_SMC, + object_property_set_int(OBJECT(&s->apu_cpu[i]), QEMU_PSCI_CONDUIT_SMC, "psci-conduit", &error_abort); - if (i > 0) { + + name = object_get_canonical_path_component(OBJECT(&s->apu_cpu[i])); + if (strcmp(name, boot_cpu)) { /* Secondary CPUs start in PSCI powered-down state */ - object_property_set_bool(OBJECT(&s->cpu[i]), true, + object_property_set_bool(OBJECT(&s->apu_cpu[i]), true, "start-powered-off", &error_abort); + } else { + s->boot_cpu_ptr = &s->apu_cpu[i]; } - object_property_set_int(OBJECT(&s->cpu[i]), GIC_BASE_ADDR, + object_property_set_int(OBJECT(&s->apu_cpu[i]), GIC_BASE_ADDR, "reset-cbar", &err); if (err) { error_propagate((errp), (err)); return; } - object_property_set_bool(OBJECT(&s->cpu[i]), true, "realized", &err); + object_property_set_bool(OBJECT(&s->apu_cpu[i]), true, "realized", + &err); if (err) { error_propagate((errp), (err)); return; } sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i, - qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_IRQ)); + qdev_get_gpio_in(DEVICE(&s->apu_cpu[i]), + ARM_CPU_IRQ)); irq = qdev_get_gpio_in(DEVICE(&s->gic), arm_gic_ppi_index(i, ARM_PHYS_TIMER_PPI)); - qdev_connect_gpio_out(DEVICE(&s->cpu[i]), 0, irq); + qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 0, irq); irq = qdev_get_gpio_in(DEVICE(&s->gic), arm_gic_ppi_index(i, ARM_VIRT_TIMER_PPI)); - qdev_connect_gpio_out(DEVICE(&s->cpu[i]), 1, irq); + qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 1, irq); + } + + for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) { + char *name; + + name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i])); + if (strcmp(name, boot_cpu)) { + /* Secondary CPUs start in PSCI powered-down state */ + object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, + "start-powered-off", &error_abort); + } else { + s->boot_cpu_ptr = &s->rpu_cpu[i]; + } + + object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "reset-hivecs", + &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + + object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "realized", + &err); + if (err) { + error_propagate((errp), (err)); + return; + } + } + + if (!s->boot_cpu_ptr) { + error_setg(errp, "ZynqMP Boot cpu %s not found\n", boot_cpu); + return; } for (i = 0; i < GIC_NUM_SPI_INTR; i++) { @@ -188,10 +235,16 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) } } +static Property xlnx_zynqmp_props[] = { + DEFINE_PROP_STRING("boot-cpu", XlnxZynqMPState, boot_cpu), + DEFINE_PROP_END_OF_LIST() +}; + static void xlnx_zynqmp_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); + dc->props = xlnx_zynqmp_props; dc->realize = xlnx_zynqmp_realize; } |