From nobody Mon Apr 13 00:05:42 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass header.i=thierry.escande@vates.tech; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=vates.tech ARC-Seal: i=1; a=rsa-sha256; t=1775669053; cv=none; d=zohomail.com; s=zohoarc; b=Mjf7biwqXaotuOC2LOrOITk13yhVaP6bRj/r1HlKuXUD5SkMnL3eAHE/vJF4pmeKROOkfi9Ka1nfiNaCPkKZ3ip2qrknLI42i32YGMN9QXNyr9VDR+jdljk8mSlbiMdnHVj8VYpTtEfGL11jy0r/Xfkyn6xZ7SzuAtCb3wgwaEo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1775669053; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=7/8Qd+P7SPVDgY0eBLO5nKimQuCthoxn0Jd92VJL7wU=; b=I306rKPsh6vKpOpcjkhPJhuodzzAS0Sguc2H/635QJAhZfVyGSnAcZaMirRkssK1J8ldVk8xmnvtJADvrCzuGOcT7xEK0NgQYpLkyjPu+1tuSTRcA16ittTbDsel/WQ2A2O3Lz+2i5wTLqT/0JfuC9mvV/j1tPGzwrMJgvYhygQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=thierry.escande@vates.tech; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 177566905308892.26067994913728; Wed, 8 Apr 2026 10:24:13 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1276425.1561905 (Exim 4.92) (envelope-from ) id 1wAWdA-0005hj-DW; Wed, 08 Apr 2026 17:23:56 +0000 Received: by outflank-mailman (output) from mailman id 1276425.1561905; Wed, 08 Apr 2026 17:23:56 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wAWdA-0005hc-9j; Wed, 08 Apr 2026 17:23:56 +0000 Received: by outflank-mailman (input) for mailman id 1276425; Wed, 08 Apr 2026 17:23:54 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wAWd8-0005gI-Mc for xen-devel@lists.xenproject.org; Wed, 08 Apr 2026 17:23:54 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wAWd8-005z9Y-1O for xen-devel@lists.xenproject.org; Wed, 08 Apr 2026 19:23:54 +0200 Received: from [10.42.69.7] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 69d68f15-e002-0a2a0a5209dd-0a2a4507ddfe-26 for ; Wed, 08 Apr 2026 19:23:54 +0200 Received: from [198.2.178.25] (helo=mail178-25.suw51.mandrillapp.com) by tlsNG-ef75cf.mxtls.expurgate.net with ESMTPS (eXpurgate 4.56.0) (envelope-from ) id 69d68f28-ba2d-0a2a45070019-c602b219cc9a-3 for ; Wed, 08 Apr 2026 19:23:53 +0200 Received: from pmta13.mandrill.prod.suw01.rsglab.com (localhost [127.0.0.1]) by mail178-25.suw51.mandrillapp.com (Mailchimp) with ESMTP id 4frVKN4P3rz4f3wgP for ; Wed, 8 Apr 2026 17:23:52 +0000 (GMT) Received: from [37.26.189.201] by mandrillapp.com id c0022b9fc07d4103bf9af3bb4037bf57; Wed, 08 Apr 2026 17:23:52 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=mte1 header.d=mandrillapp.com header.i="@mandrillapp.com" header.h="From:Subject:To:Cc:Message-Id:In-Reply-To:References:Feedback-ID:Date:MIME-Version:Content-Type:Content-Transfer-Encoding"; dkim=pass header.s=mte1 header.d=vates.tech header.i="thierry.escande@vates.tech" header.h="From:Subject:To:Cc:Message-Id:In-Reply-To:References:Feedback-ID:Date:MIME-Version:Content-Type:Content-Transfer-Encoding" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mandrillapp.com; s=mte1; t=1775669032; x=1775939032; bh=7/8Qd+P7SPVDgY0eBLO5nKimQuCthoxn0Jd92VJL7wU=; h=From:Subject:To:Cc:Message-Id:In-Reply-To:References:Feedback-ID: Date:MIME-Version:Content-Type:Content-Transfer-Encoding:CC:Date: Subject:From; b=jZazIJ0jtqK0cqYE93+/V8XeLf8Yjrc5neEFcG92fAIu8nH8ixZBnxhOpquNEYBx4 TQuEwPv9OIRSe2KRYM1bshjh9bkhVymd9MimGM2Nb8CgzHKCy0Q30hJ9TwP0qAqPPS 5tmEvbcIGjYzB5nOrss/SBrI/m9MY1Hhi092Tdl+Xrx0SpnkuylvvwdBK8aYCG/UHb BZYdrwXLHhBd3nozJ+kKVV4oZse2vIovxbdlhbFaE4Bayk8rLmO/1ufffG+qt9qFQb qZo+1/KGWp3124sgN76Ja+aftxu5hJIc045swJs/c/4otr5aOMjNk0pQanLhOMPV+w qP3JlWNKH0Awg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vates.tech; s=mte1; t=1775669032; x=1775929532; i=thierry.escande@vates.tech; bh=7/8Qd+P7SPVDgY0eBLO5nKimQuCthoxn0Jd92VJL7wU=; h=From:Subject:To:Cc:Message-Id:In-Reply-To:References:Feedback-ID: Date:MIME-Version:Content-Type:Content-Transfer-Encoding:CC:Date: Subject:From; b=E3itFUbe/nZOklJZtVcEesSu0M7DPkwzIAzJmgtTf2Nd3p9lMXWJSGOtPLZ9sWAqk b4ZUumkX/jypTAv1JETOqF6U7q3o6ZAqLxBQkItJfmjbaG0WbMLZ/9fukQm85voWGW ub6r6dAstkniBpjxcstjr1kezyCwBhilaBf55RsjFF9N11EVHsDf0DN/wk9zwc5WNr /P6lW0N2SsAo6tnkaKkXYUy3EkLKVEXEq3YG3rD6YulGlB7gaE4N53PpzEhv9F1Wbt uH/7CyuMVWoMpL2yj1uIk0PdsZoRJF5XOed7+MkwdAMu+vqS76MAYGXrTWTnlniTB+ pacSjYaac9v3w== From: "Thierry Escande" Subject: =?utf-8?Q?[RFC=20PATCH=202/3]=20libxl:=20Allow=20PCI=20device=20passthrough=20using=20-device=20Qemu=20command=20line?= X-Mailer: git-send-email 2.53.0 X-Bm-Disclaimer: Yes X-Bm-Milter-Handled: 4ffbd6c1-ee69-4e1b-aabd-f977039bd3e2 X-Bm-Transport-Timestamp: 1775669030410 To: xen-devel@lists.xenproject.org Cc: "Thierry Escande" , "Anthony PERARD" , "Juergen Gross" , "=?utf-8?Q?Daniel=20P=20.=20Berrang=C3=A9?=" , "=?utf-8?Q?Marek=20Marczykowski-G=C3=B3recki?=" Message-Id: <20260408172320.539750-3-thierry.escande@vates.tech> In-Reply-To: <20260408172320.539750-1-thierry.escande@vates.tech> References: <20260408172320.539750-1-thierry.escande@vates.tech> X-Native-Encoded: 1 X-Report-Abuse: =?UTF-8?Q?Please=20forward=20a=20copy=20of=20this=20message,=20including=20all=20headers,=20to=20abuse@mandrill.com.=20You=20can=20also=20report=20abuse=20here:=20https://mandrillapp.com/contact/abuse=3Fid=3D30504962.c0022b9fc07d4103bf9af3bb4037bf57?= X-Mandrill-User: md_30504962 Feedback-ID: 30504962:30504962.20260408:md Date: Wed, 08 Apr 2026 17:23:52 +0000 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-ef75cf/1775669034-83D4741E-F54737BC/0/0 X-purgate-type: clean X-purgate-size: 7318 X-ZohoMail-DKIM: pass (identity thierry.escande@vates.tech) (identity @mandrillapp.com) X-ZM-MESSAGEID: 1775669054772154100 Content-Type: text/plain; charset="utf-8" This change makes use of the new option 'hotplug' for host PCI devices passthrough'd to the guest. If hotplug=3D0 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=3D...' 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=3D0' option honors the 'seize' option by adding the PCI device to the assignable list if needed. Example use: pci =3D [ "00:03.0,seize=3D1,hotplug=3D0" ] Signed-off-by: Thierry Escande --- 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, l= ibxl_device_pci *pci, int r int libxl_device_pci_assignable_remove(libxl_ctx *ctx, libxl_device_pci *p= ci, int rebind); libxl_device_pci *libxl_device_pci_assignable_list(libxl_ctx *ctx, int *nu= m); void libxl_device_pci_assignable_list_free(libxl_device_pci *list, int num= ); +bool libxl_pci_assignable(libxl_ctx *ctx, libxl_device_pci *pci); =20 /* CPUID handling */ int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* s= tr); 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 =3D NULL; + + for (i =3D 0; i < guest_config->num_pcidevs; i++) { + libxl_ctx *ctx =3D libxl__gc_owner(gc); + pci =3D &guest_config->pcidevs[i]; + + if (pci->hotplug) + continue; + + if (!libxl_pci_assignable(ctx, pci) && pci->seize) { + rc =3D libxl_device_pci_assignable_add(ctx, pci, 1= ); + if (rc) + return rc; + } + qmp_json =3D libxl__device_pci_get_qmp_json(gc, pci); + rc =3D libxl__json_object_to_json_object(gc, &jso, qmp= _json); + if (rc) + return rc; + json_str =3D json_object_to_json_string_ext(jso, + JSON_C_TO_ST= RING_PLAIN); + flexarray_vappend(dm_args, "-device", json_str, NULL); + } + } } =20 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_int= ernal.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 *g= c, uint32_t domid, libxl_device_pci *pci, bool hotpl= ug); _hidden bool libxl__is_igd_vga_passthru(libxl__gc *gc, const libxl_domain_config *d_confi= g); +_hidden libxl__json_object *libxl__device_pci_get_qmp_json(libxl__gc *gc, + libxl_device_pci = *pci); =20 /* from libxl_dtdev */ =20 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 */ } =20 -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 =3D NULL; - int rc; - - /* Convenience aliases */ - libxl_domid domid =3D pas->domid; - libxl_device_pci *pci =3D &pas->pci; - libxl__ev_qmp *const qmp =3D &pas->qmp; =20 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); =20 + 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 =3D NULL; + int rc =3D 0; + + /* Convenience aliases */ + libxl_domid domid =3D pas->domid; + libxl_device_pci *pci =3D &pas->pci; + libxl__ev_qmp *const qmp =3D &pas->qmp; + + args =3D libxl__device_pci_get_qmp_json(gc, pci); + qmp->ao =3D pas->aodev->ao; qmp->domid =3D domid; qmp->payload_fd =3D -1; qmp->callback =3D pci_add_qmp_device_add_cb; - rc =3D libxl__ev_qmp_send(egc, qmp, "device_add", args); + if (pci->hotplug) + rc =3D 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; =20 @@ -1509,7 +1522,7 @@ int libxl_device_pci_add(libxl_ctx *ctx, uint32_t dom= id, return AO_INPROGRESS; } =20 -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_remov= e_state *prs) libxl_domain_type type =3D libxl__domain_type(gc, domid); libxl_device_pci *pci =3D &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 =3D libxl_device_pci_list(ctx, domid, &num); if (!pcis) { rc =3D ERROR_FAIL; --=20 2.53.0 -- Thierry Escande | Vates XCP-ng Developer XCP-ng & Xen Orchestra - Vates solutions web: https://vates.tech