shithub: riscv

Download patch

ref: 3c2093e47aaee2557aaf54bc8e0f2a68011651dd
parent: f57c46456b04992bd06a71425d8074e38a32c230
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Jun 20 14:22:38 EDT 2023

imx8: dont reuse the TTRB1 page tables for TTRB0 identity map, remove gpioinit()

instead of putting identity map into the L1,
just allocate one more page (L1BOT) for top
level page table dedicated for the identity map
(used during mmuenable and mp startup and
reboot), then we can just load TTRB0 with it
when we need it wihout all that tlb flushing.

wastes more memory, but it is the correct thing
todo...

this also makes 4K pages work as there was a
conflict with the entries between the identity
map and the uncached memory.

also instead of unmapping stuff beyond initmap,
we can just not map anything beyond INITMAP.

that gets the kernel up fine and meminit()
will later map the rest.

i will probably backport this to the bcm64
kernel later...

for gpio, remove gpioinit and just put that
in a link function.

do the lcdinit() as soon as possible...

--- a/sys/src/9/imx8/fns.h
+++ b/sys/src/9/imx8/fns.h
@@ -74,7 +74,6 @@
 extern void vunmap(void*, vlong);
 
 extern void mmu0init(uintptr*);
-extern void mmu0clear(uintptr*);
 extern void mmuidmap(uintptr*);
 extern void mmu1init(void);
 extern void meminit(void);
@@ -162,7 +161,6 @@
 extern int gpioin(uint pin);
 void gpiointrenable(uint pin, int mode, void (*f)(uint pin, void *a), void *a);
 void gpiointrdisable(uint pin);
-void gpioinit(void);
 
 /* pciimx */
 extern int pcicfgrw8(int tbdf, int rno, int data, int read);
--- a/sys/src/9/imx8/gpio.c
+++ b/sys/src/9/imx8/gpio.c
@@ -157,7 +157,7 @@
 }
 
 void
-gpioinit(void)
+gpiolink(void)
 {
 	intrenable(IRQgpio1l, gpiointerrupt, &ctlrs[0], BUSUNKNOWN, "gpio1");
 	intrenable(IRQgpio1h, gpiointerrupt, &ctlrs[0], BUSUNKNOWN, "gpio1");
--- a/sys/src/9/imx8/l.s
+++ b/sys/src/9/imx8/l.s
@@ -34,7 +34,7 @@
 	CBNZ	R1, _startup
 
 	/* clear page table and machs */
-	MOV	$(L1-KZERO), R1
+	MOV	$(L1BOT-KZERO), R1
 	MOV	$(MACHADDR(-1)-KZERO), R2
 _zerol1:
 	MOV	ZR, (R1)8!
@@ -50,6 +50,9 @@
 	BNE	_zerobss
 
 	/* setup page tables */
+	MOV	$(L1BOT-KZERO), R0
+	BL	mmuidmap(SB)
+
 	MOV	$(L1-KZERO), R0
 	BL	mmu0init(SB)
 
@@ -211,10 +214,11 @@
 	ISB	$SY
 
 	/* load the page tables */
-	MOV	$(L1TOP-KZERO), R0
+	MOV	$(L1BOT-KZERO), R0
+	MOV	$(L1TOP-KZERO), R1
 	ISB	$SY
 	MSR	R0, TTBR0_EL1
-	MSR	R0, TTBR1_EL1
+	MSR	R1, TTBR1_EL1
 	ISB	$SY
 
 	/* enable MMU and caches */
--- a/sys/src/9/imx8/main.c
+++ b/sys/src/9/imx8/main.c
@@ -173,7 +173,6 @@
 	int i;
 
 	conf.nmach = MAXMACH;
-
 	if(p = getconf("service")){
 		if(strcmp(p, "cpu") == 0)
 			cpuserver = 1;
@@ -241,7 +240,6 @@
 	extern void _start(void);
 	int i;
 
-	splhi();
 	for(i = 1; i < conf.nmach; i++){
 		Ureg u = {0};
 
@@ -255,7 +253,6 @@
 		smccall(&u);
 	}
 	synccycles();
-	spllo();
 }
 
 void
@@ -314,7 +311,6 @@
 		cpuidprint();
 		synccycles();
 		timersinit();
-		flushtlb();
 		mmu1init();
 		m->ticks = MACHP(0)->ticks;
 		schedinit();
@@ -338,15 +334,12 @@
 	procinit0();
 	initseg();
 	links();
-	chandevreset();
-	gpioinit();
 	lcdinit();
 	tmuinit();
 	lpcspiinit();
+	chandevreset();
 	userinit();
 	mpinit();
-	mmu0clear((uintptr*)L1);
-	flushtlb();
 	mmu1init();
 	schedinit();
 }
@@ -377,7 +370,7 @@
 	intrcpushutdown();
 
 	/* redo identity map */
-	mmuidmap((uintptr*)L1);
+	setttbr(PADDR(L1BOT));
 
 	/* setup reboot trampoline function */
 	f = (void*)REBOOTADDR;
--- a/sys/src/9/imx8/mem.h
+++ b/sys/src/9/imx8/mem.h
@@ -57,6 +57,10 @@
 
 #define KSEG0		(0xFFFFFFFE00000000ULL)
 
+/* temporary identity map for TTBR0 (using only top-level) */
+#define L1BOT		((L1-L1TOPSIZE)&-BY2PG)
+
+/* shared kernel page table for TTBR1 */
 #define L1		(L1TOP-L1SIZE)
 #define L1SIZE		((L1TABLES+PTLEVELS-2)*BY2PG)
 #define L1TOP		((MACHADDR(MAXMACH-1)-L1TOPSIZE)&-BY2PG)
--- a/sys/src/9/imx8/mmu.c
+++ b/sys/src/9/imx8/mmu.c
@@ -5,19 +5,42 @@
 #include "fns.h"
 #include "sysreg.h"
 
+#define INITMAP	(ROUND((uintptr)end + BY2PG, PGLSZ(1))-KZERO)
+
+/*
+ * Create initial identity map in top-level page table
+ * (L1BOT) for TTBR0. This page table is only used until
+ * mmu1init() loads m->mmutop.
+ */
 void
-mmu0init(uintptr *l1)
+mmuidmap(uintptr *l1bot)
 {
-	uintptr va, pa, pe, attr;
+	uintptr pa, pe, attr;
 
 	/* VDRAM */
 	attr = PTEWRITE | PTEAF | PTEKERNEL | PTEUXN | PTESH(SHARE_INNER);
 	pe = -KZERO;
-	for(pa = VDRAM - KZERO, va = VDRAM; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){
+	for(pa = VDRAM - KZERO; pa < pe; pa += PGLSZ(PTLEVELS-1))
+		l1bot[PTLX(pa, PTLEVELS-1)] = pa | PTEVALID | PTEBLOCK | attr;
+}
+
+/*
+ * Create initial shared kernel page table (L1) for TTBR1.
+ * This page table coveres the INITMAP and VIRTIO,
+ * and later we fill the ram mappings in meminit().
+ */
+void
+mmu0init(uintptr *l1)
+{
+	uintptr va, pa, pe, attr;
+
+	/* DRAM - INITMAP */
+	attr = PTEWRITE | PTEAF | PTEKERNEL | PTEUXN | PTESH(SHARE_INNER);
+	pe = INITMAP;
+	for(pa = VDRAM - KZERO, va = VDRAM; pa < pe; pa += PGLSZ(1), va += PGLSZ(1))
 		l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr;
-		l1[PTL1X(pa, 1)] = pa | PTEVALID | PTEBLOCK | attr;
-	}
 
+	/* VIRTIO */
 	attr = PTEWRITE | PTEAF | PTEKERNEL | PTEUXN | PTEPXN | PTESH(SHARE_OUTER) | PTEDEVICE;
 	pe = VDRAM - KZERO;
 	for(pa = VIRTIO - KZERO, va = VIRTIO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){
@@ -35,6 +58,7 @@
 	if(PTLEVELS > 2)
 	for(va = KSEG0; va != 0; va += PGLSZ(2))
 		l1[PTL1X(va, 2)] = (uintptr)&l1[L1TABLEX(va, 1)] | PTEVALID | PTETABLE;
+
 	if(PTLEVELS > 3)
 	for(va = KSEG0; va != 0; va += PGLSZ(3))
 		l1[PTL1X(va, 3)] = (uintptr)&l1[L1TABLEX(va, 2)] | PTEVALID | PTETABLE;
@@ -41,44 +65,6 @@
 }
 
 void
-mmu0clear(uintptr *l1)
-{
-	uintptr va, pa, pe;
-
-	pe = -VDRAM;
-	for(pa = VDRAM - KZERO, va = VDRAM; 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 = VDRAM - KZERO, va = VDRAM; pa < pe; pa += PGLSZ(2), va += PGLSZ(2))
-		if(PTL1X(pa, 2) != PTL1X(va, 2))
-			l1[PTL1X(pa, 2)] = 0;
-	if(PTLEVELS > 3)
-	for(pa = VDRAM - KZERO, va = VDRAM; 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;
-
-	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);
@@ -141,8 +127,6 @@
 {
 }
 
-#define INITMAP	(ROUND((uintptr)end + BY2PG, PGLSZ(1))-KZERO)
-
 static void*
 rampage(void)
 {
@@ -215,21 +199,6 @@
 void
 meminit(void)
 {
-	uintptr va, pa;
-
-	/*
-	 * now we know the real memory regions, unmap
-	 * everything above INITMAP and map again with
-	 * the proper sizes.
-	 */
-	coherence();
-	for(va = INITMAP+KZERO; va != 0; va += PGLSZ(1)){
-		pa = va-KZERO;
-		((uintptr*)L1)[PTL1X(pa, 1)] = 0;
-		((uintptr*)L1)[PTL1X(va, 1)] = 0;
-	}
-	flushtlb();
-
 	/* DDR Memory (All modules) */
 	conf.mem[0].base = PGROUND((uintptr)end - KZERO);
 
--- a/sys/src/9/imx8/reform
+++ b/sys/src/9/imx8/reform
@@ -36,6 +36,7 @@
 	pciimx		pci
 	sai
 	usdhc
+	gpio
 
 ip
 	tcp
@@ -50,7 +51,6 @@
 	ccm
 	gic
 	gpc
-	gpio
 	lcd
 	uartimx
 	iomux