hw/intc/arm_gicv3: Introduce redist-region-count array property
To prepare for multiple redistributor regions, we introduce an array of uint32_t properties that stores the redistributor count of each redistributor region. Non accelerated VGICv3 only supports a single redistributor region. The capacity of all redist regions is checked against the number of vcpus. Machvirt is updated to set those properties, ie. a single redistributor region with count set to the number of vcpus capped by 123. Signed-off-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Andrew Jones <drjones@redhat.com> Message-id: 1529072910-16156-4-git-send-email-eric.auger@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
							parent
							
								
									19d1bd0b58
								
							
						
					
					
						commit
						1e575b6664
					
				@ -523,6 +523,15 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
 | 
			
		||||
    if (!kvm_irqchip_in_kernel()) {
 | 
			
		||||
        qdev_prop_set_bit(gicdev, "has-security-extensions", vms->secure);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (type == 3) {
 | 
			
		||||
        uint32_t redist0_capacity =
 | 
			
		||||
                    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);
 | 
			
		||||
        qdev_prop_set_uint32(gicdev, "redist-region-count[0]", redist0_count);
 | 
			
		||||
    }
 | 
			
		||||
    qdev_init_nofail(gicdev);
 | 
			
		||||
    gicbusdev = SYS_BUS_DEVICE(gicdev);
 | 
			
		||||
    sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
 | 
			
		||||
