.. SPDX-License-Identifier: GPL-2.0

================================================================================
arch/wasm32 arch-hooks enumeration registry
================================================================================

:Status:           K4 (two hooks landed; entries below cover them).
                   K5+ adds a new entry per new arch hook *before* the
                   implementation patch lands.
:Pinned upstream:  Linux ``v6.12`` (see ``linux-wasm/Makefile``
                   ``LINUX_VERSION``).
:Specification:    ``docs/ARCHITECTURE.md §20`` — the principle this file
                   implements. Every new entry is reviewed against §20's
                   exhaustiveness criterion (§20.2). Behavior-enumeration
                   entries follow the §20.3 sub-discipline.

This document is the concrete artifact required by
``docs/ARCHITECTURE.md §20``: for every arch hook that wasm32 introduces
into upstream kernel sources, the design phase MUST land an entry here
recording:

1. The hook's name and the kernel invariant it enforces.
2. The literal ``rg`` / ``grep`` invocation that enumerates every
   upstream site exercising the hooked behavior.
3. The matched-line list (verbatim, with classifications):

   - **(a) hooked by this design** — the arch hook catches this site
     directly or indirectly.
   - **(b) does not affect the invariant** — with a one-line reason
     (boot-only, !CONFIG, etc.).
   - **(c) requires a new hook** — the spec is incomplete and must be
     amended; the implementation MUST NOT land until every (c) is
     reclassified to (a) or (b).

4. The upstream version range the enumeration is valid for. When the
   pinned upstream version bumps, the grep is re-run and any new
   matches are reviewed.

Entries for hooks landed retroactively (K4's two hooks were added
before §20 was written) are reconstructed to the same format as a
worked example for K5+ design reviews. The retroactive entries are
labelled ``[retroactive]``.

The K4 hooks correspond to ``docs/ARCHITECTURE.md §17.7`` (scheduler
class routing); the runqueue dispatch path enumeration corresponds to
§17.7 THIRD HISTORICAL NOTE plus ``sched-model.rst §5.3`` (peek-not-pop).

--------------------------------------------------------------------------------
0. How to use this file
--------------------------------------------------------------------------------

When a K-phase plan calls for a new arch hook:

1. Write the entry in this file FIRST, with the grep-script and a
   complete site list. Classify each matched line.
2. If any matched line is category (c), STOP. Amend the spec to
   account for it before landing the patch.
3. Once every matched line is category (a) or (b), land the doc
   commit that adds the entry to this file. THEN land the
   implementation patch.
4. Subsequent upstream-version bumps re-run every grep-script in
   this file. New matches start as category (c) until reviewed.

When reading this file as a debugger surfacing a refutation:

1. Find the entry whose hook is the closest match to the broken
   invariant.
2. Re-run the grep-script. If a new site appeared, the upstream
   pinned version drifted past the entry's validity range; bump
   the range, classify the new site, and either re-land as (b) or
   amend the design.
3. If the grep-script's matched lines are unchanged but the bug is
   real, the bug is a behavior-enumeration miss (§20.3), not a
   site-enumeration miss. Cross-check the per-site behavior list
   (path A / path B / etc.) below.

--------------------------------------------------------------------------------
1. ``arch_sched_fork`` [retroactive, K4]
--------------------------------------------------------------------------------

:Patch:        ``linux-wasm/patches/0001-sched-add-arch_sched_fork-hook.patch``
:Override:     ``arch/wasm32/kernel/sched.c::arch_sched_fork``
:Invariant:    every task that goes through ``sched_fork()`` ends that
               function with ``p->sched_class = &wasm_sched_class``.
:Hook kind:    side-effect-only ``void`` (arch wholly owns the write).

GREP-SCRIPT (run from upstream kernel root)::

    rg -n 'p->sched_class\s*=' kernel/sched/ kernel/fork.c

