xous-core/loader/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
..
fonts update generated artifacts in the loader 2025-02-17 18:26:55 +08:00
platform cleanup dead code warnings found by latest rustc 2026-01-06 13:41:04 +08:00
args.rs fixup bugs in arg extension processing. 2025-10-05 17:06:33 +08:00
asm.rs remove unused assembly code 2025-10-01 23:37:03 +08:00
bootconfig.rs improve assert message 2024-11-30 02:25:40 +08:00
consts.rs fix RPT/XPT alloc in swap; make swap resume-compatible 2024-05-12 21:50:53 +08:00
debug.rs the great loader culling 2025-10-01 14:57:40 +08:00
env.rs add a random seed to the environment 2025-12-02 01:40:49 +08:00
font6x12.png
font6x12_1bpp.raw
fonts.rs fix broken font rendering in rust 1.91 2025-11-18 00:18:55 +08:00
lib.rs fix timebase of delays in loader 2025-11-01 20:09:12 +08:00
main.rs make the init check on erase secret pass-forward more narrowly scope 2025-12-18 03:57:04 +08:00
minielf.rs make decrypt_page_at fallible 2025-10-04 18:54:15 +08:00
murmur3.rs format loader 2024-01-14 22:02:55 +08:00
phase1.rs fix breakage associated with changes to xous-semver 2025-10-06 13:17:21 +08:00
phase2.rs fix edge case in swapper 2026-01-08 02:08:03 +08:00
platform.rs FLAG DAY: fix all names to harmonize around 'bao1x' 2025-09-18 21:25:51 +08:00
secboot.rs update formatting to latest nightly rules 2024-09-24 01:49:45 +08:00
swap.rs fixup loader heap; move signature validation; fixup swap structures 2025-10-04 00:56:18 +08:00
test.rs add detached-app handling 2025-10-05 17:08:42 +08:00