From: Julien Grall Date: Tue, 28 Apr 2015 14:32:25 +0000 (+0100) Subject: xen/arm: Let the toolstack configure the number of SPIs X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~3287 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=986b4d2cfa757bfc82bfd3d627069a0a6fd50b0f;p=xen.git xen/arm: Let the toolstack configure the number of SPIs 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 Acked-by: Ian Campbell Cc: Ian Jackson Cc: Jan Beulich Cc: Wei Liu --- diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index 7cb36d9481..d1dec6cf1b 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -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; diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c index 946618c5ed..5a5cb3fb45 100644 --- a/tools/libxl/libxl_arm.c +++ b/tools/libxl/libxl_arm.c @@ -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; diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index e4d6fc88de..180bccc676 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -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 ) diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c index 4ec7c13474..711562cf18 100644 --- a/xen/arch/arm/setup.c +++ b/xen/arch/arm/setup.c @@ -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) ) diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index 8f91962eee..0d30e2ca15 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -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() ) { diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h index aba0d8044c..647f2fee83 100644 --- a/xen/include/asm-arm/vgic.h +++ b/xen/include/asm-arm/vgic.h @@ -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); diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index ed7e98f115..c029e0f4ee 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -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