Every kernel entry point moves into assembly, and the installer arrives as one #14

Open
nonos-sync wants to merge 16 commits from nonos-sync/gh-471 into main AGit
Member

Every path from a running context into the kernel is now written out in assembly, one explicit entry per vector, instead of macro-generated naked functions scattered across Rust files. exceptions.S carries the eighteen exception and interrupt trampolines plus the page fault and timer entries; the timer body hands the shim the base of the saved register block, since its handler snapshots the whole user context of a preempted capsule. vectors.S carries the 56 numbered arch-layer gates and their shared save/dispatch body. The security-relevant instructions, when swapgs runs, what gets saved, how the FPU area is handled, are one file a reviewer reads top to bottom, and the Rust side keeps only declarations and the C shims that forward a frame to its handler. The scrub loop behind memory sanitization moves the same way.

On top of that surface sits the first cut of the proof-carrying installer, a capsule that is assembly from _start to the exit syscall. Rust contributes one translation unit that assembles the sources in dependency order and the panic contract, nothing else. The survey step lists the devices the hardware broker vouches for over MkDeviceList, the verdict step prints the boot chain's recorded attestation, flags and both 32-byte roots, over MkAttestStatus, and steps whose kernel service has not landed yet announce themselves pending so the seven-step ritual runs end to end today. The capsule links position independent, its tables store offsets rather than addresses, and its capset is exactly what the landed steps call: CoreExec, IO, IPC, Memory, DeviceEnum. An image built with its feature is a live installer image and spawns it at boot through the ordinary spawn plan.

The whole set boots to the desktop under QEMU: every interrupt in that session, timer preemption, keyboard, mouse, page faults, flows through the new entries.


Opened on GitHub by eKisNonos as pull request 471. Review and merge happen there while this repository is kept in step from GitHub; this copy follows it, and is marked merged or closed when it is.

Every path from a running context into the kernel is now written out in assembly, one explicit entry per vector, instead of macro-generated naked functions scattered across Rust files. exceptions.S carries the eighteen exception and interrupt trampolines plus the page fault and timer entries; the timer body hands the shim the base of the saved register block, since its handler snapshots the whole user context of a preempted capsule. vectors.S carries the 56 numbered arch-layer gates and their shared save/dispatch body. The security-relevant instructions, when swapgs runs, what gets saved, how the FPU area is handled, are one file a reviewer reads top to bottom, and the Rust side keeps only declarations and the C shims that forward a frame to its handler. The scrub loop behind memory sanitization moves the same way. On top of that surface sits the first cut of the proof-carrying installer, a capsule that is assembly from _start to the exit syscall. Rust contributes one translation unit that assembles the sources in dependency order and the panic contract, nothing else. The survey step lists the devices the hardware broker vouches for over MkDeviceList, the verdict step prints the boot chain's recorded attestation, flags and both 32-byte roots, over MkAttestStatus, and steps whose kernel service has not landed yet announce themselves pending so the seven-step ritual runs end to end today. The capsule links position independent, its tables store offsets rather than addresses, and its capset is exactly what the landed steps call: CoreExec, IO, IPC, Memory, DeviceEnum. An image built with its feature is a live installer image and spawns it at boot through the ordinary spawn plan. The whole set boots to the desktop under QEMU: every interrupt in that session, timer preemption, keyboard, mouse, page faults, flows through the new entries. --- Opened on GitHub by eKisNonos as [pull request 471](https://github.com/NON-OS/nonos-micro-kernel/pull/471). Review and merge happen there while this repository is kept in step from GitHub; this copy follows it, and is marked merged or closed when it is.
A wipe whose loop a compiler wrote is a wipe a compiler may reason
about, and dead store elimination erodes exactly the promise this
module exists to keep. The store loop is now scrub.S: rep stosb writes
the range, sfence orders it, and the audit surface of the promise is
four instructions. Fast string stores also run at near copy bandwidth,
which is what a shutdown scale sweep needs. Other architectures keep
the volatile walk until they grow their own routine.
Every entry from a running context into the kernel was a macro
generated naked function, readable only through its expansion. The
instructions now live in exceptions.S, the two bodies written once as
assembler macros and every vector an explicit one line instantiation
naming the shim it calls. What decides swapgs and saves the interrupted
state is a single file read top to bottom, assembled by the build like
the rest of arch asm.

The Rust side shrinks to declarations and forwards: entries declares
the vector symbols the IDT installs, and the shims read the frame and
call their handler, one justified unsafe for the whole module. The
five macro era files are gone.
New capsule app.nonos_install walks the seven step install ritual from
the design doc. The survey step lists the devices the broker vouches
for over MkDeviceList and the verdict step prints the boot chain's
recorded attestation over MkAttestStatus, flags and both 32 byte roots.
Steps whose kernel service has not landed yet announce themselves
pending and succeed, so the ritual frame runs end to end today.

The program is assembly from _start to the exit syscall, one unit
assembled in dependency order; Rust contributes the translation unit
and the panic contract. Capset is CoreExec, IO, IPC, Memory and
DeviceEnum, exactly what the landed steps call.
The page fault vector is the error-code body already in exceptions.S,
so it becomes one more TRAMP_ERR line with a shim that forwards the
frame and code. The timer wants the base of the saved register block
rather than the frame pointer, since its handler snapshots the whole
UserContext of a preempted capsule; TRAMP_CTX carries that difference
and everything else stays the shared body. The two Rust naked
functions are gone; the handler and EOI logic stay where they were.
The 56 arch-layer IDT gates and their shared save/dispatch body were
macro-generated naked functions across three files; they are now one
assembly file with an explicit line per vector. The gate bodies are
unchanged: zero pushed where the CPU pushes no error code, vector
number, shared body, ds/es switched to the kernel selector, frame to
interrupt_dispatch. The Rust files keep the declarations and the
dispatch function.
An image carrying nonos-capsule-nonos-install is a live installer
image; the ritual starts on the console at boot through the same
spawn plan every app uses.
The capsule links as a PIE and the tables held absolute addresses,
which the linker rightly refused. They now store offsets from their
own base, added back after a rip-relative load; lengths stay plain
constants. The redundant syntax directive goes too, global_asm is
already Intel.
fs.S speaks the ramfs wire protocol over service lookup and ipc call:
open, bounded read, close. Every reply must echo the request's own
sequence number, a success reply too short to carry its handle is
refused as a lying peer, and the copy out of the reply is bounded by
the caller's capacity, never by the peer's claimed count. The compose
step opens /install/set, echoes the set to the console so the
operator sees exactly what would be composed, and stops the ritual on
a medium that carries none, which is what a proof carrying installer
is for. No new capabilities; the existing IPC grant covers both
syscalls.
The dialect that assembles the capsule treats a label-difference
symbol as an address whatever the operand syntax says, and the first
console write faulted reading address 29, the banner's own length.
Lengths are now words emitted beside each string and loaded rip
relative, which means one thing in every assembler. The step and
flag tables already store offsets; with this the whole capsule is
free of symbolic immediates. Boot-proven: the capsule spawns,
attests, and walks the ritual under QEMU.
Mutating ops used to answer only the kernel client. They now also
answer a sender whose MkProcStat entry names app.nonos_install, looked
up on every request so a verdict can never outlive the installer's pid.
The decision itself is pure and host-proven: exact-name matching, the
read side untouched, and a Kani harness over every op and sender.
The drift check compares the committed inventory against the tree, and
the assembly entry surface moved files it counts.
This pull request can be merged automatically.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin +refs/pull/14/head:nonos-sync/gh-471
git switch nonos-sync/gh-471
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
NON-OS/nonos-micro-kernel!14
No description provided.