⏱️ Reading time: 14 min
On December 1, 2024, in an IRC channel, someone wrote a single line: “can confirm this state gives a working usb proxy”. Behind that message was the first real step toward running Linux on a Mac mini with an M4 chip, a SoC that Apple designed specifically to block that kind of experiment.
📑 En este artículo
- TL;DR
- What Is Asahi Linux?
- Why the M4 Changed the Rules of the Game
- How Linux Boots on Apple Silicon
- Brute-Force Debugging: Bisecting With a printf
- Secondary Cores and the Forgetful CPU
- Getting Started: Try Asahi Linux Today
- Real-World Use Cases
- Common Mistakes and Best Practices in New Hardware Bringup
- Comparison With Other Bringup Approaches
- Going Deeper: SPTM and GXF Under the Hood
- Frequently Asked Questions
- References
It took more than a year of intermittent work, a serial console, and a debugging technique as old as programming itself: print a letter and see if it shows up. This is the technical story of how Asahi Linux managed to run on the M4, documented in detail by its author on her blog, and along the way, a complete lesson on how Linux boots on real ARM64 hardware.
TL;DR
- Asahi Linux booted on the Mac mini M4 despite SPTM, skipping GXF initialization and the RVBAR.
- A single-letter print in head.S made it possible to bisect the failure down to the MMU initialization code.
- Without stdout-path = serial0 in the device tree, the kernel boots silently with no clue on the console.
- The same smp_start_offset used on M1 through M3 managed to bring up the M4’s secondary cores.
- The Asahi Open Collective funds the reverse engineering work that makes this kind of bringup possible.
What Is Asahi Linux?
Asahi Linux is an open source project that adapts the Linux kernel and its driver ecosystem to run natively on Macs with Apple Silicon processors, from M1 to M4, without virtualization, replicating from scratch the drivers Apple never documented.
The project was born shortly after the launch of the first Mac with an M1 chip in 2020, and has maintained stable support for M1, M2, and M3 ever since. The work relies on m1n1, a bootloader and reverse engineering framework that runs before Linux and makes it possible to capture, step by step, how macOS talks to the hardware Apple doesn’t document. Without those captured registers, there’s no way to write a correct driver.
Why the M4 Changed the Rules of the Game
Up through the M3, the method was straightforward: run m1n1 as a hypervisor under macOS, let macOS boot with its original drivers, and log every memory-mapped I/O (MMIO) access those drivers make. That trace then becomes the basis for the Linux driver.
The M4 broke that flow because it was the first Apple Silicon generation to require SPTM (Secure Page Table Monitor), a hardware layer designed to shield macOS’s XNU kernel against exploits that manipulate page tables. For m1n1 to keep running macOS as a guest under its hypervisor, it needs deep changes that go beyond what a single developer can solve in months. For Asahi Linux, every new Apple Silicon generation is a separate race against the defenses Apple adds to XNU.
That didn’t close the door entirely. In parallel to the hypervisor work, the author started trying to boot Linux directly on the M4, without going through macOS: disabling strict boot security, installing m1n1 as a custom boot object from macOS recovery mode, and hooking up a serial console to read the raw logs.
How Linux Boots on Apple Silicon
On any ARM64 SoC, each CPU core boots by executing the memory address loaded in its RVBAR (Reset Vector Base Address Register), a per-core register that defines where code starts running on power-up. On Apple Silicon, Apple’s firmware (iBoot) boots first, loads m1n1 as an intermediate loader, and m1n1 then writes the RVBAR with the address of the next object to execute, typically the Linux kernel itself.
On the M4, that step failed. Trying to write the RVBAR hung the core. The fix, after checking the existing value, was to simply not write anything: the register already held the correct address. Something similar happened with GXF (Guarded Execution Framework), an Apple feature related to protected execution modes that comes disabled on raw boot in M4 and later chips. m1n1 just needed to make that initialization conditional and skip it on these chips.
flowchart LR
A["iBoot (Apple firmware)"] --> B["m1n1 (bootloader / hypervisor)"]
B --> C["Minimal device tree: CPU + AIC"]
C --> D["Linux kernel (head.S)"]
D --> E["MMU initialized"]
E --> F["UART mapped and shell available"]
With those two blockers resolved, m1n1 managed to start in BRINGUP mode and hand control to Linux. But the kernel still showed no signs of life: no message appeared on the serial console despite using the earlycon parameter, designed specifically to print logs as early as possible during boot.
Brute-Force Debugging: Bisecting With a printf
Without console output, there was no way to know exactly where the boot process was failing. The solution was the oldest trick in the trade: take m1n1’s character-printing routine (debug_putc), adapt it to print a single letter, and insert it progressively further into Linux’s boot code, in arch/arm64/kernel/head.S, until finding the point where the letter stopped showing up.
The first discovery was revealing: the letter printed fine right up to the MMU (memory management unit) initialization code. There it cut off, but not because the MMU failed. The reason was more subtle: the UART is accessed through memory-mapped I/O (MMIO), and m1n1 maps that region at virtual addresses identical to the physical ones. Linux doesn’t do that by default. Once the MMU is enabled, every access gets resolved against the kernel’s page tables, which didn’t yet have that address mapped. The result was an access to unmapped memory, silent from the outside.
sequenceDiagram
participant Dev as Developer
participant Kernel as Linux Kernel
participant UART as Serial Console
Dev->>Kernel: inserts debug_putc("a") in head.S
Kernel-->>UART: prints "a" before the MMU
Note over Dev,Kernel: after enabling the MMU, total silence
Dev->>Kernel: adds 1:1 mapping for the MMIO region
Kernel-->>UART: prints "a" again
Dev->>Kernel: moves the print further along
Kernel-->>UART: hangs on an AIC register
Adding that 1:1 mapping to Linux’s initial page tables brought back console output, and the bisection could move forward: the next cutoff appeared during AIC interrupt controller initialization, at a write to the Apple-specific register SYS_IMP_APL_VM_TMR_FIQ_ENA_EL2, tied to virtualization. Commenting out that write unblocked the boot process all the way to a working shell. Later iBoot versions unlocked that register, so the patch stopped being necessary.
There was a separate problem left: why earlycon hadn’t shown anything from the start. The cause was much simpler than everything before it: the hand-built device tree was missing the stdout-path = "serial0" property. Without it, the kernel doesn’t know which of its serial nodes to use as the early console, even if the hardware is perfectly initialized. Adding it uncovered register dumps and full stack traces on every subsequent failure.
💭 Key takeaway: bringing up Linux on new hardware almost never starts by reading a datasheet. It starts by capturing, with a hypervisor, every memory access the original operating system makes, and then blindly reproducing that behavior until something responds.
Secondary Cores and the Forgetful CPU
With one core booting, the rest still needed to come up. m1n1 wasn’t starting the secondary cores because it was missing smp_start_offset, a hardcoded value without which the smp_init routine gets skipped entirely. Reusing the known offset from the M1 through M3 worked on the M4 too, and the extra cores booted.
That’s where the problem that gives the original story its name showed up: “the forgetful CPU.” Previous Apple Silicon chips already had particular behaviors around the WFI (Wait For Interrupt) instruction, which puts a core into low power mode until an interrupt arrives. In certain states, a core that enters WFI can lose context that Linux assumes persists, causing hangs with no apparent connection to the code that ran right before. Tracking down that kind of failure requires the same method as the rest of the article: isolate the exact condition with prints and compare against the (partially) documented behavior of previous generations.
M1-M3 vs. M4: What Changes for Bringup
| Generation | Main Bringup Method | Status in Asahi Linux | Key Limitation |
|---|---|---|---|
| M1 to M3 | m1n1 hypervisor capturing macOS traces | Stable, installable support | Requires macOS running as a guest |
| M4 | Direct Linux boot without macOS involved | Experimental, active bringup | SPTM blocks the classic hypervisor path |
| M4 (future) | Possible hypervisor adapted to SPTM | Under development by the m1n1 team | Deep changes to m1n1, non-trivial |
Getting Started: Try Asahi Linux Today
If you want to try Asahi Linux yourself, stable, installable support today covers Macs with M1, M2, and M3; the M4 is still in active development, as everything above shows. On a compatible Mac, installation happens from within a macOS session, not from Windows or Linux, because the installer repartitions the internal disk and coexists with macOS:
curl https://alx.sh | sh
That command downloads the official installer and walks you step by step through creating a Linux partition alongside macOS. Before running it, you should have a full backup: the installer touches the internal disk’s partition table. The updated installation guide, with exact space requirements and supported models, lives in the project’s official documentation.
There’s no Windows or Linux host variant because the installer’s whole purpose is to replace part of an existing macOS installation, not to create an external boot medium.
Real-World Use Cases
Beyond the technical curiosity, having native Linux on Apple Silicon solves concrete problems. Teams that already bought Apple hardware for its power efficiency can run server workloads, containers, or development pipelines without going through a virtualization layer, with direct access to the GPU and Neural Engine depending on each generation’s support level.
It also serves as real hands-on ground for systems engineering: few projects expose the full process of bringing a kernel up on a closed SoC so clearly, from the first register that doesn’t respond to a working shell. Universities and operating systems communities use Asahi Linux’s public code and logs as low-level study material.
Common Mistakes and Best Practices in New Hardware Bringup
The M4 story leaves lessons that apply to any operating system port to new hardware, not just Apple Silicon.
- Early MMIO mapping: if your bootloader maps the UART with an identity mapping and your kernel doesn’t, you’ll lose the console right when you need it most, when enabling the MMU. Check that your initial page tables include the peripheral region you use for debugging.
- Minimal but complete device tree: a “minimal” device tree that omits
stdout-pathisn’t minimal, it’s incomplete. Without that property,earlyconhas no way of knowing which node to use. - Manual bisection when there’s no other option: without JTAG or a working debugger, moving a
printline by line is still a valid and fast technique to narrow a failure down to a specific function. - Don’t assume a locked register needs more code: sometimes the right solution is simply not writing to it, as happened with the M4’s RVBAR, which already held the correct value.
Comparison With Other Bringup Approaches
The m1n1 approach (a hypervisor that traces macOS’s behavior) isn’t the only way to port an operating system to hardware without public documentation, but it’s the one that worked best on Apple Silicon because it allows byte-by-byte comparison against an operating system that does work. Bringup projects on ARM boards from other manufacturers often instead rely on partial manufacturer documentation, leaked datasheets, or direct collaboration with the vendor, something Apple doesn’t offer.
Compared to options like coreboot, designed to replace firmware on more open x86 platforms, the Apple Silicon case is closer to complete reverse engineering from scratch: there are no official controller specs, only the observed behavior of macOS running under the hypervisor.
Going Deeper: SPTM and GXF Under the Hood
SPTM is, in essence, a hardware and firmware layer that sits between the XNU kernel and the memory page tables, so that even a compromised XNU can’t rewrite those tables without going through a separate, more privileged monitor. Apple documents the general approach behind this kind of protection in its platform security guide. For Asahi Linux, the practical effect is that the old trick of running macOS as a guest under m1n1 and watching what it does is no longer enough, without first getting SPTM to accept a hypervisor other than Apple’s.
flowchart TD
A["M4 ARM64 Cores"] --> B["SPTM: Secure Page Table Monitor"]
B --> C["macOS XNU Kernel"]
B --> D["GXF: Guarded Execution Framework"]
subgraph HardwareM4["M4 Hardware"]
A
B
D
end
C -. "cannot alter page tables without going through SPTM" .-> B
⚠️ Heads up: replicating these steps on a real Mac means disabling boot protections and editing low-level firmware. A mistake at the wrong step can leave the machine unable to boot even macOS. This is active bringup work, not a daily-use tutorial.
Your next step: clone the m1n1 repository and read the debug_putc code to understand, line by line, how a character gets printed before any console driver exists.
Frequently Asked Questions
Which Mac Can I Use Today With Asahi Linux?
Any Mac with an M1, M2, or M3 chip has stable, installable support. The M4 is still in an experimental bringup phase, with no installer ready for daily use.
What Is m1n1 Within the Free Port for Mac With an M-Series Chip?
It’s the bootloader and hypervisor that runs before Linux, used both to chainload the kernel and to capture the behavior of macOS’s original drivers.
Why Does SPTM Complicate Running Linux on Apple Silicon?
Because it protects the XNU kernel’s page tables with a separate hardware monitor, which blocks the classic trick of virtualizing macOS to spy on its drivers, unless the hypervisor is first adapted to that new layer.
Is It Safe to Try This Process on My Own Mac?
Not without prior experience. The process involves disabling boot security and writing to low-level registers; one wrong step can leave the machine unable to boot any operating system.
How Is the Asahi Project Funded?
Largely through donations to the Asahi Open Collective, which fund the time spent on this kind of reverse engineering of undocumented hardware.
References
- Yureka Lilian’s blog: the original, full account of the Linux bringup on the Mac mini M4.
- Asahi Linux: the project’s official site, with installation documentation and supported hardware.
- m1n1 repository on GitHub: source code for the bootloader and hypervisor used in the bringup.
- Asahi Open Collective: the donation fund that sustains the project’s development.
- Linux kernel documentation on device tree: the official reference for the format used to describe hardware at boot.
📱 Enjoy this content? Follow @programacion on Telegram for daily tech content in Spanish: quick summaries, fresh content every day.
Featured image: Foto de BoliviaInteligente en Unsplash
Did it work for you? Got a different error? Say so below: questions get answered and help the next reader.
Leave a comment
0 Comments