@@ -67,6 +67,7 @@ int xc_domain_create(xc_interface *xch,
/* No arch-specific configuration for now */
#elif defined (__arm__) || defined(__aarch64__)
config.gic_version = XEN_DOMCTL_CONFIG_GIC_DEFAULT;
+ config.nr_spis = 0;
#else
errno = ENOSYS;
return -1;
@@ -39,6 +39,27 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
libxl_domain_config *d_config,
xc_domain_configuration_t *xc_config)
{
+ uint32_t nr_spis = 0;
+ unsigned int i;
+
+ for (i = 0; i < d_config->b_info.num_irqs; i++) {
+ uint32_t irq = d_config->b_info.irqs[i];
+ uint32_t spi;
+
+ if (irq < 32)
+ continue;
+
+ spi = irq - 32;
+
+ if (nr_spis <= spi)
+ nr_spis = spi + 1;
+ }
+
+ LOG(DEBUG, "Configure the domain");
+
+ xc_config->nr_spis = nr_spis;
+ LOG(DEBUG, " - Allocate %u SPIs", nr_spis);
+
xc_config->gic_version = XEN_DOMCTL_CONFIG_GIC_DEFAULT;
return 0;
@@ -590,7 +590,7 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags,
if ( (rc = gicv_setup(d)) != 0 )
goto fail;
- if ( (rc = domain_vgic_init(d)) != 0 )
+ if ( (rc = domain_vgic_init(d, config->nr_spis)) != 0 )
goto fail;
if ( (rc = domain_vtimer_init(d)) != 0 )
@@ -830,6 +830,7 @@ void __init start_xen(unsigned long boot_phys_offset,
/* Create initial domain 0. */
/* The vGIC for DOM0 is exactly emulating the hardware GIC */
config.gic_version = XEN_DOMCTL_CONFIG_GIC_DEFAULT;
+ config.nr_spis = gic_number_lines() - 32;
dom0 = domain_create(0, 0, 0, &config);
if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
@@ -68,16 +68,17 @@ static void vgic_init_pending_irq(struct pending_irq *p, unsigned int virq)
p->irq = virq;
}
-int domain_vgic_init(struct domain *d)
+int domain_vgic_init(struct domain *d, unsigned int nr_spis)
{
int i;
d->arch.vgic.ctlr = 0;
- if ( is_hardware_domain(d) )
- d->arch.vgic.nr_spis = gic_number_lines() - 32;
- else
- d->arch.vgic.nr_spis = 0; /* We don't need SPIs for the guest */
+ /* Limit the number of virtual SPIs supported to (1020 - 32) = 988 */
+ if ( (nr_spis + NR_LOCAL_IRQS) > 1020 )
+ return -EINVAL;
+
+ d->arch.vgic.nr_spis = nr_spis;
switch ( gic_hw_version() )
{
@@ -177,7 +177,7 @@ enum gic_sgi_mode;
#define vgic_num_irqs(d) ((d)->arch.vgic.nr_spis + 32)
-extern int domain_vgic_init(struct domain *d);
+extern int domain_vgic_init(struct domain *d, unsigned int nr_spis);
extern void domain_vgic_free(struct domain *d);
extern int vcpu_vgic_init(struct vcpu *v);
extern struct vcpu *vgic_get_target_vcpu(struct vcpu *v, unsigned int irq);
@@ -315,6 +315,8 @@ typedef uint64_t xen_callback_t;
struct xen_arch_domainconfig {
/* IN/OUT */
uint8_t gic_version;
+ /* IN */
+ uint32_t nr_spis;
};
#endif