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);
}
}
+ /* max_vcpus depends on the GIC version, and Xen's compiled limit. */
+ max_vcpus = min(vgic_max_vcpus(config->arch.gic_version), MAX_VIRT_CPUS);
+
+ 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;
}
.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)
.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)
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);
+ switch ( domctl_vgic_version )
+ {
+ case XEN_DOMCTL_CONFIG_GIC_V2:
+ return 8;
+
+#ifdef CONFIG_GICV3
+ case XEN_DOMCTL_CONFIG_GIC_V3:
+ return 4096;
+#endif
+
+ default:
+ return 0;
+ }
}
/*
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;
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:
- vgic_vcpu_limit = VGIC_V2_MAX_CPUS;
- break;
+ case XEN_DOMCTL_CONFIG_GIC_V2:
+ return VGIC_V2_MAX_CPUS;
+
default:
- BUG();
+ return 0;
}
-
- return min_t(unsigned int, MAX_VIRT_CPUS, vgic_vcpu_limit);
}
#ifdef CONFIG_GICV3
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) )
{
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;
}
return -EINVAL;
}
+ if ( config->max_vcpus < 1 )
+ {
+ dprintk(XENLOG_INFO, "No vCPUS\n");
+ return -EINVAL;
+ }
+
return arch_sanitise_domain_config(config);
}
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 )
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;
#define OPT_CONSOLE_STR "dtuart"
#ifdef CONFIG_ARM_64
-#define MAX_VIRT_CPUS 128
+#define MAX_VIRT_CPUS 128u
#else
-#define MAX_VIRT_CPUS 8
+#define MAX_VIRT_CPUS 8u
#endif
#define INVALID_VCPU_ID MAX_VIRT_CPUS
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
/* 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 */
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);
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));