@@ -660,6 +660,12 @@ in preference. However, the availability of this option is hardware
specific. If B<xl info> reports B<virt_caps> containing
B<iommu_hap_pt_share> then this option may be used.
+=item B<unspecified>
+
+The default, which chooses between B<disabled> and B<enabled>
+according to whether passthrough devices are enabled in the config
+file.
+
=back
=back
@@ -73,6 +73,12 @@ void libxl__arch_domain_build_info_setdefault(libxl__gc *gc,
libxl_domain_build_info *b_info);
_hidden
+int libxl__arch_passthrough_mode_setdefault(libxl__gc *gc,
+ uint32_t domid,
+ libxl_domain_config *d_config,
+ const libxl_physinfo *physinfo);
+
+_hidden
int libxl__arch_extra_memory(libxl__gc *gc,
const libxl_domain_build_info *info,
uint64_t *out);
@@ -1191,6 +1191,30 @@ void libxl__arch_domain_build_info_setdefault(libxl__gc *gc,
libxl_domain_build_info_init_type(b_info, LIBXL_DOMAIN_TYPE_PVH);
}
+int libxl__arch_passthrough_mode_setdefault(libxl__gc *gc,
+ uint32_t domid,
+ libxl_domain_config *d_config,
+ const libxl_physinfo *physinfo)
+{
+ int rc;
+ libxl_domain_create_info *const c_info = &d_config->c_info;
+
+ if (c_info->passthrough == LIBXL_PASSTHROUGH_ENABLED) {
+ c_info->passthrough = LIBXL_PASSTHROUGH_SHARE_PT;
+ }
+
+ if (c_info->passthrough == LIBXL_PASSTHROUGH_SYNC_PT) {
+ LOGD(ERROR, domid,
+ "passthrough=\"sync_pt\" not supported on ARM\n");
+ rc = ERROR_INVAL;
+ goto out;
+ }
+
+ rc = 0;
+ out:
+ return rc;
+}
+
/*
* Local variables:
* mode: C
@@ -57,18 +57,6 @@ int libxl__domain_create_info_setdefault(libxl__gc *gc,
if (!c_info->ssidref)
c_info->ssidref = SECINITSID_DOMU;
- if (info->cap_hvm_directio &&
- (c_info->passthrough == LIBXL_PASSTHROUGH_UNKNOWN)) {
- c_info->passthrough = ((c_info->type == LIBXL_DOMAIN_TYPE_PV) ||
- !info->cap_iommu_hap_pt_share) ?
- LIBXL_PASSTHROUGH_SYNC_PT : LIBXL_PASSTHROUGH_SHARE_PT;
- } else if (!info->cap_hvm_directio) {
- c_info->passthrough = LIBXL_PASSTHROUGH_DISABLED;
- }
-
- /* An explicit setting should now have been chosen */
- assert(c_info->passthrough != LIBXL_PASSTHROUGH_UNKNOWN);
-
return 0;
}
@@ -904,6 +892,7 @@ int libxl__domain_config_setdefault(libxl__gc *gc,
libxl_ctx *ctx = libxl__gc_owner(gc);
int ret;
bool pod_enabled = false;
+ libxl_domain_create_info *c_info = &d_config->c_info;
libxl_physinfo physinfo;
ret = libxl_get_physinfo(CTX, &physinfo);
@@ -975,6 +964,34 @@ int libxl__domain_config_setdefault(libxl__gc *gc,
goto error_out;
}
+ bool need_pt = d_config->num_pcidevs || d_config->num_dtdevs;
+ if (c_info->passthrough == LIBXL_PASSTHROUGH_UNKNOWN) {
+ c_info->passthrough = need_pt
+ ? LIBXL_PASSTHROUGH_ENABLED : LIBXL_PASSTHROUGH_DISABLED;
+ }
+
+ bool iommu_enabled = physinfo.cap_hvm_directio;
+ if (c_info->passthrough != LIBXL_PASSTHROUGH_DISABLED && !iommu_enabled) {
+ LOGD(ERROR, domid,
+ "passthrough not supported on this platform\n");
+ ret = ERROR_INVAL;
+ goto error_out;
+ }
+
+ if (c_info->passthrough == LIBXL_PASSTHROUGH_DISABLED && need_pt) {
+ LOGD(ERROR, domid,
+ "passthrough disabled but devices are specified");
+ ret = ERROR_INVAL;
+ goto error_out;
+ }
+
+ ret = libxl__arch_passthrough_mode_setdefault(gc,domid,d_config,&physinfo);
+ if (ret) goto error_out;
+
+ /* An explicit setting should now have been chosen */
+ assert(c_info->passthrough != LIBXL_PASSTHROUGH_UNKNOWN);
+ assert(c_info->passthrough != LIBXL_PASSTHROUGH_ENABLED);
+
/* If target_memkb is smaller than max_memkb, the subsequent call
* to libxc when building HVM domain will enable PoD mode.
*/
@@ -266,8 +266,9 @@ libxl_vkb_backend = Enumeration("vkb_backend", [
libxl_passthrough = Enumeration("passthrough", [
(0, "unknown"),
(1, "disabled"),
- (2, "sync_pt"),
- (3, "share_pt"),
+ (2, "enabled"), # becomes {sync,share}_pt once defaults are evaluated
+ (3, "sync_pt"),
+ (4, "share_pt"),
])
#
@@ -631,6 +631,47 @@ void libxl__arch_domain_build_info_setdefault(libxl__gc *gc,
libxl_defbool_setdefault(&b_info->acpi, true);
}
+int libxl__arch_passthrough_mode_setdefault(libxl__gc *gc,
+ uint32_t domid,
+ libxl_domain_config *d_config,
+ const libxl_physinfo *physinfo)
+{
+ int rc;
+ libxl_domain_create_info *const c_info = &d_config->c_info;
+
+ if (c_info->passthrough != LIBXL_PASSTHROUGH_DISABLED &&
+ c_info->type == LIBXL_DOMAIN_TYPE_PVH) {
+ LOGD(ERROR, domid,
+ "passthrough not yet supported for x86 PVH guests\n");
+ rc = ERROR_INVAL;
+ goto out;
+ }
+
+ const char *whynot_pt_share =
+ c_info->type == LIBXL_DOMAIN_TYPE_PV ? "not valid for PV domain" :
+ !physinfo->cap_iommu_hap_pt_share ? "not supported on this platform" :
+ !libxl_defbool_val(d_config->c_info.hap) ?"only valid for HAP guests":
+ NULL;
+
+ if (c_info->passthrough == LIBXL_PASSTHROUGH_ENABLED) {
+ c_info->passthrough = whynot_pt_share
+ ? LIBXL_PASSTHROUGH_SYNC_PT : LIBXL_PASSTHROUGH_SHARE_PT;
+ }
+
+ if (c_info->passthrough == LIBXL_PASSTHROUGH_SHARE_PT && whynot_pt_share) {
+ LOGD(ERROR, domid,
+ "passthrough=\"share_pt\" %s\n",
+ whynot_pt_share);
+ rc = ERROR_INVAL;
+ goto out;
+ }
+
+ rc = 0;
+ out:
+ return rc;
+}
+
+
/*
* Local variables:
* mode: C
@@ -1222,7 +1222,6 @@ void parse_config_data(const char *config_source,
int pci_seize = 0;
int i, e;
char *kernel_basename;
- bool iommu_enabled, iommu_hap_pt_share;
libxl_domain_create_info *c_info = &d_config->c_info;
libxl_domain_build_info *b_info = &d_config->b_info;
@@ -1234,8 +1233,6 @@ void parse_config_data(const char *config_source,
exit(EXIT_FAILURE);
}
- iommu_enabled = physinfo.cap_hvm_directio;
- iommu_hap_pt_share = physinfo.cap_iommu_hap_pt_share;
libxl_physinfo_dispose(&physinfo);
config= xlu_cfg_init(stderr, config_source);
@@ -1509,67 +1506,13 @@ void parse_config_data(const char *config_source,
}
}
- if (xlu_cfg_get_string(config, "passthrough", &buf, 0)) {
- c_info->passthrough =
- (d_config->num_pcidevs || d_config->num_dtdevs)
- ? LIBXL_PASSTHROUGH_UNKNOWN : LIBXL_PASSTHROUGH_DISABLED;
- } else {
- if (!strcasecmp("enabled", buf))
- c_info->passthrough = LIBXL_PASSTHROUGH_UNKNOWN;
- else {
- libxl_passthrough o;
-
- e = libxl_passthrough_from_string(buf, &o);
- if (e || !strcasecmp("unknown", buf)) {
- fprintf(stderr,
- "ERROR: unknown passthrough option '%s'\n",
- buf);
- exit(-ERROR_FAIL);
- }
-
- c_info->passthrough = o;
- }
- }
-
- switch (c_info->passthrough) {
- case LIBXL_PASSTHROUGH_UNKNOWN:
- /*
- * Choose a suitable default. libxl would also do this but
- * choosing here allows the code calculating 'iommu_memkb'
- * below make an informed decision.
- */
- c_info->passthrough =
- (c_info->type == LIBXL_DOMAIN_TYPE_PV) || !iommu_hap_pt_share
- ? LIBXL_PASSTHROUGH_SYNC_PT : LIBXL_PASSTHROUGH_SHARE_PT;
- break;
-
- case LIBXL_PASSTHROUGH_DISABLED:
- if (d_config->num_pcidevs || d_config->num_dtdevs) {
+ if (!xlu_cfg_get_string(config, "passthrough", &buf, 0)) {
+ if (libxl_passthrough_from_string(buf, &c_info->passthrough)) {
fprintf(stderr,
- "ERROR: passthrough disabled but devices are specified\n");
- exit(-ERROR_FAIL);
- }
- break;
- case LIBXL_PASSTHROUGH_SHARE_PT:
- if (c_info->type == LIBXL_DOMAIN_TYPE_PV) {
- fprintf(stderr,
- "ERROR: passthrough=\"share_pt\" not valid for PV domain\n");
- exit(-ERROR_FAIL);
- } else if (!iommu_hap_pt_share) {
- fprintf(stderr,
- "ERROR: passthrough=\"share_pt\" not supported on this platform\n");
- exit(-ERROR_FAIL);
+ "ERROR: unknown passthrough option '%s'\n",
+ buf);
+ exit(1);
}
- break;
- case LIBXL_PASSTHROUGH_SYNC_PT:
- break;
- }
-
- if ((c_info->passthrough != LIBXL_PASSTHROUGH_DISABLED) &&
- !iommu_enabled) {
- fprintf(stderr,
- "ERROR: passthrough not supported on this platform\n");
- exit(-ERROR_FAIL);
}
if (!xlu_cfg_get_long(config, "shadow_memory", &l, 0))