sbl bringup: stublets, slots, maze, ffu-ref, b10 chain, docs
This commit is contained in:
+106
-4
@@ -22,6 +22,8 @@
|
||||
#include "qemu/log.h"
|
||||
|
||||
/* Real MSM8909 map (subset) */
|
||||
#define SAIMAA_RPM_BASE 0x00400000
|
||||
#define SAIMAA_RPM_SIZE 0x07C00000 /* 0x00400000..0x08000000 heap-ish */
|
||||
#define SAIMAA_OCIMEM_BASE 0x00200000
|
||||
#define SAIMAA_OCIMEM_SIZE 0x00100000
|
||||
#define SAIMAA_DDRLOW_BASE 0x08000000
|
||||
@@ -35,6 +37,8 @@
|
||||
#define SAIMAA_GICD_BASE 0x0B000000
|
||||
#define SAIMAA_GICC_BASE 0x0B002000
|
||||
#define SAIMAA_NCPUS 4
|
||||
#define SAIMAA_MYSTROM_BASE 0x69000000
|
||||
#define SAIMAA_MYSTROM_SIZE 0x00100000
|
||||
#define SAIMAA_SMEM_BASE 0x87C00000
|
||||
#define SAIMAA_SMEM_SIZE 0x00800000
|
||||
|
||||
@@ -131,6 +135,7 @@ struct SaimaaMachineState {
|
||||
char *sbl1;
|
||||
char *emmc;
|
||||
char *sblmain; /* hex: popped-PC override for PBL trampoline */
|
||||
char *regs; /* PBL reg overrides: N=V,N=V (N=r1,r4,r6-r9,sl,fp) */
|
||||
};
|
||||
typedef struct SaimaaMachineState SaimaaMachineState;
|
||||
|
||||
@@ -145,17 +150,28 @@ static void saimaa_machine_init(MachineState *machine)
|
||||
|
||||
/* RAM map */
|
||||
const struct { const char *n; hwaddr b; hwaddr s; } rams[] = {
|
||||
{ "saimaa.rpm", SAIMAA_RPM_BASE, SAIMAA_RPM_SIZE },
|
||||
{ "saimaa.ocimem", SAIMAA_OCIMEM_BASE, SAIMAA_OCIMEM_SIZE },
|
||||
{ "saimaa.ddrlow", SAIMAA_DDRLOW_BASE, SAIMAA_DDRLOW_SIZE },
|
||||
{ "saimaa.imem", SAIMAA_IMEM_BASE, SAIMAA_IMEM_SIZE },
|
||||
{ "saimaa.ddrhigh", SAIMAA_DDRHIGH_BASE, SAIMAA_DDRHIGH_SIZE },
|
||||
{ "saimaa.mystrom", SAIMAA_MYSTROM_BASE, SAIMAA_MYSTROM_SIZE },
|
||||
{ "saimaa.smem", SAIMAA_SMEM_BASE, SAIMAA_SMEM_SIZE },
|
||||
};
|
||||
for (i = 0; i < 5; i++) {
|
||||
for (i = 0; i < 7; i++) {
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||
memory_region_init_ram(ram, NULL, rams[i].n, rams[i].s,
|
||||
&error_fatal);
|
||||
memory_region_add_subregion(sysmem, rams[i].b, ram);
|
||||
memory_region_add_subregion(sysmem, rams[i].b, ram);
|
||||
if (!strcmp(rams[i].n, "saimaa.mystrom")) {
|
||||
/* Mystery handler ROM: ARM mov r0,#0; bx lr repeating,
|
||||
* so unknown blx targets return 0 instead of faulting. */
|
||||
uint32_t *p = memory_region_get_ram_ptr(ram);
|
||||
size_t k, n = SAIMAA_MYSTROM_SIZE / 4;
|
||||
for (k = 0; k < n; k++) {
|
||||
p[k] = 0xe12fff1e; /* bx lr: any 4-aligned entry returns */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* CPUs: 4x Cortex-A7, only cpu0 boots */
|
||||
@@ -182,7 +198,9 @@ static void saimaa_machine_init(MachineState *machine)
|
||||
sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(uart), 0, SAIMAA_UART_BASE);
|
||||
|
||||
/* Null-page trap at 0x0 (vectors live here; PBL normally maps ROM) */
|
||||
/* Null-page trap at 0x0 (vectors live here; PBL normally maps ROM).
|
||||
* Returns 0 for reads (data-0 invariant for SBL1 probing), logs the
|
||||
* first faulting PCs for diagnosis. */
|
||||
{
|
||||
MemoryRegion *vec = g_new(MemoryRegion, 1);
|
||||
memory_region_init_io(vec, NULL, &saimaa_vec_ops, NULL,
|
||||
@@ -239,7 +257,76 @@ static void saimaa_machine_init(MachineState *machine)
|
||||
/* sbl_main expects r5 = mem-table pointer (PBL trampoline does
|
||||
* mov r5, r0 before jumping here); point it at pbl_shared too. */
|
||||
ARM_CPU(first_cpu)->env.regs[5] = 0x00220000;
|
||||
/* (direct-start handled above; no stack override needed) */
|
||||
|
||||
/* sl/fp = SBL1 table bases (PBL trampoline would pop these from its
|
||||
* frame); point at free DDRLOW RAM so helper-built tables persist
|
||||
* instead of vanishing into the null-page trap. */
|
||||
ARM_CPU(first_cpu)->env.regs[10] = 0x08060000; /* sl */
|
||||
ARM_CPU(first_cpu)->env.regs[11] = 0x08061000; /* fp */
|
||||
if (sms->regs) {
|
||||
char comma = 59;
|
||||
char delims[2];
|
||||
char *spec, *tok, *save = NULL;
|
||||
delims[0] = comma;
|
||||
delims[1] = 0;
|
||||
spec = g_strdup(sms->regs);
|
||||
for (tok = strtok_r(spec, delims, &save); tok;
|
||||
tok = strtok_r(NULL, delims, &save)) {
|
||||
char *eq = strchr(tok, 61);
|
||||
if (eq) {
|
||||
int n = strtoul(tok, NULL, 0);
|
||||
*eq = 0;
|
||||
eq++;
|
||||
if (n >= 0 && n < 16) {
|
||||
ARM_CPU(first_cpu)->env.regs[n] =
|
||||
strtoul(eq, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
g_free(spec);
|
||||
}
|
||||
/* PBL enables VFP/NEON (CPACR CP10+CP11, FPEXC.EN) before SBL1. */
|
||||
ARM_CPU(first_cpu)->env.cp15.cpacr_el1 = 0x00f00000;
|
||||
ARM_CPU(first_cpu)->env.cp15.nsacr |= (3u << 10);
|
||||
ARM_CPU(first_cpu)->env.vfp.xregs[ARM_VFP_FPEXC] |= (1u << 30);
|
||||
/* Boot scaffolding for SBL1 BringUp (WIP stub-driven PBL):
|
||||
* pop-compensation stublets at 0x08062000 pin sp and route onward,
|
||||
* so repeated pops always hit valid slots. */
|
||||
{
|
||||
static const unsigned char stub_blob[] = { 0xf0, 0xb4, 0x2d, 0xe9, 0x00, 0x5f, 0xdf, 0xf8, 0x6c, 0xc0, 0xcd, 0xf8, 0x24, 0xc0, 0xdf, 0xf8, 0x68, 0xf0, 0x30, 0xb4, 0xdf, 0xf8, 0x64, 0xc0, 0xcd, 0xf8, 0x04, 0xc0, 0xdf, 0xf8, 0x60, 0xf0, 0xf0, 0xb4, 0x2d, 0xe9, 0x00, 0x5f, 0xdf, 0xf8, 0x5c, 0xc0, 0xcd, 0xf8, 0x24, 0xc0, 0xdf, 0xf8, 0x58, 0xf0, 0xf0, 0xb5, 0x01, 0xb4, 0xdf, 0xf8, 0x54, 0xc0, 0xcd, 0xf8, 0x14, 0xc0, 0xdf, 0xf8, 0x50, 0xf0, 0xf0, 0xb4, 0x2d, 0xe9, 0x00, 0x5f, 0xdf, 0xf8, 0x48, 0xc0, 0xcd, 0xf8, 0x24, 0xc0, 0xdf, 0xf8, 0x44, 0xf0, 0xf0, 0xb5, 0x01, 0xb4, 0xdf, 0xf8, 0x40, 0xc0, 0xcd, 0xf8, 0x14, 0xc0, 0xdf, 0xf8, 0x3c, 0xf0, 0xf0, 0xb5, 0x07, 0xb4, 0xdf, 0xf8, 0x38, 0xc0, 0xcd, 0xf8, 0x1c, 0xc0, 0xdf, 0xf8, 0x34, 0xf0, 0x01, 0x20, 0x06, 0x08, 0x5d, 0xf6, 0x02, 0x08, 0x13, 0x20, 0x06, 0x08, 0x65, 0xf6, 0x02, 0x08, 0x21, 0x20, 0x06, 0x08, 0xa5, 0x3b, 0x01, 0x08, 0x43, 0x20, 0x06, 0x08, 0x81, 0xf6, 0x02, 0x08, 0x33, 0x20, 0x06, 0x08, 0x83, 0x61, 0x01, 0x08, 0x55, 0x20, 0x06, 0x08, 0x8d, 0x8a, 0x01, 0x08, 0x65, 0x20, 0x06, 0x08, 0x7d, 0xf6, 0x02, 0x08 };
|
||||
uint32_t magic = 0x00000000; /* IMEM poll spins WHILE equal */
|
||||
uint32_t S = 0x08062100, STUB = 0x08062120;
|
||||
uint32_t w;
|
||||
uint16_t h0 = 0x2000, h1 = 0x4770; /* movs r0,#0; bx lr */
|
||||
size_t k;
|
||||
uint32_t v;
|
||||
for (k = 0; k < sizeof(stub_blob); k += 4) {
|
||||
uint32_t word;
|
||||
__builtin_memcpy(&word, &stub_blob[k], 4);
|
||||
cpu_physical_memory_write(0x08062000 + k, &word, 4);
|
||||
}
|
||||
/* pointer maze in owned RAM for SBL1 struct chains */
|
||||
w = S + 8;
|
||||
cpu_physical_memory_write(S, &w, 4);
|
||||
cpu_physical_memory_write(S + 8, &STUB, 4);
|
||||
cpu_physical_memory_write(STUB, &h0, 2);
|
||||
cpu_physical_memory_write(STUB + 2, &h1, 2);
|
||||
cpu_physical_memory_write(0x087c29d18, &S, 4);
|
||||
cpu_physical_memory_write(0x08050b28, &S, 4);
|
||||
cpu_physical_memory_write(0x08070000, &S, 4);
|
||||
/* pop-site slots -> stublets (sp values from cpu traces) */
|
||||
v = 0x08062001; /* S1 pop10 */
|
||||
cpu_physical_memory_write(0x085FFF14, &v, 4);
|
||||
v = 0x08062013; /* S2 pop2 */
|
||||
cpu_physical_memory_write(0x085FFF1C, &v, 4);
|
||||
v = 0x08062021; /* S3 pop10 */
|
||||
cpu_physical_memory_write(0x085FFF44, &v, 4);
|
||||
cpu_physical_memory_write(0x085FFF7C, &v, 4);
|
||||
v = 0x08062033; /* S4 pop6 (stublet chains S5) */
|
||||
cpu_physical_memory_write(0x085FFF34, &v, 4);
|
||||
cpu_physical_memory_write(0x08600944, &magic, 4);
|
||||
printf("saimaa: stub-scaffold live\n");
|
||||
}
|
||||
printf("saimaa: SBL1 %s loaded (%zd bytes), entry 0x%lx\n",
|
||||
sms->sbl1, sz, (unsigned long)entry);
|
||||
}
|
||||
@@ -268,6 +355,18 @@ static char *saimaa_get_sblmain(Object *obj, Error **errp)
|
||||
return g_strdup(SAIMAA_MACHINE(obj)->sblmain);
|
||||
}
|
||||
|
||||
static char *saimaa_get_regs(Object *obj, Error **errp)
|
||||
{
|
||||
return g_strdup(SAIMAA_MACHINE(obj)->regs);
|
||||
}
|
||||
|
||||
static void saimaa_set_regs(Object *obj, const char *value, Error **errp)
|
||||
{
|
||||
SaimaaMachineState *sms = SAIMAA_MACHINE(obj);
|
||||
g_free(sms->regs);
|
||||
sms->regs = g_strdup(value);
|
||||
}
|
||||
|
||||
static void saimaa_set_sblmain(Object *obj, const char *value, Error **errp)
|
||||
{
|
||||
SaimaaMachineState *sms = SAIMAA_MACHINE(obj);
|
||||
@@ -281,7 +380,10 @@ static void saimaa_machine_instance_init(Object *obj)
|
||||
sms->sbl1 = NULL;
|
||||
sms->emmc = NULL;
|
||||
sms->sblmain = NULL;
|
||||
sms->regs = NULL;
|
||||
object_property_add_str(obj, "sbl1", saimaa_get_sbl1, saimaa_set_sbl1);
|
||||
object_property_add_str(obj, "regs", saimaa_get_regs,
|
||||
saimaa_set_regs);
|
||||
object_property_add_str(obj, "sblmain", saimaa_get_sblmain,
|
||||
saimaa_set_sblmain);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
.syntax unified
|
||||
.cpu cortex-a7
|
||||
.thumb
|
||||
@ SBL1 pop-compensation stublets for saimaa (v3: slots hold STUBLET
|
||||
@ addresses, never raw CONTS; S4<->S5 ping-pong stage each other).
|
||||
.text
|
||||
.global stub10_a, stub2, stub10_b, stub6_a, stub10_c, stub6_b, stub8
|
||||
stub10_a: @ N=10, jump CONT=0x802f65d
|
||||
push {r4-r7}
|
||||
push {r8-r11,ip,lr}
|
||||
ldr ip, =stub10_a
|
||||
str ip, [sp, #36]
|
||||
ldr pc, =0x802f65d
|
||||
stub2: @ N=2, jump CONT=0x802f665
|
||||
push {r4-r5}
|
||||
ldr ip, =stub2
|
||||
str ip, [sp, #4]
|
||||
ldr pc, =0x802f665
|
||||
stub10_b: @ N=10, jump CONT=0x8013ba5
|
||||
push {r4-r7}
|
||||
push {r8-r11,ip,lr}
|
||||
ldr ip, =stub10_b
|
||||
str ip, [sp, #36]
|
||||
ldr pc, =0x8013ba5
|
||||
stub6_a: @ N=6, jump CONT=0x802f681,
|
||||
@ stage stub10_c for upcoming S5
|
||||
push {r4-r7,lr}
|
||||
push {r0}
|
||||
ldr ip, =stub10_c
|
||||
str ip, [sp, #20]
|
||||
ldr pc, =0x802f681
|
||||
stub10_c: @ N=10, jump CONT=0x8016183,
|
||||
@ restage stub6_a for future S4
|
||||
push {r4-r7}
|
||||
push {r8-r11,ip,lr}
|
||||
ldr ip, =stub6_a
|
||||
str ip, [sp, #36]
|
||||
ldr pc, =0x8016183
|
||||
stub6_b: @ N=6, jump CONT=0x8018a8d
|
||||
push {r4-r7,lr}
|
||||
push {r0}
|
||||
ldr ip, =stub6_b
|
||||
str ip, [sp, #20]
|
||||
ldr pc, =0x8018a8d
|
||||
stub8: @ N=8, jump CONT=0x802f67d
|
||||
push {r4-r7,lr}
|
||||
push {r0-r2}
|
||||
ldr ip, =stub8
|
||||
str ip, [sp, #28]
|
||||
ldr pc, =0x802f67d
|
||||
Reference in New Issue
Block a user