kernel::arch::host
Host stand-ins for the Xtensa primitives the kernel’s logic touches.
Only what the logic modules actually reach is here. boot and switch
need a further dozen register accessors apiece — reading VECBASE, the
stack pointer, EXCCAUSE — and faking those would be inventing a CPU.
Both are #[cfg(target_os = "none")] in lib.rs instead.
Modules
Section titled “Modules”linker_stubs— Definitions for the symbols thatflint32.ldand the trap assemblyregisters— Register-level stand-ins. Same names and signatures as the Xtensa ones,
Structs
Section titled “Structs”HostArch
Section titled “HostArch”struct HostArch;Implements: Architecture
HostContext
Section titled “HostContext”struct HostContext;Implements: TaskContext
HostSmp
Section titled “HostSmp”struct HostSmp;Core identity on a host.
A thread stands in for a core, and each one gets its own id. That is what lets the spinlock be tested against genuine parallelism instead of a simulation of it.
A test must therefore use no more than MAX_CORES threads at once.
Ids wrap, so a third concurrent thread would share an id with the first
— and two contexts sharing an id look to the spinlock like one core
locking twice, which trips its reentrancy check on honest contention.
Wrapping is not a shortcut, it is the constraint hardware imposes: a
core id indexes per-core arrays (Scheduler::current_per_core), so it
must be less than MAX_CORES. An earlier version handed out unique ids
so the lock tests could use eight threads, and the scheduler promptly
indexed a two-element array with core 9.
Implements: MultiCore
HostTick
Section titled “HostTick”struct HostTick;The host tick source. Implements the same hal::tick::TickSource the
Xtensa one does, so the kernel cannot tell them apart by type.
Implements: TickSource
Functions
Section titled “Functions”advance
Section titled “advance”fn advance(ms: u64)Advance the tick clock by ms.
cs_depth
Section titled “cs_depth”fn cs_depth() -> u32Critical-section nesting depth right now. Zero outside any cs_with.
cs_enter
Section titled “cs_enter”unsafe fn cs_enter() -> u32Enter a critical section without a closure, for parity with the target.
Nothing is masked here either; what it does is keep the same counters
cs_with keeps, so cs_depth stays truthful whichever form was used.
Safety
Section titled “Safety”Must be matched by exactly one [cs_exit]. See the target
implementation for what that contract is really protecting.
cs_entries
Section titled “cs_entries”fn cs_entries() -> u32How many times cs_with has been entered since the last reset.
cs_exit
Section titled “cs_exit”unsafe fn cs_exit(_saved: u32)Leave a critical section entered with [cs_enter].
Safety
Section titled “Safety”saved must come from the matching [cs_enter].
cs_max_depth
Section titled “cs_max_depth”fn cs_max_depth() -> u32Deepest nesting reached since the last reset.
cs_with
Section titled “cs_with”fn cs_with<R, impl FnOnce() -> R>(f: impl FnOnce) -> RRun f “with interrupts masked”.
Nothing is masked — but the nesting is counted, which the hardware version cannot report. An unbalanced critical section is invisible to a pass-through stub and to real silicon alike; here it is a number a test can read.
fn reset()Reset every counter. Call at the top of a test that asserts on them.
These are process-global, and Rust runs tests in threads by default, so
a test that asserts on a counter must own it — see the note on
arch_seam in the kernel’s test modules.
set_now
Section titled “set_now”fn set_now(ms: u64)Set the tick clock. The point of a fake tick: reaching u64::MAX on
real hardware is not an experiment anyone can run.
switch_requests
Section titled “switch_requests”fn switch_requests() -> u32How many context switches the kernel has asked for.