Section 04 / interface reference

Boundary contracts

The narrow seam between Linux / wasm32 and HardwareJS: shared memories, imported functions, exported entry points, packed records, rings, MMIO shadows, and lifecycle ownership.

VersionedBounds-checkedLittle-endianNever silent
04.01 / GLOBAL RULES

Every crossing has one owner and one failure shape

All integer fields are little-endian and all guest addresses are byte offsets, not JavaScript references. Shared structures have declared size, alignment, capacity, and version. Producers publish payload before advancing a sequence/head word; consumers validate before acting and publish completion after side effects are durable.

RULE-01

Validate identity

Magic, version, structure size, slot generation, and expected module provenance precede use.

RULE-02

Validate ranges

Offset plus length is checked without overflow against the owning memory or carve.

RULE-03

Publish atomically

Atomics order cross-Worker state; a wake word is notification, never the authoritative payload.

RULE-04

Reject stale work

Generation/witness checks prevent a delayed completion from mutating a reused slot.

RULE-05

Keep policy guest-side

HardwareJS transports requests and I/O. Linux owns permissions, scheduling, and POSIX semantics.

RULE-06

Fail attributed

Unsupported imports, devices, malformed descriptors, and bad transitions report their boundary.

04.02 / CONTRACT MATRIX

The complete public seam

ContractProducer → consumerTransportPurposeFailure rule
boot_info v3HardwareJS → kernel96-byte record in kernel RAMDescribe RAM, CPUs, clock, cmdline, initrd, entropyKernel panics before generic boot on bad identity/range
env.kernel_memoryHardwareJS ↔ all kernel instancesShared WebAssembly memoryPhysical RAM and global Linux stateInstantiation/preflight refusal on shape mismatch
env.user_memoryLoader ↔ user modulePer-address-space shared memoryExecutable data, heap, stack, DSOsExec/load failure on incompatible limits
linux.raw_copy_*_userKernel → process WorkerThree function importsCross kernel/user memory boundaryBytes-not-copied; kthread context throws
linux.syscallUser program → HardwareJS → kernelFunction import/export pairEnter Linux syscall table with six arguments-ENOSYS for absent table entries
park/resumeKernel continuation ↔ Worker schedulerReturn token plus slot witnessRelease JS stack while a kernel path blocksGeneration/witness mismatch aborts the resume
spawn ringKernel → spawn consumerFixed shared ringFork/thread/exec host workMalformed/stale slot rejected
signal ringKernel → signal consumerFixed shared ringRoute target delivery to owning WorkerBad target/region/signal is attributed
virtio-mmioLinux driver ↔ device backendMMIO imports + shared virtqueuesFilesystem, input, and network data planeDescriptor/range/protocol failure tied to device
scheduler wakeBackend → kernel WorkerAtomic word + notifyWake idle kernel after external completionAlignment checked; payload stays elsewhere
display controlUI ↔ wasmdrmFour shared u32 wordsRequest and acknowledge visible modeRequest clamped to fixed carve maximum
PTY bridge ringTerminal UI ↔ Linux PTYShared byte ringsMaster input/output and winsizeBounds/state errors report at bridge
serial bridge ringLinux tty ↔ Web Serial backendShared byte rings/dev/ttySER0 byte and signal transportPermission/disconnect surfaced as events
04.03 / BOOT_INFO V3

A fixed record at a host-selected RAM offset

HardwareJS writes exactly 96 bytes, then calls the architecture entry with its offset. The header makes extensions explicit: older sizes remain recognizable while the current kernel requires the fields needed by its configured boot path.

0x00magicu32 · WASM_BOOT_INFO_MAGIC
0x04abi_versionu32 · current value 3
0x08struct_sizeu32 · 96 bytes
0x0cflagsu32 · feature presence
machine fieldsRAM, command line, CPU, clock, initrd, seed

Every pointed-to byte range must fall inside env.kernel_memory. Reserved fields must carry their defined neutral value. The command line is ASCII and capped at Linux COMMAND_LINE_SIZE - 1. Optional initrd/entropy fields are paired offset and length values rather than host objects.

HardwareJS                           Linux / wasm32
-----------                          --------------
allocate shared RAM
write cmdline/initrd/seed
write payload fields
write identity header
call wasm_start(info_offset)  ─────▶ validate magic/version/size
                                      validate every range
                                      initialize memblock + CPUs
                                      start_kernel()

NORMATIVE SOURCES · host layout · kernel layout

04.04 / MEMORY & USERCOPY

Addresses name bytes only inside their declared memory

Kernel pointers and guest physical addresses are offsets in env.kernel_memory. User pointers are offsets in the current process Worker’s env.user_memory. A value has no meaning until the contract also identifies which memory owns it.

ImportArgumentsOperationResult
linux.raw_copy_to_useruser dst, kernel src, lengthCopy kernel bytes into current user memoryNumber of bytes not copied
linux.raw_copy_from_userkernel dst, user src, lengthCopy current user bytes into kernel memoryNumber of bytes not copied
linux.raw_clear_useruser dst, lengthZero a current-user rangeNumber of bytes not cleared

The host uses overflow-safe range checks before creating typed-array views. Partial or invalid ranges follow Linux’s residual-byte convention. Kernel-thread bindings install throwing implementations because treating kernel memory as a user address space would be silent corruption.

Single-memory invariant: the kernel module imports only env.kernel_memory. The three usercopy leaves are the only generic kernel data path into a process memory.

04.05 / ENTRY & SYSCALL

Strict WebAssembly signatures normalize the ABI

USER IMPORT linux.syscall

(nr, a0, a1, a2, a3, a4, a5) → result

KERNEL EXPORT wasm_syscall

(nr, a0, a1, a2, a3, a4, a5) → result

HardwareJS binds the user import to the process Worker’s kernel instance. The kernel validates the syscall number, selects a generated uniform wrapper, establishes the current task context, and returns a signed machine word. Linux errno values remain negative. Pointers are user-memory offsets and cannot bypass uaccess.

The process Worker—not the main page—performs this entry. It already owns the current user-memory binding and its kernel instance, so no synchronous cross-Worker RPC is needed for the ordinary trap.

NORMATIVE SOURCES · kernel dispatch · process Worker binding

04.06 / SUSPENSION

A park result carries a resumable kernel frame tree

Published suspension paths are compiler-transformed. When the kernel must wait, the active continuation moves into a bounded slot and returns an internal park result to the Worker drive loop. The slot’s generation, root, arena census, and witness identify exactly what may resume.

CALLsyscall entersWorker owns task + user memory
BLOCKLinux waitState is queued in kernel
PARKSave continuationPublish slot + witness
WAKEEvent/IRQLinux makes task runnable
RESUMEValidate and enterContinue after the wait

The internal -517 result selects this protocol. HardwareJS must not expose it as an application errno. A resume with stale generation or inconsistent arena state is refused, because resuming the wrong frames would be memory corruption.

NORMATIVE SOURCES · coroutine semantics · toolchain specification

04.07 / SHARED RINGS

Fixed layouts move control work across Workers

Spawn, signal, PTY, and serial boundaries use records in kernel memory. Each ring has a fixed header, bounded slot count or byte capacity, monotonic producer/consumer positions, and a notify word. Ring offsets are exported by the kernel and returned in the BootResult only when the matching contract exists.

RingPayloadProducerConsumerCompletion
spawnrequest kind, task/image data, slot generationLinux process pathMain host spawn consumerResult published to request slot and Worker awakened
signaltarget tid, signal, sender pidLinux signal pathHost signal consumerOwning Worker notified for kernel delivery
PTYinput/output bytes, requested winsizeUI and Linux ttyLinux tty and UI bridgeHead/tail advance plus notify
serialRX/TX bytes, modem/control eventsLinux tty and SerialPortSerialPort and Linux ttyProgress/event state plus notify

