Repository navigation
Run VM guests on macOS with Hypervisor.framework - #131
Merged
Merged
Conversation
On an Apple Silicon Mac with QEMU installed (brew install qemu), VM instances now run QEMU on the Mac with -accel hvf instead of emulated inside the Docker VM, which has no nested virtualization. The VM container stays and keeps the instance's address, passt, security groups, published ports, metadata route, disks and console log. In host mode its entrypoint prepares the disks and seed, starts passt and serves the disks over NBD (qemu-storage-daemon) on Unix sockets. A host runner (homecloud vm-host, a detached process per guest) starts QEMU and relays its network card and disks into the container through docker exec streams, copies the serial console into the container log, and ties QEMU's lifetime to the container's. The serial console, guest agent and QMP sockets are in the guest's run directory, where the terminal, run-command, metrics and power controls connect. The backend is chosen automatically (instances report virtualization hvf), with serve --vm-accel / vm_accel / HC_VM_ACCEL to force hvf, container, kvm or tcg, and falls back to the container when QEMU, its firmware or Hypervisor.framework is unavailable. The firmware is QEMU's edk2 build: Debian's AAVMF hangs under hvf. Also stop unit tests from pinning hostArch for later live tests.
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 32 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
- Refuse a run directory (or its parent) that is not a 0700 directory of this user, so a directory planted in a shared temp dir cannot feed the runner a command line; avoid data directories with a comma. - Only kill a stale QEMU whose command line names this run directory (pid reuse could hit another guest's QEMU), and kill it on terminate before removing the run directory instead of orphaning it. - Kill QEMU only when Docker says the container stopped or is gone, not on a failed Docker API call. - Start a runner only for the instance's current container in hvf mode. - Bound the serial console log on the host. - Reject hvf launches up front where hvf cannot work (e.g. Linux).
Deploying homecloud with
|
| Latest commit: |
7940f8e
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://d11ac770.homecloud.pages.dev |
| Branch Preview URL: | https://vm-macos-hvf.homecloud.pages.dev |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
VM instances on macOS used to run emulated (TCG). Docker Desktop and OrbStack run containers in a Linux VM that has no nested virtualization. I checked OrbStack 2.2.4 on an M5 Pro with macOS 27: containers get no
/dev/kvm, and the kernel logskvm: HYP mode not available. So passing the device through doesn't work here.On an Apple Silicon Mac with QEMU installed (
brew install qemu), guests now run on the Mac itself with-accel hvf -cpu host. Instances reportvirtualization: "hvf". Part of #3.Design
HC_VM_HOST=1,hc-vm-runprepares disks and seed as before and starts passt. It then serves the root qcow2 overlay, the extra volumes, the seed and the UEFI variable store as NBD exports ofqemu-storage-daemonon a Unix socket, and waits.homecloud vm-host DIR, hidden command): a detached process per guest that holds a lock on the guest's run directory (mode 0700).-netdev stream) and NBD disks into the container. Each connection goes throughdocker exec socat - UNIX-CONNECT:....host.docker.internal.GetConsoleOutputand boot detection are unchanged.homecloud.vm-host=1container that has none. Because the runner is its own process, guests survive a server restart. Run-command, guest metrics, the serial terminal and the ACPI power button connect directly to QEMU's sockets in the run directory.serve --vm-accel auto|hvf|container|kvm|tcg(saved asvm_accel) orHC_VM_ACCELforces a backend. If passt cannot start for a guest on the host, the guest moves into the container, emulated.edk2-aarch64-code.fd. Debian's AAVMF 2025.02, which the container uses, hangs before its boot manager under hvf. I reproduced this standalone, without NBD./dev/kvmorHC_VM_ACCELbehaviour changes, and the runner image Dockerfile is the same (qemu-storage-daemonwas already inqemu-utils).hostArchfor the whole test binary. On a Mac that made later live VM tests download and boot the amd64 image.Measured on an M5 Pro, OrbStack, Ubuntu 24.04 VM AMI
running(cloud-init done)run-instancestorunning, image cachedTestVMInstanceLifecycle(image cached, after the first runner build)Verified on this Mac
HC_TEST_VM=1and OrbStack, allVMtests pass:TestVMInstanceLifecycleandTestVMDisksImagesAndBackup. They cover:go test ./internal/svc/ec2 ./cmdpasses.go test ./...,go vet ./..., andGOOS=linux/GOOS=windows go build ./...also pass.homecloud serveplus the CLI and AWS CLI:run-instancesgavevirtualization: hvfandvm_network: passt.uname -mreported aarch64, the guest had its private IP, and IMDS answered.homecloud ec2 execandec2 logsworked.Not verified
docker execis used, but I didn't test it.