TinyComputers.io

Sponsors

More Articles

Two Addresses, One Page: Finding the Firmware Bug Behind NetBSD Corruption on the Milk-V Mars

NetBSD booted on my Milk-V Mars, joined the network, and then overwrote its own kernel with pkgsrc file data under sustained write load. The evidence first pointed at a double allocation inside UVM. That diagnosis was wrong. A custom PGAUDIT kernel, a Mars-shaped QEMU target, 256 permanent canary pages, and a controlled cache-flush experiment in DDB eventually showed two physical addresses exactly 4 GiB apart reaching the same DDR backing. The unsafe 8 GiB map came from a blank EEPROM and U-Boot SPL's private memory default. This is the sequel to my original bring-up article: the wrong theories, the two device trees hiding in one boot chain, the one-line firmware correction, and the 600-second hardware A/B that contained the corruption.

The Same Bad Luck, Quietly: Why a Fleet of Cheap Boards Feels Flakier Than One Old Xeon

My single-board computers hang, drop USB, and eat SD cards in ways my old Xeon server never does, and "you get what you pay for" is a shrug, not an explanation. So this is an attempt at the actual explanation: where the money goes in a server-class machine, why none of it shows up on a spec sheet, and why the same bit flip that increments a counter on the Xeon becomes an unwitnessed mystery hang on a NanoPi. Power delivery, SD card physics, tablet silicon versus mainframe silicon, Google's DRAM study, one Heidegger digression, and the parts of the missing margin you can buy back with a real power supply, a watchdog timer, and three idle boards' worth of Kubernetes.

FreeBSD on a 2011 MacBook Pro: Fifteen Years of Progress, and Per Core It's a Tie

I put a 2011 MacBook Pro running FreeBSD 15.1 through the same Rust compile benchmark as my single-board computer fleet. It lands sixth of nine at 131.00s - behind a Raspberry Pi 5, ahead of a Banana Pi CM5-Pro. But normalized per core and per gigahertz, a 2011 Sandy Bridge core and a 2023 Cortex-A76 do the same amount of work to within 0.3%. Also: why SHA-256 is 5.7x slower here, how the ZFS ARC nearly sold me a 2.86 GB/s hard drive, and two benchmark results I threw out.

The Config Language That Was Already There: A Ballistics REPL Written in Lattice

Every serious calculator eventually grows a configuration language — YAML, TOML, a bespoke parser — and then grows the loop of frustration that comes with it. This is what happened when I refused to write that layer, and instead made an existing programming language do the job: a stateful ballistics laboratory written entirely in Lattice, driving a Rust solver over a process boundary, with no native extension and no C ABI. A case study in what you get when the scripting language and the config language are the same language.

The Bullet Doesn't Go Where You Point It

A bullet fired at a target a thousand yards away does not travel in the direction you aimed it. It falls thirty feet, drifts a foot sideways from its own spin, and gets nudged by the rotation of the Earth. This is a piece about the Rust engine I wrote to predict all of that — how you test physics when you have no oracle, why the hard bugs were never in the equations, and the one problem worth charging for: solving ballistics backwards.

Topics

Reading Series

Written by Alex Jokela Software engineer by trade, tinkerer by nature, single-board computer hoarder by choice. More about me →