Supporting multiple architectures

Reading time: 1 minute

axle used to be a 32-bit-only OS. In late 2021, I had a hankering to fix this longstanding limitation, and plunge into a world that expanded not just our address spaces, but our hope.

Roughly, if you want to add support for x86_64 to an existing x86 OS, you’ll need to update these components:

  1. Global descriptor table
  2. Interrupt descriptor table
  3. Interrupt handlers
  4. Hand-coded assembly routines
  5. Multitasking
  6. Paging and virtual memory manager
  7. Linker scripts
  8. ELF loader
  9. Ported software
  10. Disable the red zone
  11. Build system
  12. Years of assumptions that a memory address will fit in a u32

For a lot of these items, we’ll save ourselves headache and heartache if we have one interface to do a job, and swap out the details of the implementation based on the architecture we’re targeting. For example, the API for the physical memory manager will always look like this, regardless of target architecture:

I created a small extension of axle’s build system to facilitate this without littering the code with #ifdefs.

The virtual memory manager, which has separate implementations for x86 and x86_64, is now laid out in the source tree like so:

During the build, the right files for the current architecture are templated to a source file, and the rest of the system doesn’t need to worry about the nitty-gritty.


Put your email in this funny little box, and I'll send you a message when I post new stuff.