diff --git a/docs/sbl-bringup.md b/docs/sbl-bringup.md index 8192191..6afca2e 100644 --- a/docs/sbl-bringup.md +++ b/docs/sbl-bringup.md @@ -189,3 +189,8 @@ за проход → марш sp к верху IMEM. S20 (34B @0x08006D38): `[sp+0x2C]` валиден → исходный pop; иначе r0=sl + re-run (идемпотентная математика). Эпилог `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. diff --git a/qemu/saimaa.c b/qemu/saimaa.c index 947b082..c499d2f 100644 --- a/qemu/saimaa.c +++ b/qemu/saimaa.c @@ -167,14 +167,15 @@ struct SaimaaUartState { static int saimaa_vec_n; static uint64_t saimaa_vec_read(void *opaque, hwaddr off, unsigned size) { - /* Maze blob mirrored at [0,18) for THUMB fetches: null-jump fetches - * (bx r0=0, pop 0, ldr pc,=0) execute the maze and return via lr — - * uni parity (hook_null -> STUB). ARM-mode fetches (real exception - * entry) keep BKPT vectors below. Data probes elsewhere read 0. */ - static const uint8_t maze[18] = { + /* Maze blob v2 mirrored at [0,24) for THUMB fetches: null-jump + * fetches (bx r0=0, pop 0, ldr pc,=0) execute the maze and return + * via lr — uni parity (hook_null -> STUB). ARM-mode fetches (real + * exception entry) keep BKPT vectors below. Data probes elsewhere + * read 0. */ + static const uint8_t maze[24] = { 0x00, 0x20, 0x4f, 0xea, 0x1e, 0x6c, 0xbc, 0xf1, - 0x08, 0x0f, 0x00, 0xd1, 0x70, 0x47, 0x72, 0xb6, - 0xfd, 0xe7, + 0x08, 0x0f, 0x03, 0xd1, 0x1e, 0xf0, 0x01, 0x0f, + 0x00, 0xd0, 0x70, 0x47, 0x72, 0xb6, 0xfd, 0xe7, }; { 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 + 8, &STUBV, 4); { - /* Minimal maze: movs r0,#0; bx lr (4B). No mailbox, no - * guard — vec trap already reports fault state. Less - * surface for SBL heap clobbers. */ + /* Maze v2 (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 below). */ static const uint8_t mb[] = { 0x00, 0x20, 0x4f, 0xea, 0x1e, 0x6c, 0xbc, 0xf1, - 0x08, 0x0f, 0x00, 0xd1, 0x70, 0x47, 0x72, 0xb6, - 0xfd, 0xe7, + 0x08, 0x0f, 0x03, 0xd1, 0x1e, 0xf0, 0x01, 0x0f, + 0x00, 0xd0, 0x70, 0x47, 0x72, 0xb6, 0xfd, 0xe7, }; size_t k; 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(0x08050b28, &S, 4); cpu_physical_memory_write(0x08070000, &S, 4); - /* S6 stublet at 0x08006B9E: rebuild popped frame regs, - * return to 0x8013ba5 (b14 redirects 0x8017afc pop here) */ - { - static const uint8_t s6[] = { - 0xbd, 0xe8, 0xfc, 0x47, /* ldmia.w sp!,{r2-r9,sl,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); - } - } + /* S6 stublet DISABLED (maze v2 overlaps its head [B9E,BA4); + * S6 dormant, never entered (b14 goes to 0x8005B9E). + * Bytes kept for reference (would live at 0x08006B9E): + * ldmia.w sp!,{r2-r9,sl,lr}; movw lr,#0x3ba5; + * movt lr,#0x801; bx lr. */ /* Banner stub at 0x08006BAC: print r0 string via UARTDM * (b16 redirects 0x802f690 blx here). Built from qemu/banner.S: * push frame, print loop, ldr pc,=0x802f694 (callee noreturn). diff --git a/tools/sbl_uni.py b/tools/sbl_uni.py index 313061e..90512ba 100644 --- a/tools/sbl_uni.py +++ b/tools/sbl_uni.py @@ -376,18 +376,23 @@ def main(): W32(S, S + 8) W32(S + 4, 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([ 0x00, 0x20, 0x4f, 0xea, 0x1e, 0x6c, 0xbc, 0xf1, - 0x08, 0x0f, 0x00, 0xd1, 0x70, 0x47, 0x72, 0xb6, - 0xfd, 0xe7])) - print("maze-rb:", bytes(mu.mem_read(STUB, 18)).hex()) + 0x08, 0x0f, 0x03, 0xd1, 0x1e, 0xf0, 0x01, 0x0f, + 0x00, 0xd0, 0x70, 0x47, 0x72, 0xb6, 0xfd, 0xe7])) + print("maze-rb:", bytes(mu.mem_read(STUB, 24)).hex()) for a in (0x087c29d18, 0x08050b28, 0x08070000): W32(a, S) - # S6 stublet (14B @0x08006B9E) - mu.mem_write(0x08006B9E, bytes([ - 0xbd, 0xe8, 0xfc, 0x47, 0x43, 0xf6, 0xa5, 0x3e, - 0xc0, 0xf6, 0x01, 0x0e, 0x70, 0x47])) + # S6 stublet DISABLED (maze v2 overlaps its head; S6 dormant, + # never entered (b14 goes to 0x8005B9E, not here). Bytes kept for + # reference (would live at 0x08006B9E): + # 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) mu.mem_write(0x08006BAC, bytes([ 0x10, 0xb5, 0x4f, 0xf2, 0x00, 0x03, 0xc0, 0xf2,