macOS on Apple Silicon KVM
An experimental, working macOS ARM64 virtual machine for Apple Silicon Macs
running Asahi Linux. The guest runs with KVM acceleration in QEMU's vmapple
machine and displays through Reims
and Vulkan.
This is research code, not a polished virtual-machine product. It patches the
Asahi kernel, QEMU, and Reims to bridge assumptions that normally only hold
when vmapple runs under Apple's Hypervisor.framework.
What works
The known-good configuration boots macOS Ventura 13.6 (22G120) to the normal graphical Setup Assistant on an M2 Pro host running Fedora Asahi Remix:
- KVM acceleration with eight active guest CPUs
- normal
launchd,WindowServer, andloginwindowuserspace AppleParavirtGPUandAppleParavirtDisplay- a live 1920x1080 Reims/Vulkan window
- persistent serial and QMP logs
- user-mode networking with optional SSH forwarding on
localhost:2222
Rendering was verified with Mesa llvmpipe because the experimental host kernel used for the successful run did not include the Asahi DRM driver. The complete investigation, including failed approaches and checksums, is in JOURNAL.md.
Why patches are needed
| Layer | Problem | What this repository changes |
|---|---|---|
| Linux KVM | Apple's pointer-authentication VM key, APCTL, and KERNKEY state is not part of the normal ARM KVM context | Saves/restores the Apple registers and exposes them through KVM's one-register API |
QEMU vmapple | The machine was built around TCG/HVF assumptions | Enables KVM, wires the GIC/PMU timers, forwards Apple's private PAuth HVC service to QEMU, implements that service, and pins PSCI to 1.1 for Ventura |
| XNU handoff | KVM cannot emulate one pre-indexed GIC MMIO store because the stage-2 abort lacks a valid instruction syndrome | The launcher pauses at handoff and uses GDB to rewrite that exact instruction sequence in guest RAM; the guest disk is not modified |
| Reims | Linux guest-memory mapping and llvmpipe capability reporting differed from the macOS host path | Adds direct mappings for contiguous QEMU RAM and avoids the native-FP16 shader path on CPU Vulkan devices |
The relevant files are:
patches/linux-6.19-vmapple-pac-vmkey.patchpatches/reims-qemu-linux-arm64.patchpatches/reims-rust-linux-arm64.patchscripts/inject-xnu-kvm.gdb
patches/vmapple-usb-chardev.patch and
the USB/IP scripts belong to the separate Linux restore experiment. They are
not needed when starting with a VM provisioned on macOS.
Requirements
- an Apple Silicon Mac running Asahi Linux with
/dev/kvmavailable - a matching Fedora/Asahi 16 KiB kernel source tree
- the kernel patch in this repository, built and booted as a separate kernel
- GDB, Git, a C toolchain, Cargo, Ninja, GTK 3 development files, and Vulkan development files
- temporary access to macOS for Apple firmware and VM provisioning
- roughly 20 GiB for an Apple restore image, 64 GiB apparent space for the sparse guest disk, and several GiB for builds
The proven host was Fedora 42 on an M2 Pro with kernel
6.19.14-vmapple2. Other SoCs, distributions, kernels, and macOS releases are
interesting experiments, not verified configurations.
1. Obtain AVPBooter from macOS
AVPBooter.vmapple2.bin is supplied by macOS as part of
Virtualization.framework. On a Mac, copy it out with:
cp /System/Library/Frameworks/Virtualization.framework/Resources/AVPBooter.vmapple2.bin .
shasum -a 256 AVPBooter.vmapple2.binMove it to the Asahi host and keep it under the ignored artifacts/ directory:
mkdir -p artifacts/firmware
mv /path/to/AVPBooter.vmapple2.bin artifacts/firmware/The successful run used mBoot-18000.121.3 (304,352 bytes, SHA-256
513ca3fbb2cd5accb0a6da96a5e476d593ebae403d7edb33aebca88f505dac61).
Do not publish this file: it is Apple-provided firmware and is intentionally
excluded by .gitignore.
2. Provision the guest on macOS
Install macosvm, clone this repository on the macOS machine, and supply a legitimately obtained UniversalMac restore IPSW:
brew install macosvm
IPSW=/path/to/UniversalMac_13.6_22G120_Restore.ipsw \
scripts/provision-on-macos.shThe script creates this private bundle:
artifacts/guest/
├── aux.img
├── aux.img.trimmed
├── disk.img
└── vm.jsonCopy the bundle to the same location on the Asahi host. Preserve the sparse
disk while copying; for example, use rsync --sparse. vm.json contains the
VM's machine identity, and the images contain an installed copy of macOS, so
none of these files should be committed or shared.
The known Ventura IPSW is
UniversalMac_13.6_22G120_Restore.ipsw, SHA-1
a1675f2c8412122a5e796981571b0269a966708e. Apple firmware and restore-version
compatibility can change; start with the verified versions before trying a
newer combination.
3. Build and boot the patched Asahi kernel
Apply the kernel patch after preparing the matching Fedora Asahi
6.19.14-400.asahi.fc42 source tree:
patch -d /path/to/linux-tree -p1 \
< patches/linux-6.19-vmapple-pac-vmkey.patchUse the installed 16 KiB kernel configuration, build Image, modules,
vmlinuz.efi, and dtbs, then install the result alongside the stock kernel
with a distinct LOCALVERSION such as -vmapple2. Keep the stock kernel as
the default and select the experiment for one boot first.
The exact Fedora source-package preparation, build, installation commands,
checksums, and the one failed /boot attempt are recorded under
“Custom Asahi KVM VM-key kernel built and installed” and “Custom Asahi KVM
Apple PAuth-context kernel vmapple2” in JOURNAL.md. This patch is
tied to that kernel revision; do not apply it blindly to another release.
After booting the patched kernel:
uname -r
test -r /dev/kvm && test -w /dev/kvm4. Build the patched Reims/QEMU
Clone the pinned Reims revision next to this repository and initialize its QEMU submodule:
git clone https://github.com/steelbrain-bot/reims-vgpu.git ../reims-vgpu
git -C ../reims-vgpu checkout 2844274c34baa1043d37995f5b1a9f1d265eae03
git -C ../reims-vgpu submodule update --init vendor/qemu
git -C ../reims-vgpu/vendor/qemu rev-parse HEAD
# expected: e17ddb98f71df5697daf2f830587f672a8f4f5a7
CONFIRM=1 scripts/build-gui-qemu.shThe build script verifies both revisions, copies the source under ignored
build/, applies the QEMU and Reims patches, and produces:
build/reims-linux-product/vendor/qemu/build/qemu-system-aarch64Verify the complete host side:
scripts/check-host.sh5. Launch macOS
With the firmware and guest bundle in place:
AVPBOOTER="$PWD/artifacts/firmware/AVPBooter.vmapple2.bin" \
GUEST_DIR="$PWD/artifacts/guest" \
scripts/launch-gui-kvm.shQEMU starts paused. The wrapper injects verbose boot arguments, applies the
verified XNU GIC instruction correction, detaches GDB, and leaves QEMU in the
foreground. Press Ctrl-C to stop it cleanly. Serial and QMP logs are written
under ignored logs/.
Useful overrides:
CPUS=4 RAM=8G ... # guest resources
SSH_PORT=2223 ... # host-side SSH forwarding
CONSOLE=gtk ... # also show QEMU's fallback GTK console
CONSOLE=none ... # suppress every fallback console
XNU_BOOT_ARGS='-v serial=11 debug=0x14c' ...The normal display path is the native Reims window, so the default QEMU display
is none. scripts/launch-kvm.sh is the lower-level launcher when the GDB
handoff wrapper is not wanted.
Linux restore experiment
The repository also contains an unfinished attempt to provision directly from
Asahi Linux. scripts/launch-dfu.sh exposes AVPBooter's virtual DFU device,
scripts/vmapple-usbip.py bridges it to Linux vhci-hcd, and
scripts/probe-vmapple-usb.py exercises the transport. The work reached real
DFU transfers but did not produce the known-good guest used above. See the
journal before continuing that path.
Project boundaries
- Never commit firmware, IPSWs, restore images, VM disks, VM identities, or logs. The repository ignore rules cover the expected locations and formats.
- This project does not redistribute macOS or bypass Apple's restore signing.
- Kernel and hypervisor experiments can crash or reboot the host. Keep a stock kernel boot entry and backups of anything important.
- There is no support promise. Reproduction reports with exact host, kernel, QEMU, firmware, and guest versions are welcome.