--- title: "my mainframe runs arch btw" subtitle: "porting Arch Linux to IBM s390x" author: "Josephine Pfeiffer" date: "FOSDEM 2026" --- ## the premise \only<1>{I use Arch}\only<2->{I use Arch (btw)} . . . on an IBM mainframe . . . an architecture lineage from 1964 ::: notes Pause for recognition after "I use Arch btw." Then pause again after "on an IBM mainframe." IBM System/360, now z/Architecture. The machine your bank still runs its core software on. ::: --- ## s390x in 30 seconds - IBM Z / IBM LinuxONE - 64-bit big-endian - boots via **IPL** - your bank runs on this ::: notes s390x is IBM Z, also branded LinuxONE. Basically the last big-endian architecture anyone still manufactures. It doesn't boot, it does IPL -- Initial Program Load. Storage isn't a disk, it's DASD. Networking is QETH -- QDIO Ethernet, because apparently regular Ethernet wasn't complicated enough. ::: --- ## "why?" --- ## "why?" I thought it would be funny :p --- ## the problem Arch Linux assumes you build entirely on the target architecture . . . I do not own a mainframe . . . (but I have access to one) ![](diagrams/mainframe.jpeg){ height=45% } ::: notes I am building on a laptop ::: --- ## the solution: a hybrid build ![](diagrams/hybrid-build.png){ height=80% } ::: notes Why not build everything natively on the mainframe? The z/VM runs RHEL 9.6, not Arch. To build Arch packages natively on s390x, you'd first need pacman, makepkg, and all the build dependencies -- but those don't exist for s390x yet. That's the chicken-and-egg problem this hybrid approach solves. ::: --- ## step 1: the kernel cross-compile with `s390x-linux-gnu-gcc` in a Fedora container ```bash make ARCH=s390 CROSS_COMPILE=s390x-linux-gnu- \ -j$(nproc) bzImage modules ``` this part actually works fine . . . this is the last time I will say that ::: notes The kernel cross-compiles cleanly with the s390x GCC toolchain. This is the last step that just works. I want you to appreciate this moment. ::: --- ## step 2: busybox busybox must be statically linked for the initramfs . . . reliably static-linking s390x binaries requires native compilation . . . you need a real mainframe ```bash $ ssh mainframe $ make CONFIG_STATIC=y $ scp busybox-s390x-static laptop:boot/ ``` 2.3 MB. 60+ applets ::: notes busybox is a single binary that provides stripped-down implementations of common Unix utilities (sh, cp, mount, etc). It replaces coreutils, util-linux, and a shell in a single statically-linked binary. The initramfs needs these tools before the real root filesystem is mounted, and busybox is the standard way to provide them in a minimal footprint. The "ash" applet in the later slide is busybox's Almquist shell implementation -- the shell that runs as /bin/sh in early boot. ::: --- ## step 3: mkinitcpio Arch's initramfs generator assumes it can *run* the binaries it packs . . . it cannot run s390x binaries on x86_64. . . . ```bash # Can't do this on x86_64: busybox --list # So instead: hardcode all 60+ applet names local busybox_applets=( "[" "[[" "ash" "awk" "basename" "cat" "chmod" "cp" "dd" "df" "echo" "env" # ... 50 more lines of this ) ``` ::: notes mkinitcpio has a reasonable assumption: it can execute the binaries it's packing. Except mine are s390x and I'm on x86. So it can't run `busybox --list` to discover applets. My fix: hardcode all 60-plus applet names in a bash array. Elegant? No. Works? Yes. ::: --- ## step 4: the CONFIG_UNIX incident systemd boots. systemd immediately dies. . . . ```bash CONFIG_UNIX=y # AF_UNIX sockets. systemd needs these. ``` ::: notes No error. No log. Just... nothing. After a few hours of staring at QEMU output, I find it: CONFIG_UNIX=y. AF_UNIX socket support. Systemd will not function without it. It will also not tell you this. You just have to know. ::: --- ## the boot sequence ![](diagrams/boot-sequence.png){ width=100% } ![](diagrams/boot-sequence-2.png){ width=100% } total system image: **11 MB** smaller than most Electron apps. --- ## it works :D ```bash $ uname -a Linux archlinux 6.18.6-arch1-1-s390x #1 SMP s390x GNU/Linux $ cat /etc/os-release NAME="Arch Linux" PRETTY_NAME="Arch Linux" $ busybox | head -1 BusyBox v1.37.0 (s390x) multi-call binary. $ systemctl status State: running Units: 12 loaded ``` ::: notes uname says s390x. os-release says Arch Linux. Busybox and systemd are running. This is a real, booting, functional Arch Linux system on mainframe architecture. ::: --- ## what I learned - cross-compilation has hard limits so sometimes you need the real hardware - distribution tooling has architecture assumptions everywhere - `CONFIG_UNIX=y` ::: notes And IBM actually gives away free mainframe access through the LinuxONE Community Cloud, so you can do this too. ::: --- ## Arch Linux on s390x **working today:** - kernel, initramfs, busybox, systemd - full boot to systemd shell - QEMU emulation + real z/VM hardware **next:** - pacman and makepkg for s390x - pacstrap and base packages --- ## thank you github.com/pfeifferj/archlinux-s390x josie.lol ::: notes And yes, I use Arch btw. :::