conf: formatter/parser/RNG/docs for hostdev <driver name='kvm|vfio'/>

A domain's <interface> or <hostdev>, as well as a <network>'s
<forward>, can now have an optional <driver name='kvm|vfio'/>
element. As of this patch, there is no functionality behind this new
knob - this patch adds support to the domain and network
formatter/parser, and to the RNG and documentation.

When the backend is added, legacy KVM PCI device assignment will
continue to be used when no driver name is specified (or if <driver
name='kvm'/> is specified), but if driver name is 'vfio', the new UEFI
Secure Boot compatible VFIO device assignment will be used.

Note that the parser doesn't automatically insert the current default
value of this setting. This is done on purpose because the two
possibilities are functionally equivalent from the guest's point of
view, and we want to be able to automatically start using vfio as the
default (even for existing domains) at some time in the future. This
is similar to what was done with the "vhost" driver option in
<interface>.
This commit is contained in:
Laine Stump 2013-03-15 15:15:14 -04:00
parent 9f80fc1bd5
commit c4f63ef080
6 changed files with 167 additions and 28 deletions

View File

@ -2369,7 +2369,22 @@
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>
@ -2975,6 +2990,18 @@
<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>&lt;driver&gt;</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 &lt;hostdev&gt;
@ -2993,6 +3020,7 @@
...
&lt;devices&gt;
&lt;interface type='hostdev'&gt;
&lt;driver name='vfio'/&gt;
&lt;source&gt;
&lt;address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/&gt;
&lt;/source&gt;
@ -3124,6 +3152,19 @@ qemu-kvm -net nic,model=? /dev/null
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

View File

@ -279,6 +279,20 @@
use the traditional <code>&lt; hostdev&gt;</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 &lt;forward type='hostdev'&gt; 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
&lt;driver&gt; 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>&lt; hostdev&gt;</code> device, the
@ -360,6 +374,7 @@
<pre>
...
&lt;forward mode='hostdev' managed='yes'&gt;
&lt;driver name='vfio'/&gt;
&lt;address type='pci' domain='0' bus='4' slot='0' function='1'/&gt;
&lt;address type='pci' domain='0' bus='4' slot='0' function='2'/&gt;
&lt;address type='pci' domain='0' bus='4' slot='0' function='3'/&gt;

View File

@ -1939,28 +1939,40 @@
</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>
@ -3107,14 +3119,27 @@
<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">

View File

@ -149,6 +149,17 @@
</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>

View File

@ -587,6 +587,12 @@ VIR_ENUM_IMPL(virDomainHostdevSubsys, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST,
"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",
@ -3683,6 +3689,8 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
{
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
@ -3735,7 +3743,20 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
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;
@ -3746,9 +3767,11 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
virDomainHostdevSubsysTypeToString(def->source.subsys.type));
goto error;
}
ret = 0;
error:
VIR_FREE(managed);
VIR_FREE(backendStr);
return ret;
}
@ -13822,6 +13845,19 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
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;

View File

@ -389,6 +389,16 @@ enum virDomainHostdevSubsysType {
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;
@ -406,6 +416,7 @@ struct _virDomainHostdevSubsys {
} usb;
struct {
virDevicePCIAddress addr; /* host address */
int backend; /* enum virDomainHostdevSubsysPciBackendType */
} pci;
} u;
};