Wow, a week isn't very long at all. But still, there's definitely enough to write about, even if I spent most of the week just reading mailing list threads. More on that in a bit.
Spectrum Live + nixpkgs -----------------------
I did another stream. This time, we looked at updating the Chromium OS packages in Spectrum. The script I used to update them had broken -- it was stuck on an old version, so first we had to fix the script, and then fix the package builds. A lot of the Chromium OS packages aren't actually necessary at the moment, but I made them a while ago when it looked like they would be. I couldn't get one particular such package, libchrome, to build any more at all after spending quite a few hours on it, so I ended up just dropping it, along with libbrillo, which depended on it. Some other package updates had some complexity, but we managed to work through them all on the stream.
This stream was much more focused on what I was working on than the last one. The last one was more about people asking general questions and me answering them and demonstrating things. This time I stayed on the package updates for the whole stream. I figure people asked all their questions last time. But there were lots of questions about specific issues in the package updates, etc. It was nice to know that I had explained things sufficiently well that people could follow along with what I was doing. Viewer numbers were up too, which was nice. We were on 15 for most of the stream.
The packaging work I mostly did on the stream, and then finished up afterwards is here:
And a couple of small upstream Nixpkgs PRs:
crosvm still needs to be updated in upstream Nixpkgs. If you want to help out, this might be a good thing to pick up! You'd need to copy the update.py change I made in Spectrum's Nixpkgs to the crosvm update.py in upstream Nixpkgs, and then copy the changes in Spectrum nixpkgs' crosvm to upstream Nixpkgs's crosvm.
If not, I'll probably get to it in a few days.
Last week, I said that we might me able to use Virtio Wayland as a transport for crosvm device <-> crosvm communication across a VM boundary, but that I'd just had the idea and I might decide it couldn't work.
Having researched it extensively this week, reading over the code for the virtio_wl kernel driver with puck and consuming a huge number of messages on assorted kernel-adjacent mailing lists, I think we can make it work, and it's our best path forward, but I'm still not sure how exactly. The main problem is that Virtio Wayland can only send shared memory from host to guest, not the other way around. So when a Wayland compositor in a guest hands the Wayland crosvm device, it's not going to be able to pass it over the VM boundary to the crosvm instance running a Wayland client.
Sharing a guest memory buffer with the host, or another guest, turns out not to be a solved problem in general. As an example, here is a very long mailing list thread about how a generic way to do this could work, from November/December, which reached no firm conclusions:
I expect that for most devices, e.g. the network driver, this won't be a problem. But we're definitely going to need this for Wayland. One option would be to modify a Wayland compositor to make it ask the host for some shared memory, rather than allocating its own shared memory buffer. That would work, but it's the last resort, because it would have to be a modification made to any Wayland compositor we might want to use.
At a high level, what we want to do is have a crosvm device running inside a device VM tell crosvm that a certain address in guest memory is some shared memory, and have it handle that as it would shared memory it had allocated itself.
crosvm does support sending dmabufs from guest to host, because of virtio-gpu. There's a relatively new kernel API called udmabuf that converts a memfd into a dmabuf, which sounds like it should solve exactly this problem. It has no documentation in the kernel, but I did manage to find a small amount of documentation in a patch that was for some reason never applied. I then managed to write a small test program that at least called all the ioctls properly and ended up with a dmabuf. Actually testing this any further will involve a VM, and testing this sort of thing in a VM at the moment is a real pain, and I want to make a small tooling improvement around that before I proceed any further with testing udmabuf. There are also good reasons to suspect that the udmabuf idea won't work anyway. puck thinks that the only dmabufs Virtio Wayland will be able to transfer are those allocated by virtio-gpu. So, not dmabufs that we just made out of a memfd given to us by a Wayland compositor.
If udmabuf ends up not working, I'll want to see whether we can use virtio-gpu to allocate dmabufs. The problem with this is that I don't know how we'll bridge compositor shared memory to virtio-gpu dmabufs. It'll presumably involve writing kernel code, which I've been pleased to avoid so far. I can at least probably use the udmabuf implementation as a starting point.
The third least bad option would be to modify the virtio_wl kernel driver so it supports shared memory originating from the guest. This would be very nice to use from userspace, but I just don't think there's any way I'll be able to write the required kernel code.
And the fourth least bad option (the worst one) would be to modify the compositor as mentioned above.
The current way of running a Spectrum test VM is to build and run a file called start-vm.nix that lives in the root of a non-default branch of Spectrum's nixpkgs called crosvm-demo. Any time you want to try a custom kernel, rootfs, or crosvm, you need to modify this file. This is extremely annoying. Also, as time goes on, start-vm.nix is getting longer and longer, and more and more difficult to understand. So I think it's finally time to do something better. The something better is that we introduce derivations for a Spectrum rootfs, guest kernel, and crosvm, and then provide a program, spectrum-vm, that by default runs a VM with those three components. It would also have options for overriding those components, so if you built a custom kernel you could just drop that one in instead of the default one, for example. And finally, it would allow changing the flags passed to crosvm.
I started working on this this morning, and I'm quite excited about it. It's not going to take very long at all to do, but it's going to be such a big improvement. It will also mean I no longer have a separate crosvm-demo branch, to merge Spectrum nixpkgs master into every time I update it. So I'm going to spend the next couple of days on this, and then get back into investigating udmabuf with a nice new tool.
So, that's what happened this week. I feel like I just spent most of the week reading mailing lists and not making much progress, but I've managed to write quite a lot (again) so I suppose I've accomplished something!
Now, I've been extremely immersed in this stuff all week, and I suspect that some of this update, especially the crosvm stuff, will not be clear to somebody who has not been similarly immersed. And, it's getting dangerously close to midnight UTC, my self-imposed This Week in Spectrum deadline. So I'm going to send this as is, even though it's probably confusing. But! I do want you to understand what's going on. So please feel free to reply and point out anything I didn't explain very well and ask me for a better explanation. Just be prepared for me not to know the answer, since I'm still trying to figure out a lot of this stuff! As a nice side effect, maybe we'll get a mailing list discussion going. :)