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