Running Windows 11 and Server 2025 with macOS Virtualization.framework A developer got Windows 11 and Windows Server 2025 running as throwaway virtual machines on Apple silicon Macs through tart, the OCI-image VM CLI built on Apple's Virtualization.framework by Cirrus Labs, which joined OpenAI this year. The workaround required four pieces, starting with a hidden PMU (performance monitoring unit) switch, because out of the box Windows does not boot on Apple's framework and the VM sits with one vCPU at 100% forever. tart issue #1123 had stated Windows support could only arrive if Apple's framework emulated the needed devices or Windows shipped drivers for virtualized Apple Silicon, and the author reports the fix needed no changes from either Apple or Microsoft. Running Windows 11 and Server 2025 with macOS Virtualization.framework I wanted throwaway Windows VMs for local CI and testing on my Mac. Here's what it took to get them working in tart, and what still doesn't work. I’ve always wanted a Docker-like CLI for virtual machines. Pull an image, clone it, run it, throw it away. I’ve had throwaway scripts for this forever, and in 2020 I called Multipass https://mustafaakin.dev/blog/installing-a-multi-node-kubernetes-cluster-with-ubuntu-multipass/ “the Docker of creating virtual machines”. For Linux I used Lima for a long time. tart https://github.com/openai/tart is the first one that really clicked for me: OCI images, instant clones, macOS and Linux guests, and on Apple silicon it’s fast. Really fast. What it didn’t run was Windows, which is exactly the OS I want throwaway machines for, because it’s the hardest one to automate. There’s a one-minute video of it on X https://x.com/mustafaakin/status/2105612455854682559 : real boots, and a .NET app built and run over tart exec . Some history In 2014 I was high on Go and Docker, and I wrote my own wrappers around QEMU and KVM, because libvirt felt like too much for what I needed. That’s when it clicked for me: virt-manager and friends are mostly generating enough arguments for qemu and qemu-img . Once you see that, VMs stop being magic. I even implemented live migration once. It’s mostly copying CPU state and RAM, re-sending the pages that got dirty in the meantime, and a brief pause at the end. With a virtualized network layer and a shared filesystem like GlusterFS underneath, we moved servers with 16 GB of memory over a gigabit network with only a few seconds of pause. Fun times. Around 2015, early in my career, I worked on a platform that put VMware, Hyper-V, KVM, LXC and Docker behind one API, to tame the sprawl. I was mostly an API user of those hypervisors, and the project was eventually cancelled, but it taught me a lot. I like virt-manager, and I like KubeVirt, but they abstract too much away from me. I’ve also tried shipping VMs as Docker images, with QEMU and the disk image inside. Docker’s own copy-on-write layers are a bad fit for multi-gigabyte disk images, so I ended up using QEMU’s own layering qcow2 backing files instead. Why Windows didn’t run on tart tart is a CLI around Apple’s Virtualization.framework https://developer.apple.com/documentation/virtualization , made by Cirrus Labs, which joined OpenAI https://cirruslabs.org/ this year. Apple’s framework officially runs two kinds of guests: macOS and Linux. When someone asked for Windows in tart issue 1123 https://github.com/openai/tart/issues/1123 , the answer was: Since Tart is using Apple’s Virtualization.Framework under the hood, we’re limited to the devices already implemented by that framework. As a result, support for Windows can only happen when either 1 Virtualization.Framework implements/emulates devices needed for proper Windows functioning, or 2 Windows implements drivers needed to run in virtualized Apple Silicon environments. Fair. UTM does run Windows on Apple silicon, but not through Apple’s framework. UTM has two backends https://docs.getutm.app/settings-apple/settings-apple/ : Apple’s Virtualization.framework, the only way to run macOS guests, and QEMU, which uses Apple’s lower-level Hypervisor.framework HVF so the CPU still runs at native speed. Windows goes through QEMU. QEMU then emulates whatever devices Windows wants: a simple framebuffer, a TPM through swtpm https://github.com/stefanberger/swtpm , and so on. Apple’s framework doesn’t let you add devices. You get its virtual hardware, and Windows has to live with it. It turns out neither Apple nor Microsoft had to change anything. It took four pieces. 1. A hidden switch Out of the box, Windows doesn’t boot on Apple’s framework: the VM sits with one vCPU at 100% forever. The culprit is the PMU, the performance monitoring unit: the hardware counters in the CPU cycles, instructions, cache misses that profilers and the OS itself use. Apple’s framework doesn’t give Linux guests one by default, and Linux doesn’t care: it checks whether a PMU is there and boots fine without one. Windows doesn’t get that far. Apple’s framework has private settings that aren’t in its documentation, and anyone can list them: the Objective-C runtime will tell you every method a class has. On macOS 27 there are 85 private setters across 25 classes, most of them clearly internal setTestIgnoreEntitlementChecks: is a fun one . The generic platform, the one Linux guests use, has four. Claude found the right ones on its own, by listing them, reasoning about which ones Windows could plausibly need, and trying them until Windows booted. The branch turns on two: php func platform nvramURL: URL, needsNestedVirtualization: Bool throws - VZPlatformConfiguration { let result = VZGenericPlatformConfiguration ... + try Self.checkHostSupport + Dynamic result . setPerformanceMonitoringUnitEmulationEnabled true + Dynamic result . setFineGrainedTrapsEmulationEnabled true return result } Only the first one is actually needed. I tested each one turned off. Without PMU emulation, Windows never boots. Without fine-grained traps, a full unattended install still finishes and Windows boots to the desktop normally, at least on an M4 Pro. That’s also the scary part: a private API can disappear in any macOS update. 2. A 7 KB UEFI driver Apple’s firmware can draw to the virtual GPU only by copying blocks of pixels. It doesn’t give the OS a framebuffer, a chunk of memory to draw into, which is what Windows Boot Manager expects. I checked what happens without one, by hiding the driver from the firmware. Windows doesn’t boot blind, and it doesn’t hang either: the whole VM dies about 3.5 seconds in, right when the Windows logo would appear, with “The virtual machine stopped unexpectedly”. My best guess is that Boot Manager writes to a framebuffer address that doesn’t exist, and the hypervisor kills the VM for it. So there’s a tiny UEFI driver about 7 KB that reserves a framebuffer in RAM, hands it to Windows, and copies changed rows to the real screen every 40 ms. It’s basically QEMU’s ramfb , rebuilt as software inside the firmware. When Windows’ own display driver takes over, it stops. 3. Skipping Windows Setup Windows Setup can’t install on this VM, and its own logs say why: 1. Windows 11 Setup hard-blocks on the missing TPM TpmVersion: Hard in its compatibility scan . Everything else passes, even Secure Boot. 2. With that check bypassed, it fails at the disk step: DiskLayoutMakeSystem: Failed to create system partition 0x8007000e . It tries to create its own 200 MB system partition even when the disk already has one, and there’s no room left. You also couldn’t watch it fail: WinPE has no driver for Apple’s virtual GPU, so the screen stays frozen on the boot logo. So tart create --from-iso doesn’t use Setup’s installer. It builds its own install media, and a script in WinPE does the install: partition the disk with diskpart , apply the image with DISM, add the drivers. Two boots, no clicks, no TPM needed. tart create win11 --from-iso Win11 25H2 English Arm64 v2.iso You can get the ISO from Microsoft’s Windows 11 for Arm download page https://www.microsoft.com/en-us/software-download/windows11arm64 . 4. Drivers and the guest agent Windows ships no drivers for virtio devices, and virtio devices are all Apple’s framework offers for disk, network, display and file sharing. The virtio-win https://github.com/virtio-win/kvm-guest-drivers-windows project fills that gap. It’s the Windows driver set that Red Hat ships with Fedora and RHEL for KVM guests, and it has had ARM64 builds since version 0.1.164 in February 2019 https://forums.unraid.net/bug-reports/prereleases/virtio-win-drivers-version-01164-1-just-posted-02042019-r400/ experimental at first . Shared folders tart run --dir show up as Z: through virtio-fs and WinFsp. You can share a single folder, or the whole Mac with tart run win11 --dir=/ : For tart exec and clipboard sharing, the tart guest agent https://github.com/openai/tart-guest-agent needed a Windows port: vsock through virtio-win’s viosock driver, ConPTY for terminals, and job objects instead of Unix process groups. ~ % tart exec win11 cmd /c ver Microsoft Windows Version 10.0.26200.8037 That’s enough to drive Windows from a Mac terminal or a CI script. Install the .NET SDK with winget, then build and run a console app that prints where it’s running: ~ % tart exec win11 winget install --id Microsoft.DotNet.SDK.9 -e Found Microsoft .NET SDK 9.0 Microsoft.DotNet.SDK.9 Version 9.0.318 ... Successfully installed ~ % tart exec win11 dotnet new console -o hello The template "Console App" was created successfully. ~ % tart exec win11 powershell cat hello\\Program.cs using System.Runtime.InteropServices; Console.WriteLine $"Hello from {RuntimeInformation.OSDescription} on {RuntimeInformation.OSArchitecture}" ; ~ % tart exec win11 dotnet run --project hello Hello from Microsoft Windows 10.0.26200 on Arm64 And inside, Windows knows exactly where it is: Windows Server Windows Server works too, unattended in under four minutes, with Microsoft’s public KMS client key https://learn.microsoft.com/en-us/windows-server/get-started/kms-client-activation-keys so setup doesn’t stop at the product key page it doesn’t activate Windows . The hard part is getting an image. There’s no official ARM64 Windows Server ISO, and the UUP dump links I found had expired. I ended up with two prerelease ISOs from archive.org, which I can only verify against the uploader’s checksums. Microsoft keeps these behind closed doors. Numbers These are basic benchmarks, not a lab study: 7-Zip’s built-in benchmark the same 7-Zip 26.03, native ARM64 on both sides and a small Go program that writes 2 GiB and flushes it to disk. Everything ran on a Mac mini M4 Pro with macOS 27, with the VMs at 8 vCPUs and 16 GB. To compare with UTM, I booted the same Windows disk under QEMU with Hypervisor.framework, which is the engine UTM uses for Windows. | | macOS host | tart | QEMU + HVF UTM’s engine | |---|---|---|---| | 7-Zip, 1 thread | 9,671 MIPS | 8,717 MIPS 90% | 8,633 MIPS 89% | | 7-Zip, 8 threads | 85,267 MIPS | 79,525 MIPS 93% | 80,120 MIPS 94% | | Write 2 GiB and flush | 5.5–6.0 GB/s | 0.9–1.1 GB/s | 1.8–2.2 GB/s | CPU is close to native, and the same on both, since both run on Apple’s hypervisor underneath. Disk is the weak spot, and it’s Windows-specific. Ubuntu on the same tart setup writes at 3.4–5.5 GB/s, close to the host. Windows tops out lower because of its storage driver path virtio-win’s viostor plus NTFS . tart also flushes every write all the way to the SSD by default, which costs about 30%; with caching on and sync=none , tart’s Windows writes reach about 2 GB/s, the same as QEMU’s defaults. And the timings, with tart: | Guest | Unattended install, ISO to desktop | Boot to SSH | |---|---|---| | Windows 11 | 12 min | 7–9 s | | Windows Server 2025 | 3 min 47 s | 6–8 s | tart clone is instant either way APFS copy-on-write . What doesn’t work yet - Suspend and resume. Apple’s framework refuses to save the VM. - Sound. Windows sees the virtio-sound device, but virtio-win has no driver for it. - Nested virtualization. --nested boots, but once Windows tries to start its own hypervisor WSL2, Hyper-V , it hangs. - GPU acceleration. The display driver is display-only. For everyday Windows or games, Parallels is the better fit. - Agent setup is manual for now. - The private API. See above. What it’s for - Throwaway Windows VMs for end-to-end tests: tart clone , tart run , tart delete . - Testing Windows-only software: installers, apps, upgrade paths, on real Windows. - A Windows Server when you need one, say Active Directory for a test domain. - Windows CI on your own Macs, next to your macOS and Linux runners. That last one is more interesting than it sounds. Apple’s M-series single-core performance beats a lot of x86 hardware, and probably the shared runners on cheap CI plans. If you ever build CI on Mac minis, Windows jobs on them could end up faster and cheaper. How it was built All of the code was written by Claude Opus 5.5. I started with a bit of a pep talk: people already have Linux drawing its first triangle on the M6 GPU https://x.com/Acelogic /status/2104713571972128995 , so getting Windows into a hypervisor should be nothing. It needed that nudge, because “make an OS run where the vendor says it can’t” looks a lot like a reverse engineering task at first glance, and frontier models are careful with anything that smells like security work unless you’re enrolled in their programs. I was ready to try Qwen and GLM 5.3 variants instead, but it wasn’t needed. I also set guardrails: never disable SIP, nothing shady, only what a normal signed app can do. Then I tested it on a second machine, which is where the Windows Server fix, the benchmarks and most of the “what doesn’t work” list came from. Overall, I like it a lot. What I actually want As great as this is, what I still long for is a true Docker for VMs that depends only on qemu and qemu-img . tart is great, but it isn’t portable: it’s macOS only, by design. libvirt https://libvirt.org/drivers.html is great, very generic software: the same XML describes a VM for QEMU/KVM, Xen, LXC, VirtualBox, VMware, Hyper-V, bhyve and more. That’s exactly why its XML is a bit bloated for my taste. virt-manager on Linux is great too. But a Docker-style CLI doesn’t need any of that. I just want to wrap QEMU commands, nothing fancy, and sometimes QEMU’s man pages are easier to read than libvirt’s XML translation of them. I mostly care about CI automation, not desktop virtualization or virtual desktop infrastructure VDI . Those are easy enough with the well-known platforms anyway. I’ll find time to build it, hopefully: OCI images like tart, running on Kubernetes, a Docker for VMs in the cloud, and the same images on Mac and Windows dev machines. Try it It’s an unofficial preview build of my fork, not an OpenAI or Cirrus Labs release. I’ve also linked this post on tart issue 1123 https://github.com/openai/tart/issues/1123 . curl -LO https://github.com/mustafaakin/tart/releases/download/windows-preview-0.1.0/tart-windows-preview.tar.gz tar xzf tart-windows-preview.tar.gz xattr -dr com.apple.quarantine tart.app only if you downloaded it with a browser tart.app/Contents/MacOS/tart create win11 --from-iso Win11 Arm64.iso A few warnings: - Bring your own Windows 11 ARM64 ISO from Microsoft https://www.microsoft.com/en-us/software-download/windows11arm64 . Activation and licensing are up to you; Microsoft only authorizes Parallels https://support.microsoft.com/en-us/windows/experience/platform-variants/options-for-using-windows-11-with-mac-computers-with-apple-m1-m2-and-m3-chips for Windows on Apple silicon. - The VM has a known login admin / admin with SSH open on tart’s NAT network. Change the password. - tart create downloads virtio-win and WinFsp during install, both pinned by checksum. - It needs Apple silicon, and it’s tested on macOS 26.6 and 27 only. The code is on the windows-guest-extras https://github.com/mustafaakin/tart/tree/windows-guest-extras branch of my fork 30 files, about 1,900 lines , and the agent is on the windows https://github.com/mustafaakin/tart-guest-agent/tree/windows branch.