Skip to content

[MAZ-180] Remove dead legacy CompletionRing machinery - #106

Open
iansmith wants to merge 1 commit into
masterfrom
chore/MAZ-180
Open

iansmith wants to merge 1 commit into
masterfrom
chore/MAZ-180

Conversation

@iansmith

@iansmith iansmith commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Summary

Removes the dead legacy shared-page CompletionRing IPC path — syscall 0x1039 SysRegisterCompletionRing and everything downstream. The registration syscall had zero userspace callers (verified by grep sweep over all .go/.s plus a no-filter sweep, on master 8822835e), so blockCompletionRingKVA/wmInputRingKVA were always 0 and every consumer arm was unreachable. Confirmed dead during the MAZ-179 investigation; audit trail in that ticket.

Live delivery paths are untouched: WaitSoftIRQ slot rings (softIRQRing/ringPush/RingDrain) and io_uring CQs.

Bonus defect deleted: completionRingPush bounds-checked tail-head >= hid.CompletionRingSize but indexed Events[tail%ring.Capacity] — two different moduli.

What was removed

  • Userspace (mazarin/sys/softirq.go): RegisterCompletionRing, PollCompletionRing
  • Syscall layer (kmazarin/ksyscall/): SyscallRegisterCompletionRing, dispatch entry 57, the two Register*CompletionRing linkname decls, caller-less getBlockRingFull linkname
  • Kernel (kmazarin/kmazarin/): both CompletionRing sections in soft_irq_slots.go (registration/cleanup/accessors + 6 state vars), the two shepherd-death Cleanup*CompletionRing calls in threads.go, completionRingPush + dbgBlockRingFull/GetBlockRingFull in bottom_half.go, the never-taken crKVA != 0 fallback arm in block_top_half.go (now unconditionally ringPush(&topHalfBlockRing, ev)), and input_focus.go's caller-less routeInputEvent, wakeInputConsumers shim, and WM wake chain (wakeWMViaMailbox/wakeWMViaUringFn/wakeWMViaUringImpl/hidNotifyMsg)
  • Shared: hid.CompletionRing struct + CompletionRingSize; SysRegisterCompletionRing constant (per Ian — slot 57 keeps the conventional freed-slot gap comment; unmapped slots panic like every other freed slot, no freed slot returns ENOSYS)

Kept deliberately: KernelWriteToRingFromIRQ (io_uring core), WM-role claiming (SysRequestWindowManager/windowManagerSID), blockDeviceOwnerPID, dbgBlockCQEMissed (live in the surviving fallback).

Most of the +122 is gofmt column realignment in the two syscall-number tables; git diff -w shows ~30 real non-deletion lines.

Verification

  • Pre-removal grep confirmed zero callers for every deleted identifier; post-removal sweep finds only the two intentional slot 57 freed gap comments
  • $GO tool task (ARM64) ✅ · $GO tool task all (x86_64) ✅ · $GO tool task test
  • Red-test-first N/A: pure removal of unreachable code (no observable behavior to specify)

Complexity notes

CC gate: the only 🔴 overlapping this diff is blockTopHalf (CC 20), a pre-existing violation this branch reduces (22 on master; deleting the fallback branch removed two decision points). The other 22 🔴 in touched files are pre-existing with no hunk overlap (deletion-only diff) — not blocking per repo precedent (MAZ-165/167/175). NLOC: threads.go 2090 (pre-existing, warn-only).

Ticket: https://linear.app/mazarin/issue/MAZ-180/remove-dead-legacy-completionring-machinery

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved block interrupt completion handling when no I/O completion queue is available.
    • Removed legacy completion-ring processing for block and input events.
  • Refactor
    • Simplified soft-interrupt and input event handling.
    • Freed an obsolete syscall slot and removed unsupported completion-ring registration and polling interfaces.
    • Streamlined shepherd shutdown cleanup.

