324 lines · plain
1.. SPDX-License-Identifier: GPL-2.02 3================================================================================4arch/wasm32 arch-hooks enumeration registry5================================================================================6 7:Status: K4 (two hooks landed; entries below cover them).8 K5+ adds a new entry per new arch hook *before* the9 implementation patch lands.10:Pinned upstream: Linux ``v6.12`` (see ``linux-wasm/Makefile``11 ``LINUX_VERSION``).12:Specification: ``docs/ARCHITECTURE.md §20`` — the principle this file13 implements. Every new entry is reviewed against §20's14 exhaustiveness criterion (§20.2). Behavior-enumeration15 entries follow the §20.3 sub-discipline.16 17This document is the concrete artifact required by18``docs/ARCHITECTURE.md §20``: for every arch hook that wasm32 introduces19into upstream kernel sources, the design phase MUST land an entry here20recording:21 221. The hook's name and the kernel invariant it enforces.232. The literal ``rg`` / ``grep`` invocation that enumerates every24 upstream site exercising the hooked behavior.253. The matched-line list (verbatim, with classifications):26 27 - **(a) hooked by this design** — the arch hook catches this site28 directly or indirectly.29 - **(b) does not affect the invariant** — with a one-line reason30 (boot-only, !CONFIG, etc.).31 - **(c) requires a new hook** — the spec is incomplete and must be32 amended; the implementation MUST NOT land until every (c) is33 reclassified to (a) or (b).34 354. The upstream version range the enumeration is valid for. When the36 pinned upstream version bumps, the grep is re-run and any new37 matches are reviewed.38 39Entries for hooks landed retroactively (K4's two hooks were added40before §20 was written) are reconstructed to the same format as a41worked example for K5+ design reviews. The retroactive entries are42labelled ``[retroactive]``.43 44The K4 hooks correspond to ``docs/ARCHITECTURE.md §17.7`` (scheduler45class routing); the runqueue dispatch path enumeration corresponds to46§17.7 THIRD HISTORICAL NOTE plus ``sched-model.rst §5.3`` (peek-not-pop).47 48--------------------------------------------------------------------------------490. How to use this file50--------------------------------------------------------------------------------51 52When a K-phase plan calls for a new arch hook:53 541. Write the entry in this file FIRST, with the grep-script and a55 complete site list. Classify each matched line.562. If any matched line is category (c), STOP. Amend the spec to57 account for it before landing the patch.583. Once every matched line is category (a) or (b), land the doc59 commit that adds the entry to this file. THEN land the60 implementation patch.614. Subsequent upstream-version bumps re-run every grep-script in62 this file. New matches start as category (c) until reviewed.63 64When reading this file as a debugger surfacing a refutation:65 661. Find the entry whose hook is the closest match to the broken67 invariant.682. Re-run the grep-script. If a new site appeared, the upstream69 pinned version drifted past the entry's validity range; bump70 the range, classify the new site, and either re-land as (b) or71 amend the design.723. If the grep-script's matched lines are unchanged but the bug is73 real, the bug is a behavior-enumeration miss (§20.3), not a74 site-enumeration miss. Cross-check the per-site behavior list75 (path A / path B / etc.) below.76 77--------------------------------------------------------------------------------781. ``arch_sched_fork`` [retroactive, K4]79--------------------------------------------------------------------------------80 81:Patch: ``linux-wasm/patches/0001-sched-add-arch_sched_fork-hook.patch``82:Override: ``arch/wasm32/kernel/sched.c::arch_sched_fork``83:Invariant: every task that goes through ``sched_fork()`` ends that84 function with ``p->sched_class = &wasm_sched_class``.85:Hook kind: side-effect-only ``void`` (arch wholly owns the write).86 87GREP-SCRIPT (run from upstream kernel root)::88 89 rg -n 'p->sched_class\s*=' kernel/sched/ kernel/fork.c90 91SITES FOUND (v6.12, classifications)::92 93 kernel/sched/core.c:4722:p->sched_class = &rt_sched_class;94 kernel/sched/core.c:4725:p->sched_class = &ext_sched_class;95 kernel/sched/core.c:4728:p->sched_class = &fair_sched_class;96 (a) — all three are inside sched_fork()'s policy → class97 switch, lines 4715–4730. arch_sched_fork(p) fires at98 the *end* of sched_fork(), after this switch, so the99 override is the last write and wins.100 101 kernel/sched/core.c:7233:p->sched_class = next_class;102 (b) — this is __rt_mutex_setprio(), not sched_fork().103 Caught by the separate arch_setscheduler_class hook104 (see entry 2 below) which makes next_class be105 &wasm_sched_class.106 107 kernel/sched/syscalls.c:724:p->sched_class = next_class;108 (b) — this is __sched_setscheduler(), not sched_fork().109 Caught by arch_setscheduler_class (entry 2).110 111 kernel/sched/ext.c:4524:p->sched_class = new_class;112 kernel/sched/ext.c:5240:p->sched_class = new_class;113 (b) — CONFIG_SCHED_CLASS_EXT is not set in114 arch/wasm32/configs/wasm32_defconfig, so ext.c is115 not compiled. If a future K-phase enables SCHED_CLASS_EXT116 for any reason, these two sites become (c) and the117 spec must be amended.118 119SECONDARY ENUMERATIONS — sites that initialize an idle task or stop120task to a non-wasm class (different invariant but same noun)::121 122 kernel/sched/core.c:3570:stop->sched_class = &stop_sched_class;123 kernel/sched/core.c:3594:old_stop->sched_class = &rt_sched_class;124 (b for K4) — sched_set_stop_task() runs during CPU hotplug125 (initial CPU bringup; secondary CPU bringup at K5). For K4126 only CPU0 is online and the stop task was created by127 cpuhp_threads init; we do not touch sched_class for that128 path. K5 MUST re-enumerate when secondary CPUs come online129 via Worker spawn — at that point this row may flip to (c).130 131 kernel/sched/core.c:7781:idle->sched_class = &idle_sched_class;132 (b for K4 via Site 3 override) — init_idle() runs once per133 CPU at boot. For CPU0 the idle task is init_task; our134 arch/wasm32/kernel/head.c::wasm_start_kernel directly135 overwrites init_task.sched_class = &wasm_sched_class after136 init_idle has run. (See sched-model.rst §5.1 Site 3.)137 For K5+ secondary CPUs, the per-CPU idle task created by138 fork_idle() / idle_init() will have idle_sched_class and139 the head.c override does NOT catch them. K5 MUST decide140 whether secondary-CPU idle tasks need a parallel override141 and amend this entry.142 143COVERAGE: every category-(a) primary site is hooked by144``arch_sched_fork`` directly; every category-(b) site is either145caught by ``arch_setscheduler_class`` (entry 2) or documented as a146not-yet-relevant boot/SMP path with an explicit K5+ retirement147signal. PASS for K4.148 149VALIDITY RANGE: ``v6.12`` (pinned). Re-run on upstream bump.150 151--------------------------------------------------------------------------------1522. ``arch_setscheduler_class`` [retroactive, K4]153--------------------------------------------------------------------------------154 155:Patch: ``linux-wasm/patches/0003-sched-add-arch_setscheduler_class-hook.patch``156:Override: ``arch/wasm32/kernel/sched.c::arch_setscheduler_class``157:Invariant: every call to ``__setscheduler_class(policy, prio)`` in158 upstream returns a class to be assigned via159 ``p->sched_class = next_class``; the override forces160 that return to be ``&wasm_sched_class`` unconditionally.161:Hook kind: ``const struct sched_class *`` returning value (NULL =162 passthrough to upstream policy → class mapping, non-NULL =163 use this class). See ``docs/ARCHITECTURE.md §19`` for the164 hook-shape rationale.165 166GREP-SCRIPT (run from upstream kernel root)::167 168 rg -n '__setscheduler_class\(' kernel/sched/169 170SITES FOUND (v6.12, classifications)::171 172 kernel/sched/core.c:7068:const struct sched_class *__setscheduler_class(int policy, int prio)173 — definition. The patch inserts the174 arch_setscheduler_class() consult+short-circuit175 at the top of this function.176 177 kernel/sched/core.c:7191: next_class = __setscheduler_class(p->policy, prio);178 (a) — __rt_mutex_setprio(). Caller assigns179 p->sched_class = next_class on line 7233; with the180 hook returning &wasm_sched_class, the assignment181 re-routes correctly.182 183 kernel/sched/syscalls.c:710: next_class = __setscheduler_class(policy, newprio);184 (a) — __sched_setscheduler(). Caller assigns185 p->sched_class = next_class on line 724. Triggered186 by sched_setscheduler(), sched_setscheduler_nocheck(),187 sched_setattr(), and sched_set_normal() (a wrapper).188 189 kernel/sched/ext.c:4516: __setscheduler_class(p->policy, p->prio);190 kernel/sched/ext.c:5231: __setscheduler_class(p->policy, p->prio);191 (b) — CONFIG_SCHED_CLASS_EXT not set; not compiled.192 Same retirement signal as entry 1's ext.c rows.193 194CALLER ENUMERATIONS (sites that drive ``__setscheduler_class`` via195``__sched_setscheduler``)::196 197 rg -n 'sched_setscheduler(?:_nocheck)?\(|sched_setattr\(' kernel/198 199 kernel/kthread.c:362: sched_setscheduler_nocheck(current, SCHED_NORMAL, ¶m);200 — INSIDE kthread() body. The first action of every201 kthread is to reset to SCHED_NORMAL via this path,202 which is exactly the path that motivated entry 2's203 existence. (See §17.7 SECOND HISTORICAL NOTE.)204 205 drivers/block/null_blk/null_blk_init.c, drivers/scsi/.../iscsi*,206 net/ipv4/inet_connection_sock.c, etc. — about 30 in-tree207 callers, all hitting __sched_setscheduler -> __setscheduler_class,208 all (a)-routed through entry 2.209 210COVERAGE: every category-(a) primary site has its return value211intercepted by ``arch_setscheduler_class`` before the caller212performs the assignment. PASS for K4.213 214VALIDITY RANGE: ``v6.12`` (pinned). Re-run on upstream bump.215 216--------------------------------------------------------------------------------2173. Behavior enumeration: ``__schedule`` yield paths (R3 forensic)218--------------------------------------------------------------------------------219 220:Subject: not a hook; a behavior-enumeration of a *single* upstream221 site whose internal paths each had to be modelled222 correctly. Recorded here as the worked example for223 ``docs/ARCHITECTURE.md §20.3`` (behavior enumeration224 within a single site).225:Invariant: every code path through ``__schedule()`` either leaves226 ``prev`` on ``wasm32_rq`` (if still runnable) or removes227 it (if transitioning to non-RUNNABLE), and228 ``pick_next_task_wasm`` produces a correct ``next`` for229 each path.230 231PATH ENUMERATION (v6.12, ``kernel/sched/core.c::__schedule``)::232 233 Path A: state-changing voluntary yield.234 prev->__state set to TASK_*INTERRUPTIBLE / _UNINTERRUPTIBLE /235 _DEAD / etc. BEFORE schedule() is called.236 __schedule branch (core.c:6627–6655):237 } else if (!preempt && prev_state) {238 if (signal_pending_state(prev_state, prev)) {239 WRITE_ONCE(prev->__state, TASK_RUNNING); /* falls to path B */240 } else {241 ...242 block_task(rq, prev, flags); /* DEQUEUE_NOCLOCK | DEQUEUE_SPECIAL */243 block = true;244 }245 ...246 }247 block_task -> dequeue_task(rq, p, DEQUEUE_SLEEP | flags)248 -> dequeue_task_wasm249 (removes prev from wasm32_rq).250 MODEL CORRECTNESS: pre-R3 and post-R3 both handle this path251 identically. dequeue_task_wasm is the canonical removal site252 from __schedule's perspective. deactivate_task is the253 migration-time analog (K5+, when tasks move between CPUs).254 255 Path B: state-preserving voluntary yield.256 prev->__state remains TASK_RUNNING (or signal_pending forces257 this branch). cond_resched(), bare schedule() with258 __set_current_state never called, preempt_schedule_*().259 __schedule branch: the deactivate_task block is skipped.260 pick_next_task is called, prev is still rq->curr but261 MUST also be on the rq for FIFO correctness.262 MODEL CORRECTNESS:263 - pre-R3: __wasm32_yield popped on dispatch, so prev was264 off the rq; pick_next_task_wasm saw empty rq, returned265 NULL, __schedule fell through to rq->idle, context_switch266 unwound prev permanently. WRONG.267 - post-R3: __wasm32_yield peeks; prev is still on the rq;268 pick_next_task_wasm returns prev (or a higher-priority269 head if one was enqueued via wake_up_process during prev's270 execution); __schedule sees prev == next when no preemption271 target exists and short-circuits without unwinding. CORRECT.272 273 Path C: prev is exiting (TASK_DEAD).274 do_exit() -> set_current_state(TASK_DEAD) -> schedule().275 Same as path A (state != TASK_RUNNING -> deactivate_task ->276 dequeue_task_wasm).277 MODEL CORRECTNESS: same as path A.278 279 Path D: preempt_schedule_irq / interrupt return preemption.280 Not exercised at K4 (no IRQs in cooperative model;281 CONFIG_PREEMPT_NONE-equivalent). If a future K-phase enables282 preemption, this becomes a (c) path requiring re-enumeration283 of __wasm32_yield's contract.284 285COVERAGE: paths A, B, C handled correctly post-R3. Path D not286applicable at K4; explicit (c) marker for the K-phase that introduces287preemption. PASS for K4.288 289VALIDITY RANGE: ``v6.12`` (pinned). The __schedule structure is290stable across many kernel versions; behavior enumeration is more291robust than line-number-based site enumeration. Re-run on upstream292bump but expect minimal drift.293 294--------------------------------------------------------------------------------2954. Hooks NOT yet introduced (K5+ placeholders)296--------------------------------------------------------------------------------297 298When K5+ design surfaces a new arch hook, add an entry below with299the format of entries 1 and 2. Examples of *possible* future hooks300that the §20 discipline anticipates (none of these are committed301designs):302 303* ``arch_init_idle`` — if K5's multi-CPU bringup needs secondary-CPU304 idle tasks pinned to ``wasm_sched_class``, parallel to head.c's305 CPU0 direct write. (Discovered during entry 1 secondary306 enumeration.)307* ``arch_binfmt_load_binary`` / ``arch_execve_complete`` — K5's308 binfmt_wasm + HardwareJS Worker spawn boundary. Enumeration:309 every site in ``fs/binfmt_*.c`` that calls ``->load_binary`` plus310 every site in ``fs/exec.c`` that completes an exec.311* ``arch_vm_ops`` — K5 MM hooks. Enumeration: every312 ``vma->vm_ops = ...`` and every ``->vm_ops->...()`` dispatch in313 ``mm/`` and ``fs/``.314* ``arch_file_operations`` — K6 storage hooks. Enumeration: every315 ``inode->i_fop = ...`` / ``file->f_op = ...`` and every316 dispatch through ``->f_op->...()``.317* ``arch_signal_deliver`` — K6+ signal handling. Enumeration: every318 ``get_signal()`` consumer plus ``do_signal()`` arch entry points.319 320Each placeholder above is non-binding. The K5+ commit that *actually321introduces* one of these (or any hook not listed) MUST add a real322entry to this file in the same commit as the hook patch, with323exhaustive site enumeration per §20.2.324