conf: Introduce @guestReset to hostdev's <source/>

Some USB devices have a buggy firmware that either crashes on
device reset, or make the device unusable in some other way.
Fortunately, QEMU offers a way to skip device reset either
completely, or if device is not initialized yet. Expose this
ability to users under:

    <hostdev mode='subsystem' type='usb'>
      <source guestReset='off'/>
    </hostdev>

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Michal Privoznik 2022-07-07 13:11:06 +02:00
parent dcfbfffd6a
commit 85ea114016
6 changed files with 56 additions and 3 deletions

View File

@ -4051,7 +4051,7 @@ for PCI (KVM only) and 1.0.6 for SCSI (KVM only)` :
...
<devices>
<hostdev mode='subsystem' type='usb'>
<source startupPolicy='optional'>
<source startupPolicy='optional' guestReset='off'>
<vendor id='0x1234'/>
<product id='0xbeef'/>
</source>
@ -4231,6 +4231,19 @@ or:
optional drop if missing at any start attempt
========= =====================================================================
:since:`Since 8.6.0`, the ``source`` element can contain ``guestReset``
attribute with the following value:
============= =====================================================
off all guest initiated device reset requests are ignored
uninitialized device request is ignored if device is initialized,
otherwise reset is performed
on device is reset on every guest initiated request
============= =====================================================
This attribute can be helpful when assigning an USB device with a
firmware that crashes on reset.
``pci``
PCI devices can only be described by their ``address``.
:since:`Since 6.8.0 (Xen only)` , the ``source`` element of a PCI device

View File

@ -1042,6 +1042,14 @@ VIR_ENUM_IMPL(virDomainHostdevSubsysSCSIProtocol,
"iscsi",
);
VIR_ENUM_IMPL(virDomainHostdevSubsysUSBGuestReset,
VIR_DOMAIN_HOSTDEV_USB_GUEST_RESET_LAST,
"default",
"off",
"uninitialized",
"on",
);
VIR_ENUM_IMPL(virDomainHostdevSubsysSCSIHostProtocol,
VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_LAST,
"none",
@ -5489,6 +5497,11 @@ virDomainHostdevSubsysUSBDefParseXML(xmlNodePtr node,
return -1;
virTristateBoolToBool(autoAddress, &usbsrc->autoAddress);
if (virXMLPropEnum(node, "guestReset",
virDomainHostdevSubsysUSBGuestResetTypeFromString,
VIR_XML_PROP_NONZERO, &usbsrc->guestReset) < 0)
return -1;
/* Product can validly be 0, so we need some extra help to determine
* if it is uninitialized */
vendorNode = virXPathNode("./vendor", ctxt);
@ -22989,6 +23002,11 @@ virDomainHostdevDefFormatSubsysUSB(virBuffer *buf,
if (def->missing && !(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE))
virBufferAddLit(&sourceAttrBuf, " missing='yes'");
if (usbsrc->guestReset) {
virBufferAsprintf(&sourceAttrBuf, " guestReset='%s'",
virDomainHostdevSubsysUSBGuestResetTypeToString(usbsrc->guestReset));
}
if (usbsrc->vendor) {
virBufferAsprintf(&sourceChildBuf, "<vendor id='0x%.4x'/>\n", usbsrc->vendor);
virBufferAsprintf(&sourceChildBuf, "<product id='0x%.4x'/>\n", usbsrc->product);

View File

@ -233,6 +233,17 @@ typedef enum {
VIR_ENUM_DECL(virDomainHostdevSubsysSCSIProtocol);
typedef enum {
VIR_DOMAIN_HOSTDEV_USB_GUEST_RESET_DEFAULT = 0,
VIR_DOMAIN_HOSTDEV_USB_GUEST_RESET_OFF, /* reset forbidden */
VIR_DOMAIN_HOSTDEV_USB_GUEST_RESET_UNINITIALIZED, /* reset iff uninitialized */
VIR_DOMAIN_HOSTDEV_USB_GUEST_RESET_ON, /* reset allowed */
VIR_DOMAIN_HOSTDEV_USB_GUEST_RESET_LAST
} virDomainHostdevSubsysUSBGuestReset;
VIR_ENUM_DECL(virDomainHostdevSubsysUSBGuestReset);
struct _virDomainHostdevSubsysUSB {
bool autoAddress; /* bus/device were filled automatically based
on vendor/product */
@ -241,6 +252,8 @@ struct _virDomainHostdevSubsysUSB {
unsigned vendor;
unsigned product;
virDomainHostdevSubsysUSBGuestReset guestReset;
};
struct _virDomainHostdevSubsysPCI {

View File

@ -5936,6 +5936,15 @@
<optional>
<ref name="startupPolicy"/>
</optional>
<optional>
<attribute name="guestReset">
<choice>
<value>off</value>
<value>uninitialized</value>
<value>on</value>
</choice>
</attribute>
</optional>
<choice>
<group>
<ref name="usbproduct"/>

View File

@ -26,7 +26,7 @@
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<hostdev mode='subsystem' type='usb' managed='no'>
<source>
<source guestReset='uninitialized'>
<address bus='14' device='6'/>
</source>
</hostdev>

View File

@ -34,7 +34,7 @@
<input type='keyboard' bus='ps2'/>
<audio id='1' type='none'/>
<hostdev mode='subsystem' type='usb' managed='no'>
<source>
<source guestReset='uninitialized'>
<address bus='14' device='6'/>
</source>
</hostdev>