SITES FOUND (v6.12, classifications)::

    kernel/sched/core.c:4722:p->sched_class = &rt_sched_class;
    kernel/sched/core.c:4725:p->sched_class = &ext_sched_class;
    kernel/sched/core.c:4728:p->sched_class = &fair_sched_class;
        (a) — all three are inside sched_fork()'s policy → class
        switch, lines 4715–4730. arch_sched_fork(p) fires at
        the *end* of sched_fork(), after this switch, so the
        override is the last write and wins.

    kernel/sched/core.c:7233:p->sched_class = next_class;
        (b) — this is __rt_mutex_setprio(), not sched_fork().
        Caught by the separate arch_setscheduler_class hook
        (see entry 2 below) which makes next_class be
        &wasm_sched_class.

    kernel/sched/syscalls.c:724:p->sched_class = next_class;
        (b) — this is __sched_setscheduler(), not sched_fork().
        Caught by arch_setscheduler_class (entry 2).

    kernel/sched/ext.c:4524:p->sched_class = new_class;
    kernel/sched/ext.c:5240:p->sched_class = new_class;
        (b) — CONFIG_SCHED_CLASS_EXT is not set in
        arch/wasm32/configs/wasm32_defconfig, so ext.c is
        not compiled. If a future K-phase enables SCHED_CLASS_EXT
        for any reason, these two sites become (c) and the
        spec must be amended.

SECONDARY ENUMERATIONS — sites that initialize an idle task or stop
task to a non-wasm class (different invariant but same noun)::

    kernel/sched/core.c:3570:stop->sched_class = &stop_sched_class;
    kernel/sched/core.c:3594:old_stop->sched_class = &rt_sched_class;
        (b for K4) — sched_set_stop_task() runs during CPU hotplug
        (initial CPU bringup; secondary CPU bringup at K5). For K4
        only CPU0 is online and the stop task was created by
        cpuhp_threads init; we do not touch sched_class for that
        path. K5 MUST re-enumerate when secondary CPUs come online
        via Worker spawn — at that point this row may flip to (c).

    kernel/sched/core.c:7781:idle->sched_class = &idle_sched_class;
        (b for K4 via Site 3 override) — init_idle() runs once per
        CPU at boot. For CPU0 the idle task is init_task; our
        arch/wasm32/kernel/head.c::wasm_start_kernel directly
        overwrites init_task.sched_class = &wasm_sched_class after
        init_idle has run. (See sched-model.rst §5.1 Site 3.)
        For K5+ secondary CPUs, the per-CPU idle task created by
        fork_idle() / idle_init() will have idle_sched_class and
        the head.c override does NOT catch them. K5 MUST decide
        whether secondary-CPU idle tasks need a parallel override
        and amend this entry.

COVERAGE: every category-(a) primary site is hooked by
``arch_sched_fork`` directly; every category-(b) site is either
caught by ``arch_setscheduler_class`` (entry 2) or documented as a
not-yet-relevant boot/SMP path with an explicit K5+ retirement
signal. PASS for K4.

VALIDITY RANGE: ``v6.12`` (pinned). Re-run on upstream bump.

--------------------------------------------------------------------------------
2. ``arch_setscheduler_class`` [retroactive, K4]
--------------------------------------------------------------------------------

:Patch:        ``linux-wasm/patches/0003-sched-add-arch_setscheduler_class-hook.patch``
:Override:     ``arch/wasm32/kernel/sched.c::arch_setscheduler_class``
:Invariant:    every call to ``__setscheduler_class(policy, prio)`` in
               upstream returns a class to be assigned via
               ``p->sched_class = next_class``; the override forces
               that return to be ``&wasm_sched_class`` unconditionally.
:Hook kind:    ``const struct sched_class *`` returning value (NULL =
               passthrough to upstream policy → class mapping, non-NULL =
               use this class). See ``docs/ARCHITECTURE.md §19`` for the
               hook-shape rationale.

