maze v2: reject even lr (no ARM drift)

This commit is contained in:
lumia-emu
2026-09-14 00:30:18 +00:00
parent 3d011f2994
commit d3e2efe7ba
3 changed files with 38 additions and 37 deletions
+5
View File
@@ -189,3 +189,8 @@
за проход → марш sp к верху IMEM. S20 (34B @0x08006D38): за проход → марш sp к верху IMEM. S20 (34B @0x08006D38):
`[sp+0x2C]` валиден → исходный pop; иначе r0=sl + re-run `[sp+0x2C]` валиден → исходный pop; иначе r0=sl + re-run
(идемпотентная математика). Эпилог `pop.w` (4B) → `b.w S20`. (идемпотентная математика). Эпилог `pop.w` (4B) → `b.w S20`.
## maze v2 (2026-09-13)
- Maze с чётным lr уходил в ARM-дрейф (STM-clobbers + IMEM fault).
Maze v2 (24B): возврат только при odd Thumb lr из DDR, иначе hang
громко. Залез на голову S6 (`[B9E,BA4)`, S6 dormant). Vec-maze тоже v2.
+20 -29
View File
@@ -167,14 +167,15 @@ struct SaimaaUartState {
static int saimaa_vec_n; static int saimaa_vec_n;
static uint64_t saimaa_vec_read(void *opaque, hwaddr off, unsigned size) static uint64_t saimaa_vec_read(void *opaque, hwaddr off, unsigned size)
{ {
/* Maze blob mirrored at [0,18) for THUMB fetches: null-jump fetches /* Maze blob v2 mirrored at [0,24) for THUMB fetches: null-jump
* (bx r0=0, pop 0, ldr pc,=0) execute the maze and return via lr — * fetches (bx r0=0, pop 0, ldr pc,=0) execute the maze and return
* uni parity (hook_null -> STUB). ARM-mode fetches (real exception * via lr — uni parity (hook_null -> STUB). ARM-mode fetches (real
* entry) keep BKPT vectors below. Data probes elsewhere read 0. */ * exception entry) keep BKPT vectors below. Data probes elsewhere
static const uint8_t maze[18] = { * read 0. */
static const uint8_t maze[24] = {
0x00, 0x20, 0x4f, 0xea, 0x1e, 0x6c, 0xbc, 0xf1, 0x00, 0x20, 0x4f, 0xea, 0x1e, 0x6c, 0xbc, 0xf1,
0x08, 0x0f, 0x00, 0xd1, 0x70, 0x47, 0x72, 0xb6, 0x08, 0x0f, 0x03, 0xd1, 0x1e, 0xf0, 0x01, 0x0f,
0xfd, 0xe7, 0x00, 0xd0, 0x70, 0x47, 0x72, 0xb6, 0xfd, 0xe7,
}; };
{ {
ARMCPU *cpu = ARM_CPU(current_cpu); ARMCPU *cpu = ARM_CPU(current_cpu);
@@ -555,13 +556,15 @@ static void saimaa_machine_init(MachineState *machine)
cpu_physical_memory_write(S + 4, &STUBV, 4); cpu_physical_memory_write(S + 4, &STUBV, 4);
cpu_physical_memory_write(S + 8, &STUBV, 4); cpu_physical_memory_write(S + 8, &STUBV, 4);
{ {
/* Minimal maze: movs r0,#0; bx lr (4B). No mailbox, no /* Maze v2 (24B @STUB): movs r0,#0; return 0 via lr ONLY
* guard — vec trap already reports fault state. Less * if lr is odd Thumb in DDR (top 8); even lr (stale
* surface for SBL heap clobbers. */ * mid-fn raw addr!) would ARM-drift (STM-clobbers +
* IMEM fault), so hang loud instead. Overlaps S6 head
* ([B9E,BA4), S6 dormant, documented below). */
static const uint8_t mb[] = { static const uint8_t mb[] = {
0x00, 0x20, 0x4f, 0xea, 0x1e, 0x6c, 0xbc, 0xf1, 0x00, 0x20, 0x4f, 0xea, 0x1e, 0x6c, 0xbc, 0xf1,
0x08, 0x0f, 0x00, 0xd1, 0x70, 0x47, 0x72, 0xb6, 0x08, 0x0f, 0x03, 0xd1, 0x1e, 0xf0, 0x01, 0x0f,
0xfd, 0xe7, 0x00, 0xd0, 0x70, 0x47, 0x72, 0xb6, 0xfd, 0xe7,
}; };
size_t k; size_t k;
for (k = 0; k < sizeof(mb); k += 4) { for (k = 0; k < sizeof(mb); k += 4) {
@@ -574,23 +577,11 @@ static void saimaa_machine_init(MachineState *machine)
cpu_physical_memory_write(0x087c29d18, &S, 4); cpu_physical_memory_write(0x087c29d18, &S, 4);
cpu_physical_memory_write(0x08050b28, &S, 4); cpu_physical_memory_write(0x08050b28, &S, 4);
cpu_physical_memory_write(0x08070000, &S, 4); cpu_physical_memory_write(0x08070000, &S, 4);
/* S6 stublet at 0x08006B9E: rebuild popped frame regs, /* S6 stublet DISABLED (maze v2 overlaps its head [B9E,BA4);
* return to 0x8013ba5 (b14 redirects 0x8017afc pop here) */ * S6 dormant, never entered (b14 goes to 0x8005B9E).
{ * Bytes kept for reference (would live at 0x08006B9E):
static const uint8_t s6[] = { * ldmia.w sp!,{r2-r9,sl,lr}; movw lr,#0x3ba5;
0xbd, 0xe8, 0xfc, 0x47, /* ldmia.w sp!,{r2-r9,sl,lr} */ * movt lr,#0x801; bx lr. */
0x43, 0xf6, 0xa5, 0x3e, /* movw lr,#0x3ba5 */
0xc0, 0xf6, 0x01, 0x0e, /* movt lr,#0x801 */
0x70, 0x47, /* bx lr */
};
size_t k;
for (k = 0; k < sizeof(s6); k += 4) {
uint32_t word = 0;
size_t n = sizeof(s6) - k < 4 ? sizeof(s6) - k : 4;
__builtin_memcpy(&word, &s6[k], n);
cpu_physical_memory_write(0x08006B9E + k, &word, 4);
}
}
/* Banner stub at 0x08006BAC: print r0 string via UARTDM /* Banner stub at 0x08006BAC: print r0 string via UARTDM
* (b16 redirects 0x802f690 blx here). Built from qemu/banner.S: * (b16 redirects 0x802f690 blx here). Built from qemu/banner.S:
* push frame, print loop, ldr pc,=0x802f694 (callee noreturn). * push frame, print loop, ldr pc,=0x802f694 (callee noreturn).
+13 -8
View File
@@ -376,18 +376,23 @@ def main():
W32(S, S + 8) W32(S, S + 8)
W32(S + 4, STUBV) W32(S + 4, STUBV)
W32(S + 8, STUBV) W32(S + 8, STUBV)
# maze blob (18B) # maze blob (24B @STUB): movs r0,#0; return 0 via lr ONLY if lr is
# odd Thumb in DDR (top 8); even lr (stale mid-fn raw addr!) would
# ARM-drift (STM-clobbers + IMEM fault), so hang loud instead.
# Overlaps S6 head ([B9E,BA4), S6 dormant, documented).
mu.mem_write(STUB, bytes([ mu.mem_write(STUB, bytes([
0x00, 0x20, 0x4f, 0xea, 0x1e, 0x6c, 0xbc, 0xf1, 0x00, 0x20, 0x4f, 0xea, 0x1e, 0x6c, 0xbc, 0xf1,
0x08, 0x0f, 0x00, 0xd1, 0x70, 0x47, 0x72, 0xb6, 0x08, 0x0f, 0x03, 0xd1, 0x1e, 0xf0, 0x01, 0x0f,
0xfd, 0xe7])) 0x00, 0xd0, 0x70, 0x47, 0x72, 0xb6, 0xfd, 0xe7]))
print("maze-rb:", bytes(mu.mem_read(STUB, 18)).hex()) print("maze-rb:", bytes(mu.mem_read(STUB, 24)).hex())
for a in (0x087c29d18, 0x08050b28, 0x08070000): for a in (0x087c29d18, 0x08050b28, 0x08070000):
W32(a, S) W32(a, S)
# S6 stublet (14B @0x08006B9E) # S6 stublet DISABLED (maze v2 overlaps its head; S6 dormant,
mu.mem_write(0x08006B9E, bytes([ # never entered (b14 goes to 0x8005B9E, not here). Bytes kept for
0xbd, 0xe8, 0xfc, 0x47, 0x43, 0xf6, 0xa5, 0x3e, # reference (would live at 0x08006B9E):
0xc0, 0xf6, 0x01, 0x0e, 0x70, 0x47])) # mu.mem_write(0x08006B9E, bytes([
# 0xbd, 0xe8, 0xfc, 0x47, 0x43, 0xf6, 0xa5, 0x3e,
# 0xc0, 0xf6, 0x01, 0x0e, 0x70, 0x47]))
# banner stub (34B @0x08006BAC, prints r0 via UARTDM) # banner stub (34B @0x08006BAC, prints r0 via UARTDM)
mu.mem_write(0x08006BAC, bytes([ mu.mem_write(0x08006BAC, bytes([
0x10, 0xb5, 0x4f, 0xf2, 0x00, 0x03, 0xc0, 0xf2, 0x10, 0xb5, 0x4f, 0xf2, 0x00, 0x03, 0xc0, 0xf2,