The shared-page CompletionRing IPC path (syscall 0x1039 and everything
downstream) had zero userspace callers, so registration never ran and
every consumer arm was unreachable — confirmed during the MAZ-179
investigation (audit trail in that ticket's findings). Live delivery is
the WaitSoftIRQ slot rings and io_uring CQs, both untouched. Removal
also deletes completionRingPush's latent bounds-check-vs-index modulus
defect and un-shadows the block-IRQ fallback's internal
topHalfBlockRing arm.

Per Ian, the SysRegisterCompletionRing constant is fully removed: slot
57 keeps the conventional freed-slot gap comment and behaves like every
other freed slot (syscallPanic; no freed slot returns ENOSYS).

Refs: MAZ-180

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change removes legacy block and input completion-ring registration, notification, polling, and cleanup paths. Block IRQ fallback events now enter topHalfBlockRing. The completion-ring syscall slot is retired, and related declarations and comments are updated.

Changes

Completion-ring removal

Layer / File(s) Summary
Block IRQ fallback routing
kmazarin/kmazarin/block_top_half.go, kmazarin/kmazarin/bottom_half.go
Block IRQ fallback events are pushed to topHalfBlockRing. The shared completion-ring push helper and ring-full accounting are removed.
Ring lifecycle and input notification cleanup
kmazarin/kmazarin/input_focus.go, kmazarin/kmazarin/soft_irq_slots.go, kmazarin/kmazarin/threads.go, kmazarin/ksyscall/bridge_asm.go, kmazarin/ksyscall/wait_softirq_asm.go
Completion-ring ownership, registration, cleanup, accessors, input notification routing, and shepherd teardown calls are removed.
Completion-ring syscall cleanup
kmazarin/ksyscall/mazzy.go, kmazarin/ksyscall/softirq.go, mazarin/sys/softirq.go, shared/mazzy/mazzy.go, shared/hid/hid.go
Completion-ring registration and polling APIs are removed. Syscall slot 57 is retired. Related declarations and comments are reformatted or updated.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the removal of the legacy CompletionRing machinery, which is the main change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/MAZ-180

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@iansmith

iansmith commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

Claude code review (inline, effort: high)

Verdict: clean ✅ — 0 confirmed, 0 plausible findings.

Reviewed the full diff (whitespace-blind) across correctness, reuse/simplification, and efficiency:

  • Behavior equivalence of the fallback collapse (block_top_half.go): the deleted crKVA != 0 arm was gated on blockCompletionRingKVA, which was permanently 0 (registration syscall had zero callers) — the surviving ringPush(&topHalfBlockRing, ev) arm was already the only executed path. Verified no counter regression: dbgBlockCQEMissed still increments in the surviving path; dbgBlockRingFull was only ever incremented by the dead arm and its getter/linkname chain was caller-less.
  • Shepherd-death path (threads.go): the two removed Cleanup*CompletionRing calls were no-ops — both owner SIDs were permanently -1, so both functions early-returned for every real shepherd ID. Remaining cleanup order unchanged.
  • linkname hygiene: every removed //go:linkname declaration (RegisterBlockCompletionRing, RegisterInputCompletionRing, getBlockRingFull) was removed together with its main-side implementation; both arch builds link green.
  • Dispatch table: entry 57 removed from the sparse [74]SyscallHandler literal → nil → syscallPanic, identical to the six pre-existing freed slots. Matches the recorded decision on MAZ-180.
  • Imports: unsafe (bottom_half.go), sync/atomic (mazarin/sys/softirq.go), hid/ipc (input_focus.go), kmem (soft_irq_slots.go) all correctly pruned; no unused imports remain (both arch builds would reject).
  • One deliberate non-finding: KernelWriteToRingFromIRQ (uring_ipc.go) is now caller-less but explicitly kept — io_uring core, out of scope per the ticket.

Gates: full suite ✅ (2×), both-arch builds ✅, CC gate pass (only overlapped 🔴 is blockTopHalf, reduced 22→20 by this diff), vacuity gate vacuously clean (no test files changed), simplify applied 1 stale-comment fix pre-commit.

🤖 Generated with Claude Code

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@kmazarin/kmazarin/block_top_half.go`:
- Around line 129-136: The block soft-IRQ fallback around topHalfBlockRing must
only use a slot owned by the established block-device owner. Update
RegisterSoftIRQSlotKsyscall and its cleanup to reject or atomically replace
competing registrations, and clear blockDeviceOwnerPID together with irqToSlot;
ensure the fallback cannot queue to or wake a caller-owned slot without
validated ownership.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8d00c785-7bb8-4c49-937a-4f50481a4498

📥 Commits

Reviewing files that changed from the base of the PR and between 8822835 and 6397e2a.

📒 Files selected for processing (12)
  • kmazarin/kmazarin/block_top_half.go
  • kmazarin/kmazarin/bottom_half.go
  • kmazarin/kmazarin/input_focus.go
  • kmazarin/kmazarin/soft_irq_slots.go
  • kmazarin/kmazarin/threads.go
  • kmazarin/ksyscall/bridge_asm.go
  • kmazarin/ksyscall/mazzy.go
  • kmazarin/ksyscall/softirq.go
  • kmazarin/ksyscall/wait_softirq_asm.go
  • mazarin/sys/softirq.go
  • shared/hid/hid.go
  • shared/mazzy/mazzy.go
💤 Files with no reviewable changes (7)
  • kmazarin/ksyscall/softirq.go
  • mazarin/sys/softirq.go
  • kmazarin/kmazarin/soft_irq_slots.go
  • kmazarin/kmazarin/bottom_half.go
  • kmazarin/kmazarin/threads.go
  • kmazarin/ksyscall/bridge_asm.go
  • kmazarin/ksyscall/wait_softirq_asm.go

Comment on lines +129 to +136
// No active CQ, or CQ full: fall back to the internal soft-IRQ ring.
atomic.AddUint32(&dbgBlockCQEMissed, 1)
ev := hid.HIDEvent{
Type: tag,
Code: status,
Value: info.UsedLen,
}
crKVA := blockCompletionRingKVA
if crKVA != 0 {
if !completionRingPush(crKVA, ev) {
atomic.AddUint32(&dbgBlockRingFull, 1)
}
} else {
ringPush(&topHalfBlockRing, ev)
}
ringPush(&topHalfBlockRing, ev)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline kmazarin/kmazarin/soft_irq_slots.go --items all --type function \
  --match 'RegisterSoftIRQSlotKsyscall|DrainSoftIRQSlotEvents|WakeSlotForIRQ'

rg -n -C 8 \
  'blockDeviceOwnerPID|irqToSlot\[|BlockVirtualIRQ|topHalfBlockRing|RegisterSoftIRQSlotKsyscall|DrainSoftIRQSlotEvents' \
  kmazarin

Repository: iansmith/mazarin

Length of output: 30585


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== soft_irq_slots relevant sections =="
sed -n '45,60p' kmazarin/kmazarin/soft_irq_slots.go
sed -n '107,180p' kmazarin/kmazarin/soft_irq_slots.go
sed -n '260,320p' kmazarin/kmazarin/soft_irq_slots.go
sed -n '457,502p' kmazarin/kmazarin/soft_irq_slots.go

echo "== block completion top half =="
sed -n '100,175p' kmazarin/kmazarin/block_top_half.go

echo "== block owner / SetBlockDeviceOwnerPID call sites =="
rg -n -C 5 'SetBlockDeviceOwnerPID|GetBlockDeviceOwnerPID|blockDeviceOwnerPID|WakeIOUringFromIRQ|WakeSlotForIRQ' kmazarin device kmazarin > /tmp/bg_search.txt
sed -n '1,80p' /tmp/bg_search.txt | sed -n '1,140p' /tmp/bg_search.txt

echo "== structural read-only verifier for block soft-irq ownership properties =="
python3 - <<'PY'
from pathlib import Path
import re

soft = Path('kmazarin/kmazarin/soft_irq_slots.go').read_text()
block = Path('kmazarin/kmazarin/block_top_half.go').read_text()

def fn_body(name):
    m = re.search(r'func\s+' + re.escape(name) + r'\b[\s\S]*?\n\}', soft)
    return m.group(0) if m else ''

r_body = fn_body('RegisterSoftIRQSlotKsyscall')
c_body = fn_body('CleanupSoftIRQSlotsForShepherd')
b_body = block[block.find('// No active CQ'):block.find('} else {', block.find('// No active CQ'))]

checks = {
    'block_registration_assigns_ring': 'ring = &topHalfBlockRing' in r_body,
    'block_registration_sets_owner': 'blockDeviceOwnerPID = shepherdID' in r_body,
    'block_registration_maps_irq': r_body.count('irqToSlot[irqNum] = slotNum') == 1,
    'block_registration_no_owner_guard': 'blockDeviceOwnerPID == shepherdID' not in r_body and 'blockDeviceOwnerPID' not in r_body.split('} else if irqNum == hid.BlockVirtualIRQ',1)[1].split('}')[0],
    'cleanup_clears_block_owner': c_body.count('if slot.intKind == hid.DiskInterrupt') == 1 and c_body.find('blockDeviceOwnerPID = -1') > c_body.find('if slot.intKind == hid.DiskInterrupt'),
    'fallback_pushes_to_topHalfBlockRing': 'ringPush(&topHalfBlockRing, ev)' in b_body,
    'fallback_wakes_block_virtual_irq': 'WakeSlotForIRQ(hid.BlockVirtualIRQ)' in block,
}
for k,v in checks.items():
    print(f'{k}={v}')

print('owner_writer_count=', len(re.findall(r'(?m)^\tblockDeviceOwnerPID\s*=', soft)))
print('owner_setter_count=', len(re.findall(r'(?m)^\tblockDeviceOwnerPID\s*=', open('kmazarin/kmazarin/soft_irq_slots.go').read()) +
      len(re.findall(r'(?m)^\tblockDeviceOwnerPID\s*=', open('kmazarin/kmazarin/shared/hid/hid.go').read()) if Path('kmazarin/kmazarin/shared/hid/hid.go').exists() else [])))
PY

Repository: iansmith/mazarin

Length of output: 8911


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== soft_irq_slots relevant sections =="
sed -n '45,60p' kmazarin/kmazarin/soft_irq_slots.go
sed -n '107,180p' kmazarin/kmazarin/soft_irq_slots.go
sed -n '260,320p' kmazarin/kmazarin/soft_irq_slots.go
sed -n '457,502p' kmazarin/kmazarin/soft_irq_slots.go

echo "== block completion top half =="
sed -n '100,175p' kmazarin/kmazarin/block_top_half.go

echo "== block owner / SetBlockDeviceOwnerPID call sites =="
rg -n -C 5 'SetBlockDeviceOwnerPID|GetBlockDeviceOwnerPID|blockDeviceOwnerPID|WakeIOUringFromIRQ|WakeSlotForIRQ' kmazarin device kmazarin > /tmp/bg_search.txt
sed -n '1,140p' /tmp/bg_search.txt

echo "== structural read-only verifier for block soft-irq ownership properties =="
python3 - <<'PY'
from pathlib import Path
import re

soft = Path('kmazarin/kmazarin/soft_irq_slots.go').read_text()
block = Path('kmazarin/kmazarin/block_top_half.go').read_text()

def fn_body(name):
    m = re.search(r'func\s+' + re.escape(name) + r'\b[\s\S]*?\n\}', soft)
    return m.group(0) if m else ''

r_body = fn_body('RegisterSoftIRQSlotKsyscall')
c_body = fn_body('CleanupSoftIRQSlotsForShepherd')
b_body = block[block.find('// No active CQ'):block.find('} else {', block.find('// No active CQ'))]

checks = {
    'block_registration_assigns_ring': 'ring = &topHalfBlockRing' in r_body,
    'block_registration_sets_owner': 'blockDeviceOwnerPID = shepherdID' in r_body,
    'block_registration_maps_irq': r_body.count('irqToSlot[irqNum] = slotNum') == 1,
    'block_registration_no_owner_guard': 'blockDeviceOwnerPID == shepherdID' not in r_body and 'blockDeviceOwnerPID' not in r_body.split('} else if irqNum == hid.BlockVirtualIRQ',1)[1].split('}')[0],
    'cleanup_clears_block_owner': c_body.count('if slot.intKind == hid.DiskInterrupt') == 1 and c_body.find('blockDeviceOwnerPID = -1') > c_body.find('if slot.intKind == hid.DiskInterrupt'),
    'fallback_pushes_to_topHalfBlockRing': 'ringPush(&topHalfBlockRing, ev)' in b_body,
    'fallback_wakes_block_virtual_irq': 'WakeSlotForIRQ(hid.BlockVirtualIRQ)' in block,
}
for k,v in checks.items():
    print(f'{k}={v}')

print('owner_writer_count=', len(re.findall(r'(?m)^\tblockDeviceOwnerPID\s*=', soft)))
print('owner_setter_count=', len(re.findall(r'(?m)^\tblockDeviceOwnerPID\s*=', open('kmazarin/kmazarin/soft_irq_slots.go').read()) +
      len(re.findall(r'(?m)^\tblockDeviceOwnerPID\s*=', open('kmazarin/kmazarin/shared/hid/hid.go').read()) if Path('kmazarin/kmazarin/shared/hid/hid.go').exists() else [])))
PY

Repository: iansmith/mazarin

Length of output: 8911


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files under kmazarin =="
git ls-files kmazarin 'kmazarin/**' | sed 's#^`#-` #'

echo "== exact owner writes and call sites =="
rg -n '\bblockDeviceOwnerPID\s*=|SetBlockDeviceOwnerPID\(|GetBlockDeviceOwnerPID\(' . --glob '*.go' --glob '!vendor/**'

echo "== softirq syscall and registration context =="
sed -n '120,150p' kmazarin/kmazarin/ksyscall/softirq.go
sed -n '185,225p' kmazarin/kmazarin/soft_irq_slots.go
sed -n '290,315p' kmazarin/kmazarin/soft_irq_slots.go
sed -n '457,502p' kmazarin/kmazarin/soft_irq_slots.go

Repository: iansmith/mazarin

Length of output: 14465


Security And Privacy (CWE-862): Missing Authorization

Reachability: External · Exploitability: Moderate

Authorize the block soft-IRQ consumer before this fallback.

SyscallRegisterSoftIRQ accepts a caller-selected hid.BlockVirtualIRQ. RegisterSoftIRQSlotKsyscall assigns that caller's slot to topHalfBlockRing, sets blockDeviceOwnerPID, and stores irqToSlot[irqNum] without an owner guard. This fallback then queues block completions to that ring and wakes the mapped caller-owned slot. Keep ownership only with the established block-device owner; reject or atomically replace competing registrations; clear ownership plus the IRQ mapping together during cleanup.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kmazarin/kmazarin/block_top_half.go` around lines 129 - 136, The block
soft-IRQ fallback around topHalfBlockRing must only use a slot owned by the
established block-device owner. Update RegisterSoftIRQSlotKsyscall and its
cleanup to reject or atomically replace competing registrations, and clear
blockDeviceOwnerPID together with irqToSlot; ensure the fallback cannot queue to
or wake a caller-owned slot without validated ownership.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant