diff options
author | Luc Michel <luc.michel@greensocs.com> | 2018-08-14 17:17:21 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-08-14 17:17:21 +0100 |
commit | 55ef3233586ab7acc3bbd970d4324bee8cc95112 (patch) | |
tree | 4f11a992e11d42d6229543b3d4122242f9ebec52 /hw/arm/virt.c | |
parent | 75b749af0c944a416dd5f334fc483f01110c3f5c (diff) |
arm/virt: Add support for GICv2 virtualization extensions
Add support for GICv2 virtualization extensions by mapping the necessary
I/O regions and connecting the maintenance IRQ lines.
Declare those additions in the device tree and in the ACPI tables.
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20180727095421.386-21-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/arm/virt.c')
-rw-r--r-- | hw/arm/virt.c | 52 |
1 files changed, 43 insertions, 9 deletions
diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 281ddcdf6e..0807be985c 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -131,6 +131,8 @@ static const MemMapEntry a15memmap[] = { [VIRT_GIC_DIST] = { 0x08000000, 0x00010000 }, [VIRT_GIC_CPU] = { 0x08010000, 0x00010000 }, [VIRT_GIC_V2M] = { 0x08020000, 0x00001000 }, + [VIRT_GIC_HYP] = { 0x08030000, 0x00010000 }, + [VIRT_GIC_VCPU] = { 0x08040000, 0x00010000 }, /* The space in between here is reserved for GICv3 CPU/vCPU/HYP */ [VIRT_GIC_ITS] = { 0x08080000, 0x00020000 }, /* This redistributor space allows up to 2*64kB*123 CPUs */ @@ -440,18 +442,33 @@ static void fdt_add_gic_node(VirtMachineState *vms) if (vms->virt) { qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts", - GIC_FDT_IRQ_TYPE_PPI, ARCH_GICV3_MAINT_IRQ, + GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ, GIC_FDT_IRQ_FLAGS_LEVEL_HI); } } else { /* 'cortex-a15-gic' means 'GIC v2' */ qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "arm,cortex-a15-gic"); - qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", - 2, vms->memmap[VIRT_GIC_DIST].base, - 2, vms->memmap[VIRT_GIC_DIST].size, - 2, vms->memmap[VIRT_GIC_CPU].base, - 2, vms->memmap[VIRT_GIC_CPU].size); + if (!vms->virt) { + qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", + 2, vms->memmap[VIRT_GIC_DIST].base, + 2, vms->memmap[VIRT_GIC_DIST].size, + 2, vms->memmap[VIRT_GIC_CPU].base, + 2, vms->memmap[VIRT_GIC_CPU].size); + } else { + qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", + 2, vms->memmap[VIRT_GIC_DIST].base, + 2, vms->memmap[VIRT_GIC_DIST].size, + 2, vms->memmap[VIRT_GIC_CPU].base, + 2, vms->memmap[VIRT_GIC_CPU].size, + 2, vms->memmap[VIRT_GIC_HYP].base, + 2, vms->memmap[VIRT_GIC_HYP].size, + 2, vms->memmap[VIRT_GIC_VCPU].base, + 2, vms->memmap[VIRT_GIC_VCPU].size); + qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts", + GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ, + GIC_FDT_IRQ_FLAGS_LEVEL_HI); + } } qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", vms->gic_phandle); @@ -573,6 +590,11 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic) qdev_prop_set_uint32(gicdev, "redist-region-count[1]", MIN(smp_cpus - redist0_count, redist1_capacity)); } + } else { + if (!kvm_irqchip_in_kernel()) { + qdev_prop_set_bit(gicdev, "has-virtualization-extensions", + vms->virt); + } } qdev_init_nofail(gicdev); gicbusdev = SYS_BUS_DEVICE(gicdev); @@ -584,6 +606,10 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic) } } else { sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base); + if (vms->virt) { + sysbus_mmio_map(gicbusdev, 2, vms->memmap[VIRT_GIC_HYP].base); + sysbus_mmio_map(gicbusdev, 3, vms->memmap[VIRT_GIC_VCPU].base); + } } /* Wire the outputs from each CPU's generic timer and the GICv3 @@ -610,9 +636,17 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic) ppibase + timer_irq[irq])); } - qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 0, - qdev_get_gpio_in(gicdev, ppibase - + ARCH_GICV3_MAINT_IRQ)); + if (type == 3) { + qemu_irq irq = qdev_get_gpio_in(gicdev, + ppibase + ARCH_GIC_MAINT_IRQ); + qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", + 0, irq); + } else if (vms->virt) { + qemu_irq irq = qdev_get_gpio_in(gicdev, + ppibase + ARCH_GIC_MAINT_IRQ); + sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq); + } + qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, qdev_get_gpio_in(gicdev, ppibase + VIRTUAL_PMU_IRQ)); |