Shared rings transport identity and intent. Authoritative process groups, open files, pipes, signal masks, and tty state remain normal kernel structures.

04.08 / VIRTIO & INTERRUPTS

Guest offsets are validated before backend access

Virtio frontends publish descriptor tables, available rings, and buffers in physical RAM. MMIO queue notification crosses to the matching TypeScript backend. The backend walks chains with cycle/count/range checks, performs the operation, writes used lengths, and exposes a pending interrupt.

Linux driver                         HardwareJS backend
------------                         ------------------
write descriptor chain
append available-ring index
QUEUE_NOTIFY(q)              ──────▶ read queue geometry
                                     validate descriptor chain
                                     perform device operation
                                     write used element + index
read interrupt status        ◀────── set VRING pending + wake
ack interrupt

The scheduler wake word is incremented and atomically notified after externally driven work. Interrupt status and queue payload stay in their device-defined locations; the wake word alone carries no completion data.

Memory ordering: payload and used-ring writes happen before the interrupt/wake publication observed by the guest.

NORMATIVE SOURCES · host virtqueue contract · wasm32 virtio transport

04.09 / DISPLAY CONTROL

Request, apply, acknowledge

The framebuffer carve has fixed base, stride, maximum width, and maximum height. Four 32-bit words exported by the kernel coordinate a visible mode change: request, applied, sequence, and acknowledgement. Width and height are packed into one word.

+0x00requesthost’s packed width/height
+0x04appliedguest’s committed width/height
+0x08sequencehost request generation
+0x0cackguest completed generation

The host clamps requests to the carve maximum, stores request before sequence, and wakes the kernel. The wasmdrm hotplug path commits the mode, updates applied, then acknowledges the sequence. Renderers read applied on each frame so they never blit stale geometry.

04.10 / OWNERSHIP & TEARDOWN

The creator owns every resource it starts

ResourceCreatorLifetimeTeardown
Kernel memoryMachine caller / PhysRamEntire machineReferences released after Workers/backends stop
Kernel WorkerbootKernelBoot through halt/disposeTerminate exactly once
Process Worker poolKernel spawn handlerMachine lifetimeTerminate and clear task bindings
Ring consumersbootKernelAfter ring offset publicationStop timers/listeners before memory release
Device backendsbootKernel or callerDevice negotiated to machine disposeDetach listeners, close optional transports
Permissioned deviceApplication/user gestureExplicit sessionBackend disconnect; browser object handled by owner

KernelControls.dispose() is idempotent and best-effort: it clears pause state, stops the scheduler tick and consumers, disposes the spawn handler, and terminates Workers. Navigation and relaunch must call it so old machines cannot keep running in invisible Workers.

04.11 / COMPATIBILITY POLICY

Detect shape; do not guess by browser name

Boot record
Magic + version + size; a mismatch refuses boot before generic Linux initialization.
WebAssembly
Feature probes run before Worker allocation; module compile/instantiate failures remain distinct.
Optional exports
Ring/display offsets are absent when an older kernel does not export the matching symbol.
Memory
Initial/maximum/shared declarations must match every importer and compiled module.
Toolchain
Plugin provenance attests the exact clean hwjs-cc source revision.
Devices
Negotiated features and explicit browser capability checks select behavior.

This specification describes the source snapshot published on 2026-07-23. When a contract changes incompatibly, its identity or negotiated shape must change with it; silently accepting two meanings for one layout is forbidden.

04.12 / NORMATIVE SOURCE INDEX

Trace prose to code

SNAPSHOT · kernel 9d3a35665d22084858b63b7a39b68b5cbff51024 · HardwareJS 431a0e4476a0b80e973358a7d005e384a7a82a8d · superproject 513d7b0755479c267d42df2557497dfef0c42ef9