aboutsummaryrefslogtreecommitdiff
path: root/hw/arm
diff options
context:
space:
mode:
authorEric Auger <eric.auger@redhat.com>2018-06-22 13:28:37 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-06-22 13:28:37 +0100
commit03d72fa13cef2454aeaedea387a2e505c77481b4 (patch)
tree53a69301e1167c0973e6626016d8af9fbd78ca7e /hw/arm
parenta1de312f5690a1a4f3ff37319045f6ec7bdfcd31 (diff)
downloadqemu-03d72fa13cef2454aeaedea387a2e505c77481b4.zip
qemu-03d72fa13cef2454aeaedea387a2e505c77481b4.tar.gz
qemu-03d72fa13cef2454aeaedea387a2e505c77481b4.tar.bz2
hw/arm/virt: Register two redistributor regions when necessary
With a VGICv3 KVM device, if the number of vcpus exceeds the capacity of the legacy redistributor region (123 redistributors), we now attempt to register a second redistributor region. Up to 512 redistributors can fit in this latter on top of the 123 allowed by the legacy redistributor region. Registering this second redistributor region is possible if the host kernel supports the following VGICv3 KVM device group/attribute: KVM_DEV_ARM_VGIC_GRP_ADDR/KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION. In case the host kernel does not support the registration of several redistributor regions and the requested number of vcpus exceeds the capacity of the legacy redistributor region, the GICv3 device initialization fails with a proper error message and qemu exits. At the moment the max number of vcpus still is capped by the virt machine class max_cpus. Signed-off-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Andrew Jones <drjones@redhat.com> Message-id: 1529072910-16156-8-git-send-email-eric.auger@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/arm')
-rw-r--r--hw/arm/virt.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index e5e7606..9b9bc50 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -529,6 +529,7 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
SysBusDevice *gicbusdev;
const char *gictype;
int type = vms->gic_version, i;
+ uint32_t nb_redist_regions = 0;
gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
@@ -548,14 +549,28 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
- qdev_prop_set_uint32(gicdev, "len-redist-region-count", 1);
+ nb_redist_regions = virt_gicv3_redist_region_count(vms);
+
+ qdev_prop_set_uint32(gicdev, "len-redist-region-count",
+ nb_redist_regions);
qdev_prop_set_uint32(gicdev, "redist-region-count[0]", redist0_count);
+
+ if (nb_redist_regions == 2) {
+ uint32_t redist1_capacity =
+ vms->memmap[VIRT_GIC_REDIST2].size / GICV3_REDIST_SIZE;
+
+ qdev_prop_set_uint32(gicdev, "redist-region-count[1]",
+ MIN(smp_cpus - redist0_count, redist1_capacity));
+ }
}
qdev_init_nofail(gicdev);
gicbusdev = SYS_BUS_DEVICE(gicdev);
sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
if (type == 3) {
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
+ if (nb_redist_regions == 2) {
+ sysbus_mmio_map(gicbusdev, 2, vms->memmap[VIRT_GIC_REDIST2].base);
+ }
} else {
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base);
}
@@ -1351,6 +1366,7 @@ static void machvirt_init(MachineState *machine)
*/
if (vms->gic_version == 3) {
virt_max_cpus = vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
+ virt_max_cpus += vms->memmap[VIRT_GIC_REDIST2].size / GICV3_REDIST_SIZE;
} else {
virt_max_cpus = GIC_NCPU;
}