if ( res )
return res;
- res = fdt_property_cell(fdt, "#redistributor-regions", gicv3.rdist_count);
+ res = fdt_property_cell(fdt, "#redistributor-regions",
+ d->arch.vgic.nr_regions);
if ( res )
return res;
* 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.
*/
- new_len = new_len * (gicv3.rdist_count + 1);
+ new_len = new_len * (d->arch.vgic.nr_regions + 1);
hw_reg = dt_get_property(gic, "reg", &len);
if ( !hw_reg )
/* Add Generic Redistributor */
size = sizeof(struct acpi_madt_generic_redistributor);
- for ( i = 0; i < gicv3.rdist_count; i++ )
+ /*
+ * 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);
gicr->header.type = ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR;
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)
{
/*
* Normally there is only one GICv3 redistributor region.
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 / GICV3_GICR_SIZE;
+
+ 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;
+
d->arch.vgic.intid_bits = vgic_v3_hw.intid_bits;
}
else
}
/* GICD region + number of Redistributors */
- *mmio_count = vgic_v3_rdist_count(d) + 1;
+ *mmio_count = vgic_v3_max_rdist_count(d) + 1;
/* one region per ITS */
*mmio_count += vgic_v3_its_count(d);