Show HN: vGPU and SR-IOV on consumer GPUs
arccompute.com
arccompute.com
You may want to do the same for NVMe: creating several namespaces is not supported on most consumer drives, while laptops can rarely have more than 1 NVMe (same problem as with the GPUs: a passthrough requires having 2 of them)
Being able to split the NVMe drive not by partition but by namespace would let each OS see a "full drive".
Is there any documentation you would suggest I read to get started understanding NVMe namespaces?
We're also very open to feature additions/pull requests at our repo: https://libvf.io/ I'm very new to this whole thing of building an open source community but I hope if people find value in some of what they built that they might consider helping us with our code.
If you have any suggestions on how we could improve and build a good open source community I'd love to hear them!
Thanks! Besides being technically interesting and similar to what you do, I think it would also be quite useful for your target audience: if they don't want to do a GPU passthrough, maybe it's because they only have 1 GPU. Maybe they also have only 1 physical drive!
> Is there any documentation you would suggest I read to get started understanding NVMe namespaces?
Just check the official NVMe specs. You can also grab a drive that supports namespaces to see how it works in practice.
It's not very complicated: if you have only 1 NVMe that supports namespaces, and on which you create 3 namespaces, you will have /dev/nvme0n1 /dev/nvme0n2 and /dev/nvme0n3 which can each be partitioned. If you pass /dev/nvme0n2 to a VM1 and /dev/nvme0n3 to another VM, you can be sure that neither will be able to write on the other VM volume, or to the partitions used by the host. It's that simple!
So don't waste too much time on the official specs: the goal for your driver would be just to recognize partitions of a special type, intercept them, and present them to the kernel as if they were a namespace (so they can be passed to virtual machines as if they were a namespace...) for people who have NVMe drives that don't support namespaces (the same thing could be used for regular SATA spinning drives and SSD, but the smaller IOPS compared to NVMe would make it less useful in practice)
Under the hood, you will also want to implement logical block checks to enforce barriers (just like the IOMMU!) so that VM1 can't write blocks on the VM2 virtual drive, and vice versa.
Now that I think about it, it should be quite simple as partitions have a start point and an end point : just check if the write on the virtual disk offset will be within the partition boundaries once you add the offset to map that to the physical disk: for example if /dev/nvme0n2 corresponds to /dev/nvme0n1p6 the offset would simply be the start of this partition.
Now, how to do that nicely, in a way that wouldn't confuse the host or cause problems when dual booting?
A simple way to do that could be to use a well-known GUID. A good candidate would be 024DEE41-33E7-11D3-9D69-0008C781F39F which was reserved for "MBR partition scheme" but remains mostly unused: a partition under this GUID is expected to contain a full disk image (with partitions etc) but will be ignored: https://en.wikipedia.org/wiki/GUID_Partition_Table#PROTECTIV...
On the user side, when not using your driver, each 024DEE41-33E7-11D3-9D69-0008C781F39F type partition could be mounted with losetup -P to read the partition table: https://stackoverflow.com/questions/37227233/having-losetup-...
After thinking a little more about how it would work, it should be a quite interesting project! I hope you will do that!
> We're also very open to feature additions/pull requests
Unfortunately, I don't have a lot of time for such projects at the moment but that should be enough to get you started.
> If you have any suggestions on how we could improve and build a good open source community I'd love to hear them!
Release early, release often, even if it's a bare-mininum MVP. Announce it here.
And shoot me an email at my username at outlook.com so I can do the same in other places :)
---
Relatedly, in FreeBSD you can attach ZFS file systems to jails.
FreeBSD jails is a virtualization mechanism that uses the FreeBSD kernel of the host machine to run processes in isolation. Multiple processes can be isolated together in the same jail, or you can run them in separate jails to isolate them from each others as well. If you are familiar with Linux Namespaces and Docker, I'd say that in principle those are similar to FreeBSD jails.
And the way that ZFS works is that you have something called ZFS pools, which sit on top of one or more physical storage media. For example you might have a pool sitting on top of a single NVMe, or on top of multiple NVMe, or on top of one or multiple spinning disks. And with pools that sit on top of multiple storage media you can mirror or stripe the pool across the underlying storage media, depending on your needs (greater capacity vs redundancy).
Inside of a pool you have one or more ZFS file systems. These file systems can be snapshotted, and you can roll back to previous snapshots. You can also replicate ZFS file systems and snapshots between pools as well as between different hosts.
On my server I have a ZFS pool named "zroot" sitting on top of a single device. Now due to my server itself being a VPS, the device is actually a virtual device that is provided by the hypervisor that the VPS VM is running on. But in the future when I can afford to, and when requirements grow, I can migrate to a physical host where the FreeBSD installation sits directly on physical hardware and the pool has physical devices.
Anyways, on that server, inside of the ZFS pool I have some ZFS file systems for the FreeBSD host itself, and I have additional ZFS file systems on the same pool which are attached to FreeBSD jails.
In this way, storage is managed from the host at the same time as giving isolated access to portions of it to the FreeBSD jails. Aside from the benefits of being able to snapshot, rollback, send and receive, another great thing about ZFS is that the individual ZFS file systems within a pool can each use how ever much of the available space in the pool they need at any time without dedicating any specific amount of storage to any of the individual ZFS file systems. And furthermore, you are still able to define quotas for the individual ZFS file systems, to limit the max amount of space that they are allowed to consume in the pool.
And I think that all of this provides quite closely to what you are describing, although it is using ZFS mechanisms to achieve this and not being based upon NVMe namespaces.
So to show what it looks like to use ZFS with FreeBSD jails, here you can see what the FreeBSD host sees:
$ zpool status
pool: zroot
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
zroot ONLINE 0 0 0
vtbd0p2 ONLINE 0 0 0
errors: No known data errors
$ zpool list
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
zroot 63.5G 3.56G 59.9G - - 1% 5% 1.00x ONLINE -
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
zroot 3.56G 58.0G 96K /zroot
zroot/ROOT 1.98G 58.0G 96K none
zroot/ROOT/default 1.98G 58.0G 1.78G /
zroot/jail-data 528K 58.0G 96K none
zroot/jail-data/ifee 96K 58.0G 96K /data
zroot/jail-data/www 336K 58.0G 336K /data
zroot/jail-opt 19.7M 58.0G 96K none
zroot/jail-opt/ifee 96K 58.0G 96K /opt
zroot/jail-opt/www 19.5M 58.0G 19.5M /opt
zroot/tmp 208K 58.0G 120K /tmp
zroot/usr 1.54G 58.0G 96K /usr
zroot/usr/home 529M 58.0G 529M /usr/home
zroot/usr/jail 1.02G 58.0G 96K /usr/jail
zroot/usr/jail/fullbase 640M 58.0G 639M /usr/jail/fullbase
zroot/usr/jail/ifee 3.63M 58.0G 641M /usr/jail/ifee
zroot/usr/jail/svcfw 48.4M 58.0G 686M /usr/jail/svcfw
zroot/usr/jail/www 354M 58.0G 991M /usr/jail/www
zroot/usr/ports 96K 58.0G 96K /usr/ports
zroot/usr/src 96K 58.0G 96K /usr/src
zroot/var 1.59M 58.0G 96K /var
zroot/var/audit 96K 58.0G 96K /var/audit
zroot/var/crash 96K 58.0G 96K /var/crash
zroot/var/log 1008K 58.0G 896K /var/log
zroot/var/mail 168K 58.0G 104K /var/mail
zroot/var/tmp 160K 58.0G 96K /var/tmp
And here is what one of the jails sees: $ doas jexec www zfs list
NAME USED AVAIL REFER MOUNTPOINT
zroot 3.56G 58.0G 96K /zroot
zroot/jail-data 528K 58.0G 96K none
zroot/jail-data/www 336K 58.0G 336K /data
zroot/jail-opt 19.7M 58.0G 96K none
zroot/jail-opt/www 19.5M 58.0G 19.5M /opt
$ doas jexec www df -h
Filesystem Size Used Avail Capacity Mounted on
zroot/usr/jail/www 59G 991M 58G 2% /
devfs 1.0K 1.0K 0B 100% /dev
zroot/jail-data/www 58G 336K 58G 0% /data
zroot/jail-opt/www 58G 19M 58G 0% /opt
Now let's apply some quotas. $ doas zfs set quota=4G zroot/usr/jail/www
$ doas zfs set quota=5G zroot/jail-opt/www
$ doas zfs set quota=10G zroot/jail-data/www
And we see that these quotas are then reflected inside of the jail. $ doas jexec www zfs list
NAME USED AVAIL REFER MOUNTPOINT
zroot 3.56G 58.0G 96K /zroot
zroot/jail-data 528K 58.0G 96K none
zroot/jail-data/www 336K 10.0G 336K /data
zroot/jail-opt 19.7M 58.0G 96K none
zroot/jail-opt/www 19.5M 4.98G 19.5M /opt
$ doas jexec www df -h
Filesystem Size Used Avail Capacity Mounted on
zroot/usr/jail/www 4.6G 991M 3.7G 21% /
devfs 1.0K 1.0K 0B 100% /dev
zroot/jail-data/www 10G 336K 10G 0% /data
zroot/jail-opt/www 5.0G 19M 5.0G 0% /opt
Pretty neat.It's a real shame consumer GPUs are arbitrary locked down when the enterprise counterparts (often with the exact same chip) have much better support for virtualization.
We're going to try to add support for more distributions in the coming days.
Right now we've got support in our install script for Ubuntu 20.04 hosts and arbitrary guest operating systems (Windows guests work best so far) but if people on GitHub are posting issues asking for support for other systems I'll try my best to get to those.
I'm going to try to add official support for Arch, PopOS, and Fedora as I know some people who I think would use it on those systems and a few others.
(which is the direct successor)
The advantage is that it ships inbox in Windows and doesn't need license hacks or anything. It works cross-vendor too.
However, it needs the host OS to be Windows (with Hyper-V being used).
One of the benefits to using our approach instead of Microsoft's is that our tools are free open source software and (my biased opinion) I think we have an easier user setup. :)
Some day I would love to read Hyper-V's GPU-P code as I think they did a rather good job overall.
edit - apparently while this works on Server 2019 direct pass through is the only officially "supported" option. I wonder if this is a stepping on partners' toes sort of situation?
https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/drive...
Here's a few examples of YAML for use with different GPU vendors:
Intel: https://github.com/Arc-Compute/libvf.io/blob/master/example/...
Nvidia: https://github.com/Arc-Compute/libvf.io/blob/master/example/...
AMD: https://github.com/Arc-Compute/libvf.io/blob/master/example/...
The odd one out is AMD that uses a different API due to the fact that the vendor has largely ignored standard open source interfaces in the kernel. We're still supporting that API but unfortunately there are very few AMD cards that work due to the fact that they refuse to release open source code to support their newer cards and they have locked out these features at the firmware level on consumer cards. Fortunately Nvidia and Intel GPUs are very well suited to this functionality and we've got support for most recent consumer cards from both!
I'm curious to see if this could be used in virtualizing macOS with GVT-g for 3D accelerated guests. I know that this was looked at a few year ago and no one had made it work then.
0: https://github.com/torvalds/linux/blob/2f111a6fd5b5297b4e92f...
You can see the GVT-Linux repository is also still receiving commits: https://github.com/intel/gvt-linux
As for GVT-g and Xe, according to a post in this[0] issue by one of the Intel devs, Rocket Lake (Xe) is not getting support and only does GVT-d.
Also in the same issue, someone pointed out that Intel themselves have states as much here[1].
I hope I am proven wrong in the end and GVT-g comes to then entire Xe and ARC lineup. Intel's communication on this matter has been...lacking.
0: https://github.com/intel/gvt-linux/issues/190
1: https://www.intel.com/content/www/us/en/support/articles/000...
It may be that they're changing internal APIs used for device mediation which wouldn't surprise me given both AMD and Nvidia use SR-IOV but only Intel uses GVT-g.
Makes sense as in servers you probably want static partitioning anyways, but for desktop it was perfect.
Consumers should have the ability to use their hardware well too. Selling the same thing at 2X the price differentiating only on virtualization capabilities is not a moral path.
> We remain hopeful that AMD will recognize forthcoming changes in GPU virtualization with the creation of open standards such as Auxiliary Domains (AUX Domains), Mdev (VFIO-Mdev developed by Nvidia, RedHat, and Intel), and Alternative Routing-ID Interpretation (ARI) especially in light of Intel's market entrance with their ARC line of GPUs supporting Intel Graphics Virtualization Technology (GVT-g).
Really cool to hear there are a bunch of vGPU-related efforts underway! That's so great.
We're hiring!!!
My past experience with looking-glass is that it falls on its face at anything > 1440p@60Hz. I'm interested in vGPU for my linux VMs (spice is slow and sdl/gtk display is flakey) but for gaming, I don't want looking-glass and prefer to just do the passthrough thing with a KVM switch.
Also looking-glass is an option under introspection: in the yaml. You can use whatever type of virtual display you like best. We chose looking glass as the default because in our testing it was the most performant.
edit: ok thanks so its qemu-system-x86_64
Have you guys tried to run something like android in the vm on an arm host? or what are the limitations there?
:)
How is it compared to spice/qxl - does it have some advantages?
The downside is that the sdl or gtk interface is coupled to the running vm and if they crash, the vm goes too. And in my experience, they crash a lot. I've been unable to get a two monitor setup working with either the sdl or gtk display but it works fine via spice.
https://www.collabora.com/news-and-blog/blog/2019/08/28/virg...
Looking forward someone write a Vulkan driver on Windows that just shuttles down to the Linux host. virgl used to be a promising project ...
Is this something that could work with/be integrated with libvirt for easy configuration? Itd be neat to set it up with my current install, although not at all a real problem.
E: The code generating the qemu commands is also quite readable, so I think migrating my install will be quite doable + If needs be i can add args manually.
Some of the software involved in that article simply didn't exist yet, and GPUs weren't shipping with SR-IOV support yet (instead, I did Intel iGPU for Linux fbcon, real AMD GPU fed directly to the Windows VM with PCI-E Passthrough). In the end, I bailed on that dream and moved the Linux install to its own smaller machine, and ran Windows bare on the big machine.
The problem was, if the GPU locked up hard, and GPUs back then would not respond to PCI Device Reset, if it wasn't something that merely re-initializing it on VM restart would fix... I had to restart the entire machine, thus defeating the purpose of having Windows in the VM in the first place!
All my long-lived processes now run on the stand-alone Linux machine, and anything that is free to explode runs on my Windows machine. Windows gets wonky? Restart, ssh back into my screen sessions, reopen the browser, restart a bunch of cloud slaved apps, tada.
Frustratingly this works fine using Windows.
Any ideas on how to run Linux guests on a Windows host while sharing the GPU like libvf.io? This would allow us work around the DSC issue until Nvidia implements support.
Things are becoming more open, not less!
That's partly why I wanted to make this free open source software, to help people take advantage of these cool new open source kernel capabilities on consumer gear!
I've set up a dual-GPU system in the past using two nvidia GPUs and whilst I found the trek towards PCI passthrough to other virtual machines rewarding when it finally worked, I also found the arrangement to be inconvenient.
What you've achieved here, seems the ideal. Well done :)
I will either patiently wait for an Arch Linux version of the install, or I'll eventually end up impatient and see if I can rustle up something - an install script is an install script, it should be just a matter (famous last words) of altering the install script/procedures to suit.
https://arccompute.com/blog/why-computers-suck-and-how-openb...
https://news.ycombinator.com/item?id=21776370
We're not using Nvidia's APIs in our code! libvf.io is entirely based on cross-vendor, standard APIs. :D
The one that is a bit weird is AMD who is fairly far behind Nvidia and Intel but I think if they want to modernize support they can definitely do it. My hope is that consumers will start asking for this capability more (especially with Intel's ARC GPUs enabling GVT-g at every price point) and AMD will update their stuff to reflect that demand.
i.e. you have a vgpu card (or a consumer card you an map to the equivalent vgpu card) and nvidia drivers and tools lets you load drivers that essetially partition it into XGB (all partitions being the same X) and then you just gpu passthrough the newly created device that maps to a single partition into the vm?
the whole trick being the ability to trick nvidia's drivers into thinking that the consumer gpu is really the server model, but otherwise it becomes just normal nvidia usage?
I will say though from a hobbyist point of view this project is just great. If you're trying things and spinning up VMs just to see what you can do then one of the first bottle necks is going to be that you can't use dedicated graphics (without passing through the whole card, and then you need a card per VM). This project makes it a lot easier for anyone fiddling rather than doing stuff commercially, especially with current GPU prices.
Edit: There's not really an explicit need to trick the card. Nvidia co-wrote the VFIO-Mdev API with Intel and RedHat which is what we use. If you want to use the optional nv merged driver package that will do some of the things you mention but it's not required.
The good news is that we also support consumer Nvidia GPUs and some consumer AMD GPUs as well. There are more limitations in AMD land than the other vendors but I'm hopeful that they will make some improvements across time.
Also I posted in the Level1Techs forum! https://forum.level1techs.com/t/libvf-io-a-commodity-gpu-mul...
The normal vGPU_Unlock steps aren't a part of the user setup process, rather the optional merged driver package is built with a C version of the code that's been prepackaged. If you decide to use the vGPU_Unlock merged driver option during setup you won't have to do the (somewhat intense) process of vGPU_Unlock setup, you'll just skip straight to the end result. :)
Sorry I don’t understand well. A lot of jargon is being throw around and I haven’t touched this topic much once I got my pass through setup working
By the way, we're hiring GPU driver engineers and kernel hackers!
Please reach out to me if you know anyone who might be interested. My email is: arthur@arccompute.com
Our software also works on most consumer Nvidia cards and also some consumer AMD cards.
What are the security implications of LibVF and would it be compatible with the QubesOS security model?
Ya, I have been talking with the Qubes guys. I'm trying my best to figure out how I can help them ship something with LibVF.IO but they are currently based on Xen which uses Libxl rather than VFIO which may present some challenges.
https://www.intel.com/content/www/us/en/support/articles/000...