It's been a bit of a slow week, I'm afraid.
spectrum-vm -----------
As mentioned last week, it was becoming extremely inconvenient to test out custom kernel/crosvm/rootfs builds by modifying a Nix expression every time. So I wrote spectrum-vm, a small program that takes command line arguments for kernel, crosvm, and rootfs paths to use, and falls back to pre-built defaults if any of those aren't specified. This makes turnaround time on testing different kernel builds much quicker, because they can be built incrementally outside of nix sandboxes.
To make things more concrete, suppose I have built a kernel in /home/src/linux/arch/x86_64/boot/bzImage, and I want to test it with the Spectrum crosvm demo setup. I can run
spectrum-vm -k /home/src/linux/arch/x86_64/boot/bzImage
and I get a VM booted from that kernel, with no need to nix-build anything.
By default, the launched VM will run Weston Terminal inside a Wayland compositor. But you can even replace this with a custom command:
spectrum-vm -c 'echo "Hello, world!"'
The implementation of that last bit is quite the hack. I'll leave figuring out how it works as an exercise to the reader. ;)
spectrum-vm is available now in Spectrum's Nixpkgs as spectrumPackages.spectrum-vm, as of commit 817a1a9b0de30d8bbc2ad2e80a802d87c56e96ff. Implementing this has meant that the huge start-vm.nix file that used to exist on the crosvm-demo branch had to be split up into a bunch of discreet units. This is really great, because start-vm.nix was starting to grow enormous, and experimenting with changes was becoming A Problem. Now, that's all nice and modular under the new spectrumPackages namespace. And _that_ means that the crosvm-demo branch can finally go away, and Spectrum's Nixpkgs is no longer split across two branches. (The purpose of the separation was to avoid there being a horrible start-vm.nix file in the root on master.) So in addition to a lovely helpful tool, this has also resulted in much cleaner code. Yay!
One feature I would still like to add is an option that maps to crosvm run's --shared-dir, to mount a directory into a VM over 9p. That would make getting code into a VM to test it extremely convenient. I haven't gotten around to it yet though.
Guest memory sharing --------------------
Last week I shared a bunch of research I had done on sharing guest-allocated buffers with other VMs. I was hoping to avoid having to patch a Wayland compositor to request buffers from the host instead of allocating them itself, but I've since come to the conclusion that avoiding that won't be feasible, for now at least.
Basically, the kernel primitives aren't there yet, and it would be silly for me, with almost zero kernel development experience, to attempt to write them. There are all sorts of horrible edge cases to think about, like what happens if the guest-allocated memory moves around. Compared to this, patching a Wayland compositor doesn't seem too bad. Having to go through a request/response over a vsock to the host will be a bit of a performance overhead compared to a smarter solution, but I think this kind of allocation happens rarely enough that it probably doesn't matter anyway.
A nice middle ground would have been to use virtio-gpu resources rather than a custom message over a vsock. It would have been a much cleaner way to do it, and it might not even involve writing any kernel code, but the practical benefits of it would be extremely limited when contrasted with the time it would take me to implement that.
I don't expect the approach I'm taking now of patching the Wayland compositor to necessarily be permanent. As I linked to last week, there are kernel efforts happening to add the necessary primitives to share guest allocations. At some point in the future we might be able to use them. And at basically any time we could switch to using virtio-gpu resources if somebody wanted to put in the work.
Patching a compositor really isn't a big deal, though. It's unlikely Spectrum will support more than one compositor anyway, because we'll need to customise it to do things like Qubes-style window borders that are coloured based on security domain. And, even then, if we're using a wlroots-based compositor, it's probably only wlroots that needs patching, so in that case any other wlroots-based compositor would probably work. Speaking of compositors...
Wayfire -------
If you know what Wayfire is, you're probably surprised to see it as an item in a Spectrum status update it. If you don't, Wayfire is a Wayland compositor notable for having a bunch of over-the-top Compiz-style graphical effects, like wobbly windows and the titular fire. I recommend checking out the demo videos on https://wayfire.org/ if you haven't seen them -- it's quite something.
But I bring this up not because I think support for wobbly windows is imperative to Spectrum's chances of success, but because fundamentally Wayfire is just an extremely modular Wayland compositor. Virtually everything in Wayfire is implemented as a plugin. Switching between windows is a plugin, screen zoom is a plugin, and so on.
This is really cool because in Spectrum we'll want to have, for example, coloured window decorations like in Qubes. With any other compositor, we'd have to hack that into the compositor internals somehow. With Wayfire, it can just be a plugin.
Wayfire is also a pleasantly simple but featureful windowing experience. You can drag windows around, put two side by side by dragging them to screen edges, have multiple workspaces, etc. I think it will be straightforward enough to not be a problem for people coming to Spectrum regardless of their computing background, and powerful enough to not get in the way of Serious Computer Business. And anything missing could of course be implemented as a plugin. ;)
So, I've been doing some work to package Wayfire in Nixpkgs. This is not all that easy, because Wayfire seems to assume that plugins will be installed into Wayfire's prefix. This isn't really possible with Nix unless you compile all the plugins along with Wayfire, so I'm working some patches for Wayfire to look up plugins in a search path specified as an environment variable, which on the Nix side we can then wrap in the idiomatic wayfireWithPackages style. My initial impressions of the Wayfire codebase are that it is relatively clean, and straightforward enough to understand. The core compositor is about 13000 SLoC, which is pleasantly small.
That, unfortunately, is it for this week. I didn't get as much done as I'd hoped, but I did at least have loads of good thoughts about things to do later in Spectrum's development, that aren't quite concrete enough to put into words yet.