The kernel and userspace SwapAbi enums — which the source comments on both sides explicitly mark as "copy-paste synchronized" with a "SYNC WITH ..." pointer to each other — disagree on the numeric discriminants of the Debug* variants on current main (commit 5397e1b48). The mismatch makes the single live caller (Opcode::DebugServers in the swapper) a latent process-crash vector against PID 2.
Surfaced while writing betrusted-io/xous-book#20, which updates the book's SwapAbi listing in ch10-00-swap-overview.md to match userspace. The book PR documents what SwapOp callers actually see, so it doesn't depend on how this issue gets resolved.
What disagrees
Kernel SwapAbi — kernel/src/swap.rs L35-L47:
pub enum SwapAbi {
Invalid = 0,
ClearMemoryNow = 1,
GetFreePages = 2,
RetrievePage = 3,
HardOom = 4,
StealPage = 5,
ReleaseMemory = 6,
WritePage = 7,
BlockErase = 8,
DebugServers = 9,
}Userspace SwapAbi — services/xous-swapper/src/lib.rs L14-L29:
pub enum SwapAbi {
Invalid = 0,
ClearMemoryNow = 1,
GetFreePages = 2,
// RetrievePage = 3, // meant to be initiated within the kernel to itself
// HardOom = 4, // meant to be initiated within the kernel to itself
StealPage = 5,
ReleaseMemory = 6,
WritePage = 7,
BlockErase = 8,
DebugProcesses = 9,
DebugServers = 10,
DebugFree = 11,
DebugInterrupts = 12,
}| Variant | userspace value | kernel value |
|---|---|---|
Invalid … BlockErase | 0 … 8 | 0 … 8 (match) |
DebugProcesses | 9 | — (undefined) |
DebugServers | 10 | 9 |
DebugFree | 11 | — (undefined) |
DebugInterrupts | 12 | — (undefined) |
Live consequence (latent today, but real)
services/xous-swapper/src/main.rs L836-L838:
Some(Opcode::DebugServers) => {
xous::rsyscall(xous::SysCall::SwapOp(SwapAbi::DebugServers as usize, 0, 0, 0, 0, 0, 0))
.unwrap();
}SwapAbi::DebugServers as usize evaluates to 10. Kernel SwapAbi::from(10) returns Invalid (kernel/src/swap.rs L62). The Invalid arm in kernel/src/syscall.rs (L1203-L1209) prints "Invalid SwapOp: ..." and returns Err(UnhandledSyscall). The unconditional .unwrap() then panics the swapper (PID 2) — not recoverable.
The reason this isn't observed in practice is that nothing in the tree currently sends an Opcode::DebugServers IPC into the swapper: grep -rn "Opcode::DebugServers" --include='*.rs' only finds the receiver itself. The bug is gated entirely on someone hooking that IPC up (debug shell, integration test, operator tool, etc.).
Why three of the four are dead
DebugProcesses, DebugFree, DebugInterrupts have no SwapOp callers anywhere in the tree — verified with grep -rn "SwapAbi::Debug" --include='*.rs', which finds only the enum definition in xous-swapper/src/lib.rs plus the kernel's DebugServers handler. The kernel already serves the equivalent debug operations through a completely separate syscall — SysCall::PlatformSpecific → PlatformCallAbi at kernel/src/syscall.rs L1230-L1345, gated behind #[cfg(feature = "debug-proc")]. So three of the four userspace SwapAbi::Debug* variants read like vestiges of an in-progress or aborted refactor that never reached the kernel side.
Activity
0No activity yet.