XXX
+=item B<permissive=BOOLEAN>
+
+(PV only) 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. This
+tells the pciback driver to allow all writes to PCI config space of
+this device by this domain. This option should be enabled with
+caution: it gives the guest much more control over the device, which
+may have security or stability implications. It is recommended to
+enable this option only for trusted VMs under administrator control.
+
=back
=back
+=item B<pci_permissive=BOOLEAN>
+
+(PV only) Changes the default value of 'permissive' for all PCI
+devices for this VM. This can still be overriden on a per-device
+basis. This option should be enabled with caution: it gives the guest
+much more control over the device, which may have security or
+stability implications. It is recommended to enable this option only
+for trusted VMs under administrator control. See the "pci=" section
+for more information on the "permissive" flag.
+
=back
=head2 Paravirtualised (PV) Guest Specific Options
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));
}
}
}
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:
} 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);
}
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;
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) {
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++;
}