Cloud Computing 16 min read

How to Virtualize macOS on Apple M1 with KVM/QEMU: A Step‑by‑Step Guide

This article details the exploration and implementation of macOS virtualization on Apple’s ARM‑based M1 Mac mini, covering the use of AsahiLinux, QEMU, KVM, device modeling, memory layout, boot process, and future optimization plans for a functional cloud‑native macOS environment.

ByteDance SYS Tech
ByteDance SYS Tech
ByteDance SYS Tech
How to Virtualize macOS on Apple M1 with KVM/QEMU: A Step‑by‑Step Guide

Background

Typical cloud platforms provide Windows and Linux virtual machines for users to deploy services. Virtualizing macOS on Apple’s ARM‑based M1 Mac mini would greatly benefit developers who need a macOS environment for testing, iOS builds, or office use.

The community already has mature solutions for Intel‑x86 Mac mini virtualization. After Apple introduced the ARM64 M1 chip in 2020, the ecosystem began shifting to ARM, and research on ARM64 macOS virtualization is still early. ByteDance STE and App Infra teams conducted in‑depth studies and share their findings here.

Solution Overview

What is Mac mini virtualization

Mac mini virtualization creates multiple isolated macOS instances on a single physical Mac mini, making each user feel they have exclusive access to a real machine.

The implementation uses the common cloud stack Linux + KVM + QEMU to fully simulate the CPU, memory, on‑chip devices, and peripherals of the M1 model.

Linux

AsahiLinux performs extensive reverse‑engineering of M1 hardware and provides drivers for the platform, including ongoing support for the M1 GPU. It serves as the host OS on the bare M1 hardware, providing a Linux runtime environment for building the virtualization stack.

QEMU

QEMU provides the basic framework for machine simulation. A new ARM64‑based M1 machine model is added to QEMU’s device tree, enabling software‑only emulation (TCG) and, with KVM, hardware‑accelerated virtualization.

KVM

KVM exports hardware acceleration via ioctl to QEMU, allowing most guest instructions to run directly on the CPU and enabling two‑stage page‑table translation for fast memory access.

M1 Model Simulation

M1 VCPU

Each VCPU is represented by a dedicated QEMU thread. Specific extensions for M1 include:

Multiple M1‑specific registers with read/write logic.

Simulation of the Apple Power Management Unit (PMGR) for SMP wake‑up.

FastIPI inter‑cluster communication.

M1 Memory Layout

The VM address space is partitioned for flash, firmware, interrupt controller, device MMIO, PCI ranges, and virtual memory. Key considerations are:

Relationship between CPU and device address domains.

Avoiding conflicts between system memory and DTB device addresses.

Providing a sufficiently large contiguous range for system memory.

System memory holds the kernel image, device tree, and ramdisk at boot, requiring careful placement to prevent overlap.

M1 Device Simulation

Standard virtio‑pci devices (virtio‑blk, virtio‑net) are used for storage and networking. A PCI bus is attached, and the Apple Interrupt Controller (AIC) is simulated via MMIO based on AsahiLinux driver analysis. The PCI bus uses QEMU’s generic gpex-pcihost model, with DTB‑derived configuration for address spaces.

Interrupt routing connects the PCI bus GPIO pins to AIC inputs, and AIC GPIO outputs are linked to each CPU’s interrupt line.

Virtualized macOS and Boot Process

Pre‑boot Stage

Physical M1 boot involves Boot ROM → LLB → iBoot → KernelCache. Since LLB and iBoot are closed‑source, the implementation skips these stages and lets QEMU perform early device initialization, load the KernelCache, and update the DTB.

After early initialization, the system memory layout includes KernelCache, optional ramdisk, and DTB.

Boot Flow

The overall boot flow in QEMU/KVM consists of four phases:

QEMU Phase: Create VCPU threads, initialize devices, map system memory (KernelCache, ramdisk, DTB), create boot arguments, and set the VCPU PC to the KernelCache start address.

Early Initialization Phase: Assembly code sets up interrupt vectors, page tables, and parses boot arguments.

Kernel Phase: arm_init and kernel_bootstrap parse KernelCache, configure DTB, initialize console, per‑CPU data, and start core subsystems.

User‑Space Services: The first user‑space process /sbin/launched (PID 1) starts system daemons and GUI shells.

Complete macOS Software Stack under Virtualization

The stack consists of the physical M1 hardware, AsahiLinux providing kernel drivers, KVM delivering hardware acceleration, QEMU emulating the M1 machine, and the macOS guest running on top. The guest loads multiple kexts, supports APFS or HFS ramdisk roots, and uses dyld and dyld_shared_cache for efficient library sharing.

Future Plans and Outlook

Current work achieves basic macOS M1 boot. Future work will focus on:

Improving the runtime environment (more system services, GUI, broader device support).

Enhancing compatibility by developing tools for hot‑patching KernelCache and kexts across macOS versions.

Optimizing performance by moving PMGR and AIC simulation into KVM to reduce user‑kernel transitions.

cloud computingARMQEMUKVMM1macOS virtualization
ByteDance SYS Tech
Written by

ByteDance SYS Tech

Focused on system technology, sharing cutting‑edge developments, innovation and practice, and analysis of industry tech hotspots.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.