Entering freeze for libvirt-11.2.0
by Jiri Denemark
I have just tagged v11.2.0-rc1 in the repository and pushed signed
tarballs to https://download.libvirt.org/
Please give the release candidate some testing and in case you find a
serious issue which should have a fix in the upcoming release, feel
free to reply to this thread to make sure the issue is more visible.
If you have not done so yet, please update NEWS.rst to document any
significant change you made since the last release.
Thanks,
Jirka
1 week
[PATCH] NEWS: Mention virsh hypervisor-cpu-models command
by Boris Fiuczynski
Signed-off-by: Boris Fiuczynski <fiuczy(a)linux.ibm.com>
---
NEWS.rst | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/NEWS.rst b/NEWS.rst
index 1fc80e2496..18d45656b8 100644
--- a/NEWS.rst
+++ b/NEWS.rst
@@ -67,6 +67,14 @@ v11.2.0 (unreleased)
restore. Using multiple channels can reduce the time required to save
and restore domains.
+ * virsh: Introduce new hypervisor-cpu-models command
+
+ Added a new virsh command ``hypervisor-cpu-models``. The command pulls from
+ the existing domcapabilities XML and uses xpath to parse CPU model strings.
+ By default, only models reported as usable by the hypervisor on the host
+ system are printed. A user may specify ``--all`` to also print models which
+ are not supported on the host.
+
* **Improvements**
* qemu: Improved guest agent corner case error reporting
--
2.47.0
1 week
[PATCH v3 0/3] Reflect MAC change in live domain XML
by Michal Privoznik
v3 of:
https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/message/M...
or:
https://marc.info/?l=libvir-list&m=174230601829060&w=2
since our list archive is giving me some HTTP error currently.
diff to v2:
- Rebased (there were some public APIs merged meanwhile, creating a
conflict in RPC files),
- switched from 'guestAddress' to 'currentAddress'.
Michal Prívozník (3):
qemu: Reflect MAC address change in live domain XML
Introduce NIC_MAC_CHANGE event
qemu: Emit NIC_MAC_CHANGE event
docs/formatdomain.rst | 5 ++
examples/c/misc/event-test.c | 14 +++++
include/libvirt/libvirt-domain.h | 28 +++++++++
src/conf/domain_conf.c | 6 ++
src/conf/domain_conf.h | 3 +
src/conf/domain_event.c | 93 +++++++++++++++++++++++++++++
src/conf/domain_event.h | 12 ++++
src/conf/schemas/domaincommon.rng | 5 ++
src/libvirt_private.syms | 2 +
src/qemu/qemu_domain.c | 48 ++++++++++++++-
src/qemu/qemu_domain.h | 3 +-
src/qemu/qemu_driver.c | 11 ++--
src/qemu/qemu_process.c | 2 +-
src/remote/remote_daemon_dispatch.c | 32 ++++++++++
src/remote/remote_driver.c | 34 +++++++++++
src/remote/remote_protocol.x | 16 ++++-
src/remote_protocol-structs | 8 +++
tools/virsh-domain-event.c | 20 +++++++
18 files changed, 334 insertions(+), 8 deletions(-)
--
2.48.1
1 week
[PATCH] docs: add table showing guest IP/DNS/gateway settings when using SLIRP
by Laine Stump
When using the default SLIRP backend for <interface type='user'>, the
<ip address='blah' prefix='blur'/> setting doesn't behave as might be
expected (i.e. it doesn't set the guest interface IP/prefix to exactly
the provided values). This *should* have created questions when users
originally encountered it, but instead it has become more apparent as
people are contemplating switching from using the SLIRP backend to
using passt instead (with passt, the <ip> settings do behave "as
expected").
In order to make this difference in behavior less mysterious, Yalan
Zhang kindly took the time to test and document the effect of various
representative <ip> settings on guest interface config when SLIRP is
used (see https://issues.redhat.com/browse/RHEL-46601); this patch
adds that same table to libvirt's documentation.
Signed-off-by: Laine Stump <laine(a)redhat.com>
---
docs/formatdomain.rst | 69 ++++++++++++++++++++++++++++++++++++-------
1 file changed, 58 insertions(+), 11 deletions(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index aae58fab60..a6d0660135 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -5239,15 +5239,7 @@ network address by including an ``ip`` element specifying an IPv4
address in its one mandatory attribute, ``address``. Optionally, a
second ``ip`` element with a ``family`` attribute set to "ipv6" can be
specified to add an IPv6 address to the interface. ``address``.
-Optionally, an address ``prefix`` can be specified. These settings are
-surprisingly **not** used by SLIRP to set the exact IP address;
-instead they are used to determine what network/subnet the guest's IP
-address should be on, and the guest will be given an address in that
-subnet, but the host portion of the address will still be "2.15". In
-the example below, for example, the guest will be given the IP address
-172.17.2.15 (**note that the '1.1' in the host portion of the address
-has been ignored**), default route of 172.17.2.2, and DNS server
-172.17.2.3.
+Optionally, an address ``prefix`` can be specified.
::
@@ -5263,6 +5255,59 @@ has been ignored**), default route of 172.17.2.2, and DNS server
</devices>
...
+These settings are surprisingly **not** used by SLIRP to set the exact
+IP address; instead they are used to determine what **network/subnet**
+the guest's IP address should be on, and the guest will be given an
+address in that subnet, but the host portion of the address will still
+be the host portion of "10.0.2.15" (based on the configured prefix (or
+a prefix of 24 if no prefix is specified). The DNS and default gateway
+addresses given to the guest will be similarly based on the network
+portion of the configuration-provided <ip> combined with the host
+portion of SLIRPs default settings for DNS/gateway
+(10.0.2.3/10.0.2.2). To help resolve the confusion of the previous
+sentences, the table below shows examples of the settings that will be
+provided to the guest (via a DHCP response) to use for its interface
+config (ip/prefix, DNS, default gateway) for various settings of <ip>
+element address and prefix in libvirt's <interface type='user'>
+config:
+
+.. list-table::
+ :header-rows: 1
+
+ * - libvirt <ip> element
+ - guest ip/prefix
+ - guest DNS
+ - guest default gateway
+
+ * - (unspecified)
+ - 10.0.2.15/24
+ - 10.0.2.3
+ - 10.0.2.2
+
+ * - address='172.17.1.1'
+ prefix='16'
+ - 172.17.2.15/16
+ - 172.17.2.3
+ - 172.17.2.2
+
+ * - address='172.17.1.1'
+ prefix='24'
+ - 172.17.1.15/24
+ - 172.17.1.3
+ - 172.17.1.2
+
+ * - address='172.17.1.1'
+ prefix='8'
+ - 172.0.2.15/16
+ - 172.0.2.3
+ - 172.0.2.2
+
+ * - address='172.17.1.1'
+ prefix='23'
+ - 172.17.0.15/23
+ - 172.17.0.3
+ - 172.17.0.2
+
Userspace connection using passt
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -5304,8 +5349,10 @@ any conflict).
Also different from SLIRP's behavior: if you do specify IP
address(es), the exact address and netmask/prefix you specify will be
provided to the guest (i.e. passt doesn't interpret the <ip> settings
-as a network address like SLIRP does, but as a host address). In
-example given above, the guest IP would be set to exactly 172.17.1.1.
+as a network address like SLIRP does, but as a host address). In the
+table of examples given above, the guest IP would be set to exactly
+172.17.1.1 in all cases (the DNS and default gateway will be set
+the same as they are on the host).
Just as with SLIRP, though, once traffic from the guest leaves the
host towards the rest of the network, it will always appear as if it
--
2.48.1
1 week
[PATCH] USB hostdev: allow addressing by port
by Maximilian Martin
From: Maximilian Martin <maximilian_martin(a)gmx.de>
Currently, only vendor/product and bus/device matching are supported for USB host
devices. Neither of these provide a stable and persistent way of assigning a guest
a specific host device. Vendor/product can be ambiguous. Device numbers change on
every enumeration.
This patch adds a bus/port matching, which allows a specific port on the host to be
specified using the dotted notation found in Linux's "devpath" sysfs attribute.
This patch is based on the previous work of Thomas Hebb: https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/message/7...
Resolves: https://gitlab.com/libvirt/libvirt/-/issues/513
Signed-off-by: Maximilian Martin <maximilian_martin(a)gmx.de>
---
docs/formatdomain.rst | 29 ++--
src/conf/domain_conf.c | 70 +++++++-
src/conf/domain_conf.h | 1 +
src/conf/schemas/domaincommon.rng | 11 +-
src/hypervisor/virhostdev.c | 131 +++++++++------
src/libvirt_private.syms | 2 -
src/util/virusb.c | 159 ++++++------------
src/util/virusb.h | 32 ++--
tests/virusbtest.c | 149 +++++++++++-----
.../sys_bus_usb/devices/1-1.5.3.1/devpath | 1 +
.../sys_bus_usb/devices/1-1.5.3.3/devpath | 1 +
.../sys_bus_usb/devices/1-1.5.3/devpath | 1 +
.../sys_bus_usb/devices/1-1.5.4/devpath | 1 +
.../sys_bus_usb/devices/1-1.5.5/devpath | 1 +
.../sys_bus_usb/devices/1-1.5.6/devpath | 1 +
.../sys_bus_usb/devices/1-1.5/devpath | 1 +
.../sys_bus_usb/devices/1-1.6/devpath | 1 +
.../sys_bus_usb/devices/1-1/devpath | 1 +
.../sys_bus_usb/devices/2-1.2/devpath | 1 +
.../sys_bus_usb/devices/2-1/devpath | 1 +
.../sys_bus_usb/devices/usb1/devpath | 1 +
.../sys_bus_usb/devices/usb2/devpath | 1 +
.../sys_bus_usb/devices/usb3/devpath | 1 +
.../sys_bus_usb/devices/usb4/devpath | 1 +
24 files changed, 355 insertions(+), 244 deletions(-)
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.1/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.3/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.4/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.5/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.6/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.6/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/2-1.2/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/2-1/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/usb1/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/usb2/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/usb3/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/usb4/devpath
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 543b36cb2e..bc3c11613f 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -4696,19 +4696,22 @@ or:
tweak the loading process further using the ``bar`` or ``file`` attributes
will be rejected. :since:`Since 4.3.0 (QEMU and KVM only)`.
``address``
- The ``address`` element for USB devices has a ``bus`` and ``device``
- attribute to specify the USB bus and device number the device appears at on
- the host. The values of these attributes can be given in decimal, hexadecimal
- (starting with 0x) or octal (starting with 0) form. For PCI devices the
- element carries 4 attributes allowing to designate the device as can be found
- with the ``lspci`` or with ``virsh nodedev-list``. For SCSI devices a 'drive'
- address type must be used. For mediated devices, which are software-only
- devices defining an allocation of resources on the physical parent device,
- the address type used must conform to the ``model`` attribute of element
- ``hostdev``, e.g. any address type other than PCI for ``vfio-pci`` device API
- or any address type other than CCW for ``vfio-ccw`` device API will result in
- an error. See the `Device Addresses`_ section for more details on the address
- element.
+ The ``address`` element for USB devices has a ``bus`` attribute to specify
+ the USB bus. In addition, either a ``device`` attribute or a ``port``
+ attribute is required to identify the device on the host. While the device
+ number is assigned upon connection of the device, the port number is a
+ stable identifier of the physical host port. Bus and device number can be
+ given in decimal, hexadecimal (starting with 0x) or octal (starting with 0)
+ form. The port number is a dotted path (examples: ``2``, ``1.2.5``). For PCI
+ devices the element carries 4 attributes allowing to designate the device as
+ can be found with the ``lspci`` or with ``virsh nodedev-list``. For SCSI
+ devices a 'drive' address type must be used. For mediated devices, which are
+ software-only devices defining an allocation of resources on the physical
+ parent device, the address type used must conform to the ``model`` attribute
+ of element ``hostdev``, e.g. any address type other than PCI for ``vfio-pci``
+ device API or any address type other than CCW for ``vfio-ccw`` device API
+ will result in an error. See the `Device Addresses`_ section for more details
+ on the address element.
``driver``
PCI hostdev devices can have an optional ``driver`` subelement that
specifies which host driver to bind to the device when preparing it
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b94cf99236..bd9c651a07 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2657,6 +2657,15 @@ virDomainHostdevSubsysSCSIClear(virDomainHostdevSubsysSCSI *scsisrc)
}
}
+static void
+virDomainHostdevSubsysUSBClear(virDomainHostdevSubsysUSB *usbsrc)
+{
+ if (!usbsrc)
+ return;
+
+ VIR_FREE(usbsrc->port);
+}
+
static void
virDomainHostdevDefClear(virDomainHostdevDef *def)
@@ -2700,6 +2709,8 @@ virDomainHostdevDefClear(virDomainHostdevDef *def)
g_clear_pointer(&def->source.subsys.u.pci.origstates, virBitmapFree);
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
+ virDomainHostdevSubsysUSBClear(&def->source.subsys.u.usb);
+ break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
break;
@@ -5841,6 +5852,9 @@ virDomainHostdevSubsysUSBDefParseXML(xmlNodePtr node,
xmlNodePtr productNode;
xmlNodePtr addressNode;
virTristateBool autoAddress;
+ bool found_device, found_port;
+ char *port;
+ int ret = -1;
VIR_XPATH_NODE_AUTORESTORE(ctxt)
ctxt->node = node;
@@ -5891,13 +5905,45 @@ virDomainHostdevSubsysUSBDefParseXML(xmlNodePtr node,
}
if ((addressNode = virXPathNode("./address", ctxt))) {
- if (virXMLPropUInt(addressNode, "bus", 0,
- VIR_XML_PROP_REQUIRED, &usbsrc->bus) < 0)
+ found_device = false;
+ found_port = false;
+
+ ret = virXMLPropUInt(addressNode, "bus", 0,
+ VIR_XML_PROP_REQUIRED, &usbsrc->bus);
+ if (ret < 0) {
+ return -1;
+ } else if (ret == 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing bus"));
+ return -1;
+ }
+
+ ret = virXMLPropUInt(addressNode, "device", 0,
+ VIR_XML_PROP_NONE, &usbsrc->device);
+ if (ret < 0)
return -1;
+ else if (ret > 0)
+ found_device = true;
- if (virXMLPropUInt(addressNode, "device", 0,
- VIR_XML_PROP_REQUIRED, &usbsrc->device) < 0)
+ port = virXMLPropString(addressNode, "port");
+ if (port) {
+ if (*port) {
+ usbsrc->port = port;
+ found_port = true;
+ } else {
+ VIR_FREE(port);
+ }
+ }
+
+ if (!found_device && !found_port) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("usb address needs either device id or port"));
return -1;
+ } else if (found_device && found_port) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("found both device id and port in usb address (ambiguous setting)"));
+ return -1;
+ }
}
return 0;
@@ -14522,8 +14568,13 @@ virDomainHostdevMatchSubsysUSB(virDomainHostdevDef *first,
virDomainHostdevSubsysUSB *first_usbsrc = &first->source.subsys.u.usb;
virDomainHostdevSubsysUSB *second_usbsrc = &second->source.subsys.u.usb;
- if (first_usbsrc->bus && first_usbsrc->device) {
- /* specified by bus location on host */
+ if (first_usbsrc->bus && first_usbsrc->port) {
+ /* specified by bus and port on host */
+ if (first_usbsrc->bus == second_usbsrc->bus &&
+ STREQ_NULLABLE(first_usbsrc->port, second_usbsrc->port))
+ return 1;
+ } else if (first_usbsrc->bus && first_usbsrc->device) {
+ /* specified by bus and device id on host */
if (first_usbsrc->bus == second_usbsrc->bus &&
first_usbsrc->device == second_usbsrc->device)
return 1;
@@ -23957,10 +24008,15 @@ virDomainHostdevDefFormatSubsysUSB(virBuffer *buf,
virBufferAsprintf(&sourceChildBuf, "<product id='0x%.4x'/>\n", usbsrc->product);
}
- if (usbsrc->bus || usbsrc->device)
+ if (usbsrc->bus && usbsrc->port) {
+ virBufferAsprintf(&sourceChildBuf, "<address %sbus='%d' port='%s'/>\n",
+ includeTypeInAddr ? "type='usb' " : "",
+ usbsrc->bus, usbsrc->port);
+ } else if (usbsrc->bus || usbsrc->device) {
virBufferAsprintf(&sourceChildBuf, "<address %sbus='%d' device='%d'/>\n",
includeTypeInAddr ? "type='usb' " : "",
usbsrc->bus, usbsrc->device);
+ }
virXMLFormatElement(buf, "source", &sourceAttrBuf, &sourceChildBuf);
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 3a97fd866c..e5f53c09ac 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -228,6 +228,7 @@ struct _virDomainHostdevSubsysUSB {
on vendor/product */
unsigned bus;
unsigned device;
+ char *port;
unsigned vendor;
unsigned product;
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index 3276569325..00d97f0cd8 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -6687,9 +6687,14 @@
<attribute name="bus">
<ref name="usbAddr"/>
</attribute>
- <attribute name="device">
- <ref name="usbAddr"/>
- </attribute>
+ <choice>
+ <attribute name="device">
+ <ref name="usbAddr"/>
+ </attribute>
+ <attribute name="port">
+ <ref name="usbPort"/>
+ </attribute>
+ </choice>
</element>
</define>
<define name="scsiaddress">
diff --git a/src/hypervisor/virhostdev.c b/src/hypervisor/virhostdev.c
index 0a1d8500d4..9e77477a9b 100644
--- a/src/hypervisor/virhostdev.c
+++ b/src/hypervisor/virhostdev.c
@@ -1358,6 +1358,42 @@ virHostdevMarkUSBDevices(virHostdevManager *mgr,
return -1;
}
+static int
+virHostdevFindUSBDeviceWithFlags(virDomainHostdevDef *hostdev,
+ bool mandatory,
+ unsigned int flags,
+ virUSBDevice **usb)
+{
+ virDomainHostdevSubsysUSB *usbsrc = &hostdev->source.subsys.u.usb;
+ unsigned vendor = usbsrc->vendor;
+ unsigned product = usbsrc->product;
+ unsigned bus = usbsrc->bus;
+ char *port = usbsrc->port;
+ unsigned device = usbsrc->device;
+ virUSBDeviceList *devs;
+ int rc;
+
+ rc = virUSBDeviceFind(vendor, product, bus, device, port, NULL,
+ mandatory, flags, &devs);
+ if (rc < 0)
+ return -1;
+
+ if (rc == 1) {
+ *usb = virUSBDeviceListGet(devs, 0);
+ virUSBDeviceListSteal(devs, *usb);
+ }
+ virObjectUnref(devs);
+
+ if (rc > 1) {
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ _("Multiple USB devices for %1$x:%2$x, use <address> to specify one"),
+ vendor, product);
+ return -1;
+ }
+
+ return rc;
+}
+
int
virHostdevFindUSBDevice(virDomainHostdevDef *hostdev,
@@ -1366,77 +1402,64 @@ virHostdevFindUSBDevice(virDomainHostdevDef *hostdev,
{
virDomainHostdevSubsysUSB *usbsrc = &hostdev->source.subsys.u.usb;
unsigned vendor = usbsrc->vendor;
- unsigned product = usbsrc->product;
unsigned bus = usbsrc->bus;
unsigned device = usbsrc->device;
+ char *port = usbsrc->port;
bool autoAddress = usbsrc->autoAddress;
+ unsigned int flags = 0;
int rc;
*usb = NULL;
- if (vendor && bus) {
- rc = virUSBDeviceFind(vendor, product, bus, device,
- NULL,
- autoAddress ? false : mandatory,
- usb);
- if (rc < 0) {
- return -1;
- } else if (!autoAddress) {
- goto out;
- } else {
- VIR_INFO("USB device %x:%x could not be found at previous"
- " address (bus:%u device:%u)",
- vendor, product, bus, device);
- }
+ if (vendor)
+ flags |= USB_DEVICE_FIND_BY_VENDOR;
+ if (device)
+ flags |= USB_DEVICE_FIND_BY_DEVICE;
+ if (port)
+ flags |= USB_DEVICE_FIND_BY_PORT;
+
+ /* Rule out invalid cases. */
+ if (vendor && device && port) {
+ VIR_WARN("Cannot match USB device on vendor/product, bus/device, and bus/port at once. Ignoring bus/device.");
+ flags &= ~((unsigned int) USB_DEVICE_FIND_BY_DEVICE);
+ } else if (device && port) {
+ VIR_WARN("Cannot match USB device on bus/device and bus/port at once. Ignoring bus/device.");
+ flags &= ~((unsigned int) USB_DEVICE_FIND_BY_DEVICE);
+ } else if (!vendor && !device && !port) {
+ VIR_WARN("No matching fields for USB device found. Vendor/product, bus/device, or bus/port required.");
+ return -1;
}
- /* When vendor is specified, its USB address is either unspecified or the
- * device could not be found at the USB device where it had been
- * automatically found before.
- */
- if (vendor) {
- g_autoptr(virUSBDeviceList) devs = NULL;
+ /* First attempt, matching on all valid fields. */
+ rc = virHostdevFindUSBDeviceWithFlags(hostdev,
+ autoAddress ? false : mandatory,
+ flags, usb);
+ if (rc < 0)
+ return -1;
- rc = virUSBDeviceFindByVendor(vendor, product, NULL, mandatory, &devs);
- if (rc < 0) {
- return -1;
- } else if (rc == 0) {
- goto out;
- } else if (rc > 1) {
- if (autoAddress) {
- virReportError(VIR_ERR_OPERATION_FAILED,
- _("Multiple USB devices for %1$x:%2$x were found, but none of them is at bus:%3$u device:%4$u"),
- vendor, product, bus, device);
- } else {
- virReportError(VIR_ERR_OPERATION_FAILED,
- _("Multiple USB devices for %1$x:%2$x, use <address> to specify one"),
- vendor, product);
- }
+ if (rc != 1 && autoAddress && device) {
+ VIR_INFO("USB device could not be found at previous address "
+ "(bus:%u device:%u)", bus, device);
+
+ /* Second attempt, for when the device number has changed. */
+ flags &= ~((unsigned int) USB_DEVICE_FIND_BY_DEVICE);
+ usbsrc->device = 0;
+
+ rc = virHostdevFindUSBDeviceWithFlags(hostdev, mandatory,
+ flags, usb);
+ if (rc < 0)
return -1;
- }
- *usb = virUSBDeviceListGet(devs, 0);
- virUSBDeviceListSteal(devs, *usb);
+ usbsrc->autoAddress = true;
+ }
+ if (!*usb) {
+ hostdev->missing = true;
+ } else if (!usbsrc->bus || !usbsrc->device) {
usbsrc->bus = virUSBDeviceGetBus(*usb);
usbsrc->device = virUSBDeviceGetDevno(*usb);
- usbsrc->autoAddress = true;
-
- if (autoAddress) {
- VIR_INFO("USB device %x:%x found at bus:%u device:%u (moved"
- " from bus:%u device:%u)",
- vendor, product,
- usbsrc->bus, usbsrc->device,
- bus, device);
- }
- } else if (bus) {
- if (virUSBDeviceFindByBus(bus, device, NULL, mandatory, usb) < 0)
- return -1;
}
- out:
- if (!*usb)
- hostdev->missing = true;
return 0;
}
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index e63939e2b5..dbc0778fdb 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -3668,8 +3668,6 @@ virURIResolveAlias;
# util/virusb.h
virUSBDeviceFileIterate;
virUSBDeviceFind;
-virUSBDeviceFindByBus;
-virUSBDeviceFindByVendor;
virUSBDeviceFree;
virUSBDeviceGetBus;
virUSBDeviceGetDevno;
diff --git a/src/util/virusb.c b/src/util/virusb.c
index cf3461f80a..d193f8f3ba 100644
--- a/src/util/virusb.c
+++ b/src/util/virusb.c
@@ -61,12 +61,6 @@ struct _virUSBDeviceList {
virUSBDevice **devs;
};
-typedef enum {
- USB_DEVICE_ALL = 0,
- USB_DEVICE_FIND_BY_VENDOR = 1 << 0,
- USB_DEVICE_FIND_BY_BUS = 1 << 1,
-} virUSBDeviceFindFlags;
-
static virClass *virUSBDeviceListClass;
static void virUSBDeviceListDispose(void *obj);
@@ -102,11 +96,27 @@ static int virUSBSysReadFile(const char *f_name, const char *d_name,
return 0;
}
+static int virUSBSysReadFileStr(const char *f_name, const char *d_name,
+ char **value)
+{
+ char *buf = NULL;
+ g_autofree char *filename = NULL;
+
+ filename = g_strdup_printf(USB_SYSFS "/devices/%s/%s", d_name, f_name);
+
+ if (virFileReadAll(filename, 1024, &buf) < 0)
+ return -1;
+
+ *value = buf;
+ return 0;
+}
+
static virUSBDeviceList *
virUSBDeviceSearch(unsigned int vendor,
unsigned int product,
unsigned int bus,
unsigned int devno,
+ const char *port,
const char *vroot,
unsigned int flags)
{
@@ -127,6 +137,8 @@ virUSBDeviceSearch(unsigned int vendor,
while ((direrr = virDirRead(dir, &de, USB_SYSFS "/devices")) > 0) {
unsigned int found_prod, found_vend, found_bus, found_devno;
+ char *found_port;
+ bool port_matches;
char *tmpstr = de->d_name;
if (strchr(de->d_name, ':'))
@@ -154,16 +166,32 @@ virUSBDeviceSearch(unsigned int vendor,
10, &found_devno) < 0)
goto cleanup;
- if ((flags & USB_DEVICE_FIND_BY_VENDOR) &&
- (found_prod != product || found_vend != vendor))
- continue;
+ if (virUSBSysReadFileStr("devpath", de->d_name,
+ &found_port) < 0) {
+ goto cleanup;
+ } else {
+ found_port[strlen(found_port) - 1] = '\0'; /* remove newline */
+ port_matches = STREQ_NULLABLE(found_port, port);
+ VIR_FREE(found_port);
+ }
- if (flags & USB_DEVICE_FIND_BY_BUS) {
+ if (flags & USB_DEVICE_FIND_BY_VENDOR) {
+ if (found_prod != product || found_vend != vendor)
+ continue;
+ }
+
+ if (flags & USB_DEVICE_FIND_BY_DEVICE) {
if (found_bus != bus || found_devno != devno)
continue;
found = true;
}
+ if (flags & USB_DEVICE_FIND_BY_PORT) {
+ if (found_bus != bus || !port_matches)
+ continue;
+ found = true;
+ }
+
usb = virUSBDeviceNew(found_bus, found_devno, vroot);
if (!usb)
@@ -186,36 +214,41 @@ virUSBDeviceSearch(unsigned int vendor,
}
int
-virUSBDeviceFindByVendor(unsigned int vendor,
- unsigned int product,
- const char *vroot,
- bool mandatory,
- virUSBDeviceList **devices)
+virUSBDeviceFind(unsigned int vendor,
+ unsigned int product,
+ unsigned int bus,
+ unsigned int devno,
+ const char *port,
+ const char *vroot,
+ bool mandatory,
+ unsigned int flags,
+ virUSBDeviceList **devices)
{
virUSBDeviceList *list;
int count;
- if (!(list = virUSBDeviceSearch(vendor, product, 0, 0,
- vroot,
- USB_DEVICE_FIND_BY_VENDOR)))
+ if (!(list = virUSBDeviceSearch(vendor, product, bus, devno, port,
+ vroot, flags)))
return -1;
- if (list->count == 0) {
+ count = list->count;
+ if (count == 0) {
virObjectUnref(list);
if (!mandatory) {
- VIR_DEBUG("Did not find USB device %04x:%04x",
- vendor, product);
if (devices)
*devices = NULL;
return 0;
}
virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Did not find USB device %1$04x:%2$04x"), vendor, product);
+ _("Did not find matching USB device (matching on%1$s%2$s%3$s others are ignored): vid:%4$04x, pid:%5$04x, bus:%6$u, device:%7$u, port:%8$s"),
+ flags & USB_DEVICE_FIND_BY_VENDOR ? " vid/pid," : "",
+ flags & USB_DEVICE_FIND_BY_DEVICE ? " bus/device," : "",
+ flags & USB_DEVICE_FIND_BY_PORT ? " bus/port," : "",
+ vendor, product, bus, devno, port ? port : "(null)");
return -1;
}
- count = list->count;
if (devices)
*devices = list;
else
@@ -224,86 +257,6 @@ virUSBDeviceFindByVendor(unsigned int vendor,
return count;
}
-int
-virUSBDeviceFindByBus(unsigned int bus,
- unsigned int devno,
- const char *vroot,
- bool mandatory,
- virUSBDevice **usb)
-{
- virUSBDeviceList *list;
-
- if (!(list = virUSBDeviceSearch(0, 0, bus, devno,
- vroot,
- USB_DEVICE_FIND_BY_BUS)))
- return -1;
-
- if (list->count == 0) {
- virObjectUnref(list);
- if (!mandatory) {
- VIR_DEBUG("Did not find USB device bus:%u device:%u",
- bus, devno);
- if (usb)
- *usb = NULL;
- return 0;
- }
-
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Did not find USB device bus:%1$u device:%2$u"),
- bus, devno);
- return -1;
- }
-
- if (usb) {
- *usb = virUSBDeviceListGet(list, 0);
- virUSBDeviceListSteal(list, *usb);
- }
- virObjectUnref(list);
-
- return 0;
-}
-
-int
-virUSBDeviceFind(unsigned int vendor,
- unsigned int product,
- unsigned int bus,
- unsigned int devno,
- const char *vroot,
- bool mandatory,
- virUSBDevice **usb)
-{
- virUSBDeviceList *list;
-
- unsigned int flags = USB_DEVICE_FIND_BY_VENDOR|USB_DEVICE_FIND_BY_BUS;
- if (!(list = virUSBDeviceSearch(vendor, product, bus, devno,
- vroot, flags)))
- return -1;
-
- if (list->count == 0) {
- virObjectUnref(list);
- if (!mandatory) {
- VIR_DEBUG("Did not find USB device %04x:%04x bus:%u device:%u",
- vendor, product, bus, devno);
- if (usb)
- *usb = NULL;
- return 0;
- }
-
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Did not find USB device %1$04x:%2$04x bus:%3$u device:%4$u"),
- vendor, product, bus, devno);
- return -1;
- }
-
- if (usb) {
- *usb = virUSBDeviceListGet(list, 0);
- virUSBDeviceListSteal(list, *usb);
- }
- virObjectUnref(list);
-
- return 0;
-}
-
virUSBDevice *
virUSBDeviceNew(unsigned int bus,
unsigned int devno,
diff --git a/src/util/virusb.h b/src/util/virusb.h
index d2b3f69942..cfd1ad51cc 100644
--- a/src/util/virusb.h
+++ b/src/util/virusb.h
@@ -30,30 +30,26 @@ typedef struct _virUSBDeviceList virUSBDeviceList;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virUSBDeviceList, virObjectUnref);
+typedef enum {
+ USB_DEVICE_ALL = 0,
+ USB_DEVICE_FIND_BY_VENDOR = 1 << 0,
+ USB_DEVICE_FIND_BY_DEVICE = 1 << 1,
+ USB_DEVICE_FIND_BY_PORT = 1 << 2,
+} virUSBDeviceFindFlags;
virUSBDevice *virUSBDeviceNew(unsigned int bus,
unsigned int devno,
const char *vroot);
-int virUSBDeviceFindByBus(unsigned int bus,
- unsigned int devno,
- const char *vroot,
- bool mandatory,
- virUSBDevice **usb);
-
-int virUSBDeviceFindByVendor(unsigned int vendor,
- unsigned int product,
- const char *vroot,
- bool mandatory,
- virUSBDeviceList **devices);
-
int virUSBDeviceFind(unsigned int vendor,
- unsigned int product,
- unsigned int bus,
- unsigned int devno,
- const char *vroot,
- bool mandatory,
- virUSBDevice **usb);
+ unsigned int product,
+ unsigned int bus,
+ unsigned int devno,
+ const char *port,
+ const char *vroot,
+ bool mandatory,
+ unsigned int flags,
+ virUSBDeviceList **devices);
void virUSBDeviceFree(virUSBDevice *dev);
int virUSBDeviceSetUsedBy(virUSBDevice *dev,
diff --git a/tests/virusbtest.c b/tests/virusbtest.c
index 870e136321..62b7b8bc29 100644
--- a/tests/virusbtest.c
+++ b/tests/virusbtest.c
@@ -26,9 +26,11 @@
#define VIR_FROM_THIS VIR_FROM_NONE
typedef enum {
- FIND_BY_ALL,
FIND_BY_VENDOR,
- FIND_BY_BUS
+ FIND_BY_DEVICE,
+ FIND_BY_PORT,
+ FIND_BY_VENDOR_AND_DEVICE,
+ FIND_BY_VENDOR_AND_PORT
} testUSBFindFlags;
struct findTestInfo {
@@ -37,6 +39,7 @@ struct findTestInfo {
unsigned int product;
unsigned int bus;
unsigned int devno;
+ const char *port;
const char *vroot;
bool mandatory;
int how;
@@ -70,25 +73,34 @@ static int testDeviceFind(const void *opaque)
g_autoptr(virUSBDeviceList) devs = NULL;
int rv = 0;
size_t i, ndevs = 0;
+ unsigned int flags = 0;
switch (info->how) {
- case FIND_BY_ALL:
- rv = virUSBDeviceFind(info->vendor, info->product,
- info->bus, info->devno,
- info->vroot, info->mandatory, &dev);
- break;
case FIND_BY_VENDOR:
- rv = virUSBDeviceFindByVendor(info->vendor, info->product,
- info->vroot, info->mandatory, &devs);
+ flags = USB_DEVICE_FIND_BY_VENDOR;
+ break;
+ case FIND_BY_DEVICE:
+ flags = USB_DEVICE_FIND_BY_DEVICE;
+ break;
+ case FIND_BY_PORT:
+ flags = USB_DEVICE_FIND_BY_PORT;
break;
- case FIND_BY_BUS:
- rv = virUSBDeviceFindByBus(info->bus, info->devno,
- info->vroot, info->mandatory, &dev);
+ case FIND_BY_VENDOR_AND_DEVICE:
+ flags = USB_DEVICE_FIND_BY_VENDOR |
+ USB_DEVICE_FIND_BY_DEVICE;
+ break;
+ case FIND_BY_VENDOR_AND_PORT:
+ flags = USB_DEVICE_FIND_BY_VENDOR |
+ USB_DEVICE_FIND_BY_PORT;
break;
}
+ rv = virUSBDeviceFind(info->vendor, info->product,
+ info->bus, info->devno, info->port,
+ info->vroot, info->mandatory, flags, &devs);
+
if (info->expectFailure) {
- if (rv == 0) {
+ if (rv >= 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
"unexpected success");
} else {
@@ -99,9 +111,20 @@ static int testDeviceFind(const void *opaque)
goto cleanup;
}
+ if (info->how != FIND_BY_VENDOR) {
+ if (rv == 1) {
+ dev = virUSBDeviceListGet(devs, 0);
+ virUSBDeviceListSteal(devs, dev);
+ } else {
+ goto cleanup;
+ }
+ }
+
switch (info->how) {
- case FIND_BY_ALL:
- case FIND_BY_BUS:
+ case FIND_BY_DEVICE:
+ case FIND_BY_PORT:
+ case FIND_BY_VENDOR_AND_DEVICE:
+ case FIND_BY_VENDOR_AND_PORT:
if (virUSBDeviceFileIterate(dev, testDeviceFileActor, NULL) < 0)
goto cleanup;
break;
@@ -146,14 +169,17 @@ testUSBList(const void *opaque G_GNUC_UNUSED)
virUSBDeviceList *list = NULL;
virUSBDeviceList *devlist = NULL;
virUSBDevice *dev = NULL;
+ virUSBDeviceList *devs = NULL;
int ret = -1;
+ int rv;
size_t i, ndevs;
if (!(list = virUSBDeviceListNew()))
goto cleanup;
#define EXPECTED_NDEVS_ONE 3
- if (virUSBDeviceFindByVendor(0x1d6b, 0x0002, NULL, true, &devlist) < 0)
+ if (virUSBDeviceFind(0x1d6b, 0x0002, 0, 0, NULL, NULL, true,
+ USB_DEVICE_FIND_BY_VENDOR, &devlist) < 0)
goto cleanup;
ndevs = virUSBDeviceListCount(devlist);
@@ -176,7 +202,8 @@ testUSBList(const void *opaque G_GNUC_UNUSED)
goto cleanup;
#define EXPECTED_NDEVS_TWO 3
- if (virUSBDeviceFindByVendor(0x18d1, 0x4e22, NULL, true, &devlist) < 0)
+ if (virUSBDeviceFind(0x18d1, 0x4e22, 0, 0, NULL, NULL, true,
+ USB_DEVICE_FIND_BY_VENDOR, &devlist) < 0)
goto cleanup;
ndevs = virUSBDeviceListCount(devlist);
@@ -196,8 +223,16 @@ testUSBList(const void *opaque G_GNUC_UNUSED)
EXPECTED_NDEVS_ONE + EXPECTED_NDEVS_TWO) < 0)
goto cleanup;
- if (virUSBDeviceFind(0x18d1, 0x4e22, 1, 20, NULL, true, &dev) < 0)
+ rv = virUSBDeviceFind(0x18d1, 0x4e22, 1, 20, NULL, NULL, true,
+ USB_DEVICE_FIND_BY_VENDOR |
+ USB_DEVICE_FIND_BY_DEVICE, &devs);
+ if (rv != 1) {
goto cleanup;
+ } else {
+ dev = virUSBDeviceListGet(devs, 0);
+ virUSBDeviceListSteal(devs, dev);
+ }
+ virObjectUnref(devs);
if (!virUSBDeviceListFind(list, dev)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -229,49 +264,75 @@ mymain(void)
{
int rv = 0;
-#define DO_TEST_FIND_FULL(name, vend, prod, bus, devno, vroot, mand, how, fail) \
+#define DO_TEST_FIND_FULL(name, vend, prod, bus, devno, \
+ port, vroot, mand, how, fail) \
do { \
struct findTestInfo data = { name, vend, prod, bus, \
- devno, vroot, mand, how, fail \
+ devno, port, vroot, mand, how, fail \
}; \
if (virTestRun("USBDeviceFind " name, testDeviceFind, &data) < 0) \
rv = -1; \
} while (0)
-#define DO_TEST_FIND(name, vend, prod, bus, devno) \
- DO_TEST_FIND_FULL(name, vend, prod, bus, devno, NULL, true, \
- FIND_BY_ALL, false)
-#define DO_TEST_FIND_FAIL(name, vend, prod, bus, devno) \
- DO_TEST_FIND_FULL(name, vend, prod, bus, devno, NULL, true, \
- FIND_BY_ALL, true)
-
-#define DO_TEST_FIND_BY_BUS(name, bus, devno) \
- DO_TEST_FIND_FULL(name, 101, 202, bus, devno, NULL, true, \
- FIND_BY_BUS, false)
-#define DO_TEST_FIND_BY_BUS_FAIL(name, bus, devno) \
- DO_TEST_FIND_FULL(name, 101, 202, bus, devno, NULL, true, \
- FIND_BY_BUS, true)
-
#define DO_TEST_FIND_BY_VENDOR(name, vend, prod) \
- DO_TEST_FIND_FULL(name, vend, prod, 123, 456, NULL, true, \
+ DO_TEST_FIND_FULL(name, vend, prod, 123, 456, NULL, NULL, true, \
FIND_BY_VENDOR, false)
#define DO_TEST_FIND_BY_VENDOR_FAIL(name, vend, prod) \
- DO_TEST_FIND_FULL(name, vend, prod, 123, 456, NULL, true, \
+ DO_TEST_FIND_FULL(name, vend, prod, 123, 456, NULL, NULL, true, \
FIND_BY_VENDOR, true)
- DO_TEST_FIND("Nexus", 0x18d1, 0x4e22, 1, 20);
- DO_TEST_FIND_FAIL("Nexus wrong devnum", 0x18d1, 0x4e22, 1, 25);
- DO_TEST_FIND_FAIL("Bogus", 0xf00d, 0xbeef, 1024, 768);
-
- DO_TEST_FIND_BY_BUS("integrated camera", 1, 5);
- DO_TEST_FIND_BY_BUS_FAIL("wrong bus/devno combination", 2, 20);
- DO_TEST_FIND_BY_BUS_FAIL("missing bus", 5, 20);
- DO_TEST_FIND_BY_BUS_FAIL("missing devnum", 1, 158);
+#define DO_TEST_FIND_BY_DEVICE(name, bus, devno) \
+ DO_TEST_FIND_FULL(name, 0x1010, 0x2020, bus, devno, NULL, NULL, true, \
+ FIND_BY_DEVICE, false)
+#define DO_TEST_FIND_BY_DEVICE_FAIL(name, bus, devno) \
+ DO_TEST_FIND_FULL(name, 0x1010, 0x2020, bus, devno, NULL, NULL, true, \
+ FIND_BY_DEVICE, true)
+
+#define DO_TEST_FIND_BY_PORT(name, bus, port) \
+ DO_TEST_FIND_FULL(name, 0x1010, 0x2020, bus, 456, port, NULL, true, \
+ FIND_BY_PORT, false)
+#define DO_TEST_FIND_BY_PORT_FAIL(name, bus, port) \
+ DO_TEST_FIND_FULL(name, 0x1010, 0x2020, bus, 456, port, NULL, true, \
+ FIND_BY_PORT, true)
+
+#define DO_TEST_FIND_BY_VENDOR_AND_DEVICE(name, vend, prod, bus, devno) \
+ DO_TEST_FIND_FULL(name, vend, prod, bus, devno, NULL, NULL, true, \
+ FIND_BY_VENDOR_AND_DEVICE, false)
+#define DO_TEST_FIND_BY_VENDOR_AND_DEVICE_FAIL(name, vend, prod, bus, devno) \
+ DO_TEST_FIND_FULL(name, vend, prod, bus, devno, NULL, NULL, true, \
+ FIND_BY_VENDOR_AND_DEVICE, true)
+
+#define DO_TEST_FIND_BY_VENDOR_AND_PORT(name, vend, prod, bus, port) \
+ DO_TEST_FIND_FULL(name, vend, prod, bus, 456, port, NULL, true, \
+ FIND_BY_VENDOR_AND_PORT, false)
+#define DO_TEST_FIND_BY_VENDOR_AND_PORT_FAIL(name, vend, prod, bus, port) \
+ DO_TEST_FIND_FULL(name, vend, prod, bus, 456, port, NULL, true, \
+ FIND_BY_VENDOR_AND_PORT, true)
+
+ DO_TEST_FIND_BY_DEVICE("integrated camera", 1, 5);
+ DO_TEST_FIND_BY_DEVICE_FAIL("wrong bus/devno combination", 2, 20);
+ DO_TEST_FIND_BY_DEVICE_FAIL("missing bus", 5, 20);
+ DO_TEST_FIND_BY_DEVICE_FAIL("missing devnum", 1, 158);
DO_TEST_FIND_BY_VENDOR("Nexus (multiple results)", 0x18d1, 0x4e22);
DO_TEST_FIND_BY_VENDOR_FAIL("Bogus vendor and product", 0xf00d, 0xbeef);
DO_TEST_FIND_BY_VENDOR_FAIL("Valid vendor", 0x1d6b, 0xbeef);
+ DO_TEST_FIND_BY_PORT("Logitech mouse", 1, "1.5.3.3");
+ DO_TEST_FIND_BY_PORT_FAIL("wrong bus/port combination", 2, "1.5.3.3");
+ DO_TEST_FIND_BY_PORT_FAIL("missing bus", 5, "1.5.3.3");
+ DO_TEST_FIND_BY_PORT_FAIL("missing port", 1, "8.2.5");
+
+ DO_TEST_FIND_BY_VENDOR_AND_DEVICE("Nexus", 0x18d1, 0x4e22, 1, 20);
+ DO_TEST_FIND_BY_VENDOR_AND_DEVICE_FAIL("Bogus vendor and product", 0xf00d, 0xbeef, 1, 25);
+ DO_TEST_FIND_BY_VENDOR_AND_DEVICE_FAIL("Nexus wrong devnum", 0x18d1, 0x4e22, 1, 25);
+ DO_TEST_FIND_BY_VENDOR_AND_DEVICE_FAIL("Bogus", 0xf00d, 0xbeef, 1024, 768);
+
+ DO_TEST_FIND_BY_VENDOR_AND_PORT("Nexus", 0x046d, 0xc069, 1, "1.5.3.3");
+ DO_TEST_FIND_BY_VENDOR_AND_PORT_FAIL("Bogus vendor and product", 0xf00d, 0xbeef, 1, "1.5.3.3");
+ DO_TEST_FIND_BY_VENDOR_AND_PORT_FAIL("Nexus wrong port", 0x18d1, 0x4e22, 1, "8.2.5");
+ DO_TEST_FIND_BY_VENDOR_AND_PORT_FAIL("Bogus", 0xf00d, 0xbeef, 1024, "1.1.1.1");
+
if (virTestRun("USB List test", testUSBList, NULL) < 0)
rv = -1;
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.1/devpath b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.1/devpath
new file mode 100644
index 0000000000..02a7fbef02
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.1/devpath
@@ -0,0 +1 @@
+1.5.3.1
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.3/devpath b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.3/devpath
new file mode 100644
index 0000000000..23ca863cd4
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.3/devpath
@@ -0,0 +1 @@
+1.5.3.3
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3/devpath b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3/devpath
new file mode 100644
index 0000000000..8af85beb51
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3/devpath
@@ -0,0 +1 @@
+1.5.3
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.4/devpath b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.4/devpath
new file mode 100644
index 0000000000..94fe62c274
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.4/devpath
@@ -0,0 +1 @@
+1.5.4
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.5/devpath b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.5/devpath
new file mode 100644
index 0000000000..9075be4951
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.5/devpath
@@ -0,0 +1 @@
+1.5.5
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.6/devpath b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.6/devpath
new file mode 100644
index 0000000000..eac1e0ada6
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.6/devpath
@@ -0,0 +1 @@
+1.5.6
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5/devpath b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5/devpath
new file mode 100644
index 0000000000..c239c60cba
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5/devpath
@@ -0,0 +1 @@
+1.5
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.6/devpath b/tests/virusbtestdata/sys_bus_usb/devices/1-1.6/devpath
new file mode 100644
index 0000000000..810ee4e91e
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.6/devpath
@@ -0,0 +1 @@
+1.6
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1/devpath b/tests/virusbtestdata/sys_bus_usb/devices/1-1/devpath
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1/devpath
@@ -0,0 +1 @@
+1
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/2-1.2/devpath b/tests/virusbtestdata/sys_bus_usb/devices/2-1.2/devpath
new file mode 100644
index 0000000000..5625e59da8
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/2-1.2/devpath
@@ -0,0 +1 @@
+1.2
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/2-1/devpath b/tests/virusbtestdata/sys_bus_usb/devices/2-1/devpath
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/2-1/devpath
@@ -0,0 +1 @@
+1
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/usb1/devpath b/tests/virusbtestdata/sys_bus_usb/devices/usb1/devpath
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/usb1/devpath
@@ -0,0 +1 @@
+0
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/usb2/devpath b/tests/virusbtestdata/sys_bus_usb/devices/usb2/devpath
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/usb2/devpath
@@ -0,0 +1 @@
+0
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/usb3/devpath b/tests/virusbtestdata/sys_bus_usb/devices/usb3/devpath
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/usb3/devpath
@@ -0,0 +1 @@
+0
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/usb4/devpath b/tests/virusbtestdata/sys_bus_usb/devices/usb4/devpath
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/usb4/devpath
@@ -0,0 +1 @@
+0
--
2.39.5
1 week
[PATCH] libxl_conf: Implement hyperv domain flags for Xen
by Will
Adds support for configuring <hyperv/> flags for domains
running under Xen.
The following flags, making use of QEMU's existing flags, are now
configurable for Xen: vapic, synic, stimer, frequencies, tlbflush and
ipi
Tests have been added validating translation to libxl's viridian flags
Updated docs section on <hyperv/> flags to note support and to specify
which flags work with Xen
Signed-off-by: Will <tcosprojects(a)gmail.com>
---
NEWS.rst | 5 +
docs/formatdomain.rst | 20 +--
src/libxl/libxl_conf.c | 90 ++++++++++
.../viridian-hvm-full.json | 101 ++++++++++++
.../viridian-hvm-full.xml | 45 +++++
.../viridian-hvm-none.json | 89 ++++++++++
.../viridian-hvm-none.xml | 36 ++++
.../libxlxml2domconfigdata/viridian-hvm.json | 99 +++++++++++
tests/libxlxml2domconfigdata/viridian-hvm.xml | 42 +++++
.../viridian-passthrough.json | 155 ++++++++++++++++++
.../viridian-passthrough.xml | 37 +++++
tests/libxlxml2domconfigtest.c | 9 +
12 files changed, 718 insertions(+), 10 deletions(-)
create mode 100644 tests/libxlxml2domconfigdata/viridian-hvm-full.json
create mode 100644 tests/libxlxml2domconfigdata/viridian-hvm-full.xml
create mode 100644 tests/libxlxml2domconfigdata/viridian-hvm-none.json
create mode 100644 tests/libxlxml2domconfigdata/viridian-hvm-none.xml
create mode 100644 tests/libxlxml2domconfigdata/viridian-hvm.json
create mode 100644 tests/libxlxml2domconfigdata/viridian-hvm.xml
create mode 100644 tests/libxlxml2domconfigdata/viridian-passthrough.json
create mode 100644 tests/libxlxml2domconfigdata/viridian-passthrough.xml
diff --git a/NEWS.rst b/NEWS.rst
index 9c940b1a81..d6ad961f56 100644
--- a/NEWS.rst
+++ b/NEWS.rst
@@ -17,6 +17,11 @@ v11.2.0 (unreleased)
* **New features**
+ * Support for configuration of ``<hyperv/>`` flags for Xen domains.
+
+ The following flags are now configurable for Xen: ``vapic``, ``synic``,
+ ``stimer``, ``frequencies``, ``tlbflush`` and ``ipi``.
+
* **Improvements**
* **Bug fixes**
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index cbe378e61d..4162ae7930 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -2084,31 +2084,31 @@ are:
based virtualization drivers, such as LXC.
``hyperv``
Enable various features improving behavior of guests running Microsoft
- Windows.
+ Windows. :since:`Since 11.2.0` some of these flags are also available for Xen domains running Microsoft Windows.
=============== ====================================================================== ============================================ ========================================================================
Feature Description Value Since
=============== ====================================================================== ============================================ ========================================================================
- relaxed Relax constraints on timers on, off :since:`1.0.0 (QEMU 2.0)`
- vapic Enable virtual APIC on, off :since:`1.1.0 (QEMU 2.0)`
+ relaxed Relax constraints on timers on, off :since:`1.0.0 (QEMU 2.0), 11.2.0 (Xen, always on)`
+ vapic Enable virtual APIC on, off :since:`1.1.0 (QEMU 2.0), 11.2.0 (Xen)`
spinlocks Enable spinlock support on, off; retries - at least 4095 :since:`1.1.0 (QEMU 2.0)`
- vpindex Virtual processor index on, off :since:`1.3.3 (QEMU 2.5)`
+ vpindex Virtual processor index on, off :since:`1.3.3 (QEMU 2.5), 11.2.0 (Xen, always on)`
runtime Processor time spent on running guest code and on behalf of guest code on, off :since:`1.3.3 (QEMU 2.5)`
- synic Enable Synthetic Interrupt Controller (SynIC) on, off :since:`1.3.3 (QEMU 2.6)`
- stimer Enable SynIC timers, optionally with Direct Mode support on, off; direct - on,off :since:`1.3.3 (QEMU 2.6), direct mode 5.7.0 (QEMU 4.1)`
+ synic Enable Synthetic Interrupt Controller (SynIC) on, off :since:`1.3.3 (QEMU 2.6), 11.2.0 (Xen)`
+ stimer Enable SynIC timers, optionally with Direct Mode support on, off; direct - on,off :since:`1.3.3 (QEMU 2.6), direct mode 5.7.0 (QEMU 4.1), 11.2.0 (Xen, on/off only)`
reset Enable hypervisor reset on, off :since:`1.3.3 (QEMU 2.5)`
vendor_id Set hypervisor vendor id on, off; value - string, up to 12 characters :since:`1.3.3 (QEMU 2.5)`
- frequencies Expose frequency MSRs on, off :since:`4.7.0 (QEMU 2.12)`
+ frequencies Expose frequency MSRs on, off :since:`4.7.0 (QEMU 2.12), 11.2.0 (Xen)`
reenlightenment Enable re-enlightenment notification on migration on, off :since:`4.7.0 (QEMU 3.0)`
- tlbflush Enable PV TLB flush support on, off; direct - on,off; extended - on,off :since:`4.7.0 (QEMU 3.0), direct and extended modes 11.0.0 (QEMU 7.1.0)`
- ipi Enable PV IPI support on, off :since:`4.10.0 (QEMU 3.1)`
+ tlbflush Enable PV TLB flush support on, off; direct - on,off; extended - on,off :since:`4.7.0 (QEMU 3.0), direct and extended modes 11.0.0 (QEMU 7.1.0), 11.2.0 (Xen, on/off only)`
+ ipi Enable PV IPI support on, off :since:`4.10.0 (QEMU 3.1), 11.2.0 (Xen)`
evmcs Enable Enlightened VMCS on, off :since:`4.10.0 (QEMU 3.1)`
avic Enable use Hyper-V SynIC with hardware APICv/AVIC on, off :since:`8.10.0 (QEMU 6.2)`
emsr_bitmap Avoid unnecessary updates to L2 MSR Bitmap upon vmexits. on, off :since:`10.7.0 (QEMU 7.1)`
xmm_input Enable XMM Fast Hypercall Input on, off :since:`10.7.0 (QEMU 7.1)`
=============== ====================================================================== ============================================ ========================================================================
- :since:`Since 8.0.0`, the hypervisor can be configured further by setting
+ :since:`Since 8.0.0 (QEMU) Since 11.2.0 (Xen)`, the hypervisor can be configured further by setting
the ``mode`` attribute to one of the following values:
``custom``
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index c404226e43..d79cf93573 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -582,6 +582,96 @@ libxlMakeDomBuildInfo(virDomainDef *def,
VIR_TRISTATE_SWITCH_ON);
#endif
+#ifdef LIBXL_HAVE_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE
+ if (def->features[VIR_DOMAIN_FEATURE_HYPERV] != VIR_DOMAIN_HYPERV_MODE_NONE) {
+ libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_enable,
+ LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
+
+ switch ((virDomainHyperVMode) def->features[VIR_DOMAIN_FEATURE_HYPERV]) {
+ case VIR_DOMAIN_HYPERV_MODE_CUSTOM:
+ // Base is required by Xen to enable any other flag
+ libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_BASE);
+ // Enable crash ctl register by default to allow guest logs to reach Xen
+ libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_CRASH_CTL);
+ break;
+ case VIR_DOMAIN_HYPERV_MODE_PASSTHROUGH:
+ libxl_bitmap_set_any(&b_info->u.hvm.viridian_enable);
+ break;
+ case VIR_DOMAIN_HYPERV_MODE_NONE:
+ case VIR_DOMAIN_HYPERV_MODE_LAST:
+ default:
+ virReportEnumRangeError(virDomainHyperVMode,
+ def->features[VIR_DOMAIN_FEATURE_HYPERV]);
+ return -1;
+ }
+
+ for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) {
+ switch ((virDomainHyperv) i) {
+ case VIR_DOMAIN_HYPERV_VPINDEX:
+ case VIR_DOMAIN_HYPERV_RELAXED:
+ // Already set by base flag
+ break;
+ case VIR_DOMAIN_HYPERV_SYNIC:
+ if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
+ libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_SYNIC);
+ }
+ break;
+ case VIR_DOMAIN_HYPERV_STIMER:
+ if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
+ // STIMER implies synic and clock features
+ libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_STIMER);
+ libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_SYNIC);
+ libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_TIME_REF_COUNT);
+ libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_REFERENCE_TSC);
+ }
+ break;
+ case VIR_DOMAIN_HYPERV_VAPIC:
+ if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
+ libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_APIC_ASSIST);
+ }
+ break;
+ case VIR_DOMAIN_HYPERV_FREQUENCIES:
+ if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
+ libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_FREQ);
+ }
+ break;
+ case VIR_DOMAIN_HYPERV_TLBFLUSH:
+ if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
+ libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_HCALL_REMOTE_TLB_FLUSH);
+ }
+ break;
+ case VIR_DOMAIN_HYPERV_IPI:
+ if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
+ libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_HCALL_IPI);
+ }
+ break;
+ case VIR_DOMAIN_HYPERV_SPINLOCKS:
+ case VIR_DOMAIN_HYPERV_VENDOR_ID:
+ if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
+ const char *name = virDomainHypervTypeToString(i);
+ VIR_WARN("Hyper-v flag '%s' is specified per-domain but is a global Xen setting and will be ignored.", name);
+ }
+ break;
+ case VIR_DOMAIN_HYPERV_RUNTIME:
+ case VIR_DOMAIN_HYPERV_RESET:
+ case VIR_DOMAIN_HYPERV_REENLIGHTENMENT:
+ case VIR_DOMAIN_HYPERV_EVMCS:
+ case VIR_DOMAIN_HYPERV_AVIC:
+ case VIR_DOMAIN_HYPERV_EMSR_BITMAP:
+ case VIR_DOMAIN_HYPERV_XMM_INPUT:
+ if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
+ const char *name = virDomainHypervTypeToString(i);
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Hyper-v enlightenment feature '%1$s' is not supported for Xen domains."), name);
+ }
+ break;
+ case VIR_DOMAIN_HYPERV_LAST:
+ break;
+ }
+ }
+ }
+#endif
+
/* copy SLIC table path to acpi_firmware */
b_info->u.hvm.acpi_firmware = g_strdup(def->os.slic_table);
diff --git a/tests/libxlxml2domconfigdata/viridian-hvm-full.json b/tests/libxlxml2domconfigdata/viridian-hvm-full.json
new file mode 100644
index 0000000000..5cb69f7b5d
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/viridian-hvm-full.json
@@ -0,0 +1,101 @@
+{
+ "c_info": {
+ "type": "hvm",
+ "name": "test-hvm",
+ "uuid": "2147d599-9cc6-c0dc-92ab-4064b5446e9b"
+ },
+ "b_info": {
+ "max_vcpus": 4,
+ "avail_vcpus": [
+ 0,
+ 1,
+ 2,
+ 3
+ ],
+ "max_memkb": 1048576,
+ "target_memkb": 1048576,
+ "video_memkb": 8192,
+ "shadow_memkb": 1234,
+ "device_model_version": "qemu_xen",
+ "device_model": "/bin/true",
+ "sched_params": {
+
+ },
+ "apic": "True",
+ "acpi": "True",
+ "type.hvm": {
+ "pae": "True",
+ "viridian_enable": [
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9
+ ],
+ "vga": {
+ "kind": "cirrus"
+ },
+ "vnc": {
+ "enable": "True",
+ "listen": "0.0.0.0",
+ "findunused": "False"
+ },
+ "sdl": {
+ "enable": "False"
+ },
+ "spice": {
+
+ },
+ "boot": "c",
+ "rdm": {
+
+ }
+ },
+ "arch_arm": {
+
+ }
+ },
+ "disks": [
+ {
+ "pdev_path": "/var/lib/xen/images/test-hvm.img",
+ "vdev": "hda",
+ "backend": "qdisk",
+ "format": "raw",
+ "removable": 1,
+ "readwrite": 1
+ }
+ ],
+ "nics": [
+ {
+ "devid": 0,
+ "mac": "00:16:3e:66:12:b4",
+ "bridge": "br0",
+ "script": "/etc/xen/scripts/vif-bridge",
+ "nictype": "vif_ioemu"
+ }
+ ],
+ "vfbs": [
+ {
+ "devid": -1,
+ "vnc": {
+ "enable": "True",
+ "listen": "0.0.0.0",
+ "findunused": "False"
+ },
+ "sdl": {
+ "enable": "False"
+ }
+ }
+ ],
+ "vkbs": [
+ {
+ "devid": -1
+ }
+ ],
+ "on_reboot": "restart"
+}
diff --git a/tests/libxlxml2domconfigdata/viridian-hvm-full.xml b/tests/libxlxml2domconfigdata/viridian-hvm-full.xml
new file mode 100644
index 0000000000..17f5ed5209
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/viridian-hvm-full.xml
@@ -0,0 +1,45 @@
+<domain type='xen'>
+ <name>test-hvm</name>
+ <description>None</description>
+ <uuid>2147d599-9cc6-c0dc-92ab-4064b5446e9b</uuid>
+ <memory>1048576</memory>
+ <currentMemory>1048576</currentMemory>
+ <vcpu>4</vcpu>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <clock offset='utc'/>
+ <os>
+ <type>hvm</type>
+ <loader>/usr/lib/xen/boot/hvmloader</loader>
+ <boot dev='hd'/>
+ </os>
+ <features>
+ <apic/>
+ <acpi/>
+ <pae/>
+ <hyperv>
+ <vapic state='on'/>
+ <vpindex state='on'/>
+ <synic state='on'/>
+ <stimer state='on'/>
+ <frequencies state='on'/>
+ <tlbflush state='on'/>
+ <ipi state='on'/>
+ </hyperv>
+ </features>
+ <devices>
+ <emulator>/bin/true</emulator>
+ <disk type='file' device='disk'>
+ <driver name='qemu'/>
+ <source file='/var/lib/xen/images/test-hvm.img'/>
+ <target dev='hda'/>
+ </disk>
+ <interface type='bridge'>
+ <source bridge='br0'/>
+ <mac address='00:16:3e:66:12:b4'/>
+ <script path='/etc/xen/scripts/vif-bridge'/>
+ </interface>
+ <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'/>
+ </devices>
+</domain>
diff --git a/tests/libxlxml2domconfigdata/viridian-hvm-none.json b/tests/libxlxml2domconfigdata/viridian-hvm-none.json
new file mode 100644
index 0000000000..d30875420d
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/viridian-hvm-none.json
@@ -0,0 +1,89 @@
+{
+ "c_info": {
+ "type": "hvm",
+ "name": "test-hvm",
+ "uuid": "2147d599-9cc6-c0dc-92ab-4064b5446e9b"
+ },
+ "b_info": {
+ "max_vcpus": 4,
+ "avail_vcpus": [
+ 0,
+ 1,
+ 2,
+ 3
+ ],
+ "max_memkb": 1048576,
+ "target_memkb": 1048576,
+ "video_memkb": 8192,
+ "shadow_memkb": 1234,
+ "device_model_version": "qemu_xen",
+ "device_model": "/bin/true",
+ "sched_params": {
+
+ },
+ "apic": "True",
+ "acpi": "True",
+ "type.hvm": {
+ "pae": "True",
+ "vga": {
+ "kind": "cirrus"
+ },
+ "vnc": {
+ "enable": "True",
+ "listen": "0.0.0.0",
+ "findunused": "False"
+ },
+ "sdl": {
+ "enable": "False"
+ },
+ "spice": {
+
+ },
+ "boot": "c",
+ "rdm": {
+
+ }
+ },
+ "arch_arm": {
+
+ }
+ },
+ "disks": [
+ {
+ "pdev_path": "/var/lib/xen/images/test-hvm.img",
+ "vdev": "hda",
+ "backend": "qdisk",
+ "format": "raw",
+ "removable": 1,
+ "readwrite": 1
+ }
+ ],
+ "nics": [
+ {
+ "devid": 0,
+ "mac": "00:16:3e:66:12:b4",
+ "bridge": "br0",
+ "script": "/etc/xen/scripts/vif-bridge",
+ "nictype": "vif_ioemu"
+ }
+ ],
+ "vfbs": [
+ {
+ "devid": -1,
+ "vnc": {
+ "enable": "True",
+ "listen": "0.0.0.0",
+ "findunused": "False"
+ },
+ "sdl": {
+ "enable": "False"
+ }
+ }
+ ],
+ "vkbs": [
+ {
+ "devid": -1
+ }
+ ],
+ "on_reboot": "restart"
+}
diff --git a/tests/libxlxml2domconfigdata/viridian-hvm-none.xml b/tests/libxlxml2domconfigdata/viridian-hvm-none.xml
new file mode 100644
index 0000000000..68c2ef08af
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/viridian-hvm-none.xml
@@ -0,0 +1,36 @@
+<domain type='xen'>
+ <name>test-hvm</name>
+ <description>None</description>
+ <uuid>2147d599-9cc6-c0dc-92ab-4064b5446e9b</uuid>
+ <memory>1048576</memory>
+ <currentMemory>1048576</currentMemory>
+ <vcpu>4</vcpu>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <clock offset='utc'/>
+ <os>
+ <type>hvm</type>
+ <loader>/usr/lib/xen/boot/hvmloader</loader>
+ <boot dev='hd'/>
+ </os>
+ <features>
+ <apic/>
+ <acpi/>
+ <pae/>
+ </features>
+ <devices>
+ <emulator>/bin/true</emulator>
+ <disk type='file' device='disk'>
+ <driver name='qemu'/>
+ <source file='/var/lib/xen/images/test-hvm.img'/>
+ <target dev='hda'/>
+ </disk>
+ <interface type='bridge'>
+ <source bridge='br0'/>
+ <mac address='00:16:3e:66:12:b4'/>
+ <script path='/etc/xen/scripts/vif-bridge'/>
+ </interface>
+ <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'/>
+ </devices>
+</domain>
diff --git a/tests/libxlxml2domconfigdata/viridian-hvm.json b/tests/libxlxml2domconfigdata/viridian-hvm.json
new file mode 100644
index 0000000000..4f9a52ed89
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/viridian-hvm.json
@@ -0,0 +1,99 @@
+{
+ "c_info": {
+ "type": "hvm",
+ "name": "test-hvm",
+ "uuid": "2147d599-9cc6-c0dc-92ab-4064b5446e9b"
+ },
+ "b_info": {
+ "max_vcpus": 4,
+ "avail_vcpus": [
+ 0,
+ 1,
+ 2,
+ 3
+ ],
+ "max_memkb": 1048576,
+ "target_memkb": 1048576,
+ "video_memkb": 8192,
+ "shadow_memkb": 1234,
+ "device_model_version": "qemu_xen",
+ "device_model": "/bin/true",
+ "sched_params": {
+
+ },
+ "apic": "True",
+ "acpi": "True",
+ "type.hvm": {
+ "pae": "True",
+ "viridian_enable": [
+ 0,
+ 2,
+ 3,
+ 4,
+ 6,
+ 7,
+ 8,
+ 9
+ ],
+ "vga": {
+ "kind": "cirrus"
+ },
+ "vnc": {
+ "enable": "True",
+ "listen": "0.0.0.0",
+ "findunused": "False"
+ },
+ "sdl": {
+ "enable": "False"
+ },
+ "spice": {
+
+ },
+ "boot": "c",
+ "rdm": {
+
+ }
+ },
+ "arch_arm": {
+
+ }
+ },
+ "disks": [
+ {
+ "pdev_path": "/var/lib/xen/images/test-hvm.img",
+ "vdev": "hda",
+ "backend": "qdisk",
+ "format": "raw",
+ "removable": 1,
+ "readwrite": 1
+ }
+ ],
+ "nics": [
+ {
+ "devid": 0,
+ "mac": "00:16:3e:66:12:b4",
+ "bridge": "br0",
+ "script": "/etc/xen/scripts/vif-bridge",
+ "nictype": "vif_ioemu"
+ }
+ ],
+ "vfbs": [
+ {
+ "devid": -1,
+ "vnc": {
+ "enable": "True",
+ "listen": "0.0.0.0",
+ "findunused": "False"
+ },
+ "sdl": {
+ "enable": "False"
+ }
+ }
+ ],
+ "vkbs": [
+ {
+ "devid": -1
+ }
+ ],
+ "on_reboot": "restart"
+}
diff --git a/tests/libxlxml2domconfigdata/viridian-hvm.xml b/tests/libxlxml2domconfigdata/viridian-hvm.xml
new file mode 100644
index 0000000000..c6139885aa
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/viridian-hvm.xml
@@ -0,0 +1,42 @@
+<domain type='xen'>
+ <name>test-hvm</name>
+ <description>None</description>
+ <uuid>2147d599-9cc6-c0dc-92ab-4064b5446e9b</uuid>
+ <memory>1048576</memory>
+ <currentMemory>1048576</currentMemory>
+ <vcpu>4</vcpu>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <clock offset='utc'/>
+ <os>
+ <type>hvm</type>
+ <loader>/usr/lib/xen/boot/hvmloader</loader>
+ <boot dev='hd'/>
+ </os>
+ <features>
+ <apic/>
+ <acpi/>
+ <pae/>
+ <hyperv mode="custom">
+ <synic state='on'/>
+ <stimer state='on'/>
+ <tlbflush state='on'/>
+ <ipi state='on'/>
+ </hyperv>
+ </features>
+ <devices>
+ <emulator>/bin/true</emulator>
+ <disk type='file' device='disk'>
+ <driver name='qemu'/>
+ <source file='/var/lib/xen/images/test-hvm.img'/>
+ <target dev='hda'/>
+ </disk>
+ <interface type='bridge'>
+ <source bridge='br0'/>
+ <mac address='00:16:3e:66:12:b4'/>
+ <script path='/etc/xen/scripts/vif-bridge'/>
+ </interface>
+ <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'/>
+ </devices>
+</domain>
diff --git a/tests/libxlxml2domconfigdata/viridian-passthrough.json b/tests/libxlxml2domconfigdata/viridian-passthrough.json
new file mode 100644
index 0000000000..66069931f6
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/viridian-passthrough.json
@@ -0,0 +1,155 @@
+{
+ "c_info": {
+ "type": "hvm",
+ "name": "test-hvm",
+ "uuid": "2147d599-9cc6-c0dc-92ab-4064b5446e9b"
+ },
+ "b_info": {
+ "max_vcpus": 4,
+ "avail_vcpus": [
+ 0,
+ 1,
+ 2,
+ 3
+ ],
+ "max_memkb": 1048576,
+ "target_memkb": 1048576,
+ "video_memkb": 8192,
+ "shadow_memkb": 1234,
+ "device_model_version": "qemu_xen",
+ "device_model": "/bin/true",
+ "sched_params": {
+
+ },
+ "apic": "True",
+ "acpi": "True",
+ "type.hvm": {
+ "pae": "True",
+ "viridian_enable": [
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25,
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50,
+ 51,
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 57,
+ 58,
+ 59,
+ 60,
+ 61,
+ 62,
+ 63
+ ],
+ "vga": {
+ "kind": "cirrus"
+ },
+ "vnc": {
+ "enable": "True",
+ "listen": "0.0.0.0",
+ "findunused": "False"
+ },
+ "sdl": {
+ "enable": "False"
+ },
+ "spice": {
+
+ },
+ "boot": "c",
+ "rdm": {
+
+ }
+ },
+ "arch_arm": {
+
+ }
+ },
+ "disks": [
+ {
+ "pdev_path": "/var/lib/xen/images/test-hvm.img",
+ "vdev": "hda",
+ "backend": "qdisk",
+ "format": "raw",
+ "removable": 1,
+ "readwrite": 1
+ }
+ ],
+ "nics": [
+ {
+ "devid": 0,
+ "mac": "00:16:3e:66:12:b4",
+ "bridge": "br0",
+ "script": "/etc/xen/scripts/vif-bridge",
+ "nictype": "vif_ioemu"
+ }
+ ],
+ "vfbs": [
+ {
+ "devid": -1,
+ "vnc": {
+ "enable": "True",
+ "listen": "0.0.0.0",
+ "findunused": "False"
+ },
+ "sdl": {
+ "enable": "False"
+ }
+ }
+ ],
+ "vkbs": [
+ {
+ "devid": -1
+ }
+ ],
+ "on_reboot": "restart"
+}
diff --git a/tests/libxlxml2domconfigdata/viridian-passthrough.xml b/tests/libxlxml2domconfigdata/viridian-passthrough.xml
new file mode 100644
index 0000000000..6d6b7d22cd
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/viridian-passthrough.xml
@@ -0,0 +1,37 @@
+<domain type='xen'>
+ <name>test-hvm</name>
+ <description>None</description>
+ <uuid>2147d599-9cc6-c0dc-92ab-4064b5446e9b</uuid>
+ <memory>1048576</memory>
+ <currentMemory>1048576</currentMemory>
+ <vcpu>4</vcpu>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <clock offset='utc'/>
+ <os>
+ <type>hvm</type>
+ <loader>/usr/lib/xen/boot/hvmloader</loader>
+ <boot dev='hd'/>
+ </os>
+ <features>
+ <apic/>
+ <acpi/>
+ <pae/>
+ <hyperv mode="passthrough"/>
+ </features>
+ <devices>
+ <emulator>/bin/true</emulator>
+ <disk type='file' device='disk'>
+ <driver name='qemu'/>
+ <source file='/var/lib/xen/images/test-hvm.img'/>
+ <target dev='hda'/>
+ </disk>
+ <interface type='bridge'>
+ <source bridge='br0'/>
+ <mac address='00:16:3e:66:12:b4'/>
+ <script path='/etc/xen/scripts/vif-bridge'/>
+ </interface>
+ <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'/>
+ </devices>
+</domain>
diff --git a/tests/libxlxml2domconfigtest.c b/tests/libxlxml2domconfigtest.c
index 255855b156..4654821c3f 100644
--- a/tests/libxlxml2domconfigtest.c
+++ b/tests/libxlxml2domconfigtest.c
@@ -211,6 +211,15 @@ mymain(void)
DO_TEST("single-serial");
DO_TEST("multiple-serial");
+#ifdef LIBXL_HAVE_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE
+ DO_TEST("viridian-hvm");
+ DO_TEST("viridian-hvm-full");
+ DO_TEST("viridian-hvm-none");
+#if LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH == 64
+ DO_TEST("viridian-passthrough");
+#endif
+#endif
+
unlink("libxl-driver.log");
testXLFreeDriver(driver);
--
2.48.1
1 week
[libvirt PATCH] qemu_driver: Fix virDomainSaveImageDefineXML
by Pavel Hrdina
From: Pavel Hrdina <phrdina(a)redhat.com>
Commit 28a06215280b99708ed8dc2d183f62ba7b34ccf8 added support to restore
sparse images but changed the boolean that controls if we open the file
as read-only or read-write. Editing XML in the save image resulted in
following error message:
failed to write header to domain save file '/data/images/fedora40.save': Bad file descriptor
Signed-off-by: Pavel Hrdina <phrdina(a)redhat.com>
---
src/qemu/qemu_driver.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 3cf21380ed..056a9e579d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5945,7 +5945,7 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
if (qemuSaveImageGetMetadata(driver, NULL, path, &def, &data) < 0)
goto cleanup;
- fd = qemuSaveImageOpen(driver, path, false, false, NULL, false);
+ fd = qemuSaveImageOpen(driver, path, false, false, NULL, true);
if (fd < 0)
goto cleanup;
--
2.49.0
1 week, 1 day
[libvirt PATCH 0/6] cleanup and fixes of the mapped-ram feature
by Pavel Hrdina
Pavel Hrdina (6):
tools: remove --parallel from virsh restore command
tools: remote --parallel from virsh save command
qemu: remove VIR_DOMAIN_SAVE_PARALLEL flag
tools: use virDomainRestoreParams only when necessary
tools: use virDomainSaveParams only when necessary
virsh: add --image-format option to the save command
docs/manpages/virsh.rst | 24 +++++----
include/libvirt/libvirt-domain.h | 1 -
src/qemu/qemu_driver.c | 6 +--
src/qemu/qemu_migration_params.c | 34 ++++++------
tools/virsh-domain.c | 93 ++++++++++++++++----------------
5 files changed, 80 insertions(+), 78 deletions(-)
--
2.48.1
1 week, 1 day
[PATCH] NEWS: hotplug virtio-mem device
by Boris Fiuczynski
Signed-off-by: Boris Fiuczynski <fiuczy(a)linux.ibm.com>
---
NEWS.rst | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/NEWS.rst b/NEWS.rst
index 484333e55a..1de0231c57 100644
--- a/NEWS.rst
+++ b/NEWS.rst
@@ -56,6 +56,12 @@ v11.2.0 (unreleased)
* **Bug fixes**
+ * qemu: attach virtio-mem with CCW address
+
+ Attaching a virtio-mem device on s390 without an address type now gets a
+ default type CCW address assigned. A specified CCW address is now used for
+ the virtio-mem device instead of getting overwritten by a PCI address.
+
v11.1.0 (2025-03-03)
====================
--
2.47.0
1 week, 4 days