* GIC has two memory regions: Distributor + rdist regions
* CPU interface and virtual cpu interfaces accessesed as System registers
* So cells are created only for Distributor and rdist regions
+ * The hardware domain may not use all the regions. So only copy
+ * what is necessary.
*/
len = len * (d->arch.vgic.nr_regions + 1);
new_cells = xzalloc_bytes(len);
/* Add Generic Redistributor */
size = sizeof(struct acpi_madt_generic_redistributor);
+ /*
+ * The hardware domain may not used all the regions. So only copy
+ * what is necessary.
+ */
for ( i = 0; i < d->arch.vgic.nr_regions; i++ )
{
gicr = (struct acpi_madt_generic_redistributor *)(base_ptr + table_len);
return 0;
}
-static inline unsigned int vgic_v3_rdist_count(struct domain *d)
+/*
+ * Return the maximum number possible of re-distributor regions for
+ * a given domain.
+ */
+static inline unsigned int vgic_v3_max_rdist_count(struct domain *d)
{
return is_hardware_domain(d) ? vgic_v3_hw.nr_rdist_regions :
GUEST_GICV3_RDIST_REGIONS;
int rdist_count, i, ret;
/* Allocate memory for Re-distributor regions */
- rdist_count = vgic_v3_rdist_count(d);
+ rdist_count = vgic_v3_max_rdist_count(d);
rdist_regions = xzalloc_array(struct vgic_rdist_region, rdist_count);
if ( !rdist_regions )
d->arch.vgic.rdist_regions[i].first_cpu = first_cpu;
first_cpu += size / d->arch.vgic.rdist_stride;
+
+ if ( first_cpu >= d->max_vcpus )
+ break;
}
+
+ /*
+ * The hardware domain may not use all the re-distributors
+ * regions (e.g when the number of vCPUs does not match the
+ * number of pCPUs). Update the number of regions to avoid
+ * exposing unused region as they will not get emulated.
+ */
+ d->arch.vgic.nr_regions = i + 1;
}
else
{
}
/* GICD region + number of Redistributors */
- *mmio_count = vgic_v3_rdist_count(d) + 1;
+ *mmio_count = vgic_v3_max_rdist_count(d) + 1;
register_vgic_ops(d, &v3_ops);