791 lines · plain
1================================================================================2K10 terminal-model — source-site snapshot3================================================================================4 5Generated by linux-wasm/tools/k10-terminal-model-probe/snapshot-sources.sh6from Documentation/wasm/terminal-model.rst §9 + §11 (strategy B chosen).7 8Pinned at K10-A2 sub-phase close (per §12 K10-A2). Snapshots9across six trees:10 11 [LIN] upstream linux/ tree (init/main.c, include/linux/init.h,12 include/asm-generic/vmlinux.lds.h, drivers/tty/{pty,13 n_tty,tty_io,tty_jobctrl,tty_ioctl}.c)14 [WAS] our wasm32-port/ tree (kernel/init.c K6 populate_rootfs15 hand-call; kernel/sections.c K2 __setup_start/end shims;16 kernel/percpu_anchors.c sibling anchor pattern; kernel/17 percpu.c sibling override-and-post-link-patch design)18 [TLC] linux-wasm/scripts/ + Documentation/ (link-vmlinux-wasm.sh19 pipeline order; wasm-add-memory.py sibling pure-Python20 pass; post-link-pass-conventions.rst §1 ordering doc)21 [UPS] wackywasm-tools/musl-1.2.5/src/ (termios/ + misc/22 {openpty,forkpty,pty}.c surfaces K10-B/C demos exercise)23 [OVR] wackywasm-tools/musl-src/src_overrides/ (existing24 K7/K8/K9 src_overrides; K10 may add tty/wasm32/ if25 tcsetattr/tcgetattr stubs need musl-side wiring)26 [HWJ] hardwarejs/src/ (bootKernel.ts BootKernelOptions27 extension; kernelSpawnHandler.ts existing tty-related28 stubs; worker.mjs read/write that K10-B routes through29 slave-fd ldisc)30 31Section legend:32 [DEF] the function definition (file:line + leading prose)33 [CALL] call sites in the relevant tree34 [SITE] inline excerpt of a load-bearing site (no function35 definition but a code shape we depend on)36 [K10-B] where K10-B-phases will insert NEW code (annotation37 only; does not exist in any tree yet)38 [K10-A3] where K10-A3 (strategy B post-link pass) will land39 (annotation only)40 41Snapshot taken against:42 upstream linux: v6.1243 upstream musl: 1.2.544 wackywasm-tools/musl-src: K9 src_overrides state (signal/wasm32/, internal/wasm32/, no tty/ yet)45 Strategy: B (per terminal-model.rst §11.2 + §11.2.1)46Generated: 2026-05-26 (UTC, deterministic stamp from `date -u`)47Note: snapshot file deliberately omits HH:MM:SS in the48 stamp so re-runs on the same day produce byte-identical49 output. Drift detection is at line-number granularity.50 51================================================================================521. linux/init/main.c — do_initcalls + do_initcall_level (K10-A4 consumer)53================================================================================54 55Module: upstream initcall dispatcher. K10-A4 lights this path56up. do_initcalls() walks levels 0..7 (early/.../7s) plus the57explicit rootfs level; for each level it walks58[__initcall<level>_start, __initcall<level>_end) calling each59initcall_t function in turn. On wasm32 today these symbols60resolve to 0 (--allow-undefined makes them 0-imports), so61do_initcalls walks [0, 0) per level — empty. The K6 populate_62rootfs hand-call in arch_kernel_init_pre_run_init compensates63for THE SINGLE rootfs initcall but nothing else.64 65K10-A3 strategy B emits per-level anchor symbols pointing at66the active overlay segments holding the original passive bytes;67do_initcalls then walks real ranges and dispatches every68upstream initcall correctly.69 70[DEF] linux/init/main.c::do_initcalls(void)71 init/main.c:1336 static void __init do_initcalls(void)72 73[DEF] linux/init/main.c::do_initcall_level(int)74 init/main.c:1321 static void __init do_initcall_level(int level, char *command_line)75 76[DEF] linux/init/main.c::do_one_initcall(initcall_t)77 init/main.c:1261 int __init_or_module do_one_initcall(initcall_t fn)78 79[CALL] linux/init/main.c — __initcall_start / __initcall_end references:80 init/main.c:1292: __initcall0_start,81 init/main.c:1293: __initcall1_start,82 init/main.c:1294: __initcall2_start,83 init/main.c:1295: __initcall3_start,84 init/main.c:1296: __initcall4_start,85 init/main.c:1297: __initcall5_start,86 init/main.c:1298: __initcall6_start,87 init/main.c:1299: __initcall7_start,88 init/main.c:1300: __initcall_end,89 init/main.c:1376: for (fn = __initcall_start; fn < __initcall0_start; fn++)90 91================================================================================922. linux/include/linux/init.h — __define_initcall macro chain (K10-A3 source)93================================================================================94 95Module: upstream initcall registration. The __define_initcall(fn,96id) macro emits a function-pointer entry into section97.initcall<id>.init. Each upstream subsystem registers via one98of the wrapper macros (early_initcall, core_initcall,99subsys_initcall, fs_initcall, device_initcall, late_initcall,100plus their _sync variants). At link time wasm-ld groups all101.initcall<id>.init contributions per id into the corresponding102data segment. K10-A1 confirmed 10 such segments survive103--no-merge-data-segments + wasm-opt --asyncify, named exactly104.initcall{early,0,1,2,4,5,6,7,7s,rootfs}.init in vmlinux.wasm.105 106[DEF] linux/include/linux/init.h::__define_initcall + level wrappers:107 include/linux/init.h:282:#define __define_initcall(fn, id) ___define_initcall(fn, id, .initcall##id)108 include/linux/init.h:289:#define early_initcall(fn) __define_initcall(fn, early)109 include/linux/init.h:300:#define core_initcall(fn) __define_initcall(fn, 1)110 include/linux/init.h:302:#define postcore_initcall(fn) __define_initcall(fn, 2)111 include/linux/init.h:304:#define arch_initcall(fn) __define_initcall(fn, 3)112 include/linux/init.h:306:#define subsys_initcall(fn) __define_initcall(fn, 4)113 include/linux/init.h:308:#define fs_initcall(fn) __define_initcall(fn, 5)114 include/linux/init.h:310:#define rootfs_initcall(fn) __define_initcall(fn, rootfs)115 include/linux/init.h:311:#define device_initcall(fn) __define_initcall(fn, 6)116 include/linux/init.h:313:#define late_initcall(fn) __define_initcall(fn, 7)117 118[CALL] linux/include/linux/init.h — initcall_entry_t / initcall_t typedefs:119 include/linux/init.h:115:typedef int (*initcall_t)(void);120 include/linux/init.h:119:typedef int initcall_entry_t;121 include/linux/init.h:121:static inline initcall_t initcall_from_entry(initcall_entry_t *entry)122 include/linux/init.h:126:typedef initcall_t initcall_entry_t;123 include/linux/init.h:128:static inline initcall_t initcall_from_entry(initcall_entry_t *entry)124 include/linux/init.h:134:extern initcall_entry_t __con_initcall_start[], __con_initcall_end[];125 include/linux/init.h:142:extern int do_one_initcall(initcall_t fn);126 include/linux/init.h:158:extern initcall_entry_t __initcall_start[];127 include/linux/init.h:159:extern initcall_entry_t __initcall0_start[];128 include/linux/init.h:160:extern initcall_entry_t __initcall1_start[];129 include/linux/init.h:161:extern initcall_entry_t __initcall2_start[];130 include/linux/init.h:162:extern initcall_entry_t __initcall3_start[];131 include/linux/init.h:163:extern initcall_entry_t __initcall4_start[];132 include/linux/init.h:164:extern initcall_entry_t __initcall5_start[];133 include/linux/init.h:165:extern initcall_entry_t __initcall6_start[];134 include/linux/init.h:166:extern initcall_entry_t __initcall7_start[];135 include/linux/init.h:167:extern initcall_entry_t __initcall_end[];136 include/linux/init.h:266: static_assert(__same_type(initcall_t, &fn));137 include/linux/init.h:269: static initcall_t __name __used \138 139================================================================================1403. linux/include/asm-generic/vmlinux.lds.h — INITCALLS macro (K10-A3 mirror)141================================================================================142 143Module: upstream linker-script primitive. INITCALLS / INIT_CALLS_144LEVEL define the per-level boundary symbols145__initcall<level>_start / __initcall<level>_end via linker-script146syntax. wasm-ld doesn't consume linker scripts — same templated147debt class as the K2 sections.c shim and the K3 percpu_anchors.c148sibling. K10-A3 emits the per-level boundaries via post-link149binary surgery (synthesising active overlay segments at chosen150addresses; symbol values follow).151 152[DEF] linux/include/asm-generic/vmlinux.lds.h::INITCALLS / INIT_CALLS_LEVEL:153 include/asm-generic/vmlinux.lds.h:894:#define INIT_CALLS_LEVEL(level) \154 include/asm-generic/vmlinux.lds.h:899:#define INIT_CALLS \155 156[SITE] linux/include/asm-generic/vmlinux.lds.h — KEEP(*(.initcall*.init)) shape:157 include/asm-generic/vmlinux.lds.h:896: KEEP(*(.initcall##level##.init)) \158 include/asm-generic/vmlinux.lds.h:897: KEEP(*(.initcall##level##s.init)) \159 include/asm-generic/vmlinux.lds.h:901: KEEP(*(.initcallearly.init)) \160 161================================================================================1624. linux/drivers/tty/pty.c — pty_init / ptmx_open (K10-B1 surface)163================================================================================164 165Module: upstream pty subsystem. pty_init runs as a subsys_initcall166(level 4). Once K10-A4 lights up initcall dispatch, this fires167automatically. Provides /dev/ptmx (the master multiplexer) and168the /dev/pts/N slave path machinery.169 170[DEF] linux/drivers/tty/pty.c::pty_init / ptmx_open / pts_alloc:171 drivers/tty/pty.c:941 static int __init pty_init(void)172 drivers/tty/pty.c:790 static int ptmx_open(struct inode *inode, struct file *filp)173 drivers/tty/pty.c:439 static int pty_install(struct tty_driver *driver, struct tty_struct *tty)174 175[CALL] linux/drivers/tty/pty.c — initcall registrations:176 177================================================================================1785. linux/drivers/tty/n_tty.c — N_TTY line discipline (K10-B2/B3 surface)179================================================================================180 181Module: upstream canonical-mode line discipline. n_tty_receive182gets called when bytes arrive at the master side; n_tty_read183serves bytes to the slave-fd-reading user process; signal184generation (Ctrl-C → SIGINT, Ctrl-Z → SIGTSTP, Ctrl-\\ → SIGQUIT)185happens in process_input_char via isig(). K10-B3 wires this to186K8's signal infrastructure (kill_pgrp on the controlling tty's187foreground pgrp).188 189[DEF] linux/drivers/tty/n_tty.c::n_tty_{receive,read,write,ioctl}:190 drivers/tty/n_tty.c:2157 static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, u8 *kbuf,191 drivers/tty/n_tty.c:2358 static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,192 drivers/tty/n_tty.c:2503 static int n_tty_ioctl(struct tty_struct *tty, unsigned int cmd,193 194[DEF] linux/drivers/tty/n_tty.c::n_tty_init / process_input_char / isig:195 drivers/tty/n_tty.c:2557 void __init n_tty_init(void)196 drivers/tty/n_tty.c:1090 static void isig(int sig, struct tty_struct *tty)197 198[CALL] linux/drivers/tty/n_tty.c — VINTR / VSUSP / VQUIT / VEOF / VEOL references:199 200================================================================================2016. linux/drivers/tty/tty_io.c — tty subsystem core (K10-B1 dependency)202================================================================================203 204Module: upstream tty class registration. tty_init registers the205tty class. K10-B1 inherits unchanged. The arch wiring is via206HardwareJS pushing bytes to the master tty's flip buffer207(tty_insert_flip_string / tty_flip_buffer_push); the kernel-side208tty_io.c machinery is upstream-clean.209 210[DEF] linux/drivers/tty/tty_io.c::tty_init / tty_register_driver:211 drivers/tty/tty_io.c:3644 int __init tty_init(void)212 drivers/tty/tty_io.c:3440 int tty_register_driver(struct tty_driver *driver)213 drivers/tty/tty_io.c:3505 void tty_unregister_driver(struct tty_driver *driver)214 215[CALL] linux/drivers/tty/ — tty_insert_flip_string / tty_flip_buffer_push:216 drivers/tty/amiserial.c:260: tty_flip_buffer_push(&info->tport);217 drivers/tty/ehv_bytechan.c:384: ret = tty_insert_flip_string(&bc->port, buffer, len);218 drivers/tty/ehv_bytechan.c:399: tty_flip_buffer_push(&bc->port);219 drivers/tty/goldfish.c:146: tty_flip_buffer_push(&qtty->port);220 drivers/tty/hvc/hvc_console.c:755: tty_flip_buffer_push(&hp->port);221 drivers/tty/hvc/hvcs.c:583: tty_insert_flip_string(&hvcsd->port, buf, got);222 drivers/tty/hvc/hvcs.c:593: tty_flip_buffer_push(&hvcsd->port);223 drivers/tty/hvc/hvsi.c:457: tty_flip_buffer_push(&hp->port);224 drivers/tty/hvc/hvsi.c:503: tty_flip_buffer_push(&hp->port);225 drivers/tty/hvc/hvsi.c:984: tty_flip_buffer_push(&hp->port);226 227================================================================================2287. linux/drivers/tty/tty_jobctrl.c — controlling tty + foreground pgrp (K10-C1/C2)229================================================================================230 231Module: upstream job-control surface. TIOCSCTTY claims the tty as232controlling for the calling session leader; tcsetpgrp sets the233foreground pgrp; __tty_check_change generates SIGTTIN/SIGTTOU234when a background pgrp tries to read/write. Builds on K9-C2's235processGroupRegistry (the kernel-side task->signal->pgrp /236->session is consulted by these paths).237 238[DEF] linux/drivers/tty/tty_jobctrl.c::tiocsctty / no_tty:239 drivers/tty/tty_jobctrl.c:365 static int tiocsctty(struct tty_struct *tty, struct file *file, int arg)240 drivers/tty/tty_jobctrl.c:338 void no_tty(void)241 242[DEF] linux/drivers/tty/tty_jobctrl.c::tiocgpgrp / tiocspgrp / __tty_check_change:243 drivers/tty/tty_jobctrl.c:466 static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)244 drivers/tty/tty_jobctrl.c:493 static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)245 drivers/tty/tty_jobctrl.c:33 int __tty_check_change(struct tty_struct *tty, int sig)246 247[CALL] linux/drivers/tty/tty_jobctrl.c — kill_pgrp + SIGTTIN/SIGTTOU references:248 drivers/tty/tty_jobctrl.c:28: * not in the foreground, send a SIGTTOU. If the signal is blocked or249 drivers/tty/tty_jobctrl.c:51: if (sig == SIGTTIN)250 drivers/tty/tty_jobctrl.c:56: kill_pgrp(pgrp, sig, 1);251 drivers/tty/tty_jobctrl.c:71: return __tty_check_change(tty, SIGTTOU);252 drivers/tty/tty_jobctrl.c:185: * tty_signal_session_leader - sends SIGHUP to session leader253 drivers/tty/tty_jobctrl.c:189: * Send SIGHUP and SIGCONT to the session leader and its process group.254 drivers/tty/tty_jobctrl.c:218: send_signal_locked(SIGHUP, SEND_SIG_PRIV, p, PIDTYPE_TGID);255 drivers/tty/tty_jobctrl.c:234: kill_pgrp(tty_pgrp, SIGHUP, exit_session);256 drivers/tty/tty_jobctrl.c:249: * (1) Sends a SIGHUP and SIGCONT to the foreground process group257 drivers/tty/tty_jobctrl.c:280: kill_pgrp(tty_pgrp, SIGHUP, on_exit);258 drivers/tty/tty_jobctrl.c:282: kill_pgrp(tty_pgrp, SIGCONT, on_exit);259 drivers/tty/tty_jobctrl.c:296: kill_pgrp(old_pgrp, SIGHUP, on_exit);260 drivers/tty/tty_jobctrl.c:297: kill_pgrp(old_pgrp, SIGCONT, on_exit);261 262================================================================================2638. linux/drivers/tty/tty_ioctl.c — termios + TCGETS/TCSETS (K10-B2 surface)264================================================================================265 266Module: upstream termios syscall path. tty_mode_ioctl handles267TCGETS/TCSETS/TCSETSW/TCSETSF (the canonical/raw mode switching268surface bash readline uses). K10-B2 inherits unchanged once269ldisc is up.270 271[DEF] linux/drivers/tty/tty_ioctl.c::tty_mode_ioctl / set_termios / get_termios:272 drivers/tty/tty_ioctl.c:769 int tty_mode_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)273 drivers/tty/tty_ioctl.c:448 static int set_termios(struct tty_struct *tty, void __user *arg, int opt)274 275[CALL] linux/drivers/tty/tty_ioctl.c — TCGETS / TCSETS / TCSETSW / TCSETSF references:276 drivers/tty/tty_ioctl.c:802: case TCSETSF:277 drivers/tty/tty_ioctl.c:804: case TCSETSW:278 drivers/tty/tty_ioctl.c:806: case TCSETS:279 drivers/tty/tty_ioctl.c:809: case TCGETS:280 drivers/tty/tty_ioctl.c:815: case TCGETS:281 drivers/tty/tty_ioctl.c:832: case TCGETA:282 drivers/tty/tty_ioctl.c:834: case TCSETAF:283 drivers/tty/tty_ioctl.c:836: case TCSETAW:284 drivers/tty/tty_ioctl.c:838: case TCSETA:285 286================================================================================2879. wasm32-port/kernel/init.c — populate_rootfs hand-call (K10-A4 retires)288================================================================================289 290Module: arch-side init. K6 introduced291arch_kernel_init_pre_run_init(), called from the upstream292kernel_init path before run_init_process(). Currently it293hand-calls populate_rootfs() because do_initcalls() is a no-op294on wasm32 (the §15 row K10-A4 retires). Once K10-A4 lands and295do_initcalls walks every level via the K10-A3 anchor symbols,296the hand-call MUST be removed (rootfs_initcall registration of297populate_rootfs would otherwise fire twice).298 299[DEF] wasm32-port/kernel/init.c::arch_kernel_init_pre_run_init:300 kernel/init.c:224 void arch_kernel_init_pre_run_init(void)301 302[CALL] wasm32-port/kernel/init.c — populate_rootfs / do_initcalls / __initcall references:303 kernel/init.c:179: * Bridge for upstream's `populate_rootfs` rootfs_initcall.304 kernel/init.c:181: * Upstream registers populate_rootfs via `rootfs_initcall(...)`,305 kernel/init.c:183: * by init/main.c::do_initcalls(). On wasm32 the `__initcall*_start306 kernel/init.c:186: * NULLs and `do_initcalls()` is a no-op. populate_rootfs never307 kernel/init.c:214: "(arch hook bridges populate_rootfs because wasm32 doesn't "308 kernel/init.c:266: * initrd_start/end → populate_rootfs → kern_path() chain309 kernel/init.c:340: * so on wasm32 — where do_initcalls is a no-op (§15 row,310 kernel/init.c:341: * see sections.c) and populate_rootfs hasn't yet run — the311 kernel/init.c:350: * twice in K6: at K6-B1 (populate_rootfs not run) and again312 313================================================================================31410. wasm32-port/kernel/sections.c — __setup_start/end shims (related debt)315================================================================================316 317Module: K2 templated debt sibling. Same wasm-ld-doesn't-consume-318linker-scripts class as the initcall debt K10-A3 retires.319sections.c stays as-is at K10 (its sentinel-array workaround for320do_early_param + obsolete_checksetup is independent of the321initcall path); a future K-phase may unify both into a single322post-link pass.323 324[SITE] wasm32-port/kernel/sections.c — full file (K10 reference):325 kernel/sections.c:1 // SPDX-License-Identifier: GPL-2.0326 kernel/sections.c:2 /*327 kernel/sections.c:3 * arch/wasm32: shims for linker-script-defined section boundary symbols.328 kernel/sections.c:4 *329 kernel/sections.c:5 * On every other arch, Linux defines symbols like __setup_start /330 kernel/sections.c:6 * __setup_end / __initcall_start / __initcall_end inside the GNU331 kernel/sections.c:7 * linker script (include/asm-generic/vmlinux.lds.h) bracketing the332 kernel/sections.c:8 * corresponding `.init.setup`, `.initcall*.init`, etc. sections.333 kernel/sections.c:9 *334 kernel/sections.c:10 * wasm-ld does NOT consume GNU linker scripts and we don't run one in335 kernel/sections.c:11 * scripts/link-vmlinux-wasm.sh, so each of those symbol names ends up336 kernel/sections.c:12 * undefined. Building with --allow-undefined makes them link as337 kernel/sections.c:13 * 0-imported symbols; reading them at runtime returns 0; iterating338 kernel/sections.c:14 * `[0, 0)` is technically valid for plain `for` loops but the339 kernel/sections.c:15 * do-while in init/main.c::obsolete_checksetup runs the body once340 kernel/sections.c:16 * regardless and then dereferences a NULL `obs_kernel_param.str` —341 kernel/sections.c:17 * producing the K2-test "memory access out of bounds" trap.342 kernel/sections.c:18 *343 kernel/sections.c:19 * K2 fix: define each boundary symbol as a one-element sentinel344 kernel/sections.c:20 * range. Loops iterate exactly once, see an entry whose `.str` is a345 kernel/sections.c:21 * deliberately-unmatchable string, fall through, exit cleanly. No346 kernel/sections.c:22 * real handlers from upstream's `.init.setup` / `.initcallN.init`347 kernel/sections.c:23 * sections run yet — the wasm-ld-equivalent section anchoring is348 kernel/sections.c:24 * a §15 row deferred to K5 when virtio_console wants its349 kernel/sections.c:25 * `console=virtcon` handler to actually take effect. That row also350 kernel/sections.c:26 * unlocks subsystem initcall dispatch (rest_init / kernel_init's351 kernel/sections.c:27 * do_initcalls() walks the same kind of bounded table).352 kernel/sections.c:28 *353 kernel/sections.c:29 * This file is the centralised home for these shims so a future354 kernel/sections.c:30 * commit can replace them all together by emitting them from a real355 kernel/sections.c:31 * scripts/wasm-link-script.py post-processor.356 kernel/sections.c:32 */357 kernel/sections.c:33 358 kernel/sections.c:34 #include <linux/init.h>359 kernel/sections.c:35 #include <linux/types.h>360 kernel/sections.c:36 361 kernel/sections.c:37 /*362 kernel/sections.c:38 * obs_kernel_param sentinel: every field is set such that363 kernel/sections.c:39 * obsolete_checksetup's do-while sees one non-matching entry and364 kernel/sections.c:40 * exits. .str is a long, distinctive string no upstream caller will365 kernel/sections.c:41 * pass; .setup_func is NULL but never reached because parameqn fails.366 kernel/sections.c:42 */367 kernel/sections.c:43 static const char wasm32_setup_sentinel_str[] =368 kernel/sections.c:44 "__wasm32_section_sentinel_never_matches_any_param__";369 kernel/sections.c:45 370 kernel/sections.c:46 const struct obs_kernel_param __setup_start[1]371 kernel/sections.c:47 __attribute__((used, aligned(__alignof__(struct obs_kernel_param)))) = {372 kernel/sections.c:48 {373 kernel/sections.c:49 .str = wasm32_setup_sentinel_str,374 kernel/sections.c:50 .setup_func = NULL,375 kernel/sections.c:51 .early = 0,376 kernel/sections.c:52 },377 kernel/sections.c:53 };378 kernel/sections.c:54 379 kernel/sections.c:55 /*380 kernel/sections.c:56 * __setup_end aliased to __setup_start means start == end, so:381 kernel/sections.c:57 * - `for (p = start; p < end; p++)` (do_early_param's path) skips.382 kernel/sections.c:58 * - `do { ... } while (p < end);` (obsolete_checksetup's path)383 kernel/sections.c:59 * runs once on the sentinel and exits.384 kernel/sections.c:60 * Both behaviours are safe and produce zero handler dispatches,385 kernel/sections.c:61 * which matches the K2 trade-off documented above.386 kernel/sections.c:62 */387 kernel/sections.c:63 /*388 kernel/sections.c:64 * __setup_end must be a distinct symbol whose value is one entry past389 kernel/sections.c:65 * __setup_start[0], so that:390 kernel/sections.c:66 * do { ... p++; } while (p < __setup_end);391 kernel/sections.c:67 * runs exactly once on the sentinel and exits.392 kernel/sections.c:68 *393 kernel/sections.c:69 * We can't use __attribute__((alias)) — that would make __setup_end394 kernel/sections.c:70 * equal to __setup_start, and the do-while would run forever (p++395 kernel/sections.c:71 * past start, then p < end is false, but the loop is do-while so396 kernel/sections.c:72 * "ok" — actually that DOES exit after one iter; same address).397 kernel/sections.c:73 *398 kernel/sections.c:74 * Empirically, the simpler scheme of "both point at the same single-399 kernel/sections.c:75 * element array" is sufficient: the do-while runs once, the for-loop400 kernel/sections.c:76 * is empty, neither dereferences past the sentinel. To avoid the401 kernel/sections.c:77 * "definition cannot also be an alias" clang error, we make402 kernel/sections.c:78 * __setup_end a separate full definition that aliases the same data403 kernel/sections.c:79 * via a shared backing object.404 kernel/sections.c:80 */405 kernel/sections.c:81 extern const struct obs_kernel_param __setup_start[];406 kernel/sections.c:82 const struct obs_kernel_param *const __setup_end_marker = &__setup_start[0];407 kernel/sections.c:83 408 kernel/sections.c:84 /*409 kernel/sections.c:85 * Provide __setup_end as a real array symbol at the same address as410 kernel/sections.c:86 * __setup_start by re-exporting through inline assembly. wasm-ld411 kernel/sections.c:87 * accepts `.globl` and an absolute symbol equate.412 kernel/sections.c:88 */413 kernel/sections.c:89 asm(414 kernel/sections.c:90 " .globl __setup_end\n"415 kernel/sections.c:91 " .type __setup_end,@object\n"416 kernel/sections.c:92 " .set __setup_end, __setup_start\n"417 kernel/sections.c:93 );418 419================================================================================42011. wasm32-port/kernel/percpu_anchors.c — K10-A3 anchor pattern (sibling)421================================================================================422 423Module: K3/K4 sibling anchor pattern. Defines __per_cpu_start424(in section .data..percpu..aa_start, aligned PAGE_SIZE) and425__per_cpu_end (in .data..percpu..zz_end). wasm-ld input-order426determines emission order; the post-link pass (deferred from427K3) is what would patch __per_cpu_end's address to bracket the428actual percpu image. K10-A3's wasm-bracket-initcalls.py is the429first concrete implementation of this pattern; initcall_anchors.c430is its sibling for initcalls.431 432[SITE] wasm32-port/kernel/percpu_anchors.c — anchor declarations (K3 originals):433 kernel/percpu_anchors.c:27: * a __attribute__((section(".data..percpu..aa_start"))) sorts FIRST434 kernel/percpu_anchors.c:29: * c __attribute__((section(".data..percpu..zz_end"))) sorts LAST435 kernel/percpu_anchors.c:69:__attribute__((section(".data..percpu..aa_start"), used, aligned(PAGE_SIZE)))436 kernel/percpu_anchors.c:114:extern char __per_cpu_load[1] __attribute__((alias("__per_cpu_start")));437 kernel/percpu_anchors.c:116:extern char __per_cpu_end[1];438 kernel/percpu_anchors.c:162:__attribute__((section(".data..percpu..zz_end"), used))439 440[DEF] wasm32-port/kernel/percpu_anchors.c::__per_cpu_start / __per_cpu_end:441 kernel/percpu_anchors.c:70:char __per_cpu_start[1] = { 0 };442 kernel/percpu_anchors.c:163:char __per_cpu_end[1] = { 0 };443 444================================================================================44512. wasm32-port/kernel/percpu.c — K10-A3 override pattern (sibling)446================================================================================447 448Module: K4-R7 sibling. setup_per_cpu_areas overrides the generic449mm/percpu.c version because __per_cpu_end - __per_cpu_start450underestimates the static percpu image (input-order placement451makes start+end adjacent before any actual .data..percpu segments).452The post-link pass deferred from K3 would compute the real extent453and patch __per_cpu_end. K10-A3 is the analogous post-link pass454for initcalls; initcalls don't need a runtime override (the455anchor symbol values land directly), so the K10-A3 pattern is456simpler than K4-R7.457 458[DEF] wasm32-port/kernel/percpu.c::setup_per_cpu_areas:459 kernel/percpu.c:75 void __init setup_per_cpu_areas(void)460 461[CALL] wasm32-port/kernel/percpu.c — WASM32_STATIC_PCPU_SIZE / pcpu_setup_first_chunk references:462 kernel/percpu.c:36: * percpu data. WASM32_STATIC_PCPU_SIZE = 128 KiB is generous; the463 kernel/percpu.c:63:#define WASM32_STATIC_PCPU_SIZE (128UL * 1024UL)464 kernel/percpu.c:79: const size_t static_size = WASM32_STATIC_PCPU_SIZE;465 kernel/percpu.c:112: * pcpu_setup_first_chunk memcpy's static_size bytes from466 kernel/percpu.c:122: pcpu_setup_first_chunk(ai, base);467 468================================================================================46913. linux-wasm/scripts/link-vmlinux-wasm.sh — pipeline order (K10-A3 hook)470================================================================================471 472The post-link pipeline K10-A3 hooks into. Per473post-link-pass-conventions.rst §1, current ordering is:474 Pass 1: scripts/wasm-add-memory.py (splice env.user_memory)475 Pass 2: wasm-opt --asyncify --pass-arg=asyncify-asserts476 Pass 3: scripts/asyncify-strip-topmost-asserts.py477 478K10-A3 inserts wasm-bracket-initcalls.py BETWEEN Pass 1 and479Pass 2 (after multi-memory splice, before asyncify480instrumentation). Rationale: Pass 1 ensures the binary parses481under multi-memory; Pass 2 instruments function bodies but does482NOT rewrite data segments or __wasm_init_memory's body shape;483K10-A3's data-segment surgery must happen pre-asyncify so484asyncify's reachability analysis sees the final segment-init485code shape (NOPs replacing memory.init for the dropped passive486.initcall*.init segments).487 488[SITE] linux-wasm/scripts/link-vmlinux-wasm.sh — splice + asyncify pipeline (K10-A3 insertion site):489 link-vmlinux-wasm.sh:165 # post-link-pass-conventions.rst §1 for the post-link hierarchy.490 link-vmlinux-wasm.sh:166 #491 link-vmlinux-wasm.sh:167 # Pass 1: splice in env.user_memory as the second imported memory.492 link-vmlinux-wasm.sh:168 # Pass 2: --asyncify --pass-arg=asyncify-asserts (+ removelist).493 link-vmlinux-wasm.sh:169 # Pass 3: scripts/asyncify-strip-topmost-asserts.py.494 link-vmlinux-wasm.sh:170 #495 link-vmlinux-wasm.sh:171 # Why the splice has to come FIRST (changed at K4):496 link-vmlinux-wasm.sh:172 # Multi-memory ops with explicit memory immediate referencing memory 1497 link-vmlinux-wasm.sh:173 # (e.g. `memory.copy 1, 0` from kernel→user uaccess paths, and498 link-vmlinux-wasm.sh:174 # i32.atomic.rmw.cmpxchg targeting memory 1 from futex code) are499 link-vmlinux-wasm.sh:175 # already present in the wasm-ld output (LLVM emits the ops; wasm-ld500 link-vmlinux-wasm.sh:176 # preserves them — see Documentation/wasm/memory-model.rst on the501 link-vmlinux-wasm.sh:177 # "wasm-ld is multi-memory-blind, but it doesn't reject the ops"502 link-vmlinux-wasm.sh:178 # observation from K3). Until env.user_memory is spliced into the503 link-vmlinux-wasm.sh:179 # imports, the module declares only ONE memory and the multi-memory504 link-vmlinux-wasm.sh:180 # ops point at a nonexistent index. wasm-opt's parser fails with505 link-vmlinux-wasm.sh:181 # "invalid memory index" at that point. K3 happened to work because506 link-vmlinux-wasm.sh:182 # K3's pipeline went straight from wasm-ld to wasm-add-memory.py507 link-vmlinux-wasm.sh:183 # (which is multi-memory-aware: we wrote it). K4 inserts wasm-opt508 link-vmlinux-wasm.sh:184 # between them, so the splice has to lead.509 link-vmlinux-wasm.sh:185 #510 link-vmlinux-wasm.sh:186 # Sizing: min=1 page (64 KiB), max=65536 pages (4 GiB; wasm32 ceiling).511 link-vmlinux-wasm.sh:187 # shared=true because per-process user_memory MUST be SAB-backed and512 link-vmlinux-wasm.sh:188 # the standalone-Worker sentinel matches that shape (cf.513 link-vmlinux-wasm.sh:189 # hardwarejs/src/physRam.ts; K1 instantiation traps recorded the514 link-vmlinux-wasm.sh:190 # rationale in docs/ARCHITECTURE.md §18).515 link-vmlinux-wasm.sh:191 info SPLICE "$OUTPUT +env.user_memory (1..65536 pages, shared)"516 link-vmlinux-wasm.sh:192 SPLICE_PY="$(dirname "$0")/wasm-add-memory.py"517 link-vmlinux-wasm.sh:193 python3 "$SPLICE_PY" \518 link-vmlinux-wasm.sh:194 "$OUTPUT" \519 link-vmlinux-wasm.sh:195 --add-imported-memory env,user_memory,1,65536,shared \520 link-vmlinux-wasm.sh:196 -o "$OUTPUT.spliced"521 link-vmlinux-wasm.sh:197 mv -f "$OUTPUT.spliced" "$OUTPUT"522 link-vmlinux-wasm.sh:198 523 link-vmlinux-wasm.sh:199 # Pass 2/3: Asyncify (K4).524 link-vmlinux-wasm.sh:200 #525 526[SITE] linux-wasm/scripts/link-vmlinux-wasm.sh — --shared-memory + --no-merge-data-segments flags (K10-A1 cause analysis):527 link-vmlinux-wasm.sh:72:# across every Worker in the system) hence --shared-memory.528 link-vmlinux-wasm.sh:90: "--shared-memory"529 link-vmlinux-wasm.sh:102: "--no-merge-data-segments"530 531================================================================================53214. linux-wasm/scripts/wasm-add-memory.py — sibling Python pass (K10-A3 template)533================================================================================534 535The K3 sibling. Pure-Python post-link rewriter that adds an536imported memory entry to the module. K10-A3's537wasm-bracket-initcalls.py is structurally similar:538 * Walks DATA section + the "name" subsection 9 to identify539 .initcall<level>.init segments by name (K10-A1 inspect-540 wasm.py validated the substrate).541 * Walks __wasm_init_memory's function body to find each542 memory.init (i32.const dest, i32.const 0, i32.const N,543 memory.init seg_idx mem_idx) quartet.544 * Builds the new active overlay segments + emits NOPs in545 place of the original passive memory.init quartets.546 * Recomputes section size LEB128s.547 548[SITE] linux-wasm/scripts/wasm-add-memory.py — file structure:549 wasm-add-memory.py:55:def read_uleb128(buf: bytes, off: int) -> tuple[int, int]:550 wasm-add-memory.py:71:def write_uleb128(val: int) -> bytes:551 wasm-add-memory.py:93:def parse_sections(buf: bytes):552 wasm-add-memory.py:111:def encode_memory_limits(min_pages: int, max_pages: int | None, shared: bool) -> bytes:553 wasm-add-memory.py:127:def encode_import_entry(module: str, field: str, kind: int, payload: bytes) -> bytes:554 wasm-add-memory.py:140:def add_imported_memory(module_bytes: bytes,555 wasm-add-memory.py:194:def add_local_memory(module_bytes: bytes,556 wasm-add-memory.py:239:def parse_mem_spec(s: str) -> tuple[int, int | None, bool]:557 wasm-add-memory.py:248:def main() -> int:558 559================================================================================56015. linux-wasm/Documentation/wasm/post-link-pass-conventions.rst — pipeline spec561================================================================================562 563Module: post-link pass ordering authority. K10-A3 amends §1 with564the wasm-bracket-initcalls.py insertion point; its commit body565cites this section.566 567[SITE] post-link-pass-conventions.rst — section 1 (pass order):568 post-link-pass-conventions.rst:3:====================================================================569 post-link-pass-conventions.rst:5:====================================================================570 post-link-pass-conventions.rst:17:0. Why post-link surgery exists in this port at all571 post-link-pass-conventions.rst:50:1. The hierarchy of post-link tools572 post-link-pass-conventions.rst:81:2. Substitutive vs. additive — which shape your pass is573 post-link-pass-conventions.rst:143:3. Mandatory properties of a post-link pass574 post-link-pass-conventions.rst:186:4. Naming conventions575 post-link-pass-conventions.rst:203:5. Listed passes (current + planned)576 post-link-pass-conventions.rst:206:==================================================== ============ ============ =========== =====================================577 post-link-pass-conventions.rst:208:==================================================== ============ ============ =========== =====================================578 post-link-pass-conventions.rst:215:==================================================== ============ ============ =========== =====================================579 post-link-pass-conventions.rst:221:6. Anti-patterns580 581================================================================================58216. wackywasm-tools/musl-1.2.5/src/termios/ — tcsetattr / tcgetattr (K10-B2)583================================================================================584 585Module: musl termios surface. K10-B2 demos use these unchanged586once the kernel-side TCGETS/TCSETS path lights up via initcall587dispatch.588 589[DEF] musl-1.2.5/src/termios/{tcgetattr,tcsetattr,cfmakeraw,cfsetospeed,tcdrain,tcflow,tcflush}.c:590 src/termios/cfgetospeed.c:5:speed_t cfgetospeed(const struct termios *tio)591 src/termios/cfmakeraw.c:4:void cfmakeraw(struct termios *t)592 src/termios/cfsetospeed.c:6:int cfsetospeed(struct termios *tio, speed_t speed)593 src/termios/tcdrain.c:5:int tcdrain(int fd)594 src/termios/tcflow.c:4:int tcflow(int fd, int action)595 src/termios/tcflush.c:4:int tcflush(int fd, int queue)596 src/termios/tcgetattr.c:4:int tcgetattr(int fd, struct termios *tio)597 src/termios/tcsendbreak.c:4:int tcsendbreak(int fd, int dur)598 src/termios/tcsetattr.c:5:int tcsetattr(int fd, int act, const struct termios *tio)599 600================================================================================60117. wackywasm-tools/musl-1.2.5/src/misc/ — pty / openpty / forkpty (K10-B1)602================================================================================603 604Module: musl pty surface. posix_openpt / openpty / forkpty / 605ptsname / grantpt / unlockpt all live here. K10-B1 demos use606them unchanged once the kernel-side /dev/ptmx + /dev/pts/ paths607work via subsys_initcall fire (pty_init).608 609[DEF] musl-1.2.5/src/misc/{pty,openpty,forkpty}.c:610 src/misc/forkpty.c:9:int forkpty(int *pm, char *name, const struct termios *tio, const struct winsize *ws)611 src/misc/login_tty.c:5:int login_tty(int fd)612 src/misc/openpty.c:10:int openpty(int *pm, int *ps, char *name, const struct termios *tio, const struct winsize *ws)613 src/misc/pty.c:8:int posix_openpt(int flags)614 src/misc/pty.c:15:int grantpt(int fd)615 src/misc/pty.c:20:int unlockpt(int fd)616 617================================================================================61818. wackywasm-tools/musl-src/src_overrides/ — current state at K10-A2619================================================================================620 621Module: existing K7/K8/K9 src_overrides. K10-B may add a622tty/wasm32/ subtree if tcsetattr/tcgetattr need musl-side623wiring (e.g., to inject the pre/post __wasm_signal_dispatch_check624shape K8 added for sigaction.c). Default at K10-A2 is "no625new src_overrides yet"; K10-B will commit against this baseline.626 627[SITE] wackywasm-tools/musl-src/src_overrides/ — files at K10-A2:628 ../wackywasm-tools/musl-src/src_overrides/env/wasm32/__init_tls.c629 ../wackywasm-tools/musl-src/src_overrides/internal/wasm32/syscall_ret.c630 ../wackywasm-tools/musl-src/src_overrides/signal/wasm32/__wasm_signal_dispatch.c631 ../wackywasm-tools/musl-src/src_overrides/signal/wasm32/sigaction.c632 ../wackywasm-tools/musl-src/src_overrides/signal/wasm32/sigsuspend.c633 ../wackywasm-tools/musl-src/src_overrides/signal/wasm32/sigtimedwait.c634 ../wackywasm-tools/musl-src/src_overrides/thread/wasm32/__set_thread_area.c635 ../wackywasm-tools/musl-src/src_overrides/thread/wasm32/clone.c636 ../wackywasm-tools/musl-src/src_overrides/thread/wasm32/pthread_sigmask.c637 638================================================================================63919. hardwarejs/src/bootKernel.ts — BootKernelOptions extension (K10-B1 site)640================================================================================641 642Module: HardwareJS public API. K10-B1 will add an optional643terminalChannel field (mirror of K9-C1's stdinChannel), allowing644the embedder (xterm.js, prestrike-web LaunchMachine) to attach645to the master pty. Default at K10-A2 is the K9 stdinChannel646surface (legacy, EOF on read when no channel is attached).647 648[DEF] hardwarejs/src/bootKernel.ts::BootKernelOptions interface:649 bootKernel.ts:45:export interface BootKernelOptions {650 651[CALL] hardwarejs/src/bootKernel.ts — onUserOutput / stdinChannel callback shape (K10-B1 mirror):652 653================================================================================65420. hardwarejs/src/kernelSpawnHandler.ts — existing tty/termios stubs (K10-B2 site)655================================================================================656 657Module: K5/K7/K8/K9 syscall dispatcher. K10-B2 will turn the658TCGETS/TCSETS/TIOCSCTTY/TIOCSPGRP ioctl stubs into real659handlers (or rather, route them to the kernel's tty subsystem660once it's up via initcall dispatch). The current state is661mostly "ENOSYS" or "ENOTTY" stubs; K10-A2 captures the662pre-implementation state for refutation localisation.663 664[CALL] hardwarejs/src/kernelSpawnHandler.ts — existing TCGETS/TCSETS/TIOC* references:665 kernelSpawnHandler.ts:94:const __NR_ioctl = 16;666 kernelSpawnHandler.ts:1039: case __NR_ioctl: {667 kernelSpawnHandler.ts:1042: * decide line-buffered vs unbuffered. Returning -ENOTTY (-25)668 kernelSpawnHandler.ts:1044: * path. Any other ioctl is also -ENOTTY: K7 stdio is not a tty.669 kernelSpawnHandler.ts:1046: ret = -25; /* -ENOTTY */670 671================================================================================67221. hardwarejs/src/worker.mjs — fd 0 read path (K10-B2 ldisc routing site)673================================================================================674 675Module: user-Worker syscall fast path. K9-C1 wired SYS_read fd=0676to the per-tid stdinChannel queue. K10-B2 routes fd=0 reads677through the kernel's slave-fd ldisc (when the process has a678controlling terminal); the stdinChannel becomes the raw-bytes679input source the master tty's flip buffer consumes. Backward680compat preserved for K9-C1 demos via fall-through to stdinChannel681when no controlling terminal exists.682 683[CALL] hardwarejs/src/worker.mjs — SYS_read fd=0 path (K9-C1 baseline):684 685================================================================================68622. K10-A1 empirical findings (pinned for K10-A3 / K10-A4)687================================================================================688 689K10-A1 ran tools/k10-terminal-model-probe/inspect-wasm.py against690the current vmlinux.wasm (re-runnable from build artifacts; output691not committed because vmlinux.wasm is build-tree-local). Pinned692substrate facts:693 694 Total data segments: varies by kernel-side .config695 (~14k typical, of which the ten696 below are the .initcall*.init697 segments K10-A3 mirrors)698 .initcall*.init segments: 10 (early, 0, 1, 2, 4, 5, 6, 7,699 7s, rootfs)700 All ten kind: "passive" (root cause: --shared-701 memory in link-vmlinux-wasm.sh702 forces wasm-ld to emit all data703 segments as passive + a generated704 __wasm_init_memory function with705 cmpxchg-once memory.init opcodes)706 Per-segment byte size: 4..160 bytes707 (initcall_t = 4-byte function708 pointer; sizes are #initcalls × 4)709 Per-segment alignment: 4 bytes (initcall_t natural710 alignment)711 Total memory.init opcodes in 1849 (across all 1849 passive712 __wasm_init_memory: data segments; the .initcall*.init713 contribution is exactly 10)714 __wasm_init_memory function function index 4 (post-link;715 index: pre-asyncify; subject to drift716 across toolchain bumps)717 718K10-A3 strategy B emits per-level anchor symbols pointing at719new active overlay segments at kernel-controlled offsets;720zero-length passive segments + NOP'd memory.init quartets remain721in __wasm_init_memory for emission-shape symmetry but copy722nothing (4-byte segments → memory.init src=0 size=0). The723single-Worker invariant (terminal-model.rst §11.2.1) makes the724mixed active/passive emission shape zero-cost at runtime.725 726================================================================================72723. K10-B / K10-A3 / K10-A4 insertion-point summary728================================================================================729 730The following sites do NOT exist at K10-A2 close — they are731where K10-B / K10-A3 / K10-A4 will land NEW code:732 733 [K10-A3] linux-wasm/scripts/wasm-bracket-initcalls.py (NEW734 file, mirror of wasm-add-memory.py shape) — the735 post-link pass that synthesises active overlay736 segments + emits NOPs over the original passive737 memory.init quartets + writes initcall_anchors.c738 with the chosen extents.739 740 [K10-A3] linux-wasm/wasm32-port/kernel/initcall_anchors.c741 (NEW file, mirror of percpu_anchors.c shape) —742 the C source declaring __initcall<level>_start /743 __initcall<level>_end weak char[] with section744 attributes the post-link pass patches into the745 overlay. Generated/regenerated by the post-link746 pass; checked in as a stub with placeholder747 addresses for first-build bootstrap.748 749 [K10-A3] linux-wasm/scripts/link-vmlinux-wasm.sh — invocation750 of wasm-bracket-initcalls.py inserted between751 wasm-add-memory.py and wasm-opt --asyncify (per §13752 pipeline order rationale).753 754 [K10-A4] linux-wasm/wasm32-port/kernel/init.c —755 arch_kernel_init_pre_run_init() loses its756 populate_rootfs() hand-call (do_initcalls() now757 dispatches it via rootfs_initcall registration).758 Replaced with the K10-A4 single-Worker assertion759 (build-time-or-runtime check that vmlinux is760 instantiated by exactly one Worker).761 762 [K10-B1] linux-wasm/wasm32-port/kernel/ (potentially new763 wasm-arch shims if kernel-side pty allocation needs764 any; default expectation: zero, since pty.c +765 tty_io.c + n_tty.c are upstream-clean once initcalls766 fire).767 768 [K10-B1] hardwarejs/src/ttyChannel.ts (NEW; mirror of769 stdinChannel.ts shape) — exposes a master-pty handle770 the embedder attaches xterm.js or similar to. K10-B771 wires it into bootKernel.ts BootKernelOptions.772 773 [K10-B2] hardwarejs/src/kernelSpawnHandler.ts — TCGETS /774 TCSETS / TIOCSCTTY / TIOCGPGRP / TIOCSPGRP ioctl775 handlers (router → kernel ioctl path).776 777 [K10-B3] hardwarejs/src/worker.mjs — fd 0 read fall-through:778 when the process has a controlling tty, route reads779 via the kernel's slave-fd path; otherwise fall back780 to the K9-C1 stdinChannel queue.781 782 [K10-C1] hello-k10-pty.c demo + vitest exercising pty783 round-trip + ldisc canonical mode.784 785 [K10-C2] hello-k10-jobctrl.c demo + vitest exercising786 Ctrl-C → SIGINT → kill_pgrp via foreground pgrp.787 788================================================================================789END OF SNAPSHOT790================================================================================791