@ -1322,7 +1331,7 @@ static void machvirt_init(MachineState *machine)
 | 
			
		||||
     * many redistributors we can fit into the memory map.
 | 
			
		||||
     */
 | 
			
		||||
    if (vms->gic_version == 3) {
 | 
			
		||||
        virt_max_cpus = vms->memmap[VIRT_GIC_REDIST].size / 0x20000;
 | 
			
		||||
        virt_max_cpus = vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
 | 
			
		||||
    } else {
 | 
			
		||||
        virt_max_cpus = GIC_NCPU;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -373,7 +373,17 @@ static void arm_gic_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    gicv3_init_irqs_and_mmio(s, gicv3_set_irq, gic_ops);
 | 
			
		||||
    if (s->nb_redist_regions != 1) {
 | 
			
		||||
        error_setg(errp, "VGICv3 redist region number(%d) not equal to 1",
 | 
			
		||||
                   s->nb_redist_regions);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    gicv3_init_irqs_and_mmio(s, gicv3_set_irq, gic_ops, &local_err);
 | 
			
		||||
    if (local_err) {
 | 
			
		||||
        error_propagate(errp, local_err);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    gicv3_init_cpuif(s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -247,11 +247,22 @@ static const VMStateDescription vmstate_gicv3 = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
 | 
			
		||||
                              const MemoryRegionOps *ops)
 | 
			
		||||
                              const MemoryRegionOps *ops, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    SysBusDevice *sbd = SYS_BUS_DEVICE(s);
 | 
			
		||||
    int rdist_capacity = 0;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < s->nb_redist_regions; i++) {
 | 
			
		||||
        rdist_capacity += s->redist_region_count[i];
 | 
			
		||||
    }
 | 
			
		||||
    if (rdist_capacity < s->num_cpu) {
 | 
			
		||||
        error_setg(errp, "Capacity of the redist regions(%d) "
 | 
			
		||||
                   "is less than number of vcpus(%d)",
 | 
			
		||||
                   rdist_capacity, s->num_cpu);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
 | 
			
		||||
     * GPIO array layout is thus:
 | 
			
		||||
     *  [0..N-1] spi
 | 
			
		||||
@ -277,11 +288,18 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
 | 
			
		||||
 | 
			
		||||
    memory_region_init_io(&s->iomem_dist, OBJECT(s), ops, s,
 | 
			
		||||
                          "gicv3_dist", 0x10000);
 | 
			
		||||
    memory_region_init_io(&s->iomem_redist, OBJECT(s), ops ? &ops[1] : NULL, s,
 | 
			
		||||
                          "gicv3_redist", 0x20000 * s->num_cpu);
 | 
			
		||||
 | 
			
		||||
    sysbus_init_mmio(sbd, &s->iomem_dist);
 | 
			
		||||
    sysbus_init_mmio(sbd, &s->iomem_redist);
 | 
			
		||||
 | 
			
		||||
    s->iomem_redist = g_new0(MemoryRegion, s->nb_redist_regions);
 | 
			
		||||
    for (i = 0; i < s->nb_redist_regions; i++) {
 | 
			
		||||
        char *name = g_strdup_printf("gicv3_redist_region[%d]", i);
 | 
			
		||||
 | 
			
		||||
        memory_region_init_io(&s->iomem_redist[i], OBJECT(s),
 | 
			
		||||
                              ops ? &ops[1] : NULL, s, name,
 | 
			
		||||
                              s->redist_region_count[i] * GICV3_REDIST_SIZE);
 | 
			
		||||
        sysbus_init_mmio(sbd, &s->iomem_redist[i]);
 | 
			
		||||
        g_free(name);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
@ -363,6 +381,13 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void arm_gicv3_finalize(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    GICv3State *s = ARM_GICV3_COMMON(obj);
 | 
			
		||||
 | 
			
		||||
    g_free(s->redist_region_count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void arm_gicv3_common_reset(DeviceState *dev)
 | 
			
		||||
{
 | 
			
		||||
    GICv3State *s = ARM_GICV3_COMMON(dev);
 | 
			
		||||
@ -467,6 +492,8 @@ static Property arm_gicv3_common_properties[] = {
 | 
			
		||||
    DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32),
 | 
			
		||||
    DEFINE_PROP_UINT32("revision", GICv3State, revision, 3),
 | 
			
		||||
    DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0),
 | 
			
		||||
    DEFINE_PROP_ARRAY("redist-region-count", GICv3State, nb_redist_regions,
 | 
			
		||||
                      redist_region_count, qdev_prop_uint32, uint32_t),
 | 
			
		||||
    DEFINE_PROP_END_OF_LIST(),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -488,6 +515,7 @@ static const TypeInfo arm_gicv3_common_type = {
 | 
			
		||||
    .instance_size = sizeof(GICv3State),
 | 
			
		||||
    .class_size = sizeof(ARMGICv3CommonClass),
 | 
			
		||||
    .class_init = arm_gicv3_common_class_init,
 | 
			
		||||
    .instance_finalize = arm_gicv3_finalize,
 | 
			
		||||
    .abstract = true,
 | 
			
		||||
    .interfaces = (InterfaceInfo []) {
 | 
			
		||||
        { TYPE_ARM_LINUX_BOOT_IF },
 | 
			
		||||
 | 
			
		||||
@ -784,7 +784,11 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL);
 | 
			
		||||
    gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL, &local_err);
 | 
			
		||||
    if (local_err) {
 | 
			
		||||
        error_propagate(errp, local_err);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < s->num_cpu; i++) {
 | 
			
		||||
        ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i));
 | 
			
		||||
@ -808,7 +812,8 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
 | 
			
		||||
    kvm_arm_register_device(&s->iomem_dist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
 | 
			
		||||
                            KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd, 0);
 | 
			
		||||
    kvm_arm_register_device(&s->iomem_redist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
 | 
			
		||||
    kvm_arm_register_device(&s->iomem_redist[0], -1,
 | 
			
		||||
                            KVM_DEV_ARM_VGIC_GRP_ADDR,
 | 
			
		||||
                            KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd, 0);
 | 
			
		||||
 | 
			
		||||
    if (kvm_has_gsi_routing()) {
 | 
			
		||||
 | 
			
		||||
@ -35,6 +35,8 @@
 | 
			
		||||
#define GICV3_MAXIRQ 1020
 | 
			
		||||
#define GICV3_MAXSPI (GICV3_MAXIRQ - GIC_INTERNAL)
 | 
			
		||||
 | 
			
		||||
#define GICV3_REDIST_SIZE 0x20000
 | 
			
		||||
 | 
			
		||||
/* Number of SGI target-list bits */
 | 
			
		||||
#define GICV3_TARGETLIST_BITS 16
 | 
			
		||||
 | 
			
		||||
@ -210,7 +212,9 @@ struct GICv3State {
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
 | 
			
		||||
    MemoryRegion iomem_dist; /* Distributor */
 | 
			
		||||
    MemoryRegion iomem_redist; /* Redistributors */
 | 
			
		||||
    MemoryRegion *iomem_redist; /* Redistributor Regions */
 | 
			
		||||
    uint32_t *redist_region_count; /* redistributor count within each region */
 | 
			
		||||
    uint32_t nb_redist_regions; /* number of redist regions */
 | 
			
		||||
 | 
			
		||||
    uint32_t num_cpu;
 | 
			
		||||
    uint32_t num_irq;
 | 
			
		||||
@ -292,6 +296,6 @@ typedef struct ARMGICv3CommonClass {
 | 
			
		||||
} ARMGICv3CommonClass;
 | 
			
		||||
 | 
			
		||||
void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
 | 
			
		||||
                              const MemoryRegionOps *ops);
 | 
			
		||||
                              const MemoryRegionOps *ops, Error **errp);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user