|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC PATCH 2/3] 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 a new internal function libxl__device_pci_get_qmp_json() that
is also used by pci_add_qmp_device_add().
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.
Example use:
pci = [ "00:03.0,seize=1,hotplug=0" ]
Signed-off-by: Thierry Escande <thierry.escande@xxxxxxxxxx>
---
tools/include/libxl.h | 1 +
tools/libs/light/libxl_dm.c | 31 +++++++++++++++++++++++
tools/libs/light/libxl_internal.h | 2 ++
tools/libs/light/libxl_pci.c | 41 +++++++++++++++++++++++--------
4 files changed, 65 insertions(+), 10 deletions(-)
diff --git a/tools/include/libxl.h b/tools/include/libxl.h
index 7c098edab6..66fb07ad67 100644
--- a/tools/include/libxl.h
+++ b/tools/include/libxl.h
@@ -2666,6 +2666,7 @@ int libxl_device_pci_assignable_add(libxl_ctx *ctx,
libxl_device_pci *pci, int r
int libxl_device_pci_assignable_remove(libxl_ctx *ctx, libxl_device_pci *pci,
int rebind);
libxl_device_pci *libxl_device_pci_assignable_list(libxl_ctx *ctx, int *num);
void libxl_device_pci_assignable_list_free(libxl_device_pci *list, int num);
+bool libxl_pci_assignable(libxl_ctx *ctx, libxl_device_pci *pci);
/* CPUID handling */
int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* str);
diff --git a/tools/libs/light/libxl_dm.c b/tools/libs/light/libxl_dm.c
index 511ec76a65..96bb620f87 100644
--- a/tools/libs/light/libxl_dm.c
+++ b/tools/libs/light/libxl_dm.c
@@ -1169,6 +1169,37 @@ static int libxl__build_device_model_args_new(libxl__gc
*gc,
}
}
}
+
+ if (guest_config->num_pcidevs) {
+ libxl_device_pci *pci;
+ libxl__json_object *qmp_json;
+ const char *json_str;
+#ifndef HAVE_LIBJSONC
+# error Missing JSON library
+#endif
+ json_object *jso = NULL;
+
+ for (i = 0; i < guest_config->num_pcidevs; i++) {
+ libxl_ctx *ctx = libxl__gc_owner(gc);
+ pci = &guest_config->pcidevs[i];
+
+ if (pci->hotplug)
+ continue;
+
+ if (!libxl_pci_assignable(ctx, pci) && pci->seize) {
+ rc = libxl_device_pci_assignable_add(ctx, pci, 1);
+ if (rc)
+ return rc;
+ }
+ qmp_json = libxl__device_pci_get_qmp_json(gc, pci);
+ rc = libxl__json_object_to_json_object(gc, &jso, qmp_json);
+ if (rc)
+ return rc;
+ json_str = json_object_to_json_string_ext(jso,
+
JSON_C_TO_STRING_PLAIN);
+ flexarray_vappend(dm_args, "-device", json_str, NULL);
+ }
+ }
}
if (libxl_defbool_val(b_info->u.hvm.nographic) && (!sdl && !vnc)) {
diff --git a/tools/libs/light/libxl_internal.h
b/tools/libs/light/libxl_internal.h
index b65e0064b9..06b5a14409 100644
--- a/tools/libs/light/libxl_internal.h
+++ b/tools/libs/light/libxl_internal.h
@@ -1729,6 +1729,8 @@ _hidden int libxl__device_pci_setdefault(libxl__gc *gc,
uint32_t domid,
libxl_device_pci *pci, bool hotplug);
_hidden bool libxl__is_igd_vga_passthru(libxl__gc *gc,
const libxl_domain_config *d_config);
+_hidden libxl__json_object *libxl__device_pci_get_qmp_json(libxl__gc *gc,
+ libxl_device_pci
*pci);
/* from libxl_dtdev */
diff --git a/tools/libs/light/libxl_pci.c b/tools/libs/light/libxl_pci.c
index 49d272d0de..3ef2c43412 100644
--- a/tools/libs/light/libxl_pci.c
+++ b/tools/libs/light/libxl_pci.c
@@ -1098,16 +1098,10 @@ out:
pci_add_dm_done(egc, pas, rc); /* must be last */
}
-static void pci_add_qmp_device_add(libxl__egc *egc, pci_add_state *pas)
+libxl__json_object *libxl__device_pci_get_qmp_json(libxl__gc *gc,
+ libxl_device_pci *pci)
{
- STATE_AO_GC(pas->aodev->ao);
libxl__json_object *args = NULL;
- int rc;
-
- /* Convenience aliases */
- libxl_domid domid = pas->domid;
- libxl_device_pci *pci = &pas->pci;
- libxl__ev_qmp *const qmp = &pas->qmp;
libxl__qmp_param_add_string(gc, &args, "driver",
"xen-pci-passthrough");
@@ -1134,11 +1128,30 @@ static void pci_add_qmp_device_add(libxl__egc *egc,
pci_add_state *pas)
if (pci->permissive)
libxl__qmp_param_add_bool(gc, &args, "permissive", true);
+ return args;
+}
+
+static void pci_add_qmp_device_add(libxl__egc *egc, pci_add_state *pas)
+{
+ STATE_AO_GC(pas->aodev->ao);
+ libxl__json_object *args = NULL;
+ int rc = 0;
+
+ /* Convenience aliases */
+ libxl_domid domid = pas->domid;
+ libxl_device_pci *pci = &pas->pci;
+ libxl__ev_qmp *const qmp = &pas->qmp;
+
+ args = libxl__device_pci_get_qmp_json(gc, pci);
+
qmp->ao = pas->aodev->ao;
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;
@@ -1509,7 +1522,7 @@ int libxl_device_pci_add(libxl_ctx *ctx, uint32_t domid,
return AO_INPROGRESS;
}
-static bool libxl_pci_assignable(libxl_ctx *ctx, libxl_device_pci *pci)
+bool libxl_pci_assignable(libxl_ctx *ctx, libxl_device_pci *pci)
{
libxl_device_pci *pcis;
int num;
@@ -1820,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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |