On Wed, Jun 13, 2018 at 10:48:41AM +0200, Eric Auger wrote:
> 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>
>
> ---
>
> v2 -> v3:
> - remove spare space
> ---
> hw/arm/virt.c | 18 +++++++++++++++++-
> 1 file changed, 17 insertions(+), 1 deletion(-)
>
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 5c02cc5..2a1c0fb 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -528,6 +528,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();
>
> @@ -547,14 +548,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);
> }
> @@ -1350,6 +1365,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;
> }
> --
> 2.5.5
>
>
Reviewed-by: Andrew Jones <drjones@redhat.com>