Engineering Notes
Why emulate an SGI Origin 200?
Why an Origin 200 needs an emulator and why this fork is permanent.
The Origin 200 is a 1997 SGI server: one or two node boards, each carrying up to two R10000 processors, its own memory, and a node controller called the Hub. The Hub is the whole machine in one chip. It is the processors’ memory controller, their directory-coherence engine, their interrupt controller, its node’s port onto the crosstalk I/O fabric, and its port onto the CrayLink fabric that joins nodes together. Past the Hub, reached over its crosstalk link, sits a base I/O board carrying a crosstalk-to-PCI bridge, two QLogic SCSI adapters, and a multifunction I/O chip that provides the serial console, ethernet, and a PS/2 keyboard controller. This machine has no crosstalk crossbar at all, so the Hub’s link goes straight to the bridge.
That makes it a cache-coherent non-uniform-memory-access machine, ccNUMA, of the kind that was exotic when it shipped and is ordinary now. Memory is physically attached to nodes. The node number lives in high bits of the physical address, so every node’s memory and every node’s Hub registers appear at node-strided offsets in one 40-bit global space, and each processor also sees its own node’s resources at a fixed local window. A device interrupt does not travel down a wire to the processor. The bridge that gathers it composes a crosstalk write to an address it was programmed with, that write lands on a Hub register, and the register sets a pending bit that becomes a processor exception.
Nothing else emulates one
I surveyed every SGI emulator I could find at the start of this project, in August 2026, and none of them reaches an Origin firmware banner, let alone an operating system.
MAME’s SGI directory covers the Indy, the Indigo2, the O2, the Octane and older Iris machines. The Indy works well enough to boot IRIX 5.3 and 6.5 with networking. Almost everything after it is a skeleton whose own to-do list reads “everything”. There is no IP27 file in MAME at all, not a stub, not a placeholder.
GXemul has an SGI Origin machine type, and it consists of a name string, a note that there are two processors per node, and one serial controller at an address inherited from a different SGI machine entirely. There is no Hub, no crossbar, no bridge, no I/O chip and no NUMA addressing. Its software ARC64 firmware can in principle start a 64-bit kernel, which then dies at the first access to any of the machine’s real hardware.
QEMU, the base I chose, shipped no SGI machine of any kind and no R10000-class processor. MAME’s MIPS cores stop at R5000-class. GXemul nominally knows an R10000 processor identification but interprets generic MIPS IV underneath it, and its own header admits the specifications may not be accurate.
The one precedent
Stanford’s SimOS is the only project on record that booted a commercial IRIX on simulated hardware. From 1994 it ran IRIX 5.2 and 5.3 nearly unmodified, along with unmodified SGI binaries, on a simulated Challenge-class R4000 multiprocessor. That is a bus machine, not an Origin. SimOS faked its firmware on purpose, a boot PROM that answered only the questions the operating system actually asked, with disks backed by host files and a root filesystem built by a host-side tool. Its R10000-class processor model was a timing model for studying out-of-order execution, not a system model with the privileged registers an operating system programs.
SimOS did carry a cycle-accurate model of a node controller, built for the FLASH research machine, which makes it the closest historical work to what I am doing. It was a research instrument for a machine that was never sold.
So the framing the survey landed on is this: no emulator of a real historical ccNUMA machine with node controllers exists outside 1990s academia. An Origin 200 with a working node controller, running the operating systems that shipped for it, would be a first.
Why fork QEMU
Choosing a base meant rejecting three alternatives before settling on one.
A greenfield Rust emulator was dominated on every axis. Nine to eighteen months to a first operating-system boot, running at ten to sixty guest MIPS, unusable for booting a real IRIX, unless I also wrote a just-in-time compiler, which would have been the largest single sub-project in the whole comparison.
Forking an existing Rust SGI emulator was the second option. techomancer/iris was the only actively developed SGI emulator in 2026, and a code audit found its CPU core, JIT and equivalence-checking harness all solid. But 32-bit physical addressing ran through the entire bus layer at hundreds of sites, there was no machine abstraction to hang a second machine off, and the memory model was single-threaded in a way that is an architectural dead end for coherent NUMA multiprocessing. The audit put it at two to three times slower to a first boot than the QEMU route.
GXemul or MAME as a base I rejected as dormant, slow, and without an R10000. Both remain useful reference material, and GXemul’s software-ARCS technique is the working precedent the synthesized firmware follows.
What QEMU offered was specific and measurable. Its MIPS target already had mature MIPS IV
code generation, 40-bit physical addressing, and one of the R10000’s less common control
registers. An existing PCI host bridge in the tree, hw/pci-host/astro.c, is
architecturally the same shape as a system controller with a page-directory IOMMU feeding
a PCI bus, which is exactly what the Hub and the Bridge are together. TCG delivers two to
five hundred guest MIPS, which is at or above a real 180 to 270 MHz Origin 200, for free.
Two QEMU facilities turned out to matter more than the speed. qtest drives a device’s
registers directly with no operating system running, so every device can be checked
against its specification before any guest sees it. And -d unimp turns an access to a
register nobody implemented into a log line naming the address, which converts the usual
emulator failure, a guest that stops for no visible reason, into a list of things to go
implement.
The survey supplied the last argument, and it is about people rather than code: long-lived emulators are the ones built on maintained frameworks, and the ones that die do so from solo-maintainer stall and host rot rather than from emulation being too hard.
The operating systems, in order
Three guests, in a deliberate order, chosen for what each one can prove.
OpenBSD/sgi comes first. It supported the Origin 200 through release 6.9 in 2021, prebuilt IP27 kernels are available, and its kernel is small enough to read end to end. It is the guest that got the machine from a monitor prompt to a login shell.
Linux/IP27 comes second, as an instrument rather than as a second trophy. Mainline Linux still supports this machine, reworked in 2019 against real Origin hardware. The reason it is on the critical path is that OpenBSD and Linux read disjoint parts of the machine. An entire class of defect is structurally invisible to every OpenBSD boot that could ever be written. Two are already known: the crosstalk link status, which OpenBSD never reads and Linux acts on, and the Bridge’s board-identity one-wire memory, which Linux will not attach the Bridge without. Every milestone after Linux lands is verified by two guests instead of one.
IRIX comes last, as the end goal. It is the operating system the machine was built for and the strictest consumer of the firmware’s configuration graph. It is also the one guest that brings its own external witness: the vendor’s own hardware inventory tool reports what it found, and I did not write it and cannot edit it. Each driver’s attach routine builds that inventory from its own source, so the tool reports the sum of what the devices told the kernel rather than a readback of anything I synthesized. Agreement cannot be generated by my machine, because the tool is not mine, and it exercises every device’s attach path to produce it.
A decision I took in August 2026 settled how IRIX gets there: it boots on the real, extracted IP27 firmware image rather than on the firmware surface I synthesize for OpenBSD and Linux. The reasoning is about what can be checked. Writing a firmware surface faithful enough to satisfy a vendor kernel can be checked against nothing, you guess what IRIX needs and find out by failing. Making the machine faithful enough to run the vendor’s own firmware gives me my sharpest check, because the firmware either runs or stops, and where it stops is a measurement of the machine.
Where it stands
OpenBSD 6.9 GENERIC-IP27 boots from an installed disk, through the emulated SCSI path, to an authenticated root shell. The machine identifies itself as an Origin 200, mounts root off a disk that a real OpenBSD installer wrote through the modelled SCSI adapter, authenticates a user, runs commands against that filesystem, and halts cleanly. The transcript is committed. Its one boundary is worth naming: the kernel is started directly, with no firmware-supplied boot-device string, so the root and swap prompts are answered by the test harness rather than by firmware. That belongs to the firmware-synthesis work and is not part of this result.
Linux reaches a networked multiuser login across two nodes. An unmodified mainline kernel with the standard IP27 option boots on a machine built as two nodes and four processors, rooted on a real SCSI disk. It finds all four processors across both nodes, brings up the base I/O controller’s ethernet, takes a DHCP lease, and answers a secure-shell connection forwarded from the host. Because the kernel is stock upstream rather than anything I wrote, it agrees with the machine only where the machine is right, which is what makes it a witness I do not control. Its own announcement has the detail.
The real SGI firmware runs far past its banner. The stock PROM prints its banner, answers typed commands, and netboots sash, the standalone shell that installs and boots IRIX, on both supported firmware releases and on two processors. Its factory power-on diagnostics complete with every check passing and my list of expected failures emptied, and SGI’s own field diagnostic kernel netboots on the same machine and runs its processor and memory tests with no miscompare. The diagnostics announcement sets those out.
IRIX runs multi-user. The vendor’s own installer writes a blank disk over the network end to end, overlay, foundation and application distributions, the maintenance stream, and the machine reboots from that disk into run level 2 with a root login on the console, read by the vendor kernel as current hardware the whole way: no processor-downrev, node-controller-downrev, or old-firmware complaint, and an inventory that matches the machine. The first netboot to a live console is the subject of the IRIX announcement, and the register the model stored and never used tells the wall IRIX cleared just before it.
The second chassis has since been reached. The stock firmware brings up four processors across two Origin 200 chassis to its maintenance menu, and IRIX has been installed over the network and booted to a multiuser login across both, in a run whose full acceptance is still open. The same node blocks, assembled into a larger machine, now run IRIX multi-user on eight processors and four nodes of an emulated Origin 2000. The two-chassis result and the eight-processor one have the detail. The successor generation followed: IRIX now installs and boots on an emulated Origin 300, built on the Bedrock node controller, as its announcement sets out.
Not one machine, a family
Why emulate an Origin 200? The answer has grown past the question I started with.
SGI built these machines out of shared blocks. The Hub, the Bridge, the crossbar part, the base I/O controller and the processor are the same ASICs across the Origin 200, the Origin 2000 and the Onyx2, which is why one firmware and one kernel port span all three. What differs between them is the arrangement: how many nodes, whether a crossbar is fitted at all, how many slots, what sits on the PCI bus.
The fork is organised the same way, and that was not a plan so much as what the work turned into. The device models carry no machine-conditional behaviour. Everything machine-specific, how many of what and how they are wired, lives in the file that assembles the parts. So this is a set of SGI component models plus a machine that assembles them, and the Origin 200 is the first assembly rather than the whole of it.
That reframing pays a debt elsewhere in the collection. The extracted firmware for the later generation measured out as the same container format as this one’s, which I first recorded as a fortunate finding. Under this reading it is what the family structure predicts: a successor set of parts, assembled the same way by the same design lineage, packaged the same way. The claim it licenses is narrower than it sounds, the packaging and the loading path are likely to carry, and each successor component still needs its own reading. But it is the difference between having built one machine and having built the first of a family.
The next posts in this collection take the machine apart unit by unit, then tell two stories from the build: a disk-I/O hang caused by a producer and a consumer sharing one register, and a road to a login prompt made almost entirely of walls.