QSOE Systems

systems software · risc-v · fpga

QSOE

A QNX-inspired operating system with selectable kernels.

News: QSOE 0.3 is out — a writable, checked, persistent root filesystem on both kernels, QSOE/L on every hart of the Unmatched, a third board, and a taskman that is the loader (September 2026). What's new in 0.3 →

QSOE ships in two variants that share one userspace and one build system. QSOE/N runs on Skimmer, a microkernel written from scratch for this project (SMP by design); QSOE/L runs on seL4 as its kernel.

Both variants, when compiled, offer the kernel and initrd files directly usable in e.g. U-Boot loader. The userspace is 100% identical across both variants; the only parts produced per-kernel are taskman, the task manager, and libc.so — the C library, which is around 85% shared at the source level and diverges only at the thin layer where it meets the kernel.

The design follows the QNX Neutrino tradition: a small kernel with everything else in userspace, synchronous message-passing IPC, and the resource-manager model for services.

QSOE targets 64-bit RISC-V (RV64, Sv39) on the SiFive HiFive Unmatched (FU740), the StarFive VisionFive 2 (JH7110) and the SpacemiT K3 Pico-ITX, with QEMU used for day-to-day development. Both QSOE variants boot on real hardware; the K3 — RVA23-class, sixteen harts, pure AIA — is QSOE/N only in this release. Released under Apache-2.0.

Downloads

