the device as can be found with the <code>lspci</code> or
with <code>virsh
nodedev-list</code>. <a href="#elementsAddress">See above</a> for
- more details on the address element.
+ more details on the address element.</dd>
+ <dt><code>driver</code></dt>
+ <dd>
+ PCI devices can have an optional <code>driver</code>
+ subelement that specifies which backend driver to use for PCI
+ device assignment. Use the <code>name</code> attribute to
+ select either "vfio" (for the new VFIO device assignment
+ backend, which is compatible with UEFI SecureBoot) or "kvm"
+ (for the legacy device assignment handled directly by the KVM
+ kernel module)<span class="since">Since 1.0.5 (QEMU and KVM
+ only, requires kernel 3.6 or newer)</span>. Currently, "kvm"
+ is the default used by libvirt when not explicitly provided,
+ but since the two are functionally equivalent, this default
+ could be changed in the future with no impact to domains that
+ don't specify anything.
+ </dd>
</dl>
<span class="since">Since 0.9.11</span>
</p>
+ <p>
+ To use VFIO device assignment rather than traditional/legacy KVM
+ device assignment (VFIO is a new method of device assignment
+ that is compatible with UEFI Secure Boot), a type='hostdev'
+ interface can have an optional <code>driver</code> sub-element
+ with a <code>name</code> attribute set to "vfio". To use legacy
+ KVM device assignment you can set <code>name</code> to "kvm" (or
+ simply omit the <code><driver></code> element, since "kvm"
+ is currently the default).
+ <span class="since">Since 1.0.5 (QEMU and KVM only, requires kernel 3.6 or newer)</span>
+ </p>
+
<p>
Note that this "intelligent passthrough" of network devices is
very similar to the functionality of a standard <hostdev>
...
<devices>
<interface type='hostdev'>
+ <driver name='vfio'/>
<source>
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
</source>
to 'qemu' without error.
<span class="since">Since 0.8.8 (QEMU and KVM only)</span>
</dd>
+ <dd>
+ For interfaces of type='hostdev' (PCI passthrough devices)
+ the <code>name</code> attribute can optionally be set to
+ "vfio" or "kvm". "vfio" tells libvirt to use VFIO device
+ assignment rather than traditional KVM device assignment (VFIO
+ is a new method of device assignment that is compatible with
+ UEFI Secure Boot), and "kvm" tells libvirt to use the legacy
+ device assignment performed directly by the kvm kernel module
+ (the default is currently "kvm", but is subject to change).
+ <span class="since">Since 1.0.5 (QEMU and KVM only, requires
+ kernel 3.6 or newer)</span>
+ </dd>
+
<dt><code>txmode</code></dt>
<dd>
The <code>txmode</code> attribute specifies how to handle
use the traditional <code>< hostdev></code> device
definition. <span class="since"> Since 0.10.0</span>
+ <p>
+ To use VFIO device assignment rather than
+ traditional/legacy KVM device assignment (VFIO is a new
+ method of device assignment that is compatible with UEFI
+ Secure Boot), a <forward type='hostdev'> interface
+ can have an optional <code>driver</code> sub-element
+ with a <code>name</code> attribute set to "vfio". To use
+ legacy KVM device assignment you can
+ set <code>name</code> to "kvm" (or simply omit the
+ <driver> element, since "kvm" is currently the
+ default).
+ <span class="since">Since 1.0.5 (QEMU and KVM only, requires kernel 3.6 or newer)</span>
+ </p>
+
<p>Note that this "intelligent passthrough" of network
devices is very similar to the functionality of a
standard <code>< hostdev></code> device, the
<pre>
...
<forward mode='hostdev' managed='yes'>
+ <driver name='vfio'/>
<address type='pci' domain='0' bus='4' slot='0' function='1'/>
<address type='pci' domain='0' bus='4' slot='0' function='2'/>
<address type='pci' domain='0' bus='4' slot='0' function='3'/>
</optional>
<optional>
<element name="driver">
- <optional>
- <attribute name="name">
- <choice>
- <value>qemu</value>
- <value>vhost</value>
- </choice>
- </attribute>
- </optional>
- <optional>
- <attribute name="txmode">
- <choice>
- <value>iothread</value>
- <value>timer</value>
- </choice>
- </attribute>
- </optional>
- <optional>
- <ref name="ioeventfd"/>
- </optional>
- <optional>
- <ref name="event_idx"/>
- </optional>
+ <choice>
+ <group>
+ <attribute name="name">
+ <choice>
+ <value>kvm</value>
+ <value>vfio</value>
+ </choice>
+ </attribute>
+ </group>
+ <group>
+ <optional>
+ <attribute name="name">
+ <choice>
+ <value>qemu</value>
+ <value>vhost</value>
+ </choice>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="txmode">
+ <choice>
+ <value>iothread</value>
+ <value>timer</value>
+ </choice>
+ </attribute>
+ </optional>
+ <optional>
+ <ref name="ioeventfd"/>
+ </optional>
+ <optional>
+ <ref name="event_idx"/>
+ </optional>
+ </group>
+ </choice>
<empty/>
</element>
</optional>
<attribute name="type">
<value>pci</value>
</attribute>
- <element name="source">
+ <interleave>
<optional>
- <ref name="startupPolicy"/>
+ <element name="driver">
+ <attribute name="name">
+ <choice>
+ <value>kvm</value>
+ <value>vfio</value>
+ </choice>
+ </attribute>
+ <empty/>
+ </element>
</optional>
- <element name="address">
- <ref name="pciaddress"/>
+ <element name="source">
+ <optional>
+ <ref name="startupPolicy"/>
+ </optional>
+ <element name="address">
+ <ref name="pciaddress"/>
+ </element>
</element>
- </element>
+ </interleave>
</define>
<define name="hostdevsubsysusb">
</attribute>
</element>
</optional>
+ <optional>
+ <element name="driver">
+ <attribute name="name">
+ <choice>
+ <value>kvm</value>
+ <value>vfio</value>
+ </choice>
+ </attribute>
+ <empty/>
+ </element>
+ </optional>
</interleave>
</element>
</optional>
"usb",
"pci")
+VIR_ENUM_IMPL(virDomainHostdevSubsysPciBackend,
+ VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST,
+ "default",
+ "kvm",
+ "vfio")
+
VIR_ENUM_IMPL(virDomainHostdevCaps, VIR_DOMAIN_HOSTDEV_CAPS_TYPE_LAST,
"storage",
"misc",
{
xmlNodePtr sourcenode;
char *managed = NULL;
+ char *backendStr = NULL;
+ int backend;
int ret = -1;
/* @managed can be read from the xml document - it is always an
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
if (virDomainHostdevSubsysPciDefParseXML(sourcenode, def, flags) < 0)
goto error;
+
+ backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_DEFAULT;
+ if ((backendStr = virXPathString("string(./driver/@name)", ctxt)) &&
+ (((backend = virDomainHostdevSubsysPciBackendTypeFromString(backendStr)) < 0) ||
+ backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_DEFAULT)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unknown PCI device <driver name='%s'/> "
+ "has been specified"), backendStr);
+ goto error;
+ }
+ def->source.subsys.u.pci.backend = backend;
+
break;
+
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
if (virDomainHostdevSubsysUsbDefParseXML(sourcenode, def) < 0)
goto error;
virDomainHostdevSubsysTypeToString(def->source.subsys.type));
goto error;
}
+
ret = 0;
error:
VIR_FREE(managed);
+ VIR_FREE(backendStr);
return ret;
}
unsigned int flags,
bool includeTypeInAddr)
{
+ if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
+ def->source.subsys.u.pci.backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_DEFAULT) {
+ const char *backend = virDomainHostdevSubsysPciBackendTypeToString(def->source.subsys.u.pci.backend);
+
+ if (!backend) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected pci hostdev driver name type %d"),
+ def->source.subsys.u.pci.backend);
+ return -1;
+ }
+ virBufferAsprintf(buf, "<driver name='%s'/>\n", backend);
+ }
+
virBufferAddLit(buf, "<source");
if (def->startupPolicy) {
const char *policy;
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST
};
+/* the backend driver used for PCI hostdev devices */
+typedef enum {
+ VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_DEFAULT, /* currently kvm, could change */
+ VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_KVM, /* force legacy kvm style */
+ VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_VFIO, /* force vfio */
+
+ VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST
+} virDomainHostdevSubsysPciBackendType;
+
+VIR_ENUM_DECL(virDomainHostdevSubsysPciBackend)
typedef struct _virDomainHostdevSubsys virDomainHostdevSubsys;
typedef virDomainHostdevSubsys *virDomainHostdevSubsysPtr;
} usb;
struct {
virDevicePCIAddress addr; /* host address */
+ int backend; /* enum virDomainHostdevSubsysPciBackendType */
} pci;
} u;
};