aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxl
diff options
context:
space:
mode:
authorGeorge Dunlap <george.dunlap@eu.citrix.com>2012-04-04 16:06:42 +0100
committerGeorge Dunlap <george.dunlap@eu.citrix.com>2012-04-04 16:06:42 +0100
commitabda66fdb0eaa1b7ec33e97e3e0e375f948dc651 (patch)
treeb3bee62f8dc1249e0eaa239e657204de0baf0415 /tools/libxl
parent543e95e992087a26e2e4e3a1a763ffc348bb6f30 (diff)
downloadxen-abda66fdb0eaa1b7ec33e97e3e0e375f948dc651.tar.gz
xen-abda66fdb0eaa1b7ec33e97e3e0e375f948dc651.tar.bz2
xen-abda66fdb0eaa1b7ec33e97e3e0e375f948dc651.zip
xl, libxl: Add per-device and global permissive config options for pci passthrough
By default pciback only allows PV guests to write "known safe" values into PCI config space. But many devices require writes to other areas of config space in order to operate properly. One way to do that is with the "quirks" interface, which specifies areas known safe to a particular device; the other way is to mark a device as "permissive", which tells pciback to allow all config space writes for that domain and device. This adds a "permissive" flag to the libxl_pci struct and teaches libxl how to write the appropriate value into sysfs to enable the permissive feature for devices being passed through. It also adds the permissive config options either on a per-device basis, or as a global option in the xl command-line. Because of the potential stability and security implications of enabling permissive, the flag is left off by default. Signed-off-by: George Dunlap <george.dunlap@eu.citrix.com> Committed-by: Ian Jackson <ian.jackson.citrix.com> Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Diffstat (limited to 'tools/libxl')
-rw-r--r--tools/libxl/libxl_pci.c33
-rw-r--r--tools/libxl/libxl_types.idl1
-rw-r--r--tools/libxl/libxlu_pci.c2
-rw-r--r--tools/libxl/xl_cmdimpl.c5
4 files changed, 40 insertions, 1 deletions
diff --git a/tools/libxl/libxl_pci.c b/tools/libxl/libxl_pci.c
index 94077c94d2..e8b8839847 100644
--- a/tools/libxl/libxl_pci.c
+++ b/tools/libxl/libxl_pci.c
@@ -55,7 +55,10 @@ static void libxl_create_pci_backend_device(libxl__gc *gc, flexarray_t *back, in
if (pcidev->vdevfn)
flexarray_append_pair(back, libxl__sprintf(gc, "vdevfn-%d", num), libxl__sprintf(gc, "%x", pcidev->vdevfn));
flexarray_append(back, libxl__sprintf(gc, "opts-%d", num));
- flexarray_append(back, libxl__sprintf(gc, "msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt));
+ flexarray_append(back,
+ libxl__sprintf(gc, "msitranslate=%d,power_mgmt=%d,permissive=%d",
+ pcidev->msitranslate, pcidev->power_mgmt,
+ pcidev->permissive));
flexarray_append_pair(back, libxl__sprintf(gc, "state-%d", num), libxl__sprintf(gc, "%d", 1));
}
@@ -565,6 +568,31 @@ static int do_pci_add(libxl__gc *gc, uint32_t domid, libxl_device_pci *pcidev, i
}
}
fclose(f);
+
+ /* Don't restrict writes to the PCI config space from this VM */
+ if (pcidev->permissive) {
+ int fd;
+ char *buf;
+
+ sysfs_path = libxl__sprintf(gc, SYSFS_PCIBACK_DRIVER"/permissive");
+ fd = open(sysfs_path, O_WRONLY);
+ if (fd < 0) {
+ LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Couldn't open %s",
+ sysfs_path);
+ return ERROR_FAIL;
+ }
+
+ buf = libxl__sprintf(gc, PCI_BDF, pcidev->domain, pcidev->bus,
+ pcidev->dev, pcidev->func);
+ rc = write(fd, buf, strlen(buf));
+ /* Annoying to have two if's, but we need the errno */
+ if (rc < 0)
+ LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
+ "write to %s returned %d", sysfs_path, rc);
+ close(fd);
+ if (rc < 0)
+ return ERROR_FAIL;
+ }
break;
}
default:
@@ -958,6 +986,9 @@ static void libxl__device_pci_from_xs_be(libxl__gc *gc,
} else if (!strcmp(p, "power_mgmt")) {
p = strtok_r(NULL, ",=", &saveptr);
pci->power_mgmt = atoi(p);
+ } else if (!strcmp(p, "permissive")) {
+ p = strtok_r(NULL, ",=", &saveptr);
+ pci->permissive = atoi(p);
}
} while ((p = strtok_r(NULL, ",=", &saveptr)) != NULL);
}
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 09089b219f..5cf9708c4c 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -354,6 +354,7 @@ libxl_device_pci = Struct("device_pci", [
("vfunc_mask", uint32),
("msitranslate", bool),
("power_mgmt", bool),
+ ("permissive", bool),
])
libxl_diskinfo = Struct("diskinfo", [
diff --git a/tools/libxl/libxlu_pci.c b/tools/libxl/libxlu_pci.c
index cc70d9fdf5..f5dee93b79 100644
--- a/tools/libxl/libxlu_pci.c
+++ b/tools/libxl/libxlu_pci.c
@@ -139,6 +139,8 @@ int xlu_pci_parse_bdf(XLU_Config *cfg, libxl_device_pci *pcidev, const char *str
pcidev->msitranslate = atoi(tok);
}else if ( !strcmp(optkey, "power_mgmt") ) {
pcidev->power_mgmt = atoi(tok);
+ }else if ( !strcmp(optkey, "permissive") ) {
+ pcidev->permissive = atoi(tok);
}else{
XLU__PCI_ERR(cfg, "Unknown PCI BDF option: %s", optkey);
}
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index fd458a61c5..6f4dd09c88 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -518,6 +518,7 @@ static void parse_config_data(const char *configfile_filename_report,
XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids;
int pci_power_mgmt = 0;
int pci_msitranslate = 1;
+ int pci_permissive = 0;
int e;
libxl_domain_create_info *c_info = &d_config->c_info;
@@ -991,6 +992,9 @@ skip_vfb:
if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l, 0))
pci_power_mgmt = l;
+ if (!xlu_cfg_get_long (config, "pci_permissive", &l, 0))
+ pci_permissive = l;
+
/* To be reworked (automatically enabled) once the auto ballooning
* after guest starts is done (with PCI devices passed in). */
if (c_info->type == LIBXL_DOMAIN_TYPE_PV) {
@@ -1010,6 +1014,7 @@ skip_vfb:
pcidev->msitranslate = pci_msitranslate;
pcidev->power_mgmt = pci_power_mgmt;
+ pcidev->permissive = pci_permissive;
if (!xlu_pci_parse_bdf(config, pcidev, buf))
d_config->num_pcidevs++;
}