xous-core/kernel/src
bunnie e27b30d818 fix edge case in swapper
A particular edge case was finally reproduced & fixed. The edge
case occurs when a swap is triggered while handling an interrupt,
and an OOM happens during the context switch to/from the interrupt.

The background on this is that the hardware drivers for the swapper,
as well as much of the logical heavy lifting on e.g. what pages to
swap out, live in a userspace process known as xous-swapper.

The userspace process has to run free of interrupts - when you're
OOM'd or trying to swap, interrupts should not happen. The way to
do this in Xous is to run that code inside an interurpt context,
as interrupts are not interruptable.

Thus, the xous swapper userspace consists of two halves: a regular
userspace stub that provides some amount of control/debug over
the swapper, and a handler that gets run in a "pseudo-interrupt"
context.

Like all other interrupts, the handler "borrows" the stack of the currently
running thread - interrupt contexts don't have an explicit stack, they
just grow on top of the current stack of the current thread in the
current process at the time of the interrupt.

This is broken because when you have a swap event inside an interrupt
context, there are conditions where you might not have a stack. What
was in fact happening is that the stack pointer was being orphaned
as being the "exception stack" - which is a temporary location,
only accessible by the kernel, used for storing all the registers
going into and out of exceptions. Since no stack pointer is set up,
the moment the userspace starts to run and spill its registers to
stack, the system trips a "nested swap" event, which leads to a panic
because this is not allowed.

The fix to this is to devote two hard-wired pages, mapped in the
loader, to be the swapper's private stack area. Instead of behaving
like an interrupt and borrowing the caller's stack, the swapper instead
goes back to its hard-wired stack to do all the processing.

This should also improve the performance of swap handling in some
cases because we can now guarantee the stack is always in-memory
and doesn't need to be swapped in during swap processing.

One complication is that the "reserved memory" that the swapper
puts aside in case it *does* need to allocate extra pages during
handling can't be freed at the top of the OOM routine. Thus if
the swapper ends up using new pages, we should expect yet another
crash.

However, in practice, this doesn't seem to happen, because the
cases in which we hit needing a new page are typically related
to cases early on in boot where superpages/new page table entries
are being allocated, or if we're growing the heap that passes
data back and forth between swap and userspace. Because this call
triggers in such a specific condition, I hypothesize that actually
in practice it should generally be able to run without allocations.

One case where maybe it could hit an allocation is if the swapper
hit, for the first time, in an interrupt handler that was swapped
out, and never hit before, and the interrupt handler needed a
superpage to be allocated, thus triggering an allocation request
for a new PTE or two. I think this is probably pretty unlikely, but
if we do hit it, the fix would be to, for the purposes of targets
with "swap" enabled, to mark unmap_memory and map_memory to be
legal syscalls in interrupt contexts. These are normally illegal
because interrupts should always return - and these calls could
potentially fail or block. However, I think in this case it's
a trade-off between "we should be failing if we run out of memory"
and that failure being a potentially incorrect behavior that is guarded
against by a runtime check to discourage such calls.
2026-01-08 02:08:03 +08:00
..
arch FLAG DAY: fix all names to harmonize around 'bao1x' 2025-09-18 21:25:51 +08:00
debug formatting changes due to changes in nightly rust 2025-02-01 22:26:40 +08:00
platform fixup rand for simulation target 2025-09-20 22:13:16 +08:00
args.rs ok, format the kernel now that all in-line assembly has been checked 2024-01-14 19:27:14 +08:00
io.rs allow this trait to be unused 2024-05-10 00:38:41 +08:00
irq.rs raw pointer dance for IRQ handlers 2024-12-02 19:05:56 +08:00
macros.rs
main.rs move MinSet to utils so that we can test it 2024-05-18 00:22:50 +08:00
mem.rs fix rustc-1.89 warnings 2025-08-19 19:45:29 +08:00
server.rs migrations for moving constants out of xous-rs/kernel and into board/platform 2025-05-11 12:50:02 +08:00
services.rs fix edge case in swapper 2026-01-08 02:08:03 +08:00
swap.rs cleanup retired apis and improve swap debug output 2026-01-08 02:05:01 +08:00
syscall.rs add API calls for debugging kernel under baochip targets 2025-12-09 16:19:04 +08:00
test.rs update formatting on the published crates 2024-09-23 01:43:02 +08:00
utils.rs move MinSet to utils so that we can test it 2024-05-18 00:22:50 +08:00