GREP-SCRIPT (run from upstream kernel root)::

    rg -n '__setscheduler_class\(' kernel/sched/

SITES FOUND (v6.12, classifications)::

    kernel/sched/core.c:7068:const struct sched_class *__setscheduler_class(int policy, int prio)
        — definition. The patch inserts the
        arch_setscheduler_class() consult+short-circuit
        at the top of this function.

    kernel/sched/core.c:7191:	next_class = __setscheduler_class(p->policy, prio);
        (a) — __rt_mutex_setprio(). Caller assigns
        p->sched_class = next_class on line 7233; with the
        hook returning &wasm_sched_class, the assignment
        re-routes correctly.

    kernel/sched/syscalls.c:710:	next_class = __setscheduler_class(policy, newprio);
        (a) — __sched_setscheduler(). Caller assigns
        p->sched_class = next_class on line 724. Triggered
        by sched_setscheduler(), sched_setscheduler_nocheck(),
        sched_setattr(), and sched_set_normal() (a wrapper).

    kernel/sched/ext.c:4516:		__setscheduler_class(p->policy, p->prio);
    kernel/sched/ext.c:5231:		__setscheduler_class(p->policy, p->prio);
        (b) — CONFIG_SCHED_CLASS_EXT not set; not compiled.
        Same retirement signal as entry 1's ext.c rows.

CALLER ENUMERATIONS (sites that drive ``__setscheduler_class`` via
``__sched_setscheduler``)::

    rg -n 'sched_setscheduler(?:_nocheck)?\(|sched_setattr\(' kernel/

      kernel/kthread.c:362:	sched_setscheduler_nocheck(current, SCHED_NORMAL, &param);
        — INSIDE kthread() body. The first action of every
        kthread is to reset to SCHED_NORMAL via this path,
        which is exactly the path that motivated entry 2's
        existence. (See §17.7 SECOND HISTORICAL NOTE.)

      drivers/block/null_blk/null_blk_init.c, drivers/scsi/.../iscsi*,
      net/ipv4/inet_connection_sock.c, etc. — about 30 in-tree
      callers, all hitting __sched_setscheduler -> __setscheduler_class,
      all (a)-routed through entry 2.

COVERAGE: every category-(a) primary site has its return value
intercepted by ``arch_setscheduler_class`` before the caller
performs the assignment. PASS for K4.

VALIDITY RANGE: ``v6.12`` (pinned). Re-run on upstream bump.

--------------------------------------------------------------------------------
3. Behavior enumeration: ``__schedule`` yield paths (R3 forensic)
--------------------------------------------------------------------------------

:Subject:      not a hook; a behavior-enumeration of a *single* upstream
               site whose internal paths each had to be modelled
               correctly. Recorded here as the worked example for
               ``docs/ARCHITECTURE.md §20.3`` (behavior enumeration
               within a single site).
:Invariant:    every code path through ``__schedule()`` either leaves
               ``prev`` on ``wasm32_rq`` (if still runnable) or removes
               it (if transitioning to non-RUNNABLE), and
               ``pick_next_task_wasm`` produces a correct ``next`` for
               each path.

PATH ENUMERATION (v6.12, ``kernel/sched/core.c::__schedule``)::

    Path A: state-changing voluntary yield.
      prev->__state set to TASK_*INTERRUPTIBLE / _UNINTERRUPTIBLE /
      _DEAD / etc. BEFORE schedule() is called.
      __schedule branch (core.c:6627–6655):
        } else if (!preempt && prev_state) {
            if (signal_pending_state(prev_state, prev)) {
                WRITE_ONCE(prev->__state, TASK_RUNNING);  /* falls to path B */
            } else {
                ...
                block_task(rq, prev, flags);    /* DEQUEUE_NOCLOCK | DEQUEUE_SPECIAL */
                block = true;
            }
            ...
        }
      block_task -> dequeue_task(rq, p, DEQUEUE_SLEEP | flags)
                 -> dequeue_task_wasm
                 (removes prev from wasm32_rq).
      MODEL CORRECTNESS: pre-R3 and post-R3 both handle this path
      identically. dequeue_task_wasm is the canonical removal site
      from __schedule's perspective. deactivate_task is the
      migration-time analog (K5+, when tasks move between CPUs).

    Path B: state-preserving voluntary yield.
      prev->__state remains TASK_RUNNING (or signal_pending forces
      this branch). cond_resched(), bare schedule() with
      __set_current_state never called, preempt_schedule_*().
      __schedule branch: the deactivate_task block is skipped.
      pick_next_task is called, prev is still rq->curr but
      MUST also be on the rq for FIFO correctness.
      MODEL CORRECTNESS:
        - pre-R3: __wasm32_yield popped on dispatch, so prev was
          off the rq; pick_next_task_wasm saw empty rq, returned
          NULL, __schedule fell through to rq->idle, context_switch
          unwound prev permanently. WRONG.
        - post-R3: __wasm32_yield peeks; prev is still on the rq;
          pick_next_task_wasm returns prev (or a higher-priority
          head if one was enqueued via wake_up_process during prev's
          execution); __schedule sees prev == next when no preemption
          target exists and short-circuits without unwinding. CORRECT.

    Path C: prev is exiting (TASK_DEAD).
      do_exit() -> set_current_state(TASK_DEAD) -> schedule().
      Same as path A (state != TASK_RUNNING -> deactivate_task ->
      dequeue_task_wasm).
      MODEL CORRECTNESS: same as path A.

    Path D: preempt_schedule_irq / interrupt return preemption.
      Not exercised at K4 (no IRQs in cooperative model;
      CONFIG_PREEMPT_NONE-equivalent). If a future K-phase enables
      preemption, this becomes a (c) path requiring re-enumeration
      of __wasm32_yield's contract.

COVERAGE: paths A, B, C handled correctly post-R3. Path D not
applicable at K4; explicit (c) marker for the K-phase that introduces
preemption. PASS for K4.

VALIDITY RANGE: ``v6.12`` (pinned). The __schedule structure is
stable across many kernel versions; behavior enumeration is more
robust than line-number-based site enumeration. Re-run on upstream
bump but expect minimal drift.

--------------------------------------------------------------------------------
4. Hooks NOT yet introduced (K5+ placeholders)
--------------------------------------------------------------------------------

When K5+ design surfaces a new arch hook, add an entry below with
the format of entries 1 and 2. Examples of *possible* future hooks
that the §20 discipline anticipates (none of these are committed
designs):

* ``arch_init_idle`` — if K5's multi-CPU bringup needs secondary-CPU
  idle tasks pinned to ``wasm_sched_class``, parallel to head.c's
  CPU0 direct write. (Discovered during entry 1 secondary
  enumeration.)
* ``arch_binfmt_load_binary`` / ``arch_execve_complete`` — K5's
  binfmt_wasm + HardwareJS Worker spawn boundary. Enumeration:
  every site in ``fs/binfmt_*.c`` that calls ``->load_binary`` plus
  every site in ``fs/exec.c`` that completes an exec.
* ``arch_vm_ops`` — K5 MM hooks. Enumeration: every
  ``vma->vm_ops = ...`` and every ``->vm_ops->...()`` dispatch in
  ``mm/`` and ``fs/``.
* ``arch_file_operations`` — K6 storage hooks. Enumeration: every
  ``inode->i_fop = ...`` / ``file->f_op = ...`` and every
  dispatch through ``->f_op->...()``.
* ``arch_signal_deliver`` — K6+ signal handling. Enumeration: every
  ``get_signal()`` consumer plus ``do_signal()`` arch entry points.

Each placeholder above is non-binding. The K5+ commit that *actually
introduces* one of these (or any hook not listed) MUST add a real
entry to this file in the same commit as the hook patch, with
exhaustive site enumeration per §20.2.
