simple_tmk
simple_tmk is the bare-metal guest payload containing the repository's basic
Test Microkernel processor and interrupt tests.
Runtime model
The payload is a no_std, minimal_rt executable. It has no bootloader,
firmware interface, process model, or command line. tmk_vmm loads its ELF
directly, initializes the processor, and selects one test by index.
The shared tmk_core runtime provides:
- A test entry point and panic handler.
- Guest-to-host logging and completion commands.
- Scoped interrupt-handler registration.
- Architecture-specific helpers such as x86 MSR access.
The payload is useful for code that must touch processor state directly. Use a normal VMM test when the behavior requires firmware, devices, or a guest OS.
Building
Build the x86_64 payload with the same command emitted by Petri's artifact resolver:
RUSTC_BOOTSTRAP=1 cargo build -p simple_tmk \
--config openhcl/minimal_rt/x86_64-config.toml
Build AArch64 with:
RUSTC_BOOTSTRAP=1 cargo build -p simple_tmk \
--config openhcl/minimal_rt/aarch64-config.toml
The output is an ELF consumed by tmk_vmm. Running it as a host process is not
supported; non-minimal_rt builds contain only a rejecting stub.
Flowey builds the correct payload automatically when selected Petri tests
require a SIMPLE_TMK_* artifact.
Defining a test
A test is a function annotated with #[tmk_test]:
#[tmk_test]
fn example(_: TestContext<'_>) {
log!("example started");
assert_eq!(2 + 2, 4);
}
The macro emits a static descriptor into the ELF tmk_tests section. The
descriptor gives tmk_vmm the test name, entry point, and flags needed for
discovery and execution.
Tests that intentionally fault can be marked as expected failures:
#[tmk_test(expected_failure, linux_only)]
fn expected_abort(_: TestContext<'_>) {
// Trigger the architecture condition under test.
}
Scoped interrupt handlers
On x86_64, TestContext exposes a Scope. A test can create a nested scope,
install an ISR for a vector, enable interrupts, and let the scope restore its
handler state before returning. This keeps one test's interrupt setup from
leaking into another test implementation.
Running and listing
After building both binaries:
target/debug/tmk_vmm --tmk \
target/x86_64-unknown-none/debug/simple_tmk --list
Run one test by passing its discovered name:
target/debug/tmk_vmm --tmk \
target/x86_64-unknown-none/debug/simple_tmk ud2
Output appears in the tmk_vmm tracing stream. A panic becomes a structured
protocol message when the runtime remains operational; an earlier processor
fault is reported from the host VP loop.
Adding coverage safely
When adding a test:
- Keep the initial machine assumptions explicit.
- Install handlers before enabling or triggering interrupts.
- Bound polling loops so a missing hardware event becomes a failure.
- Restore mutable processor state when later operations in the same test need a known configuration.
- Run through every backend whose behavior the test claims to cover.
Tests share the image but receive fresh VM state from tmk_vmm, so global
state does not need to survive between test cases.
TMK VMM documents the host executor, hypervisor backends, and result protocol.