I had a hankering to tweak this blog’s presentation a bit. Here’s what it looked like this morning:
Bleugh! Straightforward content? Simple design? Restraint? Thanks, but no. It’s like this guy’s never heard of responsive web pages.
First, let’s make each of those posts pop a little bit more.
Yeah, yeah! Subtle, I like it. Tiny thing, it needs more color.
Now we’re talking.
I manually picked out some pastels and selected one randomly for each blog post chip.
Rearranging the computer
Programming the computer allows you to take something you see and rearrange the pieces a bit to better fit your needs. It’s really a delightful and powerful thing.
A few weeks ago, Daisy and I were staying in a cottage with poor internet speeds. We were trying to stream a series of videos, but the embedded player would only get through a few seconds of playback before it choked for several minutes on the next chunk.
Supporting multiple architectures
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:
Global descriptor table Interrupt descriptor table Interrupt handlers Hand-coded assembly routines Multitasking Paging and virtual memory manager Linker scripts ELF loader Ported software Disable the red zone Build system 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.
axle’s red rectangle of doom
Over the course of developing an operating system, things are going to crash, and they’re going to crash a lot.
One way to make crashes slightly less annoying is to isolate them: the rest of the system continues running, and you can poke around further after an unexpected condition arises in one process. Perhaps surprisingly, it took me several years before this became feasible!
Previously, when any code path, in any process, encountered an error condition (such as a page fault, or an explicit assert()), the kernel would spew some debug information over the serial port, then lock up to prevent further shenanigans.
Adding vmnet support to QEMU
Every hobby operating system developer dreams of the day that a stack wrought from their own blood, sweat, and keystrokes renders its first webpage.
Back in early 2021, I decided to break ground on the first step towards this goal.
Before we can connect to the web, we need to handle all the necessary protocols to exchange packets over both the web and our humble local network link. This includes implementing protocols such as TCP, DNS, and ARP.
Running axle on multiple CPUs
In the beginning, Intel created the 8086. This has been widely regarded as a bad move, but boy is it popular.
The enduring success of the 8086 has been bought on the blood altar of Compatibility: software written for the original 8086, even very low-level software that runs without any supporting OS infrastructure, must continue to function on every new x86-line CPU manufactured today1.
This selling point enforces some pretty annoying constraints on both the advancement of the x86 line and on developers who need to interface directly with x86 CPUs.
Seeking the eternal satisfaction that’d come from a [email protected] email, I checked out the trusty internet marketplace.
Hmm, I think I’d be willing to shell out a few hundred for the security of holding on to my own name.
Ah! After speed-running The Art of the Deal, I was ready: $200 budget and complimentary Red Sox tickets in hand.
The broker was certain over the phone he knew my game. Tennen, it is apparently well-known, means ’natural’ in Japanese.
Syscalls, what gives?
Syscalls are a fundamental piece of the processes model within contemporary operating systems.
OS’s generally like to provide the abstraction that a given program is running on the CPU, linearly and largely in an uninterrupted fashion, from start to finish.
Of course, this isn’t the case; programs are interrupted all the time, for a variety of reasons. Some examples of times the kernel needs to step in:
The kernel needs to handle an event from a peripheral device The program has page-faulted and needs the kernel’s VMM to make everyone play nice The program has been preempted to give other programs the chance to use the CPU for a few milliseconds The underlying reality of what the CPU spends its time on is a complex juggling act of contexts scheduling in and out.
Chess.com is a great online chess server and content creator. One of their hallmark features is their chess puzzles:
Present the player with a position
The player needs to find the ’tactic’: the best sequence of moves, typically resulting in an advantage over the opponent
The quicker the player completes a puzzle, the more points they earn
They look like this:
Puzzles are nice because they help players train their pattern recognition and develop their intuition for chess.
Footsteps of pi
Imagine you have a compass.
Now, instead of the 4 cardinal directions, mark the compass with 10 evenly-divided indications.
You and I are going to play a game. You are standing on a plane, and in front of you is a ball.
I am going to tell you a number. Push the ball with enough force to impart a 1 meter-per-second change in velocity in the direction matching the number’s annotation on your compass.
Incrementally replacing axle’s initrd (Draft)
When a computer starts up, before the operating system can display applications, menus, and wallpapers, the operating system needs to first perform a complex initialization sequence. This sequence serves to get both the underlying hardware, and the operating system’s own software components, ready for further use.
While the full details of this sequence are out of the scope of this blog post, here’s a rough rundown of what this might look like:
GameBoy: The PPU (Draft)
Similarly to how it’s nice and convenient to think of memory as one big list of bytes (but is, in reality, backed by lots of different peripherals whose access is mediated by the MMU), it’d be nice to live in a world in which all it took to display pixels was to write some RGB values to a pixel-list. Alas, things are never quite so straightforward. The GameBoy’s LCD display is driven by a subsystem called the Picture Processing Unit, or PPU.
Writing axle’s GameBoy emulator
This post was discussed further on Hacker News
The Nintendo GameBoy is an exceptionally well-documented system, perfect for anybody who’d like to take a crack at emulation. Publicly-maintained resources like the Pan Docs make it both approachable and convenient to get an overview of the GameBoy’s address space layout, to understand the mechanics of hardware peripherals, and to learn about various edge-case behaviors that some games depend on.