kernel-image bless: byte-verified static dispatch for the relocated kernel window

The generated dispatcher ran kernel-window table hits (RAM [0x500,0x8500),
the BIOS's boot-time copy of ROM 0x1FC10000+) natively with NO check that
the live RAM bytes still match the ROM image the functions were compiled
from — unsound for runtime-patched kernel code (the BIOS installs pad/SIO
handlers INSIDE compiled bodies; live diff: 15 clusters, 348 bytes). It
never misfired only because entry points happened to avoid patched keys.

A static kernel hit now requires psx_kernel_bless_dispatchable(): the
emitter emits psx_bios_kernel_bodies[] (key -> full RAM extent of the code
reachable from it; continuations carry their parent's extent, 499 entries),
and the runtime lazily byte-compares each entry's body against the ROM
source, caches the verdict, and invalidates precisely on writes into the
body (store chokepoint, DMA/EXE range marks, savestate restore). Clean ->
guarded native; patched/unverifiable -> the faithful dirty-RAM interpreter,
exactly as Rule 18 prescribes. This implements the runtime half of the
relocation-manifest contract (docs/RELOCATION_MANIFEST_FORMAT.md).

Measured on Tomba (SCUS-94236): 208-214 of 219 verified functions clean
(the 5 mismatches are the genuinely patched pad-driver family, faithfully
interpreted); millions of guarded native hits per boot; title 1.00x,
village 0.92x (parity — kernel keys were already native, now they are
PROVEN native); LLE and HLE boots + gameplay input verified. Kernel-window
interp measures 1.3% of interp burden (dirty_ram_stats), so this is a
soundness fix, not a speedup; the dominant interp cost is overlay-region
coverage (cg-tag hygiene), tracked separately.

Observability: TCP kernel_bless (entries/clean/mismatch/native_hits/
verifies/invalidations), always-on. PSX_KERNEL_BLESS=0 reverts to
unguarded-table behavior for A/B.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Matthew Stanley
2026-07-10 19:12:32 -07:00
parent a0818de0b4
commit 71c2df0f54
5 changed files with 244 additions and 0 deletions
+64
View File
@@ -1372,6 +1372,55 @@ void FullFunctionEmitter::emit_dispatch(
}
out += "};\n\n";
// --- Kernel body-extent table (runtime kernel-image bless) ---
// The BIOS copies Kernel Part 2 from ROM [0x1FC10000,0x1FC18000) to RAM
// [0x500,0x8500) at boot; the functions above with keys in that window
// were compiled FROM those ROM bytes. The runtime may execute a key's
// static native function instead of interpreting the (dirty) kernel page
// IFF the live RAM bytes of everything that function can execute still
// byte-match the ROM source. This table gives the runtime that judgment
// boundary: for each kernel-RAM dispatch key, the FULL RAM extent of the
// compiled code reachable from it. A continuation wrapper re-enters its
// PARENT (backward branches reachable), so continuations carry the
// parent's whole extent. Synthetic vector/alias wrappers are excluded —
// their stub bytes are runtime-installed and never ROM-matching.
{
// Function extents by normalized entry, from discovery (end inclusive).
std::map<uint32_t, std::pair<uint32_t, uint32_t>> extent_by_norm;
for (const auto& fn : dr.functions) {
uint32_t lo = normalize_address(fn.entry_addr);
uint32_t hi = normalize_address(fn.end_addr) + 4u;
extent_by_norm[normalize_address(fn.entry_addr)] = {lo, hi};
(void)lo;
}
std::string kb;
size_t kb_count = 0;
for (uint32_t norm : emitted_normalized) {
if (norm < 0x500u || norm >= 0x8500u) continue;
uint32_t owner = norm;
if (continuations.count(norm))
owner = continuations.at(norm).parent_func_norm;
auto it = extent_by_norm.find(owner);
if (it == extent_by_norm.end()) continue;
uint32_t lo = it->second.first, hi = it->second.second;
// Only bodies that live entirely inside the relocated window are
// verifiable against the ROM source; skip anything straddling it.
if (lo < 0x500u || hi > 0x8500u || lo >= hi) continue;
kb += fmt::format(" {{ 0x{:08X}u, 0x{:08X}u, 0x{:08X}u }},\n",
norm, lo, hi);
kb_count++;
}
out += "typedef struct {\n";
out += " uint32_t key; /* dispatch key (RAM, normalized) */\n";
out += " uint32_t body_lo; /* RAM extent of code reachable from key */\n";
out += " uint32_t body_hi; /* exclusive */\n";
out += "} PsxKernelBody;\n\n";
out += fmt::format("const PsxKernelBody psx_bios_kernel_bodies[{}] = {{\n", kb_count);
out += kb;
out += "};\n";
out += fmt::format("const uint32_t psx_bios_kernel_body_count = {}u;\n\n", kb_count);
}
// Dispatch function with binary search.
out += "static uint32_t normalize(uint32_t addr) {\n";
out += " uint32_t phys = addr & 0x1FFFFFFFu;\n";
@@ -1386,6 +1435,7 @@ void FullFunctionEmitter::emit_dispatch(
out += "extern int dirty_ram_dispatch(CPUState* cpu, uint32_t addr, uint32_t stop_addr);\n";
out += "extern int dirty_ram_is_dirty(uint32_t phys);\n";
out += "extern int psx_kernel_bless_dispatchable(uint32_t phys);\n";
out += "extern void fntrace_record(CPUState* cpu, uint32_t target);\n";
out += "extern uint64_t g_dispatch_static_hits;\n";
out += "\n";
@@ -1479,6 +1529,20 @@ void FullFunctionEmitter::emit_dispatch(
out += " while (lo <= hi) {\n";
out += " int mid = (lo + hi) / 2;\n";
out += " if (dispatch_table[mid].addr == phys) {\n";
out += " /* Kernel-image bless guard (CLAUDE.md Rule 18). The keys in\n";
out += " * the relocated kernel window [0x500,0x8500) were compiled\n";
out += " * from the ROM source of the BIOS's boot-time kernel copy —\n";
out += " * but the BIOS (and games) PATCH kernel RAM at runtime (pad/\n";
out += " * SIO installs land inside compiled bodies). A static hit\n";
out += " * here may only run if the live RAM bytes of everything the\n";
out += " * function can execute still byte-match the ROM image\n";
out += " * (memory.c psx_kernel_bless_dispatchable, lazily verified,\n";
out += " * invalidated on writes). Mismatched/unverifiable bodies\n";
out += " * fall through to the faithful dirty-RAM interpreter below.\n";
out += " * Non-kernel keys are unaffected. */\n";
out += " if (phys - 0x500u < 0x8000u &&\n";
out += " !psx_kernel_bless_dispatchable(phys))\n";
out += " break; /* found stays 0 -> dirty_ram_dispatch */\n";
out += " g_debug_current_func_addr = phys;\n";
out += " debug_server_trace_dispatch(phys);\n";
out += " dispatch_table[mid].func(cpu);\n";
+11
View File
@@ -86,6 +86,17 @@ extern uint32_t g_overlay_region_floor;
* written-to since boot. Defined in memory.c. */
int dirty_ram_is_dirty(uint32_t phys);
/* Kernel-image bless (memory.c). A dispatch key in the relocated kernel
* window (RAM [0x500,0x8500), the BIOS's boot-time copy of ROM 0x1FC10000+)
* may run its statically-recompiled native function IFF the live RAM bytes
* of the code reachable from it (emitter-supplied body extent) byte-match
* the ROM source. Lazily verified, cached per entry, invalidated precisely
* on writes into the body. Runtime-patched bodies (pad/SIO install stubs)
* never verify and keep interpreting — faithful either way. */
int psx_kernel_bless_dispatchable(uint32_t phys);
void psx_kernel_bless_note_range(uint32_t phys, uint32_t len);
void psx_kernel_bless_stats(uint64_t out[6]);
/* Capture/candidate window membership. Kernel window and overlay region are
* unconditional; main-EXE text [KERNEL_WINDOW_END, FLOOR) is included only
* when the page is dirty — i.e. a gameplay overlay overwrote the boot text
+4
View File
@@ -205,6 +205,10 @@ static int apply_section(uint32_t tag, const uint8_t* p, uint32_t len,
case BS_SEC_RAM:
if (len != RAM_SIZE) return 0;
memcpy(memory_get_ram_ptr(), p, RAM_SIZE);
{ /* Kernel-bless: RAM changed wholesale — force re-verification. */
extern void psx_kernel_bless_note_range(uint32_t phys, uint32_t l);
psx_kernel_bless_note_range(0, RAM_SIZE);
}
return 1;
case BS_SEC_SPAD:
if (len != SPAD_SIZE) return 0;
+18
View File
@@ -6743,6 +6743,23 @@ static void handle_ws_hud_mode(int id, const char *json)
send_fmt("{\"id\":%d,\"ok\":true,\"tag_rects\":%d}", id, v ? 1 : 0);
}
/* Kernel-image bless state: {"cmd":"kernel_bless"} ->
* entries/clean/mismatch/native_hits/verifies/invalidations.
* (memory.c psx_kernel_bless_*; PSX_KERNEL_BLESS=0 disables the mechanism.) */
static void handle_kernel_bless(int id, const char *json)
{
extern void psx_kernel_bless_stats(uint64_t out[6]);
(void)json;
uint64_t s[6];
psx_kernel_bless_stats(s);
send_fmt("{\"id\":%d,\"ok\":true,\"entries\":%llu,\"clean\":%llu,"
"\"mismatch\":%llu,\"native_hits\":%llu,\"verifies\":%llu,"
"\"invalidations\":%llu}",
id, (unsigned long long)s[0], (unsigned long long)s[1],
(unsigned long long)s[2], (unsigned long long)s[3],
(unsigned long long)s[4], (unsigned long long)s[5]);
}
static void handle_ws_margin(int id, const char *json)
{
int v = json_get_int(json, "value", -2);
@@ -11810,6 +11827,7 @@ static const CmdEntry s_commands[] = {
{ "gpu_state", handle_gpu_state },
{ "ws_margin", handle_ws_margin },
{ "ws_hud_mode", handle_ws_hud_mode },
{ "kernel_bless", handle_kernel_bless },
{ "ws_aspect", handle_ws_aspect },
{ "ws_nw", handle_ws_nw },
{ "ws_backdrop_ring", handle_ws_backdrop_ring },
+147
View File
@@ -100,9 +100,155 @@ static inline void dirty_ram_mark_page(uint32_t phys) {
dirty_ram_bitmap[page >> 5] |= bit;
}
/* ---- Kernel-image bless -------------------------------------------------
* Kernel Part 2 (RAM [0x500,0x8500)) is the BIOS's boot-time copy of ROM
* [0x1FC10000,0x1FC18000); the statically-recompiled kernel functions in the
* generated dispatch table were compiled FROM those ROM bytes. Those pages
* are permanently dirty (TCB saves, event tables, install stubs share the
* window), which diverted EVERY kernel dispatch to the interpreter — the
* dominant cost of event-heavy scenes (a Tomba village frame samples ~97%
* in kernel PCs) and CD-load drains.
*
* A dispatch key may run its static native function IFF the live RAM bytes
* of everything that function can execute (its body extent, emitter-supplied
* via psx_bios_kernel_bodies[]) still byte-match the ROM source. Per-entry,
* lazily verified, cached; a guest write landing INSIDE an entry's body
* drops that entry back to unverified (next dispatch re-compares). Entries
* whose bodies were runtime-patched (the BIOS installs pad/SIO handlers into
* ROM-zero gaps of the pad driver) simply never verify and stay on the
* faithful interpreter path — their behavior is unchanged by design. This is
* the runtime half of the relocation-manifest contract
* (docs/RELOCATION_MANIFEST_FORMAT.md: "runtime verifies against live RAM
* before dispatching the AOT function"). */
#define KBLESS_RAM_LO 0x500u
#define KBLESS_RAM_HI 0x8500u
#define KBLESS_ROM_OFF 0x10000u /* bios_rom[] offset of RAM 0x500 */
typedef struct {
uint32_t key;
uint32_t body_lo;
uint32_t body_hi;
} PsxKernelBody;
extern const PsxKernelBody psx_bios_kernel_bodies[];
extern const uint32_t psx_bios_kernel_body_count;
#define KBLESS_UNKNOWN 0u
#define KBLESS_CLEAN 1u
#define KBLESS_MISMATCH 2u
#define KBLESS_MAX_ENTRIES 4096u
static uint8_t kbless_state[KBLESS_MAX_ENTRIES]; /* parallel to bodies[] */
static int kbless_enabled = -1; /* env PSX_KERNEL_BLESS=0 disables */
/* Always-on counters (TCP kernel_bless). */
static uint64_t kbless_native_hits = 0;
static uint64_t kbless_verifies = 0;
static uint64_t kbless_mismatches = 0;
static uint64_t kbless_invalidations = 0;
static int kbless_on(void) {
if (kbless_enabled < 0) {
const char* e = getenv("PSX_KERNEL_BLESS");
kbless_enabled = (e && e[0] == '0') ? 0 : 1;
if (psx_bios_kernel_body_count > KBLESS_MAX_ENTRIES) kbless_enabled = 0;
}
return kbless_enabled;
}
/* Binary search the (key-sorted) body table. -1 if absent. */
static int kbless_find(uint32_t phys) {
uint32_t lo = 0, hi = psx_bios_kernel_body_count;
while (lo < hi) {
uint32_t mid = (lo + hi) >> 1;
uint32_t k = psx_bios_kernel_bodies[mid].key;
if (k == phys) return (int)mid;
if (k < phys) lo = mid + 1; else hi = mid;
}
return -1;
}
/* Dispatch-time query: may `phys` run its static native function?
* Verifies lazily; every failure mode falls back to the interpreter. */
int psx_kernel_bless_dispatchable(uint32_t phys) {
if (phys - KBLESS_RAM_LO >= (KBLESS_RAM_HI - KBLESS_RAM_LO)) return 0;
if (!kbless_on()) return 0;
int i = kbless_find(phys);
if (i < 0) return 0;
uint8_t st = kbless_state[i];
if (st == KBLESS_CLEAN) { kbless_native_hits++; return 1; }
if (st == KBLESS_MISMATCH) return 0;
const PsxKernelBody* b = &psx_bios_kernel_bodies[i];
kbless_verifies++;
if (memcmp(ram + b->body_lo,
bios_rom + KBLESS_ROM_OFF + (b->body_lo - KBLESS_RAM_LO),
b->body_hi - b->body_lo) == 0) {
kbless_state[i] = KBLESS_CLEAN;
kbless_native_hits++;
return 1;
}
kbless_state[i] = KBLESS_MISMATCH;
kbless_mismatches++;
return 0;
}
/* A write landed in the kernel window: any entry whose body contains the
* written byte must re-verify before its next native dispatch. Kernel DATA
* writes (TCB saves, event tables — the frequent case) lie outside every
* body and fall through the loop without invalidating anything; genuine
* code-window writes (install-time, patches) are rare. */
static void kbless_note_write(uint32_t phys) {
if (phys - KBLESS_RAM_LO >= (KBLESS_RAM_HI - KBLESS_RAM_LO)) return;
if (kbless_enabled == 0) return;
uint32_t n = psx_bios_kernel_body_count;
if (n > KBLESS_MAX_ENTRIES) return;
for (uint32_t i = 0; i < n; i++) {
/* No early exit: a continuation key can sort ABOVE the written
* address while its parent body contains it (bodies overlap). n is
* a few hundred; this path fires only on kernel-window writes. */
const PsxKernelBody* b = &psx_bios_kernel_bodies[i];
if (phys >= b->body_lo && phys < b->body_hi &&
kbless_state[i] != KBLESS_UNKNOWN) {
kbless_state[i] = KBLESS_UNKNOWN;
kbless_invalidations++;
}
}
}
/* Range write (DMA / EXE load / savestate restore) overlapping the window:
* bulk, rare events — reset every entry rather than per-byte scanning. */
void psx_kernel_bless_note_range(uint32_t phys, uint32_t len) {
if (len == 0) return;
uint32_t end = phys + len;
if (end < phys) end = 0xFFFFFFFFu;
if (end <= KBLESS_RAM_LO || phys >= KBLESS_RAM_HI) return;
uint32_t n = psx_bios_kernel_body_count;
if (n > KBLESS_MAX_ENTRIES) return;
for (uint32_t i = 0; i < n; i++) {
if (kbless_state[i] != KBLESS_UNKNOWN) {
kbless_state[i] = KBLESS_UNKNOWN;
kbless_invalidations++;
}
}
}
void psx_kernel_bless_stats(uint64_t out[6]) {
uint32_t n = psx_bios_kernel_body_count;
uint32_t clean = 0, mism = 0;
if (n > KBLESS_MAX_ENTRIES) n = KBLESS_MAX_ENTRIES;
for (uint32_t i = 0; i < n; i++) {
if (kbless_state[i] == KBLESS_CLEAN) clean++;
if (kbless_state[i] == KBLESS_MISMATCH) mism++;
}
out[0] = psx_bios_kernel_body_count;
out[1] = clean;
out[2] = mism;
out[3] = kbless_native_hits;
out[4] = kbless_verifies;
out[5] = kbless_invalidations;
}
static inline void dirty_ram_mark_kernel_write(uint32_t phys) {
if (phys >= DIRTY_RAM_KERNEL_TRACK_BYTES) return;
dirty_ram_mark_page(phys);
kbless_note_write(phys);
}
int dirty_ram_is_dirty(uint32_t phys);
@@ -247,6 +393,7 @@ uint32_t dirty_ram_text_diverged_pages(void) { return g_text_diverged_pages; }
void dirty_ram_mark_executable_range(uint32_t phys, uint32_t len) {
if (len == 0 || phys >= RAM_SIZE) return;
psx_kernel_bless_note_range(phys, len);
uint32_t end = phys + len - 1u;
if (end >= RAM_SIZE || end < phys) end = RAM_SIZE - 1u;