QSOE can be built from source or installed from pre-built binaries. Ready-made images for each release are published at github.com/qsoe-dev/dl (current release: 0.3). The files are:

  • The Skimmer microkernel — the kernel of the QSOE/N variant. A raw binary image, loaded by the bootloader (or QEMU) together with the userspace package below. Skimmer is linked once per board, so take the one for yours: skimmer-sifive.bin (HiFive Unmatched), skimmer-k3.bin (SpacemiT K3), skimmer-vf2.bin (StarFive VisionFive 2), or skimmer-qemu.bin (QEMU virt). What the board decides is the load address; the platform itself is read from the device tree at run time. So the QEMU and Unmatched images are byte-for-byte identical — either name gets you the same kernel — while the K3, whose DRAM starts at 4 GiB, and the VisionFive 2, whose firmware still holds the low end of its RAM, are each linked for their own address and their images are their own. Take one across those lines, in any direction, and the machine loads a kernel and then does nothing recognizable.
  • modpkg.cpio — the module package: the shared QSOE userspace (taskman, init, the C library, the shell, the file manager, drivers and utilities) as a CPIO archive. One archive for every board and both variants. QSOE/N boots it as an initrd alongside skimmer-<board>.bin.
  • qsoe-l-qemu.elf — the QSOE/L variant (on the seL4 kernel) as a single, self-contained ELF for the QEMU virt machine. It bundles the elfloader, the seL4 kernel, taskman and the userspace together — nothing else is needed to boot.
  • qsoe-l-sifive.elf and qsoe-l-vf2.elf — the same QSOE/L image, built for the SiFive HiFive Unmatched (FU740) and for the StarFive VisionFive 2 (JH7110). There is no K3 equivalent in this release.
  • mrbml-efi-riscv64_1.0_riscv64.deb — mr-bml 1.0, QSOE's own bootloader (an EFI application for RISC-V), as a Debian package for the board itself. It can load either variant and drives the boot menu on real hardware. A package rather than a bare binary because the image has to know where its configuration lives, which differs per machine: mrbml-install assembles it on the board, for that board's volume.
  • nvme.img.gz — a ready-to-run, self-booting QEMU disk image (GPT). Its EFI partition holds mr-bml, and an on-disk root holds both kernels — so QEMU boots straight to the mr-bml menu, no -kernel needed. The fastest way to see QSOE run; see Running under QEMU below.
  • virtio.img.gz — a companion root disk used only when running QSOE/L under QEMU (stock seL4 predates the interrupt controller QEMU's NVMe needs, so it mounts its root from a virtio disk instead). Not needed for QSOE/N or for real hardware.

In short: to run it in QEMU, grab nvme.img.gz (plus virtio.img.gz for QSOE/L) and see Running under QEMU. To put it on real hardware, you need the mr-bml package plus the kernels — QSOE/N uses skimmer-<board>.bin + modpkg.cpio, QSOE/L uses one of the qsoe-l-*.elf images — and see Installation.

Running under QEMU

The quickest way to see QSOE run — no hardware, no -kernel juggling. The nvme.img download is a self-booting UEFI disk: QEMU's firmware runs mr-bml from it, and mr-bml's menu starts either variant straight off the disk.

You need

  • qemu-system-riscv64 — version 11.0.1 or newer for QSOE/N (its NVMe needs the AIA interrupt controller).
  • edk2 RISC-V UEFI firmware — on Debian/Ubuntu, the qemu-efi-riscv64 package.
  • The launcher run-nvme.sh from the os repository — it wraps the right QEMU machine, firmware and disks for each variant, so you don't have to.

Run it

# unpack the image(s) — add virtio.img.gz only if you want QSOE/L
gunzip nvme.img.gz virtio.img.gz

# point the launcher at them and pick a variant from its menu
NVME_IMG=./nvme.img VIRTIO_IMG=./virtio.img ./run-nvme.sh

Pass n or l to skip the menu (./run-nvme.sh n). The script selects the matching QEMU machine automatically — QSOE/N on the AIA machine with an NVMe root, QSOE/L on the PLIC machine with the virtio root disk. The mr-bml menu and the system console both appear on your terminal; choose a variant and it boots to a login: prompt. Log in as root with password QSOE.

Installation

Real hardware, real disk. QSOE 0.3 boots on the SiFive HiFive Unmatched (FU740), the StarFive VisionFive 2 (JH7110) and the SpacemiT K3 Pico-ITX; on the K3, QSOE/N only. This assumes a board already running Linux — you'll be placing files on its existing EFI and boot partitions, so familiarity with the board's firmware is expected.

The boot model is simple: mr-bml lives in the EFI System Partition; it reads its menu and the kernels from an ext2/3/4 partition; the chosen variant then mounts its own root from a fs-qrv partition.

Steps

  1. On the board's Linux, apt install ./mrbml-efi-riscv64_1.0_riscv64.deb and run mrbml-install: it reads the label of the filesystem /boot is on, assembles an image that finds that volume by label, and places it in the ESP at EFI/BOOT/BOOTRISCV64.EFI (the UEFI removable-media path; a displaced loader is saved once as .bak). mrbml-install(8) has the explicit --root-label / --prefix forms.
  2. On your boot/root filesystem, create /boot/qsoe/ and copy the kernels there: your board's skimmer-<board>.bin + modpkg.cpio for QSOE/N, qsoe-l-<board>.elf for QSOE/L.
  3. Create /boot/mr-bml/mr-bml.cfg with one entry per variant — for example:
# /boot/mr-bml/mr-bml.cfg  — adjust the mainfs= partition to your disk
menuentry 'QSOE/N (Skimmer)' {
    kernel /boot/qsoe/skimmer-sifive.bin mainfs=/dev/nvme0n1p8
    modpkg /boot/qsoe/modpkg.cpio
}
menuentry 'QSOE/L (seL4)' {
    kernel /boot/qsoe/qsoe-l-sifive.elf mainfs=/dev/nvme0n1p8
}

The mainfs= device names the partition holding the QSOE root filesystem (fs-qrv) — set it to whichever partition you've devoted to QSOE on your board. On real hardware there is no QEMU virtio split: both variants drive the NVMe disk directly.

Building from source

QSOE is built with a riscv64-linux-gnu- cross toolchain (rv64gc) and a stock make; QEMU is handy for testing. The umbrella repository orchestrates the build and pulls in the component repositories that match its release tag.

git clone https://gitlab.com/qsoe/os
cd os
make prepare   # fetch the components for this tag (see component.list)
make           # build both variants: QSOE/N, then QSOE/L
make dist      # optional: the QEMU disk images (nvme.img.gz, virtio.img.gz)

QSOE/L additionally shallow-clones the seL4 kernel during make prepare. The build produces exactly the files on the Downloads list. The whole tree is Apache-2.0; the source lives under gitlab.com/qsoe.

Documentation

The QSOE manuals, published as PDF alongside the releases:

  • Design.pdf — the architecture: the two-kernel model, taskman, the IPC and resource-manager design.
  • UserGuide.pdf — installation, the shell, the basic commands, the text editor and the utilities.
  • ProgrammingBook.pdf — programming for QSOE, including the Resource Server Framework chapter.
  • AppPortingGuide.pdf — porting Unix (and QNX) software to QSOE: what to account for — no fork(), no brk(), select() via poll(), ioctl() via devcontrol(), and the rest.
  • Networking.pdf — QSP, the transparent distributed networking: stations and call signs, circuits and transactions, and why a resource manager reached across the wire is never told that anything happened.
  • LibcReference.pdf — the C library reference. A delta rather than a complete reference: the functions libc gained since 0.1, grouped by subject, in the entry shape a QNX reader already knows — with, since 0.3, a chapter for the new release and an appendix that compiles SQLite against QSOE and lists exactly what it finds missing.
Roadmap

It is often said that the Linux kernel has no roadmap. QSOE does — the releases that carry it from today's 0.3 to 1.0 are mapped out, feature by feature. A working plan, not a contract: milestones shift as the work reveals what is really next, and they have.

1.0 is a capability rather than a compatibility claim: a RISC-V real-time operating environment with a stated, measured worst-case latency, sustained for a week under full load across three different boards, able to rebuild itself, with a documented porting path from QNX and POSIX. Four criteria, each pass or fail.

  • 0.1 — Foundation and login. Both kernels boot to an interactive shell on one shared, dynamically linked userspace; read-only fs-qrv at /usr, spawn from disk, getty and login. Sources opened under Apache-2.0. (released June 2026)
  • 0.2 — Video console and QSP. A text console on a handed-over graphics controller with a USB keyboard on it, and QSP transparent distributed networking over a shared descriptor ring. The system stops being something observed over a serial cable and becomes something a person sits at. (released September 2026 — release notes)
  • 0.3 — Writable filesystem. qrvfs writes: create, unlink, truncate, rename, symbolic links; checked by fscheck before every mount and proven by a stress that fills the disk and reads every byte back. With it: taskman as the loader sharing one copy of a library's text, identity that reaches every server, the VisionFive 2, and QSOE/L on every hart. A disk that is only read can afford to be approximate; a disk that is compiled on cannot — and 0.6 compiles on it. (current — release notes)
  • 0.4 — Sound out: deva-hdmi. HDMI audio brought up as a device. Audio is the instrument for every measurement from here to 1.0 — a dropped buffer is audible long before it is visible — which is why it comes this early.
  • 0.5 — The real-time package. Priorities, interrupt service threads, priority inheritance and bounded paths end to end: up to N hard-real-time tasks on an N-CPU system, with every step between an interrupt and the thread that services it accounted for.
  • 0.6 — Self-hosting. The compiler runs on the target, against the writable filesystem, and rebuilds QSOE from source on the board.
  • 0.7 — Hardening, and the first long run. Leak hunts, lifetime and teardown, error paths nobody has taken — everything the soak will break, broken deliberately first. Then 24 hours of continuous audio under sustained multi-core load with live NVMe and Ethernet traffic.
  • 0.8 — The number. The week-long soak, and the worst-case latency figure it earns — published with its conditions, its methodology and its instrumentation, so the result can be reproduced and argued with from outside the project.
  • 0.9 — The porting set. A named set of QNX and POSIX programs recompiled and running, with two documented edits: fork → posix_spawn and select → poll.
  • 1.0 — QSOE. All four criteria met on every supported board.

Throughout: both kernels advance together — the userspace is identical by construction, NQ leads on the real-time path and LQ follows where the seam can express it. Platforms at 1.0 are the SiFive Unmatched (FU740), the SpacemiT K3 Pico-ITX, the StarFive VisionFive 2 and QEMU virt — three different SoCs with three different Ethernet controllers, speaking one protocol to each other. Packaging is deliberately not a 1.0 milestone; documentation is a release gate.

Other projects

Earlier and adjacent work.

  • GateMate PC — a personal computer built on the Cologne Chip GateMate FPGA.
  • GateMate System/359 — an IBM S/360-inspired FPGA implementation of a computing system, with I/O channels and a powerful macroassembler.
  • QRV — a QNX port to RISC-V (historical); fed hardware bring-up lessons into QSOE/N.

Services

Consulting and development in low-level and systems software.

  • Microkernel-based operating systems
  • System libraries and low-level runtime
  • Virtualization for real-time applications
  • RISC-V systems bring-up
  • AI-assisted development for FPGAs

Engagements range from focused bring-up work to longer-term architecture and implementation. Get in touch to discuss scope.

About

QSOE Systems is the independent practice of Yuri Zaporozhets, a systems software developer with 25+ years of experience building low-level software — kernels, operating systems, runtimes, and the hardware bring-up underneath them.

Contact

Email is the best way to reach me.

yuriz@qsoe.net