Skip to content

Boot from /dev/vda by default#134

Merged
jserv merged 1 commit intomasterfrom
rework-initrd
Apr 28, 2026
Merged

Boot from /dev/vda by default#134
jserv merged 1 commit intomasterfrom
rework-initrd

Conversation

@jserv
Copy link
Copy Markdown
Collaborator

@jserv jserv commented Apr 28, 2026

Boot Linux directly from a virtio-blk ext4 image instead of unpacking an initramfs cpio archive. The new path skips the unpack_to_rootfs RCU stall and shortens guest boot. Add ENABLE_EXTERNAL_ROOT=0 to fall back to the legacy initramfs path; auto-fall back when fakeroot is unavailable.

Also:

  • Add -H/--headless so make check and benchmark scripts can run without an SDL window.
  • Wire an atexit msync hook in virtio-blk so MAP_SHARED pages reach disk on graceful shutdown.
  • Source prebuilt Image and rootfs.cpio from the GitHub releases endpoint and detect stale artifacts via PREBUILT_INPUTS_SHA1. Cache key in main.yml hashes every input that defines the prebuilt content so CI does not silently restore stale artifacts.
  • New prebuilt.yml workflow republishes the release whenever any PREBUILT_INPUTS file changes.
  • Move clang-format and prebuilt manifest logic out of inline shell into .ci/suggest-format.sh and .ci/publish-prebuilt.sh.
  • Cap -c hart count to [1,32] (matches plic_state_t.ie[] dimension) with strtol-based validation.
  • Check vm->hart calloc result, free wake_fd[] on realloc failure, call coro_cleanup() on normal SMP exit.
  • Install SIGINT/SIGTERM handlers via sigaction (no SA_RESTART) so poll() returns EINTR; signal handler also writes to wake_fd[1] so the threaded VIRTIOINPUT path wakes up and runs atexit hooks.

Summary by cubic

Boot Linux from /dev/vda (virtio‑blk ext4) by default to skip initramfs unpack, avoid the RCU stall, and speed up boot. Adds a headless mode and safer shutdown so disk writes flush on exit.

  • New Features

    • Default root on /dev/vda; ext4.img is built from rootfs.cpio via scripts/rootfs_ext4.sh. Auto‑fallback to the legacy initramfs path when fakeroot is unavailable or unusable. -i now requires ENABLE_EXTERNAL_ROOT=0 or a DTB that advertises linux,initrd-*.
    • -H/--headless runs without an SDL window (used by make check and CI).
    • Safer shutdown: virtio‑blk msyncs MAP_SHARED pages at exit; SIGINT/SIGTERM handled via sigaction and a wake pipe so loops break and atexit hooks run.
    • CLI hardening: -c hart count validated to 1–32; better allocation cleanup; coro_cleanup() on normal SMP exit; DTB bootargs updated for vda boot and quieter logs.
    • Prebuilts: fetched from the repo’s blob branch; mk/external.mk compares PREBUILT_INPUTS_SHA1 to detect stale artifacts. prebuilt.yml and .ci/publish-prebuilt.sh publish a rolling prerelease and CI cache keys hash all inputs. A CI job keeps the legacy initramfs path tested.
  • Bug Fixes

    • Pin PREBUILT_INPUTS_SHA1 to the current inputs so stale-prebuilt detection is active.
    • Guard /dev/vda bootargs on both EXTERNAL_ROOT and VIRTIOBLK.
    • virtio-blk: check fstat() return and reject empty/invalid disk sizes.
    • scripts/bench-login.expect: use Tcl list expansion (spawn {*}$argv) to pass args safely.
    • Makefile: detect non‑functional fakeroot via a real exec (fakeroot /bin/sh -c :) so macOS arm64e falls back to initramfs automatically.

Written for commit eb6705c. Summary will update on new commits. Review in cubic

cubic-dev-ai[bot]

This comment was marked as resolved.

jserv added a commit that referenced this pull request Apr 28, 2026
Findings identified by cubic on PR #134:
- mk/external.mk: PREBUILT_INPUTS_SHA1 was the all-zero placeholder, so
  the stale-prebuilt detection silently skipped every comparison. Pin
  it to the SHA1 of the current PREBUILT_INPUTS concatenation; once the
  Publish prebuilt images workflow runs and refreshes the artifacts,
  bump this value alongside KERNEL_DATA_SHA1 / INITRD_DATA_SHA1.
- minimal.dts: Guard the /dev/vda bootargs on SEMU_FEATURE_VIRTIOBLK in
  addition to SEMU_FEATURE_EXTERNAL_ROOT. The Makefile already forces
  VIRTIOBLK on whenever EXTERNAL_ROOT is enabled, but the dts is the
  contract guests rely on -- a defensive guard prevents a future
  feature-flag rearrangement from emitting a root=/dev/vda command line
  that has no backing device.
- virtio-blk.c: Check the fstat() return before reading st.st_size.
  Failure leaves st uninitialized, so the existing st_size <= 0 guard
  was reading indeterminate memory.
- scripts/bench-login.expect: Replace `eval spawn $argv` with the Tcl
  list-expansion form `spawn {*}$argv` so each argv element is passed
  verbatim instead of being re-split through eval's parser.

Also fix the macOS CI failure introduced by the new EXTERNAL_ROOT path.
The Makefile detected fakeroot via `command -v` only, but the brew
fakeroot 1.37.2 dylib on Apple Silicon is built for arm64 while the
macOS runner's bash and mkfs.ext4 are arm64e -- DYLD_INSERT_LIBRARIES
fails to load and `fakeroot true` aborts at runtime. Switch the probe
to `fakeroot true` so a non-functional install also falls back to the
initramfs path instead of dying inside scripts/rootfs_ext4.sh.
Boot Linux directly from a virtio-blk ext4 image instead of unpacking an
initramfs cpio archive. The new path skips the unpack_to_rootfs RCU
stall and shortens guest boot. Add ENABLE_EXTERNAL_ROOT=0 to fall back
to the legacy initramfs path; auto-fall back when fakeroot is
unavailable.

Also:
- Add -H/--headless so make check and benchmark scripts can run
  without an SDL window.
- Wire an atexit msync hook in virtio-blk so MAP_SHARED pages reach
  disk on graceful shutdown.
- Source prebuilt Image and rootfs.cpio from the GitHub releases
  endpoint and detect stale artifacts via PREBUILT_INPUTS_SHA1.
  Cache key in main.yml hashes every input that defines the prebuilt
  content so CI does not silently restore stale artifacts.
- New prebuilt.yml workflow republishes the release whenever any
  PREBUILT_INPUTS file changes.
- Move clang-format and prebuilt manifest logic out of inline shell
  into .ci/suggest-format.sh and .ci/publish-prebuilt.sh.
- Cap -c hart count to [1,32] (matches plic_state_t.ie[] dimension)
  with strtol-based validation.
- Check vm->hart calloc result, free wake_fd[] on realloc failure,
  call coro_cleanup() on normal SMP exit.
- Install SIGINT/SIGTERM handlers via sigaction (no SA_RESTART) so
  poll() returns EINTR; signal handler also writes to wake_fd[1] so
  the threaded VIRTIOINPUT path wakes up and runs atexit hooks.
@jserv jserv merged commit c722c11 into master Apr 28, 2026
12 checks passed
@jserv jserv deleted the rework-initrd branch April 28, 2026 01:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant