[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH v4 5/6] libxl: Allow PCI device passthrough using -device Qemu command line



This change makes use of the new option 'hotplug' for host PCI devices
passthrough'd to the guest. If hotplug=0 is used in the pci device
configuration table, the device will be attached to the guest using the
Qemu command line as '-device xen-pci-passthrough,hostaddr=...'

The host device configuration is passed to the -device option as a json
array, just like it's done for hotplug using QMP. The json array is
created by using libxl__device_pci_get_qapi_json() introduced by the
previous patch.

Then, instead of sending the 'device_add' command, the device_add
callback is called to perform the 'query-pci' check to make sure the
passthrough'd device is present.

In the same way at shutdown, the device is not removed using QMP and
only the pci_remove_done() function is called.

As with QMP, the use of the 'hotplug=0' option honors the 'seize' option
by adding the PCI device to the assignable list if needed. This mimics
what is done in libxl__device_pci_add() with regards to seize option and
the assignable PCI device list. This allows to display a proper error
message if the device is not assignable before Qemu starts.

Signed-off-by: Thierry Escande <thierry.escande@xxxxxxxxxx>
---
Changes in v2:
 - Add support for YAJL json parser

Changes in v3:
 - Move code block for device command line parameters creation to a
   correct place.
 - Better handling of PCI device assignation check to display the correct
   error message if the device is not assignable.

Changes in v4:
 - Move function refactoring parts into their own patches
 - Use libxl__json_object_to_json() that can now return plain json strings
---
 tools/libs/light/libxl_dm.c  | 33 +++++++++++++++++++++++++++++++++
 tools/libs/light/libxl_pci.c | 13 ++++++++++++-
 2 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/tools/libs/light/libxl_dm.c b/tools/libs/light/libxl_dm.c
index 511ec76a65..fb0aeea640 100644
--- a/tools/libs/light/libxl_dm.c
+++ b/tools/libs/light/libxl_dm.c
@@ -1798,6 +1798,39 @@ static int libxl__build_device_model_args_new(libxl__gc 
*gc,
             break;
         }
 
+        if (guest_config->num_pcidevs) {
+            libxl_device_pci *pci;
+            libxl__json_object *qmp_json;
+            char *json_str;
+
+            for (i = 0; i < guest_config->num_pcidevs; i++) {
+                pci = &guest_config->pcidevs[i];
+
+                if (pci->hotplug)
+                    continue;
+
+                if (pci->seize && !libxl__pciback_dev_is_assigned(gc, pci)) {
+                    rc = libxl__device_pci_assignable_add(gc, pci, 1);
+                    if (rc)
+                        return rc;
+                }
+
+                if (!libxl_device_pci_assignable(libxl__gc_owner(gc), pci)) {
+                    LOGD(ERROR, guest_domid, "PCI device %x:%x:%x.%x is not 
assignable",
+                         pci->domain, pci->bus, pci->dev, pci->func);
+                    return ERROR_FAIL;
+                }
+
+                qmp_json = libxl__device_pci_get_qapi_json(gc, pci);
+
+                json_str = libxl__json_object_to_json(gc, qmp_json, false);
+                if (!json_str)
+                    return ERROR_NOMEM;
+
+                flexarray_vappend(dm_args, "-device", json_str, NULL);
+            }
+        }
+
         if (state->dm_runas) {
             if (qemu_opts->have_runwith_user) {
                 flexarray_append_pair(dm_args, "-run-with",
diff --git a/tools/libs/light/libxl_pci.c b/tools/libs/light/libxl_pci.c
index 5004ca47d9..f5216f6b33 100644
--- a/tools/libs/light/libxl_pci.c
+++ b/tools/libs/light/libxl_pci.c
@@ -1148,7 +1148,10 @@ static void pci_add_qmp_device_add(libxl__egc *egc, 
pci_add_state *pas)
     qmp->domid = domid;
     qmp->payload_fd = -1;
     qmp->callback = pci_add_qmp_device_add_cb;
-    rc = libxl__ev_qmp_send(egc, qmp, "device_add", args);
+    if (pci->hotplug)
+        rc = libxl__ev_qmp_send(egc, qmp, "device_add", args);
+    else
+        pci_add_qmp_device_add_cb(egc, qmp, NULL, 0);
     if (rc) goto out;
     return;
 
@@ -1830,6 +1833,14 @@ static void do_pci_remove(libxl__egc *egc, 
pci_remove_state *prs)
     libxl_domain_type type = libxl__domain_type(gc, domid);
     libxl_device_pci *pci = &prs->pci;
     int rc, num;
+
+    /* Passthrough'd device has been passed to Qemu command line so there is
+     * no need to remove it via QMP */
+    if (!pci->hotplug) {
+        pci_remove_done(egc, prs, 0);
+        return;
+    }
+
     pcis = libxl_device_pci_list(ctx, domid, &num);
     if (!pcis) {
         rc = ERROR_FAIL;
-- 
2.53.0



--
Thierry Escande | Vates XCP-ng Developer

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.