shithub: riscv

Download patch

ref: a3b5e3994f7f2897ab1b5bb20b91224d145c1fc1
parent: 3b36daa2bb8c0f4169455baf829b9695b520c5fc
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon May 13 15:20:21 EDT 2019

bcm64: implement reboot support

--- a/sys/src/9/bcm64/archbcm3.c
+++ b/sys/src/9/bcm64/archbcm3.c
@@ -17,7 +17,7 @@
 #define	POWERREGS	(VIRTIO+0x100000)
 
 Soc soc = {
-	.dramsize	= GiB,
+	.dramsize	= 0x3F000000,
 	.physio		= 0x3F000000,
 	.busdram	= 0xC0000000,
 	.busio		= 0x7E000000,
@@ -164,5 +164,5 @@
 void
 archbcm3link(void)
 {
-//	addclock0link(wdogfeed, HZ);
+	addclock0link(wdogfeed, HZ);
 }
--- a/sys/src/9/bcm64/dat.h
+++ b/sys/src/9/bcm64/dat.h
@@ -194,7 +194,6 @@
 extern register Mach* m;			/* R27 */
 extern register Proc* up;			/* R26 */
 extern int normalprint;
-extern ulong memsize;
 
 /*
  *  a parsed plan9.ini line
--- a/sys/src/9/bcm64/fns.h
+++ b/sys/src/9/bcm64/fns.h
@@ -33,6 +33,9 @@
 extern void flushtlb(void);
 extern void tlbivmalle1(void);
 
+extern void flushlocaltlb(void);
+extern void tlbivmalle1(void);
+
 /* cache */
 extern ulong cachesize(int level);
 
@@ -68,6 +71,7 @@
 
 extern void mmu0init(uintptr*);
 extern void mmu0clear(uintptr*);
+extern void mmuidmap(uintptr*);
 extern void mmu1init(void);
 
 extern void putasid(Proc*);
@@ -76,6 +80,7 @@
 extern void clockinit(void);
 extern void synccycles(void);
 extern void armtimerset(int);
+extern void clockshutdown(void);
 
 /* fpu */
 extern void fpuinit(void);
@@ -127,6 +132,7 @@
 extern void gpiomeminit(void);
 
 /* arch */
+extern void archreboot(void);
 extern char *cputype2name(char*, int);
 extern void cpuidprint(void);
 extern void uartconsinit(void);
@@ -134,6 +140,7 @@
 extern int getncpus(void);
 extern int startcpu(uint);
 extern void okay(int);
+extern void wdogoff(void);
 
 /* dma */
 extern uintptr dmaaddr(void*);
--- a/sys/src/9/bcm64/l.s
+++ b/sys/src/9/bcm64/l.s
@@ -50,8 +50,6 @@
 	MOV	$(L1-KZERO), R0
 	BL	mmu0init(SB)
 
-	BL	cachedwbinv(SB)
-	BL	l2cacheuwbinv(SB)
 	SEVL
 _startup:
 	WFE
@@ -162,7 +160,6 @@
 	ORR	$KZERO, LR
 	MOV	LR, -16(RSP)!
 
-	BL	cachedwbinv(SB)
 	BL	flushlocaltlb(SB)
 
 	/* memory attributes */
--- a/sys/src/9/bcm64/main.c
+++ b/sys/src/9/bcm64/main.c
@@ -8,12 +8,12 @@
 #include "io.h"
 #include "init.h"
 #include "sysreg.h"
+#include "reboot.h"
 
 #include <pool.h>
 #include <libsec.h>
 
 Conf conf;
-ulong memsize = GiB;
 
 /*
  *  starting place for first process
@@ -122,7 +122,7 @@
 	pg = newpage(1, 0, UTZERO);
 	pg->txtflush = ~0;
 	segpage(s, pg);
-	k = kmap(s->map[0]->pages[0]);
+	k = kmap(pg);
 	memmove((void*)VA(k), initcode, sizeof initcode);
 	kunmap(k);
 
@@ -133,7 +133,7 @@
 confinit(void)
 {
 	int i, userpcnt;
-	ulong kpages;
+	ulong kpages, memsize = 0;
 	uintptr pa;
 	char *p;
 
@@ -149,12 +149,10 @@
 	else
 		userpcnt = 0;
 
-	if((p = getconf("*maxmem")) != nil){
+	if(p = getconf("*maxmem"))
 		memsize = strtoul(p, 0, 0) - PHYSDRAM;
-		if (memsize < 16*MB)		/* sanity */
-			memsize = 16*MB;
-	}
-
+	if (memsize < 16*MB)		/* sanity */
+		memsize = 16*MB;
 	getramsize(&conf.mem[0]);
 	if(conf.mem[0].limit == 0){
 		conf.mem[0].base = PHYSDRAM;
@@ -247,7 +245,7 @@
 	for(i = 1; i < conf.nmach; i++)
 		MACHP(i)->machno = i;
 
-	cachedwbinv();
+	coherence();
 
 	for(i = 1; i < conf.nmach; i++)
 		((uintptr*)SPINTABLE)[i] = PADDR(_start);
@@ -257,6 +255,9 @@
 	delay(100);
 	sev();
 	synccycles();
+
+	for(i = 0; i < MAXMACH; i++)
+		((uintptr*)SPINTABLE)[i] = 0;
 }
 
 void
@@ -276,12 +277,11 @@
 		schedinit();
 		return;
 	}
+	quotefmtinstall();
 	bootargsinit();
 	confinit();
 	xinit();
 	printinit();
-	fmtinstall('H', encodefmt);
-	quotefmtinstall();
 	uartconsinit();
 	screeninit();
 	print("\nPlan 9\n");
@@ -308,17 +308,64 @@
 	schedinit();
 }
 
+static void
+rebootjump(void *entry, void *code, ulong size)
+{
+	void (*f)(void*, void*, ulong);
+
+	intrsoff();
+	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
 exit(int)
 {
 	cpushutdown();
-	for(;;);
+	splfhi();
+	if(m->machno == 0)
+		archreboot();
+	rebootjump(0, 0, 0);
 }
 
 void
-reboot(void*, void*, ulong)
+reboot(void *entry, void *code, ulong size)
 {
-	error(Egreg);
+	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 (and watchdog if any) */
+	clockshutdown();
+	wdogoff();
+
+	/* off we go - never to return */
+	rebootjump(entry, code, size);
 }
 
 /*
--- a/sys/src/9/bcm64/mkfile
+++ b/sys/src/9/bcm64/mkfile
@@ -1,6 +1,5 @@
 CONF=pi3
 CONFLIST=pi3
-EXTRACOPIES=
 
 loadaddr=0xffffffff80080000
 
@@ -8,8 +7,6 @@
 </$objtype/mkfile
 p=9
 
-OS=7
-
 DEVS=`{rc ../port/mkdevlist $CONF}
 
 PORT=\
@@ -89,12 +86,7 @@
 install:V: /$objtype/$p$CONF
 
 /$objtype/$p$CONF:D: $p$CONF s$p$CONF
-	cp -x $p$CONF s$p$CONF /$objtype/ &
-	for(i in $EXTRACOPIES)
-		{ 9fs $i && cp $p$CONF s$p$CONF /n/$i/$objtype && echo -n $i... & }
-	wait
-	echo
-	touch $target
+	cp -x $p$CONF s$p$CONF /$objtype/
 
 
 REPCC=`{../port/mkfilelist ../bcm}
@@ -108,8 +100,9 @@
 arch.$O clock.$O fpiarm.$O main.$O mmu.$O screen.$O syscall.$O trap.$O: \
 	/$objtype/include/ureg.h
 
-l.$O cache.v8.$O lexception.$O lproc.$O mmu.$O: mem.h
+l.$O cache.v8.$O mmu.$O: mem.h
 l.$O cache.v8.$O archbcm3.$O clock.$O fpu.$O trap.$O mmu.$O: sysreg.h
+main.$O: reboot.h
 
 devmouse.$O mouse.$O screen.$O: screen.h
 usbdwc.$O: dwcotg.h ../port/usb.h
@@ -130,14 +123,14 @@
 		sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
 	 echo '};'} > init.h
 
-#reboot.h:D:	rebootcode.s arm.s arm.h mem.h
-#	$AS rebootcode.s
-#	# -T arg is REBOOTADDR
-#	$LD -l -s -T0x1c00 -R4 -o reboot.out rebootcode.$O
-#	{echo 'uchar rebootcode[]={'
-#	 xd -1x reboot.out |
-#		sed -e '1,2d' -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
-#	 echo '};'} > reboot.h
+reboot.h:D:	rebootcode.s cache.v8.$O mem.h sysreg.h
+	$AS rebootcode.s
+	# -T arg is REBOOTADDR
+	$LD -l -o reboot.out -H6 -R1 -T0x1c00 rebootcode.$O cache.v8.$O
+	{echo 'uchar rebootcode[]={'
+	 xd -1x reboot.out |
+		sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
+	 echo '};'} > reboot.h
 
 errstr.h:D:	../port/mkerrstr ../port/error.h
 	rc ../port/mkerrstr > errstr.h
--- a/sys/src/9/bcm64/mmu.c
+++ b/sys/src/9/bcm64/mmu.c
@@ -54,9 +54,9 @@
 	pe = PHYSDRAM + soc.dramsize;
 
 	if(PTLEVELS > 3)
-	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3)){
-		if(PTL1X(pa, 3) != PTL1X(va, 3))
-			l1[PTL1X(pa, 3)] = 0;
+	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){
+		if(PTL1X(pa, 1) != PTL1X(va, 1))
+			l1[PTL1X(pa, 1)] = 0;
 	}
 	if(PTLEVELS > 2)
 	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2)){
@@ -63,10 +63,38 @@
 		if(PTL1X(pa, 2) != PTL1X(va, 2))
 			l1[PTL1X(pa, 2)] = 0;
 	}
+	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3)){
+		if(PTL1X(pa, 3) != PTL1X(va, 3))
+			l1[PTL1X(pa, 3)] = 0;
+	}
+}
+
+void
+mmuidmap(uintptr *l1)
+{
+	uintptr va, pa, pe;
+
+	mmuswitch(nil);
+	flushtlb();
+
+	pe = PHYSDRAM + soc.dramsize;
+
 	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){
 		if(PTL1X(pa, 1) != PTL1X(va, 1))
-			l1[PTL1X(pa, 1)] = 0;
+			l1[PTL1X(pa, 1)] = pa | PTEVALID | PTEBLOCK | PTEWRITE | PTEAF
+				 | PTEKERNEL | PTESH(SHARE_INNER);
 	}
+	if(PTLEVELS > 2)
+	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2)){
+		if(PTL1X(pa, 2) != PTL1X(va, 2))
+			l1[PTL1X(pa, 2)] = PADDR(&l1[L1TABLEX(pa, 1)]) | PTEVALID | PTETABLE;
+	}
+	if(PTLEVELS > 3)
+	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3)){
+		if(PTL1X(pa, 3) != PTL1X(va, 3))
+			l1[PTL1X(pa, 3)] = PADDR(&l1[L1TABLEX(pa, 2)]) | PTEVALID | PTETABLE;
+	}
+	setttbr(PADDR(&l1[L1TABLEX(0, PTLEVELS-1)]));
 }
 
 void
@@ -264,7 +292,6 @@
 	uintptr *pte, old;
 	int s;
 
-// iprint("cpu%d: putmmu va %#p asid %d proc %lud %s\n", m->machno, va, up->asid, up->pid, up->text);
 	s = splhi();
 	while((pte = mmuwalk(va, 0)) == nil){
 		spllo();
@@ -345,7 +372,6 @@
 	if(allocasid(p))
 		flushasid((uvlong)p->asid<<48);
 
-// iprint("cpu%d: mmuswitch asid %d proc %lud %s\n", m->machno, p->asid, p->pid, p->text);
 	setttbr((uvlong)p->asid<<48 | PADDR(&m->mmul1[L1TABLEX(0, PTLEVELS-1)]));
 }
 
--- /dev/null
+++ b/sys/src/9/bcm64/rebootcode.s
@@ -1,0 +1,51 @@
+#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
+
+	MRS	MPIDR_EL1, R27
+	ANDW	$(MAXMACH-1), R27
+	LSL	$3, R27
+	ADD	$(SPINTABLE-KZERO), R27
+
+	CBZ	R0, _mmuoff
+	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)
+	SEVL
+
+_mmuoff:
+	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)
+_wait:
+	WFE
+	MOV	(R27), LR
+	CBZ	LR, _wait
+	RETURN