{"id":51279425,"url":"https://github.com/splch/honk","last_synced_at":"2026-06-30T00:32:20.693Z","repository":{"id":361966179,"uuid":"1255570408","full_name":"splch/honk","owner":"splch","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-06T23:48:13.000Z","size":807,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-30T00:32:19.377Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://splch.github.io/honk/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/splch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"docs/ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-01T01:18:59.000Z","updated_at":"2026-06-06T22:49:13.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/splch/honk","commit_stats":null,"previous_names":["splch/honk"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/splch/honk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/splch%2Fhonk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/splch%2Fhonk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/splch%2Fhonk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/splch%2Fhonk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/splch","download_url":"https://codeload.github.com/splch/honk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/splch%2Fhonk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34948227,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-29T02:00:05.398Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-30T00:32:19.979Z","updated_at":"2026-06-30T00:32:20.678Z","avatar_url":"https://github.com/splch.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# honk\n\n```\n   __     honk\n \u003e(o )___   pure-Go RISC-V64 OS\n  (  ._\u003e /  HS-mode under OpenSBI\n   '---'\n```\n\n**honk is a modern, multiprocess, SMP RISC-V 64 operating system written entirely in Go** — and it is also a Type-1 hypervisor. It boots in HS-mode under OpenSBI on QEMU `virt`, brings every hart up as a real Go scheduler `M`, runs first-party apps as goroutines and untrusted apps as WebAssembly, serves a verified immutable core over a writable log-structured store, talks TCP/IP and HTTP, drives a framebuffer GUI, and hosts guest VMs through the RISC-V H-extension.\n\nThe design rule is one sentence:\n\n\u003e **Map operating-system concepts onto Go language primitives, and write low-level code only where the hardware genuinely requires it.**\n\nThe Go runtime is the scheduler and memory manager, the type system is the isolation boundary, WebAssembly is the untrusted-code sandbox, and channels / interfaces / `io/fs.FS` are the IPC, driver, and filesystem models. What is left to write by hand is small: hart bring-up, device drivers, and — only for hosting full guests — paging.\n\nA second rule follows: **where the choice is invent-vs-plug-in, plug in.** WASI over a custom ABI, Linux guests over toy guests, signed image updates over plugins — because honk's capability and immutability discipline is exactly what makes the ecosystem-friendly choice *safe*.\n\n## Why this works (it's proven, not speculative)\n\n- **[Biscuit](https://github.com/mit-pdos/biscuit)** (MIT, OSDI '18) — a full multicore POSIX kernel in Go, GC cost ≤13% of kernel CPU. Proves Go drivers, Go SMP, and Go-as-kernel-language.\n- **[eggos](https://github.com/icexin/eggos)** — a Go x86 unikernel: \"no processes, only goroutines and channels.\" Proves the goroutine-as-process model.\n- **[TamaGo](https://github.com/usbarmory/tamago)** — runs unmodified Go on bare-metal RV64 with the full stdlib. honk's foundation; honk does not re-create the runtime/GC/scheduler.\n- **[wazero](https://github.com/tetratelabs/wazero)** — a pure-Go, zero-dependency WebAssembly interpreter designed to embed where there is no OS. honk's untrusted sandbox.\n\nhonk's novelty is combining these into the first pure-Go, RISC-V, SMP, genuinely-multiprocess, immutable OS that is also a hypervisor.\n\n## Status\n\nhonk is built milestone by milestone, each verified in QEMU before the next. **M0–M12 are complete and verified; every M13 mechanism is proven** against hand-rolled guests — the remaining M13 work is integrating a real Linux/rCore guest.\n\n| Phase | Milestones | State |\n|---|---|---|\n| **A — foundation** | M0 boot + SMP · M1 IRQ/console/shell · M2 process model | ✅ complete |\n| **B — storage** | M3 NVMe/virtio-blk · M4 KV store + VFS · M5 immutable signed core (A/B) | ✅ complete |\n| **C — networked OS** | M6 virtio-net + gVisor → stdlib `net`/`net/http` · M7 WASM/WASI (wazero) · M8 host files (9p) | ✅ complete |\n| **D — display/GUI** | M9 virtio-gpu framebuffer · M10 virtio-input + `image/draw` toolkit | ✅ complete |\n| **E — hypervisor** | M11 H-ext bring-up · M12 timer + preemptible vCPU · M13 real Linux guest | ✅ M11–M12; **M13 mechanisms proven** |\n\nSee [`docs/STATUS.md`](docs/STATUS.md) for the living, per-milestone record of what is implemented and exactly how each piece is verified.\n\n## Quickstart\n\n**Requirements:** a host Go toolchain and `qemu-system-riscv64`. The forked Go distribution (`tamago-go`) is auto-built on first use into your OS cache dir. (`python3` enables the headless framebuffer/GUI pixel checks; `curl` is used by the networking smoke test.)\n\n```sh\nmake run        # build + boot under QEMU virt (quit with Ctrl-A x)\nmake test       # host -race tests of every pure-Go package\nmake smoke      # build + boot + assert M0–M12 behavior (the CI gate)\nmake phase-a    # M0/M1/M2 acceptance: race tests + a QEMU boot matrix\nmake vet        # go vet under the tamago toolchain\n```\n\n`make run` defaults to `-smp 4 -m 512M`, attaches NVMe + virtio-blk + virtio-net (`:80` forwarded to host `:8080`) + virtio-gpu + keyboard/tablet, and shares `./share` into honk over 9p. Booting drops into an interactive shell:\n\n```\nhonk: HS-mode boot ok  hart=0  dtb=0x9fe00000\nhonk: SMP up  harts=4  GOMAXPROCS=4\nhonk: SMP OK - goroutines ran on 4/4 harts [0 1 2 3]\n\nhonk: shell ready (type 'help')\nhonk\u003e\n```\n\nShell commands:\n\n```\nhelp  harts  uptime  mem  echo \u003ctext\u003e\nrun [name]   ps   kill \u003cpid\u003e   crash   reap   stress [n]\nls [dir]   cat \u003cfile\u003e   cp \u003csrc\u003e \u003cdst\u003e   put \u003ckey\u003e \u003ctext\u003e   rm \u003cfile\u003e\nblk  net  mount  wasm \u003cfile.wasm\u003e  fb  ui\nvm [timer|paging|dbcn|mmio|irq|virtio]   reset --confirm   fault   exit\n```\n\nWith the defaults, `curl http://localhost:8080/` reaches honk's HTTP server, and files in `./share` appear inside honk (`mount`, `ls`, `cat`).\n\n## The design in one table\n\nThis is the whole system. Each row is something a traditional kernel writes thousands of lines for, replaced by a language feature honk already has.\n\n| OS concept | honk uses |\n|---|---|\n| Process / thread | **goroutine** (M:N across harts by the Go scheduler) |\n| Lifecycle / kill | **`context.Context`** — cancel = kill, `Done()` = reaped |\n| Scheduler | **the Go runtime** — `GOMAXPROCS = nharts` |\n| Per-process address space | **the type system + capabilities** (no MMU for native code) |\n| Fault containment | **`recover()`** at the goroutine boundary |\n| IPC | **channels**, `io.Pipe`, stdlib `net` |\n| Syscalls (native code) | **direct calls on capability interfaces** — no ECALL, no ABI |\n| Untrusted-code sandbox | **WASM via wazero** — bounds-checked, capability-gated, force-killable |\n| Drivers | **Go interfaces** (`block.Device`, `NetworkDevice`, framebuffer…) |\n| Filesystem / VFS | **`io/fs.FS`** composition (KV store + embedded core + 9p host) |\n| Async device I/O | **a goroutine blocks on a channel the IRQ handler signals** |\n| 2D / GUI | **`image`, `image/draw`, `x/image/font`** |\n| Integrity / verity | **`crypto/sha256`, `crypto/ed25519`** + a small Merkle tree |\n| Concurrency correctness | **`go test -race`**, the Go memory model |\n\n**Three isolation tiers**, trust matched to mechanism:\n\n1. **Goroutines** — first-party signed code. Memory safety + capabilities + `recover()`; bugs panic, not exploit.\n2. **WASM modules** — untrusted/dynamic/any-toolchain code in wazero. Every WASI call is capability-gated (implementing a host function ≠ granting it); force-killable via `context`.\n3. **Guest VMs** — full OSes under the H-extension with two-stage paging. **The only place honk uses page tables.**\n\nThe full table, the trust model, and the reuse-vs-write accounting are in [`docs/HONK.md`](docs/HONK.md).\n\n## Repository layout\n\n```\nhonk/\n├── block/          # block.Device interface, Slice partitioning, Memory test device (pure Go)\n├── board/virt/     # the only hardware-touching code (QEMU virt):\n│   │               #   HS-mode cpuinit + runtime/goos overlay, SMP (SBI HSM),\n│   │               #   S-mode traps, PLIC/UART console, NVMe/PCIe,\n│   │               #   one virtio-mmio transport under blk/net/9p/gpu/input,\n│   │               #   and the H-extension VMM (world switch + G-stage paging)\n│   └── ring/       #   SPSC console-input ring (host-tested)\n├── kernel/         # the HS-mode Go program — the OS logic, mostly pure Go:\n│   │               #   main/shell/net/wasm/display/ui/vm/fsmount\n│   ├── proc/       #   process model (goroutine + context + caps + recover)\n│   ├── kv/         #   crash-safe log-structured key/value store\n│   ├── vfs/        #   io/fs.FS synthesis + union overlay\n│   ├── image/      #   signed, Merkle-tree'd immutable core + A/B slots\n│   ├── p9/         #   read-only 9P2000.L client → io/fs.FS\n│   ├── gui/        #   retained-mode image/draw toolkit\n│   ├── vmm/        #   pure, host-tested VMM core (RV64 assembler, guest payloads, page tables)\n│   └── core/       #   files baked into the verified core image\n├── tools/          # build.sh, mkboot (boot trampoline), mkimage (sign images),\n│                   #   run-qemu.sh, smoke-test.sh, phase-a-test.sh, screendump/uitest\n└── docs/           # HONK.md  STATUS.md  OS.md  GO.md  RV64.md\n```\n\n## How it boots\n\nhonk targets QEMU `virt` and boots as an **HS-mode payload under OpenSBI** (`-bios default`) — the mainline RISC-V model and the prerequisite for the hypervisor. Three things TamaGo doesn't do out of the box are solved in `board/virt`:\n\n1. **HS-mode startup, no M-mode CSRs.** honk supplies its own `cpuinit` (`boot_riscv64.s`) and the full `runtime/goos` overlay, so OpenSBI keeps the M-mode CSRs it owns.\n2. **The fw_dynamic entry quirk.** QEMU enters the payload at the load *base*, not the ELF entry. `tools/mkboot` emits a 24-byte trampoline at `0x80200000` that jumps to honk's real entry; honk links at `0x80400000` to clear it.\n3. **SMP without a runtime fork.** Secondary harts start via SBI HSM `hart_start` into a park loop; the runtime's `goos.Task` hook hands each one a stack + g0 + `mstart`. Then `GOMAXPROCS = nharts`.\n\n`RamSize` is discovered from the DTB pointer (OpenSBI/QEMU place the DTB at the top of usable RAM), so any `-m` works with no FDT parsing. Hardware details consulted only where they touch silicon are collected in [`docs/RV64.md`](docs/RV64.md).\n\n## Testing \u0026 quality gates\n\nhonk splits correctness by where its authority lives:\n\n- **Pure-Go logic → host `go test -race`.** The process state machine, the SPSC console ring, the KV store (incl. a 600-op crash-consistency property test), the VFS overlay, image verity, the 9P client, the GUI toolkit (rendered pixels and all), and the VMM's encoders/page-tables/guest payloads are all exercised on the host — authoritative for concurrency and the \"works-on-QEMU/silent-fault\" bug class.\n- **Hardware-contact behavior → QEMU.** `make smoke` boots honk and asserts M0–M12 end to end across both block backends, networking (a real `curl`), the framebuffer and GUI (captured headlessly over QMP), and every `vm` demo. `make phase-a` is a dedicated foundation gate (SMP 1/4/8, RAM 256M–2G, the fatal-trap path, the live process model).\n\nCoding standards and the idioms honk holds itself to are in [`docs/GO.md`](docs/GO.md).\n\n## Scope \u0026 honest non-goals\n\nhonk is a focused appliance, not a general-purpose UNIX. By design:\n\n- **`io/fs.FS` composition, not POSIX** — whole-value writes, no partial write/append/rename/mmap/metadata; `Open` materializes a whole file.\n- **Polled, serialized device I/O** — the IRQ-driven fast path is the same deferred async-I/O item across all virtio drivers.\n- **QEMU `virt` first** — minimal PCIe/NVMe, reliance on coherent DMA; real-silicon caveats (A/D bits, fences, cache maintenance) are tracked, not yet exercised.\n- **The hypervisor's M13 deliverable** — loading a real third-party kernel image, a full guest device tree, PLIC/AIA, virtio-fs, and time-sharing a hart — is the remaining integration work; the mechanisms it stands on are done.\n\n## Footprint — the \"fewest lines\" accounting\n\nThe original Go honk maintains is small because the language already is an OS (gVisor, wazero, and the stdlib are upstream and unmodified):\n\n- **Networked appliance (M0–M8):** ~4,000–5,000 lines, most of it device drivers and the SMP hook — the pure OS-mechanism code (process table, caps, VFS) is ~1.5k.\n- **+ GUI (M9–M10):** ~+1,300 lines.\n- **+ Hypervisor (M11–M13):** ~+6,000–8,500 lines — the one component where hardware virtualization can't be a language feature.\n\nA C/Rust equivalent is six figures.\n\n## Documentation\n\n| Doc | What it is |\n|---|---|\n| [`docs/HONK.md`](docs/HONK.md) | The full design: the mapping, architecture, reuse-vs-write, roadmap, risks. |\n| [`docs/STATUS.md`](docs/STATUS.md) | Living build status — what is implemented and verified, milestone by milestone. |\n| [`docs/RV64.md`](docs/RV64.md) | Build-oriented RISC-V 64 reference (boot, SBI, traps, paging, virtio, H-ext). |\n| [`docs/GO.md`](docs/GO.md) | Go language rules + modern idioms and the quality bar honk holds. |\n| [`docs/OS.md`](docs/OS.md) | What a modern OS is for; the small-TCB, memory-safe-kernel thesis. |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsplch%2Fhonk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsplch%2Fhonk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsplch%2Fhonk/lists"}