From: Alexander Shursha <kekek2@ya.ru>
Signed-off-by: Alexander Shursha <kekek2@ya.ru>
---
src/bhyve/bhyve_parse_command.c | 60 +++++++++++++++++++
.../bhyveargv2xml-passthru.args | 7 +++
.../bhyveargv2xml-passthru.xml | 22 +++++++
tests/bhyveargv2xmltest.c | 1 +
4 files changed, 90 insertions(+)
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-passthru.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-passthru.xml
diff --git a/src/bhyve/bhyve_parse_command.c b/src/bhyve/bhyve_parse_command.c
index 7a4e48fbf8..9ca5e1aab9 100644
--- a/src/bhyve/bhyve_parse_command.c
+++ b/src/bhyve/bhyve_parse_command.c
@@ -6,6 +6,7 @@
* Copyright (c) 2011 NetApp, Inc.
* Copyright (C) 2020 Fabian Freyer
* Copyright (C) 2025 The FreeBSD Foundation
+ * Copyright (C) 2024-2025 Future Crew, LLC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -666,6 +667,63 @@ bhyveParsePCIRND(virDomainDef *def,
return 0;
}
+static int
+bhyveParsePassthru(virDomainDef *def G_GNUC_UNUSED,
+ unsigned pcibus,
+ unsigned pcislot,
+ unsigned pcifunction,
+ char *addr)
+{
+ /* -s slot,bus/slot/function */
+ /* -s slot,pcibus:slot:function */
+ virDomainHostdevDef *hostdev = NULL;
+ g_auto(GStrv) params = NULL;
+ GStrv param;
+ char *p = NULL;
+
+ hostdev = virDomainHostdevDefNew();
+ hostdev->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
+ hostdev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
+
+ hostdev->info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+ hostdev->info->addr.pci.bus = pcibus;
+ hostdev->info->addr.pci.slot = pcislot;
+ hostdev->info->addr.pci.function = pcifunction;
+
+ if (!addr)
+ goto error;
+
+ if (!(params = g_strsplit(addr, ":", -1))) {
+ virReportError(VIR_ERR_OPERATION_FAILED, _("Failed to parse PCI address %1$s"), addr);
+ goto error;
+ }
+ if (g_str_equal(addr, *params)) {
+ g_free(params);
+ if (!(params = g_strsplit(addr, "/", -1))) {
+ virReportError(VIR_ERR_OPERATION_FAILED, _("Failed to parse PCI address %1$s"), addr);
+ goto error;
+ }
+ }
+ if (g_strv_length(params) != 3) {
+ virReportError(VIR_ERR_OPERATION_FAILED, _("Failed to parse PCI address %1$s"), addr);
+ goto error;
+ }
+ param = params;
+ hostdev->source.subsys.u.pci.addr.bus = g_ascii_strtoull(*param++, &p, 10);
+ hostdev->source.subsys.u.pci.addr.slot = g_ascii_strtoull(*param++, &p, 10);
+ hostdev->source.subsys.u.pci.addr.function = g_ascii_strtoull(*param, &p, 10);
+
+ hostdev->source.subsys.u.pci.addr.domain = 0;
+ hostdev->managed = false;
+
+ VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, hostdev);
+ return 0;
+
+ error:
+ virDomainHostdevDefFree(hostdev);
+ return -1;
+}
+
static int
bhyveParseBhyvePCIArg(virDomainDef *def,
virDomainXMLOption *xmlopt,
@@ -732,6 +790,8 @@ bhyveParseBhyvePCIArg(virDomainDef *def,
bhyveParsePCIFbuf(def, xmlopt, caps, bus, slot, function, conf);
else if (STREQ(emulation, "virtio-rnd"))
bhyveParsePCIRND(def, xmlopt, caps, bus, slot, function, conf);
+ else if (STREQ(emulation, "passthru"))
+ bhyveParsePassthru(def, bus, slot, function, conf);
VIR_FREE(emulation);
VIR_FREE(slotdef);
diff --git a/tests/bhyveargv2xmldata/bhyveargv2xml-passthru.args b/tests/bhyveargv2xmldata/bhyveargv2xml-passthru.args
new file mode 100644
index 0000000000..4eb1ff14b5
--- /dev/null
+++ b/tests/bhyveargv2xmldata/bhyveargv2xml-passthru.args
@@ -0,0 +1,7 @@
+/usr/sbin/bhyve \
+-c 1 \
+-m 214 \
+-H \
+-P \
+-s 0:0,hostbridge \
+-s 7,passthru,3/0/0 bhyve
diff --git a/tests/bhyveargv2xmldata/bhyveargv2xml-passthru.xml b/tests/bhyveargv2xmldata/bhyveargv2xml-passthru.xml
new file mode 100644
index 0000000000..64118ff89c
--- /dev/null
+++ b/tests/bhyveargv2xmldata/bhyveargv2xml-passthru.xml
@@ -0,0 +1,22 @@
+<domain type='bhyve'>
+ <name>bhyve</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type>hvm</type>
+ </os>
+ <clock offset='localtime'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>destroy</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <hostdev mode='subsystem' type='pci' managed='no'>
+ <source>
+ <address domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
+ </source>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
+ </hostdev>
+ </devices>
+</domain>
diff --git a/tests/bhyveargv2xmltest.c b/tests/bhyveargv2xmltest.c
index 82abce5b8f..acfaade24c 100644
--- a/tests/bhyveargv2xmltest.c
+++ b/tests/bhyveargv2xmltest.c
@@ -161,6 +161,7 @@ mymain(void)
DO_TEST("virtio-blk");
DO_TEST("virtio-net");
DO_TEST("e1000");
+ DO_TEST("passthru");
DO_TEST_WARN("virtio-net2");
DO_TEST_WARN("virtio-net3");
DO_TEST_WARN("virtio-net4");
--
2.51.0
On 11/1/25 07:24, Roman Bogorodskiy wrote:
> From: Alexander Shursha <kekek2@ya.ru>
>
> Signed-off-by: Alexander Shursha <kekek2@ya.ru>
> ---
> src/bhyve/bhyve_parse_command.c | 60 +++++++++++++++++++
> .../bhyveargv2xml-passthru.args | 7 +++
> .../bhyveargv2xml-passthru.xml | 22 +++++++
> tests/bhyveargv2xmltest.c | 1 +
> 4 files changed, 90 insertions(+)
> create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-passthru.args
> create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-passthru.xml
Please squash this in:
diff --git a/src/bhyve/bhyve_parse_command.c b/src/bhyve/bhyve_parse_command.c
index 9ca5e1aab9..5c1527e9c5 100644
--- a/src/bhyve/bhyve_parse_command.c
+++ b/src/bhyve/bhyve_parse_command.c
@@ -681,6 +681,12 @@ bhyveParsePassthru(virDomainDef *def G_GNUC_UNUSED,
GStrv param;
char *p = NULL;
+ if (!addr) {
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("No PCI address provided"));
+ return -1;
+ }
+
hostdev = virDomainHostdevDefNew();
hostdev->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
hostdev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
@@ -690,9 +696,6 @@ bhyveParsePassthru(virDomainDef *def G_GNUC_UNUSED,
hostdev->info->addr.pci.slot = pcislot;
hostdev->info->addr.pci.function = pcifunction;
- if (!addr)
- goto error;
-
if (!(params = g_strsplit(addr, ":", -1))) {
virReportError(VIR_ERR_OPERATION_FAILED, _("Failed to parse PCI address %1$s"), addr);
goto error;
@@ -709,9 +712,12 @@ bhyveParsePassthru(virDomainDef *def G_GNUC_UNUSED,
goto error;
}
param = params;
- hostdev->source.subsys.u.pci.addr.bus = g_ascii_strtoull(*param++, &p, 10);
- hostdev->source.subsys.u.pci.addr.slot = g_ascii_strtoull(*param++, &p, 10);
- hostdev->source.subsys.u.pci.addr.function = g_ascii_strtoull(*param, &p, 10);
+ if (virStrToLong_uip(*param++, &p, 10, hostdev->source.subsys.u.pci.addr.bus) < 0 ||
+ virStrToLong_uip(*param++, &p, 10, hostdev->source.subsys.u.pci.addr.slot) < 0 ||
+ virStrToLong_uip(*param++, &p, 10, hostdev->source.subsys.u.pci.addr.function) < 0) {
+ virReportError(VIR_ERR_OPERATION_FAILED, _("Failed to parse PCI address %1$s"), addr);
+ goto error;
+ }
hostdev->source.subsys.u.pci.addr.domain = 0;
hostdev->managed = false;
@@ -719,9 +725,9 @@ bhyveParsePassthru(virDomainDef *def G_GNUC_UNUSED,
VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, hostdev);
return 0;
- error:
- virDomainHostdevDefFree(hostdev);
- return -1;
+ error:
+ virDomainHostdevDefFree(hostdev);
+ return -1;
}
Michal
© 2016 - 2025 Red Hat, Inc.