Four things actually determine VM performance
"Which hypervisor is fastest" is the wrong question — nearly every serious hypervisor on a given CPU architecture converges on similar numbers, because they're all constrained by the same four things: how expensive it is to trap from guest to host on the CPU, how much overhead the memory translation path adds, how interrupts get delivered into the guest, and whether I/O devices are emulated, paravirtualized, or handed to the guest directly. ARM and x86 answer these differently at the architecture level, and that's what actually explains why VM performance differs between platforms — not brand, not marketing.
CPU: a dedicated exception level, not a shared privilege ring
Every trap from guest to hypervisor and back costs cycles: saving and restoring state, flushing pipelines, switching contexts. How expensive that is depends on the CPU architecture. ARM's Virtualization Extensions add a dedicated hardware exception level for this, EL2, with its own register file, its own MMU context, and its own exception vectors — architecturally separate from EL1 and EL0, where the guest OS and its user processes run. x86's VMX, by contrast, has historically required the hypervisor and the host OS kernel to share the same privilege ring, which is a fundamentally more entangled arrangement. That architectural separation is why ARM research from Columbia University characterizing ARM virtualization performance treats EL2 as a first-class design advantage rather than a compatibility layer bolted onto an existing privilege model.
ARMv8.1 added a further refinement, Virtualization Host Extensions (VHE), which lets a Type-2 hypervisor's host kernel run directly at EL2 instead of trampolining through it. That eliminates a full EL1↔EL2 transition on every host system call while a VM is running — small per-call, but it adds up on workloads with a high guest-to-host syscall rate, like network-heavy I/O.
Memory: two-stage translation, and why it doesn't cost what it sounds like it should
A VM's guest OS manages its own page tables like any OS does, translating guest virtual addresses to what it believes are physical addresses. But the hypervisor still needs to control what real memory the VM can actually touch, so ARM (like x86) adds a second translation stage: Stage-1 translates guest-virtual to intermediate-physical, and Stage-2, controlled entirely by the hypervisor, translates that intermediate address to the real physical address. Two lookups per memory access sounds like it should double memory latency. In practice it doesn't, for the same reason single-stage translation doesn't cost a full page-table walk on every access: modern implementations cache the combined guest-virtual-to-physical translation in the TLB, so the two-stage walk only happens on a genuine TLB miss, not on every access.
Interrupts: the one place ARM has a real, architectural edge over x86
This is the part that doesn't get talked about enough, and it's a genuine, measurable difference rather than a marketing point. When a virtual device or another virtual CPU needs to signal an interrupt, the guest has to acknowledge and eventually clear it — on x86, that acknowledgment (EOI) has historically had to trap to the hypervisor and be emulated in software, for every single virtual interrupt, including inter-processor interrupts between virtual CPUs. ARM's Virtual Generic Interrupt Controller (vGIC) does this in hardware instead: the guest OS can acknowledge and clear virtual interrupts directly, without trapping to the hypervisor at all. The KVM/ARM paper from Columbia's research group that introduced this design is explicit that avoiding a hypervisor trap on every interrupt is a structural advantage ARM has over x86's software-emulated EOI path — not a tuning difference, an architectural one. It isn't free of overhead entirely — vGIC state lives at EL2, so there's still some cost to reading and writing that control-register state on each VM transition — but it's a different order of magnitude from trapping on every interrupt.
I/O: paravirtualization vs. hardware passthrough, plainly defined
This is the tradeoff most people actually mean when they ask about virtualization performance, and it's worth defining precisely rather than treating as a vague spectrum:
- Full emulation — the hypervisor pretends to be a specific real piece of hardware (an old Intel NIC, a specific disk controller) in software. The guest's unmodified driver talks to it exactly like real hardware, but every register access can trap to the hypervisor. Simple and maximally compatible; slow.
- Paravirtualization (virtio) — the guest runs a driver that knows it's virtualized, and talks to the hypervisor through an efficient, purpose-built ring-buffer protocol instead of imitating real hardware register-by-register. Virtio is the de facto standard for this. It requires guest cooperation (a virtio-aware driver), but gets close to native throughput while still letting the hypervisor share, meter, and multiplex the underlying device across multiple VMs.
- Hardware passthrough (SR-IOV / VFIO) — the hypervisor hands a VM direct, largely unmediated access to a physical device, or to a hardware-virtualized slice of one via SR-IOV. This gets closest to bare-metal performance, in the low single-digit microseconds of added latency in benchmarked NIC passthrough setups, because the hypervisor mostly gets out of the way. The cost is exclusivity: a passed-through device typically can't be shared or migrated the way a paravirtualized one can, and it usually requires an IOMMU (ARM's SMMU) to isolate what the guest can DMA into safely.
| Overhead source | Naive approach | ARM's hardware-assisted approach |
|---|---|---|
| CPU traps | Hypervisor shares a privilege level with the host OS | Dedicated EL2 exception level, with VHE letting the host kernel run there directly |
| Memory | Every access re-walks a two-stage page table | Combined translation is TLB-cached; the two-stage walk only happens on a miss |
| Interrupts | Every ACK/EOI traps to the hypervisor for emulation | vGIC lets the guest ACK/EOI in hardware, no trap required |
| I/O | Full device emulation, trapping on every register access | virtio (paravirtualized) for shared/flexible devices, SR-IOV passthrough for exclusive near-native access |
How this shows up on Apple Silicon specifically
Apple built virtualization into macOS as a first-class part of the Apple Silicon transition rather than retrofitting it, and it rides on exactly the ARM mechanisms above. The Hypervisor framework gives low-level access to the CPU's Virtualization Extensions — EL2, Stage-2 translation, EL1/EL0 instruction and register trapping — and Apple's own approach diverges deliberately from how virtualization worked on Intel Macs, precisely because the hardware underneath it is different. Virtualization.framework, the higher-level API Velo Workspaces builds on, sits on top of that. (Apple added support for exposing EL2 itself inside a guest in macOS 15 — nested virtualization, letting a VM run its own hypervisor — which is a distinct, newer capability from the base EL2 virtualization every Apple Silicon Mac has always used to run VMs at all.)
The I/O side is where the passthrough-vs-paravirtualization tradeoff gets concrete and, honestly, a little disappointing if you were hoping for GPU passthrough: Apple's Virtualization.framework gives a Linux guest virtio-gpu, a paravirtualized 2D framebuffer, with no path to the host's actual GPU — confirmed directly by Apple's own container team in public discussion. That's a deliberate choice, not a missing feature Apple forgot: unlike a NIC or a disk, there's no SR-IOV-equivalent standard for slicing up a GPU this way on this platform yet, so the options are full paravirtualization (slow, 2D-only) or nothing. It's exactly why AI Bridge takes a different path entirely — instead of trying to get compute into the guest over an I/O boundary that doesn't support it, the model server stays on the host, on the real GPU, and the guest reaches it over vsock, itself a virtio device (VZVirtioSocketDeviceConfiguration) — the same paravirtualization pattern as virtio-net or virtio-blk, just carrying a model API instead of a filesystem or a network stack. See the full architecture and what it actually costs, benchmarked rather than asserted, and how the GPU story compares to other VM apps on the same hardware.
The cloud reached the same conclusion from a different direction
This isn't an Apple-specific story. AWS's Nitro system and Google's Titanium offload exactly the categories of overhead described above — network and storage I/O especially — onto dedicated hardware next to the CPU, so guest instances see close to bare-metal performance without the hypervisor mediating every packet or disk write in software. AWS Graviton's newer generations also added ARMv8.3+ nested-virtualization support, the same underlying capability Apple added to Virtualization.framework in macOS 15. Different companies, different silicon, converging on the same answer: push I/O virtualization overhead into hardware, and use ARM's EL2/vGIC-class primitives for everything else, rather than trying to out-engineer trap-and-emulate in software.
Why this explains our own benchmark numbers
This is the mechanism behind results we've published elsewhere on this blog rather than just asserted. At single-request scale, an MLX inference benchmark through a VM on Apple Silicon came out statistically indistinguishable from running on the host directly — inside normal run-to-run noise. Under concurrent load, the gap was a real but small single-digit percentage. Given everything above, that's exactly what you'd expect: CPU traps are cheap (dedicated EL2, not a shared privilege ring), interrupt delivery doesn't need to trap to the hypervisor at all (vGIC), memory translation overhead is TLB-amortized, and the one I/O path that matters here — AI Bridge's vsock channel — is a lightweight paravirtualized ring buffer, not a heavyweight emulated device or a full virtualized network stack processing TCP/IP.
Related reading: the architecture behind AI Bridge, the full inference benchmark, and what VM isolation costs compared across two different inference engines. Or download Velo Workspaces and try it yourself.