ref: 32183b1abf7a670e11c59595fda4cd64dad1008b
parent: 414cefcb0b40082d73942ea619de59b371bd685d
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Jul 10 07:35:58 EDT 2022
imx8: implement /dev/reboot support
--- 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 @@
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 @@
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 @@
{
}
+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
--- 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 */
@@ -63,6 +63,9 @@
#define L1TOP ((MACHADDR(MAXMACH-1)-L1TOPSIZE)&-BY2PG)
#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 */
--- a/sys/src/9/imx8/mkfile
+++ b/sys/src/9/imx8/mkfile
@@ -87,8 +87,15 @@
<../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
--- a/sys/src/9/imx8/mmu.c
+++ b/sys/src/9/imx8/mmu.c
@@ -61,6 +61,24 @@
}
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);
--- /dev/null
+++ b/sys/src/9/imx8/rebootcode.s
@@ -1,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