diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5 index 38c977c184..382f30b5d4 100644 --- a/docs/man/xl.cfg.pod.5 +++ b/docs/man/xl.cfg.pod.5 @@ -1680,6 +1680,40 @@ The default is B. See L for more information. +=head2 Architecture Specific options + +=head3 ARM + +=over 4 + +=item B + +Version of the GIC emulated for the guest. Currently, the following +versions are supported: + +=over 4 + +=item B + +Emulate a GICv2 + +=item B + +Emulate a GICv3. Note that the emulated GIC does not support the +GICv2 compatibility mode. + +=item B + +Emulate the same version as the native GIC hardware used by host where +the domain was created. + +=back + +This requires hardware compatibility with the requested version. Either +natively or via hardware backwards compatibility support. + +=back + =head1 SEE ALSO =over 4 diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 942cbf147d..e9d63c9a5b 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -199,6 +199,11 @@ */ #define LIBXL_HAVE_DEVICETREE_PASSTHROUGH 1 +/* + * libxl_domain_build_info has the arm.gic_version field. + */ +#define LIBXL_HAVE_BUILDINFO_ARM_GIC_VERSION 1 + /* * libxl ABI compatibility * diff --git a/tools/libxl/libxl_arch.h b/tools/libxl/libxl_arch.h index d04871c55d..9a80d436e2 100644 --- a/tools/libxl/libxl_arch.h +++ b/tools/libxl/libxl_arch.h @@ -21,6 +21,12 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc, libxl_domain_config *d_config, xc_domain_configuration_t *xc_config); +/* save the arch specific configuration for the domain */ +_hidden +int libxl__arch_domain_save_config(libxl__gc *gc, + libxl_domain_config *d_config, + const xc_domain_configuration_t *xc_config); + /* arch specific internal domain creation function */ _hidden int libxl__arch_domain_create(libxl__gc *gc, libxl_domain_config *d_config, diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c index 03a92053bd..d30690548a 100644 --- a/tools/libxl/libxl_arm.c +++ b/tools/libxl/libxl_arm.c @@ -61,7 +61,40 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc, xc_config->nr_spis = nr_spis; LOG(DEBUG, " - Allocate %u SPIs", nr_spis); - xc_config->gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE; + switch (d_config->b_info.arch_arm.gic_version) { + case LIBXL_GIC_VERSION_DEFAULT: + xc_config->gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE; + break; + case LIBXL_GIC_VERSION_V2: + xc_config->gic_version = XEN_DOMCTL_CONFIG_GIC_V2; + break; + case LIBXL_GIC_VERSION_V3: + xc_config->gic_version = XEN_DOMCTL_CONFIG_GIC_V3; + break; + default: + LOG(ERROR, "Unknown GIC version %d\n", + d_config->b_info.arch_arm.gic_version); + return ERROR_FAIL; + } + + return 0; +} + +int libxl__arch_domain_save_config(libxl__gc *gc, + libxl_domain_config *d_config, + const xc_domain_configuration_t *xc_config) +{ + switch (xc_config->gic_version) { + case XEN_DOMCTL_CONFIG_GIC_V2: + d_config->b_info.arch_arm.gic_version = LIBXL_GIC_VERSION_V2; + break; + case XEN_DOMCTL_CONFIG_GIC_V3: + d_config->b_info.arch_arm.gic_version = LIBXL_GIC_VERSION_V3; + break; + default: + LOG(ERROR, "Unexpected gic version %u\n", xc_config->gic_version); + return ERROR_FAIL; + } return 0; } diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c index 69bfa335fd..b785ddd7a1 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -527,6 +527,10 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config, goto out; } + rc = libxl__arch_domain_save_config(gc, d_config, xc_config); + if (rc < 0) + goto out; + ret = xc_cpupool_movedomain(ctx->xch, info->poolid, *domid); if (ret < 0) { LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "domain move fail"); diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index ec4cee5cf1..8dacf8d006 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -380,6 +380,12 @@ libxl_vnode_info = Struct("vnode_info", [ ("vcpus", libxl_bitmap), # vcpus in this node ]) +libxl_gic_version = Enumeration("gic_version", [ + (0, "DEFAULT"), + (0x20, "v2"), + (0x30, "v3") + ], init_val = "LIBXL_GIC_VERSION_DEFAULT") + libxl_domain_build_info = Struct("domain_build_info",[ ("max_vcpus", integer), ("avail_vcpus", libxl_bitmap), @@ -492,6 +498,11 @@ libxl_domain_build_info = Struct("domain_build_info",[ ])), ("invalid", None), ], keyvar_init_val = "LIBXL_DOMAIN_TYPE_INVALID")), + + + ("arch_arm", Struct(None, [("gic_version", libxl_gic_version), + ])), + ], dir=DIR_IN ) diff --git a/tools/libxl/libxl_x86.c b/tools/libxl/libxl_x86.c index ed2bd388cb..8cd15ca698 100644 --- a/tools/libxl/libxl_x86.c +++ b/tools/libxl/libxl_x86.c @@ -10,6 +10,13 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc, return 0; } +int libxl__arch_domain_save_config(libxl__gc *gc, + libxl_domain_config *d_config, + const xc_domain_configuration_t *xc_config) +{ + return 0; +} + static const char *e820_names(int type) { switch (type) { diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index 14527c577f..609cf04af9 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -2257,6 +2257,15 @@ skip_vfb: } } + if (!xlu_cfg_get_string (config, "gic_version", &buf, 1)) { + e = libxl_gic_version_from_string(buf, &b_info->arch_arm.gic_version); + if (e) { + fprintf(stderr, + "Unknown gic_version \"%s\" specified\n", buf); + exit(-ERROR_FAIL); + } + } + xlu_cfg_destroy(config); } diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index b97ab6ca00..b2bfc7d293 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -531,7 +531,6 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags, struct xen_arch_domainconfig *config) { int rc; - uint8_t gic_version; d->arch.relmem = RELMEM_not_started; @@ -560,28 +559,38 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags, if ( (rc = p2m_alloc_table(d)) != 0 ) goto fail; - /* - * Currently the vGIC is emulating the same version of the - * hardware GIC. Only the value XEN_DOMCTL_CONFIG_GIC_NATIVE - * is allowed. The DOMCTL will return the actual version of the - * GIC. - */ - rc = -EOPNOTSUPP; - if ( config->gic_version != XEN_DOMCTL_CONFIG_GIC_NATIVE ) - goto fail; - - switch ( gic_hw_version() ) + switch ( config->gic_version ) { - case GIC_V3: - gic_version = XEN_DOMCTL_CONFIG_GIC_V3; + case XEN_DOMCTL_CONFIG_GIC_NATIVE: + switch ( gic_hw_version () ) + { + case GIC_V2: + config->gic_version = XEN_DOMCTL_CONFIG_GIC_V2; + d->arch.vgic.version = GIC_V2; + break; + + case GIC_V3: + config->gic_version = XEN_DOMCTL_CONFIG_GIC_V3; + d->arch.vgic.version = GIC_V3; + break; + + default: + BUG(); + } break; - case GIC_V2: - gic_version = XEN_DOMCTL_CONFIG_GIC_V2; + + case XEN_DOMCTL_CONFIG_GIC_V2: + d->arch.vgic.version = GIC_V2; break; + + case XEN_DOMCTL_CONFIG_GIC_V3: + d->arch.vgic.version = GIC_V3; + break; + default: - BUG(); + rc = -EOPNOTSUPP; + goto fail; } - config->gic_version = gic_version; if ( (rc = domain_vgic_init(d, config->nr_spis)) != 0 ) goto fail; diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index 01fc9d8722..a6835a806c 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -81,7 +81,7 @@ int domain_vgic_init(struct domain *d, unsigned int nr_spis) d->arch.vgic.nr_spis = nr_spis; - switch ( gic_hw_version() ) + switch ( d->arch.vgic.version ) { #ifdef HAS_GICV3 case GIC_V3: @@ -95,7 +95,7 @@ int domain_vgic_init(struct domain *d, unsigned int nr_spis) break; default: printk(XENLOG_G_ERR "d%d: Unknown vGIC version %u\n", - d->domain_id, gic_hw_version()); + d->domain_id, d->arch.vgic.version); return -ENODEV; } diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h index 8f5a6898af..56aa208995 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -77,6 +77,8 @@ struct arch_domain } virt_timer_base; struct { + /* Version of the vGIC */ + enum gic_version version; /* GIC HW version specific vGIC driver handler */ const struct vgic_ops *handler; /*