Orthox-64 — an x86-64 OS that compiles its own kernel (musl, Python/NumPy, lwIP, DOOM)
Posted: Mon Jun 15, 2026 8:15 am
Orthox-64 is a from-scratch, monolithic x86-64 (long mode) OS. The headline feature, and the thing I'm proudest of: it self-hosts — the running OS can rebuild its own kernel from source using a natively-ported GCC 4.7.4, and the resulting kernel boots and runs.
What works today
- Boot: Limine (UEFI/BIOS)
- Memory: PMM + paging VMM
- Scheduling: preemptive multitasking, SMP (4 CPUs in QEMU, LAPIC timer, reschedule IPI, per-CPU run queue)
- FS: VFS + a read-write xv6fs (ported from xv6-riscv, extended with triple-indirect blocks, ~16 GB/file)
- Userland: musl libc + BusyBox; full dynamic linking (.so, dlopen/dlsym, TLS, C++ runtime); Python 3.12 importing/running NumPy 1.26.4
- Networking: virtio-net + lwIP — DHCP, DNS, ICMP, UDP, TCP, sockets, BusyBox httpd, and a userspace HTTPS client (BearSSL)
- Self-hosting: GCC 4.7.4 + binutils 2.26 ported to run on the OS; rebuilds /kernel.elf in-place; boots it
- And yes, it runs DOOM (doomgeneric)
A few design decisions that might interest people here
- I started the "sensible" way — extending xv6 with newlib, assuming something 10+ years old would have room to grow. I actually got surprisingly far: Binutils (as/ld/ar/objcopy), a POSIX shell, and a triple-indirect ~1 GB filesystem all running on xv6. But it was all held together by xv6-specific hacks — a hand-rolled printf to dodge Newlib's FPU use (xv6 has no FPU context switching), a 16 MB gap so malloc wouldn't smash the stack, a 1 MB stack for Binutils' deep call chains. The moment I tried to do it properly and move to a standard ABI, the whole thing collapsed — the shell jumped into kernel space in an infinite reboot loop. That was the lesson: bridging xv6's deliberately minimal design and what the GNU toolchain actually demands is a losing battle. So I started clean with an original kernel, and later moved newlib -> musl — which is what finally made a real userland possible.
- Why GCC 4.7.4? It's the last GCC that bootstraps with a C compiler alone (4.8+ needs a working C++ toolchain to build itself). That gave me a C-only self-hosting loop first, and an older/lighter compiler is far more forgiving on a young kernel whose MM and FS are still stabilizing.
- Actually closing the self-hosting loop took ~100 smoke-test iterations and ripping out the original filesystem entirely when it couldn't survive a real build load — that's where the ~16 GB triple-indirect xv6fs came from.
Demo — a recording of it compiling its own kernel and then booting that kernel:
https://github.com/itoh5588/Orthox-64/b ... ADME.en.md
(raw asciicast is in the repo under assets/)
Repo + build/run (host toolchain is clang -target x86_64-elf + lld; boots in QEMU):
https://github.com/itoh5588/Orthox-64 (see INSTALL.md)
Honest notes
- Integration over reinvention: third-party ports are credited — musl, lwIP, BearSSL, Limine, CPython, zlib, BusyBox, GNU make/binutils/gcc; the FS is from xv6-riscv (MIT).
- It runs in QEMU; I haven't tested it on real hardware yet.
- A short personal note: I'm in my 70s, ~46 years in the industry (DEC, Apollo Computer, and OSF during the Unix Wars — on the localization side, not the kernel). Orthox-64 is the first OS kernel I've written end to end.
- I did use an AI agent as a tool. It made generating code cheap; it did not make the judgment to close the self-hosting loop cheap — the decisions above and the ~100 iterations were the actual work. Happy to go into specifics on any of it.
Feedback and pointers very welcome — especially on what you'd consider worth tackling next (I'm eyeing procfs expansion and more userland).
What works today
- Boot: Limine (UEFI/BIOS)
- Memory: PMM + paging VMM
- Scheduling: preemptive multitasking, SMP (4 CPUs in QEMU, LAPIC timer, reschedule IPI, per-CPU run queue)
- FS: VFS + a read-write xv6fs (ported from xv6-riscv, extended with triple-indirect blocks, ~16 GB/file)
- Userland: musl libc + BusyBox; full dynamic linking (.so, dlopen/dlsym, TLS, C++ runtime); Python 3.12 importing/running NumPy 1.26.4
- Networking: virtio-net + lwIP — DHCP, DNS, ICMP, UDP, TCP, sockets, BusyBox httpd, and a userspace HTTPS client (BearSSL)
- Self-hosting: GCC 4.7.4 + binutils 2.26 ported to run on the OS; rebuilds /kernel.elf in-place; boots it
- And yes, it runs DOOM (doomgeneric)
A few design decisions that might interest people here
- I started the "sensible" way — extending xv6 with newlib, assuming something 10+ years old would have room to grow. I actually got surprisingly far: Binutils (as/ld/ar/objcopy), a POSIX shell, and a triple-indirect ~1 GB filesystem all running on xv6. But it was all held together by xv6-specific hacks — a hand-rolled printf to dodge Newlib's FPU use (xv6 has no FPU context switching), a 16 MB gap so malloc wouldn't smash the stack, a 1 MB stack for Binutils' deep call chains. The moment I tried to do it properly and move to a standard ABI, the whole thing collapsed — the shell jumped into kernel space in an infinite reboot loop. That was the lesson: bridging xv6's deliberately minimal design and what the GNU toolchain actually demands is a losing battle. So I started clean with an original kernel, and later moved newlib -> musl — which is what finally made a real userland possible.
- Why GCC 4.7.4? It's the last GCC that bootstraps with a C compiler alone (4.8+ needs a working C++ toolchain to build itself). That gave me a C-only self-hosting loop first, and an older/lighter compiler is far more forgiving on a young kernel whose MM and FS are still stabilizing.
- Actually closing the self-hosting loop took ~100 smoke-test iterations and ripping out the original filesystem entirely when it couldn't survive a real build load — that's where the ~16 GB triple-indirect xv6fs came from.
Demo — a recording of it compiling its own kernel and then booting that kernel:
https://github.com/itoh5588/Orthox-64/b ... ADME.en.md
(raw asciicast is in the repo under assets/)
Repo + build/run (host toolchain is clang -target x86_64-elf + lld; boots in QEMU):
https://github.com/itoh5588/Orthox-64 (see INSTALL.md)
Honest notes
- Integration over reinvention: third-party ports are credited — musl, lwIP, BearSSL, Limine, CPython, zlib, BusyBox, GNU make/binutils/gcc; the FS is from xv6-riscv (MIT).
- It runs in QEMU; I haven't tested it on real hardware yet.
- A short personal note: I'm in my 70s, ~46 years in the industry (DEC, Apollo Computer, and OSF during the Unix Wars — on the localization side, not the kernel). Orthox-64 is the first OS kernel I've written end to end.
- I did use an AI agent as a tool. It made generating code cheap; it did not make the judgment to close the self-hosting loop cheap — the decisions above and the ~100 iterations were the actual work. Happy to go into specifics on any of it.
Feedback and pointers very welcome — especially on what you'd consider worth tackling next (I'm eyeing procfs expansion and more userland).