Skip to content

Commit e9d5651

Browse files
riccajasonclaude
andcommitted
games: move tree/worm/sprouty off colliding IPC endpoints
What: - tree 31 -> 61 - worm 29 -> 62 - sprouty 15 -> 63 Each game's window-input endpoint is reassigned to the top of the 64-wide endpoint space, above the dense boot-service band (14..=33). Stale "Revisit when: MAX_ENDPOINTS > 32" comments are rewritten and re-pointed at ADR-018 (the trigger already fired — the bound is 64). Why: Endpoint IDs are ad-hoc `const u32`s with no kernel-enforced one-owner-per-endpoint check, and IPC queues are per-endpoint global (SHARDED_IPC.shards[endpoint]). Games written months ago picked numbers that auto-started boot services later claimed: - tree=31 collided with usb-host (live): usb-host blocks on recv_verified(31) and drained the compositor's routed input, so `play tree` opened a window that ignored all input. - sprouty=15 collided with terminal-window's front layer (live) — same input-theft mechanism. - worm=29 aliases hello-window (disabled in limine.conf) — latent. Parking games at 61/62/63 clears every auto-started service. Out of scope: - ping (19) is collision-free; left unchanged. - The structural fix is ADR-018's endpoint-reservation table (kernel rejects RegisterEndpoint(N) from non-owners). This commit is the band-aid that unblocks the games now; high-end parking can still re-collide if a service grows past ~34. - No kernel changes. Each endpoint is referenced only inside its own game crate; the compositor learns it via the Client::open handshake. Verification: - make tree worm sprouty — all three build clean (x86_64). - make check-deferrals — 0 new (485 baseline). - make check-doc-refs — 0 new (46 baseline). - Runtime input routing needs an interactive GUI test: make run-gui, then `play tree` / `play sprouty` / `play worm`. Staged files: user/sprouty/src/main.rs user/tree/src/main.rs user/worm/src/main.rs Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 80225e3 commit e9d5651

3 files changed

Lines changed: 42 additions & 35 deletions

File tree

user/sprouty/src/main.rs

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,27 +37,23 @@ use cambios_sprouty::{
3737
level,
3838
};
3939

40-
/// IPC endpoint. `MAX_ENDPOINTS` is a SCAFFOLDING bound of 32 in
41-
/// [src/ipc/mod.rs], so valid IDs are 0..=31. 22 is free under the
42-
/// current allocation (16=FS, 17=KS, 18=shell, 19=ping, 20=virtio-net,
43-
/// 21=udp-stack, 24/25/26=virtio-blk, 27=scanout-driver, 28=compositor,
44-
/// 29=worm/hello-window, 30=input, 31=tree).
45-
///
46-
/// Revisit when: MAX_ENDPOINTS is raised — sprouty moves to
47-
/// its class-grouped slot (34) alongside Tree=31 / Worm=32 / Ping=33.
48-
// Was 22 (POLICY_QUERY_ENDPOINT collision). Then 23, which silently
49-
// collides with `POLICY_RESP_ENDPOINT` -- the kernel hardcodes a
50-
// "only the policy service may write to ep 23" check in
51-
// handle_write (src/syscalls/dispatcher.rs:417), so the compositor's
52-
// Welcome reply to sprouty got -EPERM at the kernel level and
53-
// sprouty blocked forever on recv_verified.
54-
// 15 is in the kernel-task grant range (0..16 per
55-
// capability_manager_init) but no service registers there, and
56-
// the kernel has no hardcoded intercept on it. After Phase 3.4
57-
// MAX_ENDPOINTS bump + name-server lands, games will stop hand-
58-
// picking and this comment can be retired.
59-
// Revisit when: name-server lands or MAX_ENDPOINTS > 32.
60-
const SPROUTY_ENDPOINT: u32 = 15;
40+
/// Sprouty's window input endpoint. Games sit at the top of the now-64-wide
41+
/// endpoint space (Tree=61, Worm=62, Sprouty=63), deliberately above the
42+
/// boot-service band (14..=33). Sprouty's endpoint has collided repeatedly
43+
/// as the low band filled in — a worked example of why ad-hoc `const u32`
44+
/// endpoints need the structural fix in ADR-018:
45+
/// - 22 aliased POLICY_QUERY_ENDPOINT.
46+
/// - 23 aliased POLICY_RESP_ENDPOINT; the kernel hardcodes a "only the
47+
/// policy service may write to ep 23" check in handle_write, so the
48+
/// compositor's Welcome reply got -EPERM and sprouty blocked forever
49+
/// on recv_verified.
50+
/// - 15 looked free, but terminal-window (auto-started) opens its front
51+
/// layer on 15 and drains the shared per-endpoint queue, stealing
52+
/// sprouty's routed input.
53+
/// 63 is at the top of the space, clear of every auto-started service.
54+
/// Revisit when: ADR-018's endpoint reservation table lands — hand-picked
55+
/// game endpoints move under manifest-declared reservations.
56+
const SPROUTY_ENDPOINT: u32 = 63;
6157

6258
/// TUNING: physics tick interval in kernel ticks (1 tick = 10 ms at
6359
/// 100 Hz). 3 → 30 ms → 33 FPS — first game past ping's 20 FPS, first

user/tree/src/main.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,18 @@ mod sprites;
4646

4747
use game::{Board, RevealOutcome, State};
4848

49-
const TREE_ENDPOINT: u32 = 31;
49+
/// Tree's window input endpoint. Games sit at the top of the now-64-wide
50+
/// endpoint space (Tree=61, Worm=62, Sprouty=63), deliberately above the
51+
/// boot-service band (14..=33). That band is densely allocated and
52+
/// auto-started services keep growing into it: Tree originally used 31 and
53+
/// silently lost all input to `usb-host`, which also claims 31 and drains
54+
/// the shared per-endpoint queue, so the compositor's routed events never
55+
/// reached this game. Endpoint IDs are ad-hoc `const u32`s with no
56+
/// kernel-enforced one-owner-per-endpoint check; ADR-018's endpoint
57+
/// reservation table is the structural fix.
58+
/// Revisit when: ADR-018's endpoint reservation table lands — hand-picked
59+
/// game endpoints move under manifest-declared reservations.
60+
const TREE_ENDPOINT: u32 = 61;
5061

5162
/// HID usage codes we care about. Full evdev→HID table lives in
5263
/// `user/virtio-input/src/evdev.rs`; we re-declare only the two we

user/worm/src/main.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,19 @@ use cambios_worm::game::{Direction, State, StepOutcome, Worm};
5656

5757
mod render;
5858

59-
/// Worm's IPC endpoint. The launch-plan direction is "one endpoint
60-
/// per app, grouped by class" (Tree=31, Worm=32, Pong=33, Mario=34),
61-
/// but the kernel's `MAX_ENDPOINTS` is currently a SCAFFOLDING bound
62-
/// of 32 — endpoint IDs are 0..=31, so 32 is out of range and
63-
/// `register_endpoint(32)` fails. Worm sits at 29 (free between
64-
/// compositor=28 and compositor-input=30) until the bound is bumped
65-
/// per docs/ASSUMPTIONS.md's replacement trigger ("first service that
66-
/// needs >32 endpoints"). When MAX_ENDPOINTS grows, move Worm to the
67-
/// planned slot and group by app class.
68-
///
69-
/// Revisit when: MAX_ENDPOINTS is raised kernel-side — Worm + Pong +
70-
/// Mario all move to their class-grouped IDs at that point.
71-
const WORM_ENDPOINT: u32 = 29;
59+
/// Worm's window input endpoint. Games sit at the top of the now-64-wide
60+
/// endpoint space (Tree=61, Worm=62, Sprouty=63), deliberately above the
61+
/// boot-service band (14..=33). The old launch-plan slots (Tree=31,
62+
/// Worm=32, Pong=33, Mario=34) were eaten by services that grew into that
63+
/// range (usb-host=31, fde-mount=32, ccid=33), so class-grouping moved to
64+
/// the high end. Worm previously sat at 29, which aliases hello-window's
65+
/// endpoint — it only worked because hello-window is disabled in
66+
/// limine.conf. Endpoint IDs are ad-hoc `const u32`s with no
67+
/// kernel-enforced ownership; ADR-018's reservation table is the
68+
/// structural fix.
69+
/// Revisit when: ADR-018's endpoint reservation table lands — hand-picked
70+
/// game endpoints move under manifest-declared reservations.
71+
const WORM_ENDPOINT: u32 = 62;
7272

7373
/// USB HID usage codes we bind. Full evdev→HID table lives in
7474
/// `user/virtio-input/src/evdev.rs`; we re-declare only the ones the

0 commit comments

Comments
 (0)