On Fri, 2016-03-18 at 11:03 -0600, Alex Williamson wrote:
> Anyway, after reading your explanation I'm wondering if we
> shouldn't always recommend a setup where devices that are going
> to be assigned to guests are just never bound to any host driver,
> as that sounds like it would have the most chances of working
> reliably.
>
> IIUC, the pci-stubs.ids kernel parameter you mentioned above does
> exactly that. Maybe blacklisting the host driver as well might be
> a good idea? Anything else a user would need to do? Would the
> user or management layer not be able to configure something like
> that in a oVirt / OpenStack environment? What should we change
> to make it possible or easier?
Both pci-stub.ids and blacklisting have some serious problems. A
common thread on the vfio-users list is that someone has two identical
devices and wants to use one for the host and one for a VM and can't
figure out how to make that work.
Right, because pci-stub.ids works on 'vendor product' and not
on 'domain:bus:slot.function', so if you have two or more
identical devices it's all or nothing.
The only solution I know is to
escalate to initramfs scripts that are smarter about which device to
pick. Maybe this implies that we need some initramfs integration for
driver_override so that we can force a particular driver for a
particular device, but that fails to acknowledge that a user may want
the device to use the default driver, up until the point that they
don't.
Is that really something we want to encourage? See below.
Blacklisting has similar issues, but worse. Not all SR-IOV drivers
are
partitioned such that there's a separate driver for PF vs VF, quite a
few use the same driver for both. So immediately blacklisting doesn't
work for a large class of drivers. In general it's even more broad
than pci-stub.ids, for instance I might not want snd-hda-intel to bind
to the GPU audio device used for a VM, but I definitely want
snd-hda-intel binding to my primary audio device. I've also found that
marking i915 for blacklist does absolutely nothing... go figure.
Of course driver blacklisting is even more coarse-grained
than pci-stub.ids, so not suitable in a lot of situations.
Got it.
BTW, even if we do either of these, do we still need
managed='yes'
since the device will be bound to either pci-stub or nothing and needs
to get to vfio-pci? I don't recall if libvirt accepts those cases or
not. If not, then we're unnecessarily bouncing back and forth between
drivers even if we take a pci-stub/blacklist approach unless we inject
another layer that actually binds them to vfio-pci.
Well, if a device is bound to pci-stub and we want to use
VFIO passthrough we're always going to have to unbind it
from pci-stub and bind it to vfio-pci, aren't we?
Shouldn't that be safe anyway? As long as the device is
never bound to a host driver...
Let's take it one step further, what if we made an initramfs
script
that would set "vfio-pci" for the driver_override for a user specified
list of devices. Recall that driver_override means that only the
driver with the matching name can bind to the device. So now we boot
up with the user defined set of devices without drivers. What happens
in either the managed='yes' or 'no' scenarios? Logically this seems
like exactly when we want to use 'detach'.
If managed='no', libvirt will not attempt to rebind the
device to the host driver after detaching it from the
guest, so we're good.
If managed='yes', libvirt *will* attempt to rebind it
to the host driver, but due to driver_override it will
end up being bound to vfio-pci anyway: still safe.
This looks like the perfect solution for people who
want to dedicate some host devices to VFIO passthrough
exclusively... Of course it requires implementing the
smart initramfs bits.
Could this be controlled by a kernel parameter? So you
can just add something like
vfio-pci.devices=0000:02:00.0,0000:03:00.0
to your bootloader configuration and be sure that the
devices you've listed will never be touched by the host.
Note that I have no idea how much work implementing
something like the above would be, or whether it would
even be possible :)
> That would give us a setup we can rely on, and cover all use
> cases you mentioned except that of someone assigning his laptop's
> GPU to a guest and needing the console to be available before the
> guest has started up because no other access to the machine is
> available. But in that case, even with managed='detach', the user
> would need to blindly restart the machine after guest shutdown,
> wouldn't he?
I don't want to make this issue about any one particular driver because
I certainly hope that we'll eventually fix that one driver.
Of course :)
The
problem is more that this is not an uncommon scenario. In one of my
previous replies I listed all of the driver issues that I know about.
In some cases we can't fix them because the driver is proprietary, in
others we just don't have the bandwidth. Users have far more devices
at their disposal to test than we do, so they're likely going to
continue to run into these issues.
Summing up the issues you listed in that message, along with
my thoughts:
* stealing audio device from host when running a game in a
guest, giving it back afterwards
- desktop use case
- seems to be working fine with managed='yes'
- if something goes wrong when reattaching to the host,
the user can probably still go about his business;
rebooting the host is going to be annoying but not a
huge deal
- limited number of in-kernel slots means you can only
do this a number of time before it stops working;
again, having to reboot the host once every so-many
guest boots is probably not a deal breaker
- managed='detach' is not helpful here, and neither is
the proposal above
* NIC reserved for guest use
- both server and desktop use case
- may or may not handle going back and forth between
the host and the guest
- managed='detach' would still prevent most issues,
assuming the host driver detaches cleanly
- best would be if the host never touched the device
- a solution like the one outlined above seems perfect
- for oVirt / OpenStack, the management layer could
take care of updating the bootloader configuration
- for pure libvirt, that responsability would fall on
the user
- should virt-manager etc. rather default to
managed='detach' when assigning a NIC to a guest?
* GPU with binary driver
- both server and desktop use case
- doesn't handle dynamic unbind gracefully
- best would be if the host never touched the device
- a solution like the one outlined above seems perfect
- for oVirt / OpenStack, the management layer could
take care of updating the bootloader configuration
- for pure libvirt, that responsability would fall on
the user
- managed='detach' can prevent some failures, but not
those that happen on host driver unbind
* Primary Intel GPU
- desktop use case (any reason to do this for servers?)
- will probably fail on reattach
- mananged='detach' would prevent host crashes and the
like
- must assume the user has some other way to connect to
the host, because at some point they're going to be
unable to use the GPU from the host anyway
Have I missed anything?
Yes, managed='no' is an
alternative, but if we go down the path of saying 'well that feature
sounds like foo+bar and we already do both of those, so we don't need
that feature', then we have to start asking why do we even have
managed='yes'? Why do we have an autostart feature, we can clearly
start a VM and it's the app's problem when to call that, etc. It seems
useful to me, but I can understand the concern about feature bloat.
If we've added redundant features in the past, then that's
only the more reason to avoid adding even more now ;)
Thanks for taking the time to reply in such detail and
providing concrete examples, it's been really helpful for
me!
Cheers.
--
Andrea Bolognani
Software Engineer - Virtualization Team