diff --git a/tools/libs/light/libxl_create.c b/tools/libs/light/libxl_create.c index 41252ec553..edeadd57ef 100644 --- a/tools/libs/light/libxl_create.c +++ b/tools/libs/light/libxl_create.c @@ -372,7 +372,6 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc, libxl_defbool_setdefault(&b_info->u.hvm.viridian, false); libxl_defbool_setdefault(&b_info->u.hvm.hpet, true); libxl_defbool_setdefault(&b_info->u.hvm.vpt_align, true); - libxl_defbool_setdefault(&b_info->u.hvm.altp2m, false); libxl_defbool_setdefault(&b_info->u.hvm.usb, false); libxl_defbool_setdefault(&b_info->u.hvm.vkb_device, true); libxl_defbool_setdefault(&b_info->u.hvm.xen_platform_pci, true); @@ -678,6 +677,28 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config, if (info->passthrough == LIBXL_PASSTHROUGH_SYNC_PT) create.iommu_opts |= XEN_DOMCTL_IOMMU_no_sharept; + LOG(DETAIL, "altp2m: %s", libxl_altp2m_mode_to_string(b_info->altp2m)); + switch(b_info->altp2m) { + case LIBXL_ALTP2M_MODE_MIXED: + create.altp2m_opts |= + XEN_DOMCTL_ALTP2M_mode(XEN_DOMCTL_ALTP2M_mixed); + break; + + case LIBXL_ALTP2M_MODE_EXTERNAL: + create.altp2m_opts |= + XEN_DOMCTL_ALTP2M_mode(XEN_DOMCTL_ALTP2M_external); + break; + + case LIBXL_ALTP2M_MODE_LIMITED: + create.altp2m_opts |= + XEN_DOMCTL_ALTP2M_mode(XEN_DOMCTL_ALTP2M_limited); + break; + + case LIBXL_ALTP2M_MODE_DISABLED: + /* Nothing to do - altp2m disabled is signaled as mode == 0. */ + break; + } + /* Ultimately, handle is an array of 16 uint8_t, same as uuid */ libxl_uuid_copy(ctx, (libxl_uuid *)&create.handle, &info->uuid); diff --git a/tools/libs/light/libxl_x86.c b/tools/libs/light/libxl_x86.c index a50ec37eb3..60643d6f53 100644 --- a/tools/libs/light/libxl_x86.c +++ b/tools/libs/light/libxl_x86.c @@ -407,19 +407,9 @@ static int hvm_set_conf_params(libxl__gc *gc, uint32_t domid, libxl_ctx *ctx = libxl__gc_owner(gc); xc_interface *xch = ctx->xch; int ret = ERROR_FAIL; - unsigned int altp2m = info->altp2m; switch(info->type) { case LIBXL_DOMAIN_TYPE_HVM: - /* The config parameter "altp2m" replaces the parameter "altp2mhvm". For - * legacy reasons, both parameters are accepted on x86 HVM guests. - * - * If the legacy field info->u.hvm.altp2m is set, activate altp2m. - * Otherwise set altp2m based on the field info->altp2m. */ - if (info->altp2m == LIBXL_ALTP2M_MODE_DISABLED && - libxl_defbool_val(info->u.hvm.altp2m)) - altp2m = libxl_defbool_val(info->u.hvm.altp2m); - if (xc_hvm_param_set(xch, domid, HVM_PARAM_HPET_ENABLED, libxl_defbool_val(info->u.hvm.hpet))) { LOG(ERROR, "Couldn't set HVM_PARAM_HPET_ENABLED"); @@ -444,10 +434,6 @@ static int hvm_set_conf_params(libxl__gc *gc, uint32_t domid, LOG(ERROR, "Couldn't set HVM_PARAM_TIMER_MODE"); goto out; } - if (xc_hvm_param_set(xch, domid, HVM_PARAM_ALTP2M, altp2m)) { - LOG(ERROR, "Couldn't set HVM_PARAM_ALTP2M"); - goto out; - } break; default: @@ -818,6 +804,18 @@ int libxl__arch_domain_build_info_setdefault(libxl__gc *gc, libxl_defbool_setdefault(&b_info->acpi, true); libxl_defbool_setdefault(&b_info->arch_x86.msr_relaxed, false); + /* + * The config parameter "altp2m" replaces the parameter "altp2mhvm". + * For legacy reasons, both parameters are accepted on x86 HVM guests. + * + * If the legacy field info->u.hvm.altp2m is set, activate altp2m. + * Otherwise set altp2m based on the field info->altp2m. + */ + libxl_defbool_setdefault(&b_info->u.hvm.altp2m, false); + if (b_info->altp2m == LIBXL_ALTP2M_MODE_DISABLED && + libxl_defbool_val(b_info->u.hvm.altp2m)) + b_info->altp2m = libxl_defbool_val(b_info->u.hvm.altp2m); + return 0; } diff --git a/tools/ocaml/libs/xc/xenctrl_stubs.c b/tools/ocaml/libs/xc/xenctrl_stubs.c index 2b6d3c09df..c6da9bb091 100644 --- a/tools/ocaml/libs/xc/xenctrl_stubs.c +++ b/tools/ocaml/libs/xc/xenctrl_stubs.c @@ -257,7 +257,7 @@ CAMLprim value stub_xc_domain_create(value xch_val, value wanted_domid, value co #if defined(__i386__) || defined(__x86_64__) /* Quick & dirty check for ABI changes. */ - BUILD_BUG_ON(sizeof(cfg) != 64); + BUILD_BUG_ON(sizeof(cfg) != 68); /* Mnemonics for the named fields inside xen_x86_arch_domainconfig */ #define VAL_EMUL_FLAGS Field(arch_domconfig, 0) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 34cbfe699a..8bde2f730d 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -688,6 +688,12 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config) return -EINVAL; } + if ( config->altp2m_opts ) + { + dprintk(XENLOG_INFO, "Altp2m not supported\n"); + return -EINVAL; + } + return 0; } diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 00a3aaa576..1988f5e19a 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -637,6 +637,8 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config) bool hap = config->flags & XEN_DOMCTL_CDF_hap; bool nested_virt = config->flags & XEN_DOMCTL_CDF_nested_virt; unsigned int max_vcpus; + unsigned int altp2m_mode = MASK_EXTR(config->altp2m_opts, + XEN_DOMCTL_ALTP2M_mode_mask); if ( hvm ? !hvm_enabled : !IS_ENABLED(CONFIG_PV) ) { @@ -715,6 +717,26 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config) return -EINVAL; } + if ( config->altp2m_opts & ~XEN_DOMCTL_ALTP2M_mode_mask ) + { + dprintk(XENLOG_INFO, "Invalid altp2m options selected: %#x\n", + config->flags); + return -EINVAL; + } + + if ( altp2m_mode && nested_virt ) + { + dprintk(XENLOG_INFO, + "Nested virt and altp2m are not supported together\n"); + return -EINVAL; + } + + if ( altp2m_mode && !hap ) + { + dprintk(XENLOG_INFO, "altp2m is only supported with HAP\n"); + return -EINVAL; + } + return 0; } diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 2c66fe0f7a..8334ab1711 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -658,6 +658,22 @@ int hvm_domain_initialise(struct domain *d, d->arch.hvm.params[HVM_PARAM_TRIPLE_FAULT_REASON] = SHUTDOWN_reboot; + /* Set altp2m based on domctl flags. */ + switch ( MASK_EXTR(config->altp2m_opts, XEN_DOMCTL_ALTP2M_mode_mask) ) + { + case XEN_DOMCTL_ALTP2M_mixed: + d->arch.hvm.params[HVM_PARAM_ALTP2M] = XEN_ALTP2M_mixed; + break; + + case XEN_DOMCTL_ALTP2M_external: + d->arch.hvm.params[HVM_PARAM_ALTP2M] = XEN_ALTP2M_external; + break; + + case XEN_DOMCTL_ALTP2M_limited: + d->arch.hvm.params[HVM_PARAM_ALTP2M] = XEN_ALTP2M_limited; + break; + } + vpic_init(d); rc = vioapic_init(d); @@ -4166,6 +4182,12 @@ static int hvm_allow_set_param(struct domain *d, case HVM_PARAM_CONSOLE_EVTCHN: case HVM_PARAM_X87_FIP_WIDTH: break; + + /* The following parameters are read-only. */ + case HVM_PARAM_ALTP2M: + rc = -EEXIST; + break; + /* The following parameters are deprecated. */ case HVM_PARAM_PAE_ENABLED: case HVM_PARAM_DM_DOMAIN: @@ -4207,7 +4229,6 @@ static int hvm_allow_set_param(struct domain *d, case HVM_PARAM_BUFIOREQ_PFN: case HVM_PARAM_IOREQ_SERVER_PFN: case HVM_PARAM_NR_IOREQ_SERVER_PAGES: - case HVM_PARAM_ALTP2M: case HVM_PARAM_MCA_CAP: if ( value != 0 && new_value != value ) rc = -EEXIST; diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 6cd39ea46d..2a49fe46ce 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -86,6 +86,24 @@ struct xen_domctl_createdomain { uint32_t grant_opts; +/* + * Enable altp2m mixed mode. + * + * Note that 'mixed' mode has not been evaluated for safety from a security + * perspective. Before using this mode in a security-critical environment, + * each subop should be evaluated for safety, with unsafe subops blacklisted in + * XSM. + */ +#define XEN_DOMCTL_ALTP2M_mixed (1U) +/* Enable altp2m external mode. */ +#define XEN_DOMCTL_ALTP2M_external (2U) +/* Enable altp2m limited mode. */ +#define XEN_DOMCTL_ALTP2M_limited (3U) +/* Altp2m mode signaling uses bits [0, 1]. */ +#define XEN_DOMCTL_ALTP2M_mode_mask (0x3U) +#define XEN_DOMCTL_ALTP2M_mode(m) ((m) & XEN_DOMCTL_ALTP2M_mode_mask) + uint32_t altp2m_opts; + /* Per-vCPU buffer size in bytes. 0 to disable. */ uint32_t vmtrace_size; diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h index a22b4ed45d..99c40b4287 100644 --- a/xen/include/public/hvm/params.h +++ b/xen/include/public/hvm/params.h @@ -246,16 +246,11 @@ #define HVM_PARAM_VM_GENERATION_ID_ADDR 34 /* - * Set mode for altp2m: - * disabled: don't activate altp2m (default) + * Get mode for altp2m: + * disabled: altp2m not active (default) * mixed: allow access to all altp2m ops for both in-guest and external tools * external: allow access to external privileged tools only * limited: guest only has limited access (ie. control VMFUNC and #VE) - * - * Note that 'mixed' mode has not been evaluated for safety from a - * security perspective. Before using this mode in a - * security-critical environment, each subop should be evaluated for - * safety, with unsafe subops blacklisted in XSM. */ #define HVM_PARAM_ALTP2M 35 #define XEN_ALTP2M_disabled 0