kernel is the policy-minimal microkernel core in the EriX boot chain.
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Erik Inkinen aa85648019
All checks were successful
CI / markdown (push) Successful in 14s
CI / test (push) Successful in 3m26s
chore: Merge native CLI development into main
Merge the selected feature/native-cli history with an explicit two-parent commit so main retains the development lineage and the validated source snapshot. The resulting tree is identical to the selected feature commit; no dependency pins or runtime behavior are changed by this merge.

Previous main: 539b4418ac
Selected feature: 4330175e27

Publish this integration point following the requested cross-repository merge. Preserve the feature branch and immutable dependency objects for reproducibility; do not squash, rebase or rewrite existing commits.
2026-09-12 08:28:44 +03:00
.github build: Pin dependency and CI helper source commits 2026-09-12 07:47:22 +03:00
src fix: Support both Rust CPUID intrinsic contracts 2026-09-12 08:06:36 +03:00
.editorconfig Initial commit 2026-02-26 17:46:35 +01:00
.gitignore Ignore local .ci workspace 2026-04-15 21:52:44 +03:00
.markdownlint-cli2.yaml Tighten CI markdown policy 2026-05-22 15:10:06 +03:00
ARCHITECTURE.md fix: Support both Rust CPUID intrinsic contracts 2026-09-12 08:06:36 +03:00
Cargo.toml build: Pin dependency and CI helper source commits 2026-09-12 07:47:22 +03:00
CODE_OF_CONDUCT.md docs: Synchronize shared contribution and review policies 2026-09-12 06:38:12 +03:00
CONTRIBUTING.md build: Pin dependency and CI helper source commits 2026-09-12 07:47:22 +03:00
LICENSE Initial commit 2026-02-26 17:46:35 +01:00
linker.ld Prepare kernel dynamic relink entry 2026-05-24 19:13:46 +03:00
README.md perf: Traverse live mapping chunks directly 2026-09-12 04:47:58 +03:00
ROADMAP.md perf: Traverse live mapping chunks directly 2026-09-12 04:47:58 +03:00
rustfmt.toml kernel: drop unstable rustfmt options for stable toolchains 2026-03-23 10:19:52 +02:00
SECURITY.md docs: Synchronize shared contribution and review policies 2026-09-12 06:38:12 +03:00

EriX Kernel

kernel is the policy-minimal microkernel core in the EriX boot chain.

EriX is a clean-room, capability-based microkernel operating system written entirely in Rust.

Technical requirements are tracked in the EriX requirements, conventions, and project documentation.

See:

  • docs for design documents, specifications, and development plans.
  • Related architecture repositories for kernel, services, libraries, drivers, and integration tooling.

Purpose of This Repository

The existing time-control endpoint returns boot-calibrated processor elapsed time in nanosecond ticks, never query-count progress. Its source is anchored once on the bootstrap CPU; unsynchronized AP reads, missing calibration, counter reversal and conversion overflow fail with zero response metadata. This does not add time authority or widen the current BSP-local userspace scheduling domain.

Caller-local syscall 0x49 derives a revocable SEND-only endpoint alias from an already-owned exact SEND endpoint. It accepts only two distinct empty local destinations, never a target process or foreign CSpace. The revoker follows the derived alias through normal copies and IPC replies, but cannot revoke the original source. Existing staged install and staged revocation guards continue to reject started targets.

Read-only syscall 0x4A exposes only the live actual caller of a delivered pending CALL to its authenticated recorded receiver with local RECV authority. Its process ID and generation match staged-process creation evidence; forwarded SEND aliases do not impersonate their original holders. The query consumes no pending state and grants no capability or process-discovery authority.

This repository implements the EriX kernel component. Its purpose in EriX is to provide the minimal capability kernel substrate for user-space services.

Functionally, it owns kernel memory, scheduling, interrupt, and capability primitives while keeping policy in user space. The repository keeps the implementation, interface contracts, tests, and documentation for that behavior in one reviewable ownership boundary.

The maintained responsibilities are:

  • provide process, memory, interrupt, IPC, and capability primitives
  • keep policy in user-space services wherever possible
  • maintain the system-call and authority boundaries used by the rest of EriX

Clean-Room Policy

EriX follows a strict clean-room philosophy:

  • No external source code may be copied.
  • No external Rust crates are allowed.
  • No code generation tools that embed third-party code.
  • All code must be authored within the project.

Violations will result in rejection of the contribution.

License

All EriX repositories are licensed under the ISC License.

Development Model

EriX development is modular, deterministic, reproducible, authority-explicit, security-first, and self-hosting oriented.

This repository follows the project roadmap and the validation rules documented in its own roadmap.

Build Status

Current implementation status:

  • strict bl -> kernel ingress wrapper and deterministic kernel markers
  • length-delimited bootloader handoff ingress whose externally supplied byte length must equal the serialized header length before variable tables are parsed
  • memory reservation extraction and usable-RAM extent derivation
  • bootstrap object/capability setup for root CSpace/VSpace/TCB/endpoint and the single RAM allocator domain
  • kernel -> root handoff builder with lib-handoff validation roundtrip
  • default kernel bootstrap path selects required root module and attempts CPL3 root launch
  • root launch records required boot-provided metadata blobs as read-only root VSpace grants so rootd can validate boot-config, dynamic-link manifests, and early dynamic object bundles before filesystem services exist
  • a dedicated, non-delegatable root endpoint performs one no-input retirement of that exact kernel-recorded boot-blob set: all page-table preparation precedes PTE retirement and TLB invalidation, while rootd's executable image remains mapped and catalog/table/endpoint sources are consumed. The dedicated console endpoint may transfer exact read-only font backing to fbcond; root access is still removed and no unrelated VSpace inherits that backing
  • bootloader dynamic catalog ingress validation enumerates signed boot-image executables, shared objects, segment permissions, source ranges, hashes, and dependency edges before root startup; catalog and mapping records grow from reclaiming kernel-reserved memory instead of imposing parallel object, segment, shared-backing, or process-mapping caps
  • early ELF graph discovery also stores program-load records, dependency offsets, and discovered objects in fallible heap collections, so valid dependency graphs are constrained only by explicit identifier/address-space bounds and available kernel-owned memory
  • root handoff bytes are copied into a zeroed, page-aligned, exact-span heap allocation rather than a fixed 64 KiB static buffer; root receives read-only access to those pages, while its independently allocated bootstrap stack is the only writable launch region; both grants are represented in VSpace metadata, nested syscall pointers are accepted only through those explicit rights, and launch failure revokes every registered range before releasing storage; serialization checks every wire-width conversion and reserves the complete output fallibly
  • memory-map reservations and RAM extent subtraction grow through checked kernel-heap reservations, so valid firmware maps neither reach allocation abort paths nor disappear behind an implementation-specific record ceiling
  • production catalog installation is one-shot, mapping storage is reserved before page/backing mutation, relocation metadata commits only after its VSpace write, and process cleanup revokes mapped pages before forgetting their records or shared-backing references
  • VSpace objects, aliases, explicit user/physical ranges, and device-frame bindings all grow fallibly from reclaiming kernel memory; released VSpace identifiers are reused, and record/capability creation rolls back atomically on failure instead of imposing bootstrap-era table ceilings; mapping, kernel-owned user-range, and physical-range authority cannot overlap
  • per-page VSpace mapping records use dense 256-entry chunks rather than a geometrically growing flat allocation, so staging large ext4-backed dynamic executables never requires old and doubled mapping tables to coexist in the kernel heap; each mapping-data allocation is bounded to 20 KiB and teardown still retires every exact page record and backing reference
  • activation/restoration traverse read-only chunk slices directly, retaining pending updates across storage chunks and ignoring reserved empty chunks. Every live mapping check, permission barrier, 64-update boundary and error remains ordered; neither chunk boundaries nor traversal create authority, additional flushes or persistent mapping state
  • mapping tables retain one last-full-search index for fresh validation/copy cursors, checked against the live bound and exact page under the existing VSpace lock. Only a first-match scan replaces this table-owned hint; mutable record access, removal, and clear invalidate it, while local/neighbor cursor hits retain their original behavior. New/cloned tables start cold, and rights, ownership, and backing are never cached. Host lookup tests and an explicit bounded cost experiment do not establish a guest speedup
  • managed frames of at most 64 aligned pages select their lowest unused page in the same current-mapping pass that searches for an existing exact virtual address, using a temporary occupancy bitmap. An existing address retains first-match priority; a new-page selection error remains deferred until the original overlap and storage-reservation checks. Exact frame identity and physical address remain authoritative; aliases share occupancy, holes are reused, and no bitmap survives the call. Larger or noncanonical allocations retain the original selection/error path; device frames, rights checks, backing retention, and page-table policy are unchanged. The allocator-domain selftest adds a private 64-page alias/full/ hole-reuse proof with physical byte readback and exact cleanup before its managed-frame success marker. Host tests are not a VM speedup claim
  • physical-page and anonymous-shadow VSpace switches apply up to 64 exact mappings per interrupt-masked page-table batch, with local TLB flushing even on preparation failure and explicit invalidation of GLOBAL translations. Aliases preserve their original flag/backing policy; dependent backing translations or repeated targets start a new flushed group to retain sequential semantics. Exact group-local target lookup and borrowed prepared leaves avoid repeated prefix scans and whole-array copies without caching authority. Strictly ascending targets, including gaps, avoid hashing: contiguous prior addresses use an exact interval; in-range backings after a gap use binary search of the actual prior targets. Duplicate/decreasing targets retain the original lookup path, without changing any dependency or flush boundary. Activation/restoration builders select their constant mode once while still reading every live mapping's rights, backing and saved entry. Inlined hardware preparation removes per-leaf aggregate return shuffling while preserving the same live reads, group boundaries, and flushes. Bounded staging initializes only the used prefix of Copy leaves and reads it only after every preparation succeeds, removing redundant empty tags. Partial failure never reads that prefix and retains the existing flush; host trace/codegen evidence is not matching-image performance acceptance. A staged leaf keeps its complete entry and exact target address, using only the validated address's zero bit 0 for old-or-new GLOBAL invalidation. The hardware key is checked non-null when resolving a new PT span; neither pointer bits nor authority are encoded in the address flag. Independent untagged-oracle tests cover address/entry integrity and ordered failures. Group-local target and non-huge backing PT-span hints avoid repeated ancestor walks while every leaf and alias backing remains live and exact; each flush discards both hints. The immutable update slice is validated once before entering the lock, with no skipped per-record permission or backing checks
  • permission-only ranges resolve one PT span per pass instead of one ancestor walk per leaf, preserving whole-range preflight and sparse absent mappings. Success/error synchronization finishes before lock/interrupt restoration; visited GLOBAL leaves are invalidated even after ancestor-only promotion
  • the opt-in kernel-mapping-batch-selftest verifies actual scratch-page remapping, read/write flags, GLOBAL-cache replacement, and complete backing restoration plus anonymous alias dependencies before its kernel-only VM exit. Permission probes cover PT boundaries, absent leaves, and a real GLOBAL write after parent permission promotion under CR0.WP
  • its sparse-target extension checks actual alias reads/writes, unchanged gap pages, GLOBAL replacement, user-access revocation and exact restoration; ERIX_KERNEL:MAPPING_BATCH_SPARSE_OK follows private scratch cleanup. These bounded cost refinements have host-oracle and generated-code coverage; rebuilt-image hardware/performance acceptance remains separate and pending
  • multi-page mapping validation and copying use operation-local index hints with exact page/rights/backing revalidation under the VSpace lock; sequential forward or backward pages avoid repeated full-table scans without caching authority or changing whole-range preflight and overlapping-copy behavior. Successful preflight retains its first page index for copying, avoiding a duplicate initial scan. The copy pass reacquires the lock and authorizes every live page again; no mapping, rights or backing result survives the lock
  • the physically ordered managed-frame registry uses fallibly allocated 256-entry chunks as well, so crossing 32,768 ext4-executable pages cannot demand a contiguous doubled frame table from a fragmented kernel heap; alias, mapping-reference, exact-range reuse, and cleanup rules are unchanged
  • multi-page user-permission changes prepare page-table structure in one locked pass and apply leaf flags in a second locked pass, so switching a large process never allocates rollback storage proportional to its image span
  • early dynamic mapping now reuses immutable shared-object backing by object hash and segment identity, keeps writable/zero-fill relocation state private per process, preserves exact ELF segment virtual starts even when a segment begins inside an aligned page, rejects text relocations, and exposes only process-control kernel ops 39..41 for manifest-bounded map/apply/seal requests; each VSpace grows its mapping metadata from kernel-reserved memory instead of rejecting a valid image at a per-address-space page ceiling, and anonymous backing pages return to the reclaiming kernel heap on unmap, aborted launch, final-capability drop, or process teardown
  • dynamic rootd bootstrap can create the initial root address space from the signed boot dynamic catalog, materialize executable and dependency PT_LOAD pages in the root VSpace, map and relocate required shared objects before root entry, seal the mappings, and clean up all partial user mappings on bootstrap failure without granting object-store authority
  • pre-procd dynamic service launch now uses the same catalog-bound mapping surface for memd, vspaced, pagerd, and procd, with kernel-owned child mappings, private relocation state, explicit endpoint authority, and cleanup of partial process/VSpace state on failure; duplicate inactive cleanup is a no-op, and inactive VSpace teardown cannot clear the active root VSpace's overlapping user leaves
  • operator evidence records the kernel as a dynamic ET_DYN artifact entered at erix_dynlink_entry, validates the boot catalog handoff before root startup, and keeps early service dynamic-link failures separate from bootloader kernel-link, bootloader catalog, dynlinkd, and ordinary service failures
  • runtime replies to pending calls are written through the caller TCB's tracked VSpace, so service replies to dynamically spawned processes do not depend on the current server address space
  • a runtime reply may write that VSpace only while the exact caller generation remains nonterminal. A killed, exited, missing, or recycled caller retires the stale call with NOT_FOUND before caller-buffer sizing, payload writes, or caller wakeup. A terminal caller therefore cannot strand an accepted call merely because its response is larger than the retired request buffer; only a caller still blocked on that call is woken
  • capability-transfer, process-creation, device-frame, VSpace, and dynamic-map rollbacks revoke every derived authority before returning; an impossible rollback failure is a kernel invariant violation and therefore fail-stops instead of continuing with residual authority
  • x86_64 user-permission changes split inherited huge mappings before touching a leaf, enforce read-only versus writable intent at that leaf, and allocate required page-table pages fallibly instead of using fixed split pools; this prevents a narrow launch range from exposing neighboring kernel pages
  • capability-transfer delivery preserves a kernel-normalized receipt table, rejects destinations outside the receiver's immutable CSpace window, and records the rights actually installed so services can reject and revoke every unwanted alias; occupied destinations return terminal CONFLICT without consuming the live receive rendezvous, while rendezvous backpressure remains retryable BUSY
  • the memory-control endpoint may drop caps in the caller's allowed local slot range, enabling memd to release allocator-owned frame caps without gaining broader kernel-control authority
  • RAM-frame allocation atomically selects a page-granular, caller-constrained subrange inside any extent of the delegated allocator domain, installs a frame with the requested attenuated rights, and returns the kernel-selected physical range; callers cannot nominate physical addresses or create unbacked ordinary frames
  • before installing the new frame capability, allocation clears the complete selected RAM range through a transaction-local, supervisor-only mapping. The mapping borrows one page from the reclaiming kernel heap, restores that page's original backing before release, and exposes neither stale bytes nor a fixed scratch virtual-address reservation to the recipient
  • ordinary frame aliases and VSpace mappings share one kernel-tracked backing identity; each mapping is an explicit lifetime reference, so deleting the final frame alias cannot invalidate a live mapping. The exact physical subrange returns to the allocator domain only after both aliases and mappings are gone, while DEVICE_FRAME mappings remain a separate explicit path
  • the focused RAM allocator-domain VM self-test proves that every authenticated extent names one exact manage-only capability, then exercises a three-page alignment, copied-alias lifetime, final-alias deletion, and exact physical-range reuse before root launch without leaving test capabilities installed
  • the kernel binary now exports erix_dynlink_entry as the stable dynamic entry symbol for the generated kernel ET_DYN artifact; its SysV64 v2 contract receives the handoff pointer in rdi and exact byte length in rsi, and the keep marker lives in data so the true dynamic relink does not need text relocations while kernel_entry remains the internal implementation entry
  • runtime endpoint path no longer synthesizes non-root service replies in normal builds; service interactions use endpoint queue/call-recv-reply mechanics
  • runtime replies prefer their completed blocked caller when no follow-up call remains; only an actual queued call defers that caller so the replying server can drain the endpoint, and application payloads do not alter this rule
  • transfer-bearing runtime replies now also require GRANT on the replying endpoint slot itself, so capability materialization stays explicit in the sender's local policy instead of being inferred from endpoint receipt
  • page-fault delivery now targets a kernel-retained endpoint object whose sole userspace receive binding is moved to pagerd; process registration carries no endpoint slot, and faulting children receive no pager endpoint capability
  • a queued page-fault notification revalidates that endpoint's recorded receive binding and immediately prefers its live pager. If the pager is blocked on a separate empty receive, the kernel cancels only that receive and wakes it with RETRY; endpoint identities and capability inventories do not change
  • page-fault delivery is limited to non-present user accesses and contains one architecture-independent read, write, or execute value; protection, reserved-bit, protection-key, shadow-stack, SGX, supervisor, contradictory, and unknown fault classes are terminated in the kernel
  • process-event delivery now targets the stable endpoint identity that procd explicitly registers through its process-control endpoint; registration requires the caller's TCB-bound RECV capability, so an exiting child's CSpace is never consulted for wake authority
  • terminal process cleanup and explicit removal of a recorded receiver's final live receive binding retire that exact endpoint, complete outstanding callers with NOT_FOUND, and clear queued state so neither IPC work nor reply authority survives the receiver
  • exit and kill are a single-winner TCB transition: the first terminal action publishes the generation's only process event, while a later managed kill returns NOT_FOUND without changing the original state or status
  • root-process process_exit exhaustively clears the complete root CSpace after retiring its recorded receiver and before publishing the terminal event; a focused kernel test proves both an empty capability snapshot and NOT_FOUND wakeup of a caller blocked on that receiver
  • transfer-bearing runtime calls still require a live receive rendezvous for capability materialization; if a sender reaches the endpoint first, the endpoint retains only the waiting sender identity and first prefers its already-bound receiver so that the exact receive can be armed, never a residual cap or queued transfer table; non-blocking RECV reports BUSY while this rendezvous is pending, and the timed receive then prefers the sender to complete delivery
  • a non-blocking RECV that cannot dequeue observes transfer-waiter liveness under that same endpoint lock, avoiding a second capability/binding lookup solely for advisory BUSY versus RETRY. Existing generation/liveness checks still clear stale waiters. Blocking registration retains its second live lookup; no endpoint hint, epoch, cache, or new authority is retained
  • reply scheduling makes completed callers runnable without preempting the replying process; within the handoff quantum, a sole completed caller is next at the server's cooperative boundary while previously committed work remains deferred, and an actual queued endpoint call keeps the server's drain work ahead without decoding service-specific results
  • additional callers queued behind an outstanding auxiliary-endpoint call retain its recorded receiver preference, just like the first queued call; live generation, CSpace, endpoint binding, and RECV rights are revalidated without changing receive retirement or capability-transfer rendezvous
  • preferential CALL, exact reply, and pending-wake selections share a budget of eight handoffs across blocking and voluntary-yield boundaries; a CALL/reply pair uses two. The next selection follows the persistent round-robin cursor without losing pending work. Only a successful ordinary selection resets this budget, including when the exact caller is the only runnable peer. Short RPC chains avoid unrelated address-space switches, while other tasks receive a bounded cooperative fairness turn, not a wall-clock guarantee
  • voluntary yields honor existing receiver and pending-wake preferences too, including a transfer-bearing caller retrying BUSY before its receiver arms a rendezvous. Exact replies remain first; absent or ineligible pending work falls back to ordinary selection, and all paths share the same eight budget
  • calls through send aliases whose receiver has retired fail with NOT_FOUND until a nonterminal replacement explicitly holds the endpoint's receive authority; a live receiver blocked on an outbound RPC remains a valid queue owner, while stale aliases cannot accumulate unserviceable work
  • x86_64 syscall entry now switches to a kernel-owned stack before saving the full resume frame, copies blocked-task frames into per-TCB kernel storage, and records the return user RSP explicitly so user-stack page faults cannot turn syscall delivery or trap-side scheduler switches into residual stack authority; TCB identifiers, runtime records, saved frames, process events, scheduler contexts, and runnable entries grow fallibly from reclaiming kernel memory instead of imposing bootstrap-era object or queue ceilings
  • ACPI LAPIC discovery, SMP bring-up records, AP bootstrap stacks, and scheduler per-CPU state follow the same topology-sized fallible policy. Duplicate LAPIC identities are rejected, the actual BSP is normalized to slot zero, and sparse failed/offline slots remain explicit so AP trampoline indices cannot acquire another CPU's scheduler state; xAPIC IPI destinations are width-checked so x2APIC IDs cannot silently alias low-numbered CPUs
  • runtime preemption keeps the raw LAPIC one-shot interval separate from the scheduler accounting-tick quantum. AP accounting workers use calibrated processor-clock deadlines instead of polling the global scheduler lock without a bound
  • INIT/SIPI spacing, ICR dispatch, AP-online observation, scheduler attachment, and development UART polling use elapsed processor-clock deadlines derived from the bootloader's explicitly firmware-calibrated handoff value. Their behavior no longer changes with host CPU speed, and missing or conflicting clock metadata is an explicit failure instead of an undocumented spin ceiling or an implicit kernel timer-device acquisition
  • endpoint objects, capability aliases, queued messages, pending callers, and install-grant records likewise grow fallibly from reclaiming kernel memory; queued payloads reserve only their actual byte length, released endpoint and grant identifiers are reusable, and partial allocation or cap-install failures leave neither a runtime record nor residual capability authority
  • CSpace records also grow from reclaiming kernel memory and allocate slot storage only through their highest installed capability; lib_capabi::CSPACE_SLOT_COUNT_V1 defines the addressable CSpace ABI namespace, not a global object-table reservation
  • every authenticated usable-RAM extent belongs to one manage-only capability at SLOT_RAM_ALLOCATOR; extent count is bounded only by reclaiming kernel memory, and MMIO authority remains on the separate device-frame path
  • CAP_TYPE_DEVICE_FRAME is now a first-class capability type distinct from ordinary RAM frames, and the kernel-control path can derive one validated BAR-backed MMIO frame for deviced without exposing a generic device-memory escape hatch
  • feature-gated, root-only host-report kernel-control endpoint (kernel-rootd-runtime) for deterministic VM completion:
    • accepts only IPC_KERNEL_CONTROL_OP_REPORT_HOST_EVENT on its dedicated endpoint object
    • the endpoint is installed only in rootd's initial CSpace; ordinary processes receive neither this endpoint nor an ambient reporting syscall
    • accepts ROOTD_STAGE:* progress events and emits deterministic stage markers without exiting
    • rootd ready -> 0x10
    • rootd internal failure/unknown status -> 0x13
    • downstream service bootstrap failure -> 0x14
  • kernel-rootd-smoke-test adds the VM-only debug-exit terminal to the same explicit endpoint path used by smoke and negative integration scenarios; when combined with kernel-runtime-image, it does not disable normal runtime SMP discovery, AP bring-up, or per-processor scheduler counters
  • kernel-integration-runtime-quiet is a VM-fixture-only refinement of that smoke build. It suppresses repetitive successful demand-fault, process-exit, event-queue, endpoint-retirement, lifecycle-wake, and rootd/logd reply debug projection while leaving process state, event delivery, cleanup, selected focused evidence, and the final host-report terminal unchanged.
  • kernel-integration-stress-quiet is the compatibility alias used by older exact-lifecycle fixture builders; it implies the general runtime-quiet refinement and grants no behavior or authority of its own.
  • rootd host events include a failure-only ERIX_KERNEL:ROOTD_WARN:* diagnostic family for late bootstrap triage; these markers do not authorize extra kernel output paths and remain gated by the runtime-report surface
  • pre-module rootd failures decode a stable numeric boundary step through that same diagnostic family; the decoder does not add a route or capability
  • runtime/appliance kernel builds enable kernel-runtime-image without kernel-rootd-smoke-test; deterministic debug-exit remains an integration harness opt-in, not part of packaged runtime images
  • normal runtime builds seed only the narrow preinstalled runtime endpoints; the generic procd driver-lifecycle and loader-materialization routes are distinct endpoint objects, and no broad compatibility endpoint or reserved root slot exists
  • dev-profile early console feature (kernel-dev-console) validates and caches one PF2 index, then mirrors kernel markers to the framebuffer via lib-console until rootd submits ROOTD_REPORT_STAGE_FBCOND_READY through its host-report endpoint
  • the capability-gated console mapping records the exact boot framebuffer range and applies an explicit x86_64 write-combining PAT policy; ordinary physical mappings retain write-back semantics
  • runtime can retire the kernel framebuffer mirror separately at fbcond handoff, then disable early kernel serial/log output after direct userspace sinks are available
  • disabled kernel direct-log IPC requests are denied and retained as in-memory warning records without reusing the retired serial/framebuffer output path; the kernel control ABI has no raw serial-write operation, and remaining COM1 writes are internal debug-serial mirroring behind retained-log control markers
  • retained early kernel logs split messages longer than one IPC log chunk into sequential in-memory records instead of truncating the tail before logd takes them; the single-consumer queue grows fallibly from kernel-owned memory, has no fixed record ceiling, and releases its allocation when drained
  • centralized-process-authority deep runtime trace families stay smoke-only, so ordinary appliance dev/release images do not emit ad-hoc staged lifecycle or capability-trace chatter
  • direct syscall/save/switch, IPC call/reply, process-yield, and memory-provider trace probes sit behind the opt-in kernel-verbose-trace feature, keeping default VM images on readiness/failure evidence instead of staged-create, capability-copy, demand-fault, and hot-path serial chatter
  • the narrow integration-only kernel-rtc-startup-trace reports whether an RTC startup call was delivered directly to an already blocked receiver or queued for the bound child; it observes scheduling without changing delivery order or adding an endpoint, capability, or runtime input, and it does not enable the broader IPC-block trace families
  • the completed call-first scheduling fixture is absent: retained serial evidence proves ordinary queued CALL admission, reply, provider exit, and subsequent rootd progress, so every kernel build keeps normal scheduler policy and the remaining RTC trace is observation-only
  • successful rootd transport polling and procd receive/reply iterations emit no boot-report code; terminal transport and reply failures remain observable
  • bootstrap pager faults emit ERIX_KERNEL:BOOTSTRAP:FAULT_* diagnostics only when resolution fails; successfully delegated and resolved demand faults stay silent
  • runtime images suppress successful per-block virtio-block read trace chatter while preserving request/status failures and higher-level storage readiness evidence
  • runtime IPC reply sizing is derived only from the generic IPC envelope and caller buffer; the kernel does not decode service-specific reply bodies
  • completed CALL syscalls return the exact encoded reply length in rdx for both queued service replies and immediately dispatched kernel-control replies, so callers can validate only initialized response bytes
  • rootd stage-marker mapping includes input readiness stages (DRV_I8042_READY, DRV_PS2_KEYBOARD_READY, DRV_PS2_MOUSE_READY, INPUTD_READY, INPUT_ROUTING_READY, CONSOLE_INPUT_READY)
  • rootd stage-marker mapping now also includes the current filesystem slice (MEMORY_PROVIDER_READY, VFSD_READY, VFS_MOUNT_READY, VFS_IO_READY)
  • rootd runtime report decoding recognizes the expanded VFS backend operation debug family (rename, truncate, symlink, readlink, link, and metadata update) so diagnostics remain non-terminal during filesystem API verification
  • rootd stage-marker mapping now also includes storage bring-up (BLOCKD_READY, STORAGE_READY)
  • rootd stage-marker mapping now also includes Filesystem provider work filesystem providers, private key service, and program-loader service (KEYD_READY, E2FSD_READY, FATD_READY, LOADERD_READY, DYNLINKD_READY)
  • Phase 5 post-mount reporting recognizes POWERBOXD_READY, TTYD_READY, LAUNCHD_READY, and RTC_PROVIDER_COMPLETE; these remain explicit root-only host-report events and do not grant runtime services kernel-report authority
  • kernel-control op READ_PLATFORM_CAPS (26) exposes deterministic platform-presence bits for probe-gated driver activation
  • kernel-origin failure class is 0x12 in kernel binary integration flow
  • scheduler, SMP, exception, and simultaneous interrupt-line delivery and acknowledgement selftests remain behind explicit integration-only feature flags
  • scheduler/SMP selftests cross the retired 64-LAPIC, 64-CPU, 16-stack, and 16-scheduler-slot ceilings and verify sparse online topology indexing
  • the online-topology helper is compiled only for its global-scheduler selftest or production runtime SMP callers; CI separately builds coherent bring-up, failed-AP, global-scheduler and runtime profiles with warnings denied
  • runtime IPC dispatch now enforces endpoint send/recv rights:
    • CALL / NOTIFY require SEND
    • RECV / REPLY require RECV
  • timed runtime CALLs remember the exact TCB that last received or polled each endpoint, allowing a multi-endpoint server to wake while blocked on a different endpoint without inferring a receiver by scanning CSpaces; the recorded stage generation and live receive capability are revalidated before every wake
  • syscall return now preserves the user return RIP/RFLAGS on the kernel syscall stack across dispatch and trace hooks, and last-binding endpoint teardown drops heap-backed queued message and caller state without constructing large transient endpoint objects or retaining payload storage
  • kernel-control slot arguments used by process/capability operations are now constrained to the caller-visible process window
  • kernel-control op QUERY_CAP (29) now exposes local capability type/rights for startup-time authority inventory checks without opening foreign-slot visibility
  • kernel-control op QUERY_CAP (29) now also supports opt-in endpoint-kind reporting via IPC_KERNEL_CONTROL_QUERY_CAP_FLAG_INCLUDE_ENDPOINT_KIND, with the upper 32 bits of value1 carrying endpoint kind while non-endpoint caps report GENERIC/0
  • kernel-control op CREATE_ENDPOINT (30) now materializes a fresh send/recv generic IPC endpoint in one caller-local slot; bootstrap uses the dedicated CHILD_POPULATE family, while vfsd receives a distinct ENDPOINT_FACTORY family that permits only creation and attenuated copying. Callers cannot select or mint a kernel-control endpoint family
  • caller-local syscall SAME_ENDPOINT_OBJECT (0x48) compares two endpoint capabilities already visible to the current process and returns only one boolean. It exposes no kernel endpoint identifier and creates no authority
  • controlled user page aliases now allocate missing x86_64 page-table levels for anonymous materialized child mappings, so filesystem-backed dynamic images are not constrained to virtual ranges already covered by the kernel identity map
  • x86_64 page-table walkers use a supervisor-only recursive PML4 window rather than dereferencing physical frame addresses through an assumed low-memory identity mapping, including when runtime table pools reside above 1 GiB
  • kernel-control fast-path dispatch is now keyed by the endpoint object's stored family kind rather than by canonical slot numbers: the optional test-only root endpoint retains the full kernel-operation surface when enabled, while normal runtime boot seeds rootd with the dedicated log endpoint plus the narrow runtime endpoint inventory: the dedicated timed endpoint at slot 2128 accepts only READ_MONOTONIC_CLOCK and local QUERY_CAP
  • the dedicated irqd endpoint at slot 2144 accepts only interrupt wait, acknowledgement, and line configuration; capability inspection uses the caller-local syscall instead of widening this endpoint
  • kernel interrupt events carry line, CPU, and a nonzero per-line sequence only; the kernel retains no unused timestamp, and pending lines are selected in round-robin order so repeated timer delivery cannot starve COM1
  • the dedicated hotplugd endpoint at slot 2160 accepts only hotplug-event wait plus local QUERY_CAP
  • hotplug event retention grows fallibly from kernel-owned heap memory and reports storage or sequence-namespace exhaustion; it no longer silently drops events after an eight-record implementation limit
  • the dedicated platform-discovery-read endpoint at slot 2176 accepts only READ_PLATFORM_CAPS and READ_PCI_CONFIG_DWORD; it carries no local capability-query authority
  • the dedicated console endpoint at slot 2192 accepts only framebuffer/font query/map operations, the fbcond probe verifier, and local QUERY_CAP
  • the dedicated COM1 endpoint at slot 2208 accepts only IOPORT_READ8, IOPORT_WRITE8, and local QUERY_CAP, with hardware-port policy restricted to 0x3F8..=0x3FF
  • the private RTC endpoint at slot 3000 is narrower than generic byte I/O: it reads only data port 0x71 and writes only an NMI-preserving, closed set of wall-clock/status register selectors to index port 0x70; writes to CMOS data and reads of unrelated CMOS storage cannot be expressed
  • the dedicated memory endpoint at slot 2224 accepts only ALLOCATE_RAM_FRAME and local QUERY_CAP; allocation accepts an explicit RAM allocator cap, destination slot, size, alignment, and frame rights, while the kernel alone selects the physical subrange. Transient scheduler or rendezvous backpressure remains BUSY/RETRY, while permanent RAM-domain or kernel-heap exhaustion is RESOURCE_EXHAUSTED; development runtime images also retain the exact kernel error marker for allocator-failure diagnosis, without exposing another endpoint operation or capability. The managed-frame registry remains ordered by physical address, so first-fit selection scans it directly and does not require heap-backed transaction scratch storage. After the development console is ready, an actual kernel-heap allocation failure reports the requested size/alignment and total/largest free block internally. ERIX_KERNEL_RESERVED_HEAP_BYTES selects page-aligned kernel-private storage at build time; the selected extent is part of the authenticated kernel image, not a service record limit or authority delegated from usable RAM
  • the dedicated vspace endpoint at slot 2240 accepts only MAP_FRAME, UNMAP_FRAME, and local QUERY_CAP
  • the dedicated pager endpoint at slot 2256 accepts only RESOLVE_FAULT and local QUERY_CAP. Smoke-test images retain the faulting TCB, pending/requested pages, run state, and saved instruction/stack pointers when resolution fails, without widening the pager endpoint or exposing those diagnostics in a runtime image
  • the dedicated log/query endpoint at slot 2272 accepts only QUERY_CAP, LOG_STRING, and TAKE_EARLY_LOG, which narrows runtime logging to the generic retained-log path. Each successful take consumes the oldest record, so no cursor retains already-transferred kernel storage. Long messages are committed atomically across sequential records. Nested log input/output pointers are validated across the complete current-VSpace range for their exact read or write rights before dereference. No raw serial-write IPC path exists, and the internal debug COM1 mirror is not service-callable. LOG_STRING acknowledges OK only after that bounded mirror commits the complete line; transient UART backpressure returns RETRY
  • the dedicated query endpoint accepts only QUERY_CAP, which lets services validate caller-local caps without inheriting LOG_STRING or early-log reads
  • the endpoint-factory endpoint at slot 2400 accepts only CREATE_ENDPOINT and CAP_COPY_ATTENUATED; it cannot inspect foreign slots, populate a staged child, install a grant, or drop unrelated capabilities
  • the dedicated process-control endpoint at slot 2288 accepts only the bounded process and attenuated-capability lifecycle operations that procd uses, including an exact process/generation CPU-time query; unrestricted local copy and move operations are absent, and returned nanoseconds carry no authority
  • the dedicated ACPI RSDP endpoint at slot 2320 accepts only GET_ACPI_RSDP; platform-capability, table-memory, and local-capability reads are not bundled into that authority
  • the dedicated i8042 endpoint at slot 2336 accepts only IOPORT_READ8, IOPORT_WRITE8, and local QUERY_CAP, with hardware-port policy restricted to 0x60 and 0x64
  • canonical boot-root slot numbers no longer imply authority in non-root CSpaces; runtime policy follows the endpoint kind or cap actually installed in the caller's local slot, and services consume only their explicit local startup transfers instead of inferring access from slot numbers
  • syscall QUERY_LOCAL_CAP (0x45) now exposes the same caller-local slot type/rights introspection path to peer-only services that do not carry a kernel-control endpoint, and on x86_64 it now returns additive endpoint-kind metadata in r8
  • syscall DROP_LOCAL_CAP (0x47) now lets callers clear one caller-local slot directly so fixed-slot peer bindings can be dropped before retrying late rematerialization
  • syscall slot checks now require a valid current TCB; absent or invalid caller attribution is denied instead of falling back to root CSpace authority
  • syscall dispatch rejects every non-zero reserved register; reply and notify reject the unused timeout position, and cooperative yield also requires an attributable current TCB
  • bootstrap/root CSpace capacity is now 4096 slots so explicit local slots in the extended startup-transfer range remain representable without falling back to shared canonical windows
  • runtime TCB records now carry private CSpace/VSpace identities, and kernel slot lookup resolves against the current process CSpace rather than a single shared runtime slot table; each registered TCB retains only its VSpace lifetime, not map or management authority, until terminal process teardown
  • endpoint capability copy/move/drop now preserves endpoint-object identity across multiple local slots:
    • copied endpoint caps alias the same endpoint runtime queue
    • dropping one alias removes only that slot binding
    • kernel-control family dispatch follows the endpoint object, so a copied local control slot keeps the same bounded policy surface as the canonical control endpoint it aliases
  • kernel-control op CAP_COPY_ATTENUATED (31) now installs explicit rights-reduced local aliases, which rootd uses to materialize startup control, driver-lifecycle, and loader-materialization slots instead of treating transfer descriptors as metadata only
  • runtime IPC now supports explicit capability transfer tables on CALL, REPLY, and NOTIFY messages when the sender's endpoint cap carries GRANT
  • IPC syscalls take one exact-size, fallibly allocated snapshot of caller bytes before parsing or transfer application. They no longer construct a maximum-envelope scratch array on the kernel stack or duplicate that snapshot during preparation
  • the syscall boundary checks the caller's current VSpace over the full buffer capacity: CALL requires read/write, RECV write, and REPLY/NOTIFY read access. Root and ordinary users follow the same policy before endpoint or control handling. Snapshot creation copies the 40-byte generic header once and only its declared body for valid envelopes; malformed and raw messages retain their full-buffer fallback, with unchanged capability checks
  • delayed reply/receive delivery rechecks live target write authority for the exact payload before copying. A raw root-bootstrap fallback additionally requires registered writable user ranges; a failed tracked-backing lookup never grants raw access, and no unused response-capacity tail is exposed
  • CAP_TYPE_INSTALL_GRANT is now implemented in-kernel for staged child population, and START_PROCESS is denied while live grants still target the child stage
  • CAP_TYPE_REVOCATION_GRANT is a distinct manage-only, move-only kernel object. It follows every kernel-derived alias of one installed child capability, revokes all surviving aliases when deleted, and cannot revoke a later same-slot replacement after the original lineage disappears
  • kernel-control ops CREATE_STAGED_PROCESS (32), DERIVE_INSTALL_GRANT (33), INSTALL_WITH_GRANT (34), and ABORT_STAGED_PROCESS (35) now provide private-child creation and scoped startup-cap installation
  • kernel-control op INSTALL_WITH_REVOCATION_GRANT (45) atomically installs one attenuated child capability and creates its separate revocation grant; failure leaves both destination slots empty
  • staged child creation now emits the same ERIX_KERNEL:HARDWARE:CSPACE_WINDOW_SET smoke marker as the explicit window-setting control path, so integration validation observes child-window establishment independent of which kernel entrypoint performed it
  • the obsolete direct process-creation operation has been removed; staged child creation is the only process-construction path
  • TCB endpoint and pager registration now validate the target process's private CSpace instead of assuming the caller's current CSpace
  • kernel-control op KILL_PROCESS (28) provides explicit managed-stop support for procd; an already-terminal target returns NOT_FOUND and cannot acquire a second terminal event
  • kernel-control op WRITE_PROCESS_MEMORY (38) copies caller bytes only into already mapped anonymous child process pages, allowing procd to populate file-backed loader images without accepting caller-selected frame or VSPACE authority; it validates the complete readable caller range and complete anonymous child range before streaming, with no page-sized call ceiling or partial destination write when a later page is absent
  • default smoke images suppress successful per-chunk process-memory and per-page VSPACE mapping traces; kernel-verbose-trace retains those diagnostics without making large filesystem-launched services miss the VM readiness deadline
  • inactive staged anonymous mappings may be sealed from writable staging rights to final executable rights before first activation; live mappings still reject execute upgrades, and every mapping rejects simultaneous writable and executable rights
  • obsolete pager/process image-frame slots are no longer special-cased; executable mappings are staged anonymously before activation and the boot-module frame remains the only non-anonymous bootstrap frame
  • initial syscall-resume frames are written into the target VSpace's anonymous stack backing before first activation, so materialized file-backed children do not depend on the caller's currently active page mapping
  • process-control operation CONFIGURE_PROCESS_STARTUP (46) binds an exact staged generation to one complete readable process-owned image range, accepts only an identical retry while the child remains created, places its address and length in initial rdi/rsi, preserves the bound receive endpoint in rdx, and retires the retained register data after constructing the frame
  • process-control operation QUERY_PROCESS_CPU_TIME (47) returns saturating user and system nanoseconds for one live or terminal exact TCB generation. Accounting closes intervals at initial user entry and syscall/user-fault boundaries, stale or malformed identities return no values, and no timing or process capability is created by the reply
  • process-control operations READ_PROCESSOR_TOPOLOGY (48) and READ_PROCESSOR_COUNTERS (49) expose explicit indexed online state plus monotonic total/non-idle scheduler ticks; the memory-only READ_ALLOCATOR_TOTALS (50) reports usable and live managed-frame bytes. All three are read-only service-owner inputs and are never delegated to an application process.

Governance Principles

kernel governance is scoped to minimal mechanism: scheduling, memory, IPC, interrupts, and capability enforcement.

The scoped governance rules are:

  • Policy belongs in user-space services unless enforcing it in the kernel is necessary for isolation.
  • Capability checks must be explicit and auditable at every authority boundary.
  • Unsafe Rust and architecture-specific code must stay narrow, documented, and covered by invariants.
  • Kernel ABI changes require matching updates in libraries, services, and integration validation.

Authority Boundaries

  • The kernel creates and enforces capabilities; it does not grant ambient service authority.
  • New kernel mechanisms must preserve deterministic startup and fail-closed behavior.

Contact

Development occurs in EriX organization and discussions happen in issues and design documents.

No decisions are considered valid without documented rationale.

Maintainers can be reached via email: admin@erikinkinen.fi.