shithub: riscv

Download patch

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