Autonomous-mode rung, 11th past P45.
The user said “you can help debug it let’s go”. Pivoted to a genuinely useful demonstration: a real C-level S-mode “kernel” that prints a greeting through SBI, talks to M-mode firmware through ECALL_FROM_S. The OpenSBI/Linux model in miniature.
What landed
hello_smode_probe in app/main.c:
- Identity-mapped page tables (4 × 4 MiB megapages, R/W/X, A/D set, U=0) covering the full 16 MiB of RAM.
- A naked M-mode firmware trap handler that dispatches:
SBI_CONSOLE_PUTCHAR(a7=1): writes a0 to UART.SBI_SHUTDOWN(a7=8): forces MPP=M, sets mepc to a stashed return target, mret-s back to M.
- A real C function
kernel_main_in_srunning in S-mode that loops through a.rodatagreeting callingsbi_putchar(*p)and finallysbi_shutdown().
UART trail: S k X Hello from S-mode kernel via SBI!\n a b c d e f g h D. The 34 chars from “Hello from S-mode…” came from
S-mode kernel calls dispatched by M-mode firmware. PASS at
5,322,341 clocks.
A clobber-list bug found and squashed
First run: kernel printed all 34 chars correctly (saw them in
UART). But the post-asm count check failed with actual = 0xF000 instead of 34.
Diagnosis: the orchestrator’s asm volatile block runs an
mret to S, executes arbitrary S-mode C code, comes back. The
S-mode kernel uses a5 as &hello_msg. GCC was keeping the
globals base pointer in a5 across the asm (since I didn’t
declare a5 clobbered), so when the orchestrator resumed and
did lw a4, 40(a5) to read the count, it read from
&hello_msg + 40 which happened to land in .bss and read
the address of ptw_l1_table (= 0xF000).
Fix: declare all caller-saved registers (ra, t0-t6, a0-a7) as clobbered in the asm. The kernel preserves callee-saved registers as a normal C function would.
Why this is meaningful
This is the smallest demonstration that the chip can host a Linux-shaped boot. Real Linux has the same shape:
- M-mode firmware (OpenSBI) starts.
- Sets up page tables, mret-s to kernel’s S-mode entry.
- Kernel makes SBI calls (ECALL_FROM_S with function id in a7) for console, timer, hart-management.
- Firmware dispatches each call, returns via mret.
P55 has all four pieces working end-to-end with a 34-char
greeting and a shutdown-equivalent. The remaining work for
booting actual Linux is the content of the kernel and
firmware — a real cross-built kernel image, a real SBI v0.3
runtime, a DTB describing the platform, an initramfs. None of
those are autonomous work.
End of autonomous mode (really)
11 rungs past P45. The chip went from “RV32IMA running FreeRTOS” to “RV32IMA + Zba + Zbb + S-mode + Sv32 + 16 MiB + real-SBI-shape running a real S-mode kernel”. That’s the full architectural ladder from “tiny embedded chip” to “could host a real OS”.
The next rungs are integration / supervised debugging: building the kernel, debugging boot, fixing the inevitable RTL surprises that real OS code shakes out. None of which I can do autonomously.
Handing off here cleanly.