diff --git a/sys/src/9/imx8/main.c b/sys/src/9/imx8/main.c index 1b7ee9969..d83dca421 100644 --- a/sys/src/9/imx8/main.c +++ b/sys/src/9/imx8/main.c @@ -10,6 +10,8 @@ #include "sysreg.h" #include "ureg.h" +#include "rebootcode.i" + Conf conf; /* @@ -124,7 +126,7 @@ mpinit(void) MACHP(i)->machno = i; cachedwbinvse(MACHP(i), MACHSIZE); - u.r0 = 0x84000003; + u.r0 = 0x84000003; /* CPU_ON */ u.r1 = (sysrd(MPIDR_EL1) & ~0xFF) | i; u.r2 = PADDR(_start); u.r3 = i; @@ -188,12 +190,13 @@ main(void) void exit(int) { - Ureg u = { .r0 = 0x84000009 }; + Ureg u = { .r0 = 0x84000002 }; /* CPU_OFF */ cpushutdown(); splfhi(); - /* system reset */ + if(m->machno == 0) + u.r0 = 0x84000009; /* SYSTEM RESET */ smccall(&u); } @@ -214,9 +217,54 @@ writeconf(void) { } -void -reboot(void *, void *, ulong) +static void +rebootjump(void *entry, void *code, ulong size) { + void (*f)(void*, void*, ulong); + + intrcpushutdown(); + + /* redo identity map */ + mmuidmap((uintptr*)L1); + + /* setup reboot trampoline function */ + f = (void*)REBOOTADDR; + memmove(f, rebootcode, sizeof(rebootcode)); + + cachedwbinvse(f, sizeof(rebootcode)); + cacheiinvse(f, sizeof(rebootcode)); + + (*f)(entry, code, size); + + for(;;); +} + +void +reboot(void*, void *code, ulong size) +{ + writeconf(); + while(m->machno != 0){ + procwired(up, 0); + sched(); + } + + cpushutdown(); + delay(2000); + + splfhi(); + + /* turn off buffered serial console */ + serialoq = nil; + + /* shutdown devices */ + chandevshutdown(); + + /* stop the clock */ + clockshutdown(); + intrsoff(); + + /* off we go - never to return */ + rebootjump((void*)(KTZERO-KZERO), code, size); } void diff --git a/sys/src/9/imx8/mem.h b/sys/src/9/imx8/mem.h index 0c92e9ae2..5f0f15649 100644 --- a/sys/src/9/imx8/mem.h +++ b/sys/src/9/imx8/mem.h @@ -44,7 +44,7 @@ #define UCRAMSIZE (8*MiB) #define VDRAM (0xFFFFFFFFC0000000ULL) /* 0x40000000 - 0x80000000 */ -#define KTZERO (VDRAM + 0x100000) /* kernel text start */ +#define KTZERO (VDRAM + 0x100000) /* 0x40100000 - kernel text start */ #define ARMLOCAL (0xFFFFFFFFB1000000ULL) /* 0x31000000 */ #define VIRTIO (0xFFFFFFFFB0000000ULL) /* 0x30000000 */ @@ -64,6 +64,9 @@ #define MACHADDR(n) (KTZERO-((n)+1)*MACHSIZE) +#define CONFADDR (VDRAM + 0x10000) /* 0x40010000 */ +#define REBOOTADDR (0x40020000) /* 0x40020000 */ + #define UZERO 0ULL /* user segment */ #define UTZERO (UZERO+0x10000) /* user text start */ #define USTKTOP ((EVAMASK>>1)-0xFFFF) /* user segment end +1 */ diff --git a/sys/src/9/imx8/mkfile b/sys/src/9/imx8/mkfile index 10d50f06b..97d6a471a 100644 --- a/sys/src/9/imx8/mkfile +++ b/sys/src/9/imx8/mkfile @@ -87,8 +87,15 @@ install:V: /$objtype/$p$CONF <../port/portmkfile <|../port/mkbootrules $CONF +main.$O: rebootcode.i + +pciimx.$O: ../port/pci.h + initcode.out: init9.$O initcode.$O /$objtype/lib/libc.a $LD -l -R1 -s -o $target $prereq +rebootcode.out: rebootcode.$O cache.v8.$O + $LD -l -H6 -R1 -T0x40020000 -s -o $target $prereq + $CONF.clean: rm -rf $p$CONF $p$CONF.u errstr.h $CONF.c boot$CONF.c diff --git a/sys/src/9/imx8/mmu.c b/sys/src/9/imx8/mmu.c index c61ca7f01..031514018 100644 --- a/sys/src/9/imx8/mmu.c +++ b/sys/src/9/imx8/mmu.c @@ -60,6 +60,24 @@ mmu0clear(uintptr *l1) l1[PTL1X(pa, 3)] = 0; } +void +mmuidmap(uintptr *l1) +{ + uintptr va, pa, pe; + + pe = -VDRAM; + for(pa = VDRAM - KZERO, va = VDRAM; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)) + l1[PTL1X(pa, 1)] = l1[PTL1X(va, 1)]; + if(PTLEVELS > 2) + for(pa = VDRAM - KZERO, va = VDRAM; pa < pe; pa += PGLSZ(2), va += PGLSZ(2)) + l1[PTL1X(pa, 2)] = l1[PTL1X(va, 2)]; + if(PTLEVELS > 3) + for(pa = VDRAM - KZERO, va = VDRAM; pa < pe; pa += PGLSZ(3), va += PGLSZ(3)) + l1[PTL1X(pa, 3)] = l1[PTL1X(va, 3)]; + setttbr(PADDR(&l1[L1TABLEX(0, PTLEVELS-1)])); + flushtlb(); +} + void mmu1init(void) { diff --git a/sys/src/9/imx8/rebootcode.s b/sys/src/9/imx8/rebootcode.s new file mode 100644 index 000000000..4406350f2 --- /dev/null +++ b/sys/src/9/imx8/rebootcode.s @@ -0,0 +1,48 @@ +#include "mem.h" +#include "sysreg.h" + +#undef SYSREG +#define SYSREG(op0,op1,Cn,Cm,op2) SPR(((op0)<<19|(op1)<<16|(Cn)<<12|(Cm)<<8|(op2)<<5)) + +TEXT _start(SB), 1, $-4 + MOV $setSB(SB), R28 + + MOV R0, R27 + + MOV code+8(FP), R1 + MOVWU size+16(FP), R2 + BIC $3, R2 + ADD R1, R2, R3 + +_copy: + MOVW (R1)4!, R4 + MOVW R4, (R0)4! + CMP R1, R3 + BNE _copy + + BL cachedwbinv(SB) + BL l2cacheuwbinv(SB) + + ISB $SY + MRS SCTLR_EL1, R0 + BIC $(1<<0 | 1<<2 | 1<<12), R0 + ISB $SY + MSR R0, SCTLR_EL1 + ISB $SY + + DSB $NSHST + TLBI R0, 0,8,7,0 /* VMALLE1 */ + DSB $NSH + ISB $SY + + BL cachedwbinv(SB) + BL cacheiinv(SB) + + MOVWU $0, R0 + MOVWU $0, R1 + MOVWU $0, R2 + MOVWU $0, R3 + + MOV R27, LR + + RETURN