@@ -182,6 +182,23 @@
#define PCID_RESULT_KEY_IOMEM "iomem"
#define PCID_RESULT_KEY_IRQS "irqs"
+/*
+ *******************************************************************************
+ * Write BDF values to the pciback sysfs path
+ *
+ * This command resets PCI device
+ *
+ * Request (see other mandatory fields above):
+ * - "cmd" field of the request must be set to "write_bdf".
+ * - "sbdf" SBDF of the device in format defined by PCID_SBDF_FMT.
+ * - "name" name of sysfs file of pciback driver
+ *
+ * Response (see other mandatory fields above):
+ * - "resp" field of the response must be set to "write_bdf".
+ */
+#define PCID_CMD_WRITE_BDF "write_bdf"
+#define PCID_MSG_FIELD_NAME "name"
+
/*
*******************************************************************************
* Reset PCI device
@@ -94,6 +94,8 @@ static int pci_handle_response(libxl__gc *gc,
else if (strcmp(command_name, PCID_CMD_RESOURCE_LIST) == 0)
*result = (libxl__json_object *)libxl__json_map_get(PCID_MSG_FIELD_RESOURCES,
response, JSON_MAP);
+ else if (strcmp(command_name, PCID_CMD_WRITE_BDF) == 0)
+ *result = libxl__json_object_alloc(gc, JSON_NULL);
return ret;
}
@@ -511,33 +513,6 @@ static bool is_pci_in_array(libxl_device_pci *pcis, int num,
return i < num;
}
-/* Write the standard BDF into the sysfs path given by sysfs_path. */
-static int sysfs_write_bdf(libxl__gc *gc, const char * sysfs_path,
- libxl_device_pci *pci)
-{
- int rc, fd;
- char *buf;
-
- fd = open(sysfs_path, O_WRONLY);
- if (fd < 0) {
- LOGE(ERROR, "Couldn't open %s", sysfs_path);
- return ERROR_FAIL;
- }
-
- buf = GCSPRINTF(PCI_BDF, pci->domain, pci->bus,
- pci->dev, pci->func);
- rc = write(fd, buf, strlen(buf));
- /* Annoying to have two if's, but we need the errno */
- if (rc < 0)
- LOGE(ERROR, "write to %s returned %d", sysfs_path, rc);
- close(fd);
-
- if (rc < 0)
- return ERROR_FAIL;
-
- return 0;
-}
-
#define PCI_INFO_PATH "/libxl/pci"
static char *pci_info_xs_path(libxl__gc *gc, libxl_device_pci *pci,
@@ -1384,6 +1359,36 @@ static bool pci_supp_legacy_irq(void)
#endif
}
+static int pciback_write_bdf(libxl__gc *gc, char *name, libxl_device_pci *pci)
+{
+ struct vchan_info *vchan;
+ int rc;
+ libxl__json_object *args, *result;
+
+ vchan = pci_vchan_get_client(gc);
+ if (!vchan) {
+ rc = ERROR_NOT_READY;
+ goto out;
+ }
+
+ args = libxl__vchan_start_args(gc);
+
+ libxl__vchan_arg_add_string(gc, args, PCID_MSG_FIELD_SBDF,
+ GCSPRINTF(PCID_SBDF_FMT, pci->domain,
+ pci->bus, pci->dev, pci->func));
+ libxl__vchan_arg_add_string(gc, args, PCID_MSG_FIELD_NAME, name);
+
+ result = vchan_send_command(gc, vchan, PCID_CMD_WRITE_BDF, args);
+ if (!result) {
+ rc = ERROR_FAIL;
+ goto vchan_free;
+ }
+vchan_free:
+ pci_vchan_free(gc, vchan);
+out:
+ return rc;
+}
+
static void pci_add_dm_done(libxl__egc *egc,
pci_add_state *pas,
int rc)
@@ -1421,8 +1426,9 @@ static void pci_add_dm_done(libxl__egc *egc,
libxl__vchan_arg_add_integer(gc, args, PCID_MSG_FIELD_DOMID, domid);
result = vchan_send_command(gc, vchan, PCID_CMD_RESOURCE_LIST, args);
+ pci_vchan_free(gc, vchan);
if (!result)
- goto vchan_free;
+ goto out;
value = libxl__json_map_get(PCID_RESULT_KEY_IOMEM, result, JSON_ARRAY);
/* stubdomain is always running by now, even at create time */
@@ -1483,8 +1489,7 @@ static void pci_add_dm_done(libxl__egc *egc,
/* Don't restrict writes to the PCI config space from this VM */
if (pci->permissive) {
- if ( sysfs_write_bdf(gc, SYSFS_PCIBACK_DRIVER"/permissive",
- pci) < 0 ) {
+ if (pciback_write_bdf(gc, "permissive", pci)) {
LOGD(ERROR, domainid, "Setting permissive for device");
rc = ERROR_FAIL;
goto out;
@@ -1512,8 +1517,6 @@ out_no_irq:
rc = libxl__device_pci_add_xenstore(gc, domid, pci, starting);
else
rc = 0;
-vchan_free:
- pci_vchan_free(gc, vchan);
out:
libxl__ev_time_deregister(gc, &pas->timeout);
libxl__ev_time_deregister(gc, &pas->timeout_retries);
@@ -257,6 +257,41 @@ static int pciback_dev_is_assigned(libxl__gc *gc, unsigned int domain,
return 0;
}
+static int process_pciback_write_bdf(libxl__gc *gc, yajl_gen gen,
+ char *command_name,
+ const struct libxl__json_object *request,
+ struct libxl__json_object **response)
+{
+ const struct libxl__json_object *json_o;
+ unsigned int dom, bus, dev, func;
+ int rc = 0;
+ const char *name;
+ char *spath;
+
+ json_o = libxl__json_map_get(PCID_MSG_FIELD_SBDF, request, JSON_STRING);
+ if (!json_o) {
+ make_error_reply(gc, gen, "No mandatory parameter 'sbdf'", command_name);
+ return ERROR_FAIL;
+ }
+
+ if (sscanf(libxl__json_object_get_string(json_o), PCID_SBDF_FMT,
+ &dom, &bus, &dev, &func) != 4) {
+ make_error_reply(gc, gen, "Can't parse SBDF", command_name);
+ return ERROR_FAIL;
+ }
+
+ json_o = libxl__json_map_get(PCID_MSG_FIELD_NAME, request, JSON_STRING);
+ if (!json_o) {
+ make_error_reply(gc, gen, "No mandatory parameter 'rebind'", command_name);
+ return ERROR_FAIL;
+ }
+
+ name = libxl__json_object_get_string(json_o);
+ spath = GCSPRINTF("%s/%s", SYSFS_PCIBACK_DRIVER, name);
+ LOG(WARN, "sysf_write_bdf(%s, %d, %d, %d, %d)", spath, dom, bus, dev,func);
+ return rc;
+}
+
#define PCID_INFO_PATH "pcid"
#define PCID_BDF_XSPATH "%04x-%02x-%02x-%01x"
@@ -746,6 +781,9 @@ static int pcid_handle_request(libxl__gc *gc, yajl_gen gen,
else if (strcmp(command_name, PCID_CMD_RESOURCE_LIST) == 0)
ret = process_list_resources(gc, gen, command_name,
request, &command_response);
+ else if (strcmp(command_name, PCID_CMD_WRITE_BDF) == 0)
+ ret = process_pciback_write_bdf(gc, gen, command_name,
+ request, &command_response);
else {
/*
* This is an unsupported command: make a reply and proceed over