xen/arm: Let the toolstack configure the number of SPIs
authorJulien Grall <julien.grall@linaro.org>
Tue, 28 Apr 2015 14:32:25 +0000 (15:32 +0100)
committerIan Campbell <ian.campbell@citrix.com>
Fri, 8 May 2015 14:41:57 +0000 (15:41 +0100)
Each domain may have a different number of IRQs depending on the devices
assigned to it.

Rather than re-using the number of IRQs used by the hardwared GIC, let
the toolstack specify the number of SPIs when the domain is created.
This will avoid wasting memory.

To calculate the number of SPIs, we take advantage of the fact that the
libxl interface can only expose 1:1 mapping and look for the largest SPI
in the list.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Wei Liu <wei.liu2@citrix.com>
tools/libxc/xc_domain.c
tools/libxl/libxl_arm.c
xen/arch/arm/domain.c
xen/arch/arm/setup.c
xen/arch/arm/vgic.c
xen/include/asm-arm/vgic.h
xen/include/public/arch-arm.h

index 7cb36d9481143e8c254041cc2794e41dea57600d..d1dec6cf1b46baae10d6a0b5523cb8a84fb87778 100644 (file)
@@ -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;
index 946618c5ed1e2317d513de81e3c46bf2df8508aa..5a5cb3fb45ca728ca803b447308dfb3cb455843a 100644 (file)
@@ -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;
index e4d6fc88def6b8032d5c89dc4ae6b5798ab257f9..180bccc676dadded267e64801afcedab3c72124c 100644 (file)
@@ -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 )
index 4ec7c1347423b2d5fb661f2364d82029daddb492..711562cf18771e03f1310343fdb2798cfcf1b855 100644 (file)
@@ -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) )
index 8f91962eeedb9c9b3e0624534e3b8237d120ff0c..0d30e2ca15877dc8ba0894d2c246ad0229287d42 100644 (file)
@@ -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 > (1020 - NR_LOCAL_IRQS) )
+        return -EINVAL;
+
+    d->arch.vgic.nr_spis = nr_spis;
 
     switch ( gic_hw_version() )
     {
index aba0d8044c67a8de2ee9263e76cff7d515a55e36..647f2fee837caadac95b6318f01ed752c4c58754 100644 (file)
@@ -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);
index ed7e98f11592ebaacfda0a7868eaf8ee66caf783..c029e0f4ee1f203da49698357008893d9d23bba2 100644 (file)
@@ -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