diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-07-10 11:35:58 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-07-10 11:35:58 +0000 |
commit | 32183b1abf7a670e11c59595fda4cd64dad1008b (patch) | |
tree | df981740dcf697e8c3f4f13b553364a95b1aaec3 /sys/src/9/imx8 | |
parent | 414cefcb0b40082d73942ea619de59b371bd685d (diff) |
imx8: implement /dev/reboot support
Diffstat (limited to 'sys/src/9/imx8')
-rw-r--r-- | sys/src/9/imx8/main.c | 56 | ||||
-rw-r--r-- | sys/src/9/imx8/mem.h | 5 | ||||
-rw-r--r-- | sys/src/9/imx8/mkfile | 7 | ||||
-rw-r--r-- | sys/src/9/imx8/mmu.c | 18 | ||||
-rw-r--r-- | sys/src/9/imx8/rebootcode.s | 48 |
5 files changed, 129 insertions, 5 deletions
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) { } +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 *, ulong) +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 @@ -61,6 +61,24 @@ mmu0clear(uintptr *l1) } 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) { m->mmutop = mallocalign(L1TOPSIZE, BY2PG, 0, 0); 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 |