[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 4/5] xen/domain: Allocate d->vcpu[] earlier during domain_create()
The ARM code has a chicken-and-egg problem. One of the vGIC_v3 emulations wants to know d->max_vcpus to be able to size itself appropriately, but the current order of initialisation requires the vGIC to be set up before the requested number of vcpus can be checked. Move the range checking of config->max_vcpus into sanitise_domain_config() path, which allows for the allocation of d->vcpu[] and d->max_vcpus to happen earlier during create, and in particular, before the call to arch_domain_create(). The x86 side is fairly easy, and implements the logical equivalent of domain_max_vcpus() but using XEN_DOMCTL_CDF_hvm_guest rather than is_hvm_domain(). For the ARM side, re-purpose vgic_max_vcpus() to take a domctl vGIC version, and return the maximum number of supported vCPUs, reusing 0 for "version not supported". To avoid exporting the vgic_ops structures (which are in the process of being replaced), hard code the upper limits. This allows for the removal of the domain_max_vcpus() infrastructure, which is done to prevent it being reused incorrectly in the future. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx> --- CC: Wei Liu <wei.liu2@xxxxxxxxxx> CC: Stefano Stabellini <sstabellini@xxxxxxxxxx> CC: Julien Grall <julien.grall@xxxxxxx> v3: * Fix 4092/4096 typo * Fix build in NEW_VGIC case --- xen/arch/arm/domain.c | 18 ++++++++++++++++++ xen/arch/arm/vgic-v2.c | 1 - xen/arch/arm/vgic-v3.c | 5 ----- xen/arch/arm/vgic.c | 22 ++++++++++++++++++++-- xen/arch/arm/vgic/vgic-init.c | 3 --- xen/arch/arm/vgic/vgic.c | 9 +++++---- xen/arch/x86/domain.c | 10 ++++++++++ xen/common/domain.c | 33 ++++++++++++++++++++------------- xen/include/asm-arm/domain.h | 6 ------ xen/include/asm-arm/vgic.h | 5 ++--- xen/include/asm-x86/domain.h | 2 -- 11 files changed, 75 insertions(+), 39 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 71ad1f9..2c5ff65 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -601,6 +601,8 @@ void vcpu_switch_to_aarch64_mode(struct vcpu *v) int arch_sanitise_domain_config(struct xen_domctl_createdomain *config) { + unsigned int max_vcpus; + if ( config->flags != (XEN_DOMCTL_CDF_hvm_guest | XEN_DOMCTL_CDF_hap) ) { dprintk(XENLOG_INFO, "Unsupported configuration %#x\n", config->flags); @@ -626,6 +628,22 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config) } } + /* Calculate the maximum number of vcpus from the selected GIC version. */ + max_vcpus = vgic_max_vcpus(config->arch.gic_version); + + if ( max_vcpus == 0 ) + { + dprintk(XENLOG_INFO, "Unsupported GIC version\n"); + return -EINVAL; + } + + if ( config->max_vcpus > max_vcpus ) + { + dprintk(XENLOG_INFO, "Requested vCPUs (%u) exceeds max (%u)\n", + config->max_vcpus, max_vcpus); + return -EINVAL; + } + return 0; } diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c index bf77899..64b141f 100644 --- a/xen/arch/arm/vgic-v2.c +++ b/xen/arch/arm/vgic-v2.c @@ -725,7 +725,6 @@ static const struct vgic_ops vgic_v2_ops = { .domain_free = vgic_v2_domain_free, .lpi_to_pending = vgic_v2_lpi_to_pending, .lpi_get_priority = vgic_v2_lpi_get_priority, - .max_vcpus = 8, }; int vgic_v2_init(struct domain *d, int *mmio_count) diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c index c14bcd8..519cc72 100644 --- a/xen/arch/arm/vgic-v3.c +++ b/xen/arch/arm/vgic-v3.c @@ -1822,11 +1822,6 @@ static const struct vgic_ops v3_ops = { .emulate_reg = vgic_v3_emulate_reg, .lpi_to_pending = vgic_v3_lpi_to_pending, .lpi_get_priority = vgic_v3_lpi_get_priority, - /* - * We use both AFF1 and AFF0 in (v)MPIDR. Thus, the max number of CPU - * that can be supported is up to 4096(==256*16) in theory. - */ - .max_vcpus = 4096, }; int vgic_v3_init(struct domain *d, int *mmio_count) diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index 5a4f082..e05b6b6 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -667,9 +667,27 @@ void vgic_free_virq(struct domain *d, unsigned int virq) clear_bit(virq, d->arch.vgic.allocated_irqs); } -unsigned int vgic_max_vcpus(const struct domain *d) +unsigned int vgic_max_vcpus(unsigned int domctl_vgic_version) { - return min_t(unsigned int, MAX_VIRT_CPUS, d->arch.vgic.handler->max_vcpus); + unsigned int max_vcpus; + + switch ( domctl_vgic_version ) + { + case XEN_DOMCTL_CONFIG_GIC_V2: + max_vcpus = 8; + break; + +#ifdef CONFIG_GICV3 + case XEN_DOMCTL_CONFIG_GIC_V3: + max_vcpus = 4096; + break; +#endif + + default: + return 0; + } + + return min_t(unsigned int, MAX_VIRT_CPUS, max_vcpus); } /* diff --git a/xen/arch/arm/vgic/vgic-init.c b/xen/arch/arm/vgic/vgic-init.c index bfd3d09..62ae553 100644 --- a/xen/arch/arm/vgic/vgic-init.c +++ b/xen/arch/arm/vgic/vgic-init.c @@ -112,9 +112,6 @@ int domain_vgic_register(struct domain *d, int *mmio_count) BUG(); } - if ( d->max_vcpus > domain_max_vcpus(d) ) - return -E2BIG; - d->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF; d->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF; d->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF; diff --git a/xen/arch/arm/vgic/vgic.c b/xen/arch/arm/vgic/vgic.c index 7c3cfc5..b8ff840 100644 --- a/xen/arch/arm/vgic/vgic.c +++ b/xen/arch/arm/vgic/vgic.c @@ -949,17 +949,18 @@ void vgic_sync_hardware_irq(struct domain *d, spin_unlock_irqrestore(&desc->lock, flags); } -unsigned int vgic_max_vcpus(const struct domain *d) +unsigned int vgic_max_vcpus(unsigned int domctl_vgic_version) { unsigned int vgic_vcpu_limit; - switch ( d->arch.vgic.version ) + switch ( domctl_vgic_version ) { - case GIC_V2: + case XEN_DOMCTL_CONFIG_GIC_V2: vgic_vcpu_limit = VGIC_V2_MAX_CPUS; break; + default: - BUG(); + return 0; } return min_t(unsigned int, MAX_VIRT_CPUS, vgic_vcpu_limit); diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 272fd84..295b10c 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -421,6 +421,7 @@ void arch_vcpu_destroy(struct vcpu *v) int arch_sanitise_domain_config(struct xen_domctl_createdomain *config) { bool hvm = config->flags & XEN_DOMCTL_CDF_hvm_guest; + unsigned int max_vcpus; if ( hvm ? !hvm_enabled : !IS_ENABLED(CONFIG_PV) ) { @@ -428,6 +429,15 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config) return -EINVAL; } + max_vcpus = hvm ? HVM_MAX_VCPUS : MAX_VIRT_CPUS; + + if ( config->max_vcpus > max_vcpus ) + { + dprintk(XENLOG_INFO, "Requested vCPUs (%u) exceeds max (%u)\n", + config->max_vcpus, max_vcpus); + return -EINVAL; + } + return 0; } diff --git a/xen/common/domain.c b/xen/common/domain.c index f69f405..78cc524 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -300,6 +300,12 @@ static int sanitise_domain_config(struct xen_domctl_createdomain *config) return -EINVAL; } + if ( config->max_vcpus < 1 ) + { + dprintk(XENLOG_INFO, "No vCPUS\n"); + return -EINVAL; + } + return arch_sanitise_domain_config(config); } @@ -345,6 +351,20 @@ struct domain *domain_create(domid_t domid, TRACE_1D(TRC_DOM0_DOM_ADD, d->domain_id); + /* + * Allocate d->vcpu[] and set ->max_vcpus up early. Various per-domain + * resources want to be sized based on max_vcpus. + */ + if ( !is_system_domain(d) ) + { + err = -ENOMEM; + d->vcpu = xzalloc_array(struct vcpu *, config->max_vcpus); + if ( !d->vcpu ) + goto fail; + + d->max_vcpus = config->max_vcpus; + } + lock_profile_register_struct(LOCKPROF_TYPE_PERDOM, d, domid, "Domain"); if ( (err = xsm_alloc_security_domain(d)) != 0 ) @@ -396,19 +416,6 @@ struct domain *domain_create(domid_t domid, if ( !is_idle_domain(d) ) { - /* Check d->max_vcpus and allocate d->vcpu[]. */ - err = -EINVAL; - if ( config->max_vcpus < 1 || - config->max_vcpus > domain_max_vcpus(d) ) - goto fail; - - err = -ENOMEM; - d->vcpu = xzalloc_array(struct vcpu *, config->max_vcpus); - if ( !d->vcpu ) - goto fail; - - d->max_vcpus = config->max_vcpus; - watchdog_domain_init(d); init_status |= INIT_watchdog; diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h index d682307..175de44 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -208,12 +208,6 @@ void vcpu_show_execution_state(struct vcpu *); void vcpu_show_registers(const struct vcpu *); void vcpu_switch_to_aarch64_mode(struct vcpu *); -/* On ARM, the number of VCPUs is limited by the type of GIC emulated. */ -static inline unsigned int domain_max_vcpus(const struct domain *d) -{ - return vgic_max_vcpus(d); -} - /* * Due to the restriction of GICv3, the number of vCPUs in AFF0 is * limited to 16, thus only the first 4 bits of AFF0 are legal. We will diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h index 56ed5fe..447d24e 100644 --- a/xen/include/asm-arm/vgic.h +++ b/xen/include/asm-arm/vgic.h @@ -234,8 +234,6 @@ struct vgic_ops { /* lookup the struct pending_irq for a given LPI interrupt */ struct pending_irq *(*lpi_to_pending)(struct domain *d, unsigned int vlpi); int (*lpi_get_priority)(struct domain *d, uint32_t vlpi); - /* Maximum number of vCPU supported */ - const unsigned int max_vcpus; }; /* Number of ranks of interrupt registers for a domain */ @@ -350,7 +348,8 @@ extern void vgic_clear_pending_irqs(struct vcpu *v); extern bool vgic_emulate(struct cpu_user_regs *regs, union hsr hsr); -unsigned int vgic_max_vcpus(const struct domain *d); +/* Maximum vCPUs for a specific vGIC version, or 0 for unsupported. */ +unsigned int vgic_max_vcpus(unsigned int domctl_vgic_version); void vgic_v2_setup_hw(paddr_t dbase, paddr_t cbase, paddr_t csize, paddr_t vbase, uint32_t aliased_offset); diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 643e69a..277f99f 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -664,8 +664,6 @@ unsigned long pv_guest_cr4_to_real_cr4(const struct vcpu *v); X86_CR4_OSXSAVE | X86_CR4_SMEP | \ X86_CR4_FSGSBASE | X86_CR4_SMAP | X86_CR4_PCIDE)) -#define domain_max_vcpus(d) (is_hvm_domain(d) ? HVM_MAX_VCPUS : MAX_VIRT_CPUS) - static inline struct vcpu_guest_context *alloc_vcpu_guest_context(void) { return vmalloc(sizeof(struct vcpu_guest_context)); -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |