changelog shortlog tags branches changeset file revisions annotate raw help

Mercurial > hg > plan9front / sys/src/9/bcm64/mmu.c

revision 7244: 2e8af1bf191d
parent 7239: c0e23a8829f7
child 7246: 424a0569af2c
     1.1--- a/sys/src/9/bcm64/mmu.c
     1.2+++ b/sys/src/9/bcm64/mmu.c
     1.3@@ -8,45 +8,65 @@
     1.4 void
     1.5 mmu0init(uintptr *l1)
     1.6 {
     1.7-	uintptr va, pa, pe;
     1.8+	uintptr va, pa, pe, attr;
     1.9 
    1.10-	/* 0 identity map */
    1.11+	/* KZERO */
    1.12+	attr = PTEWRITE | PTEAF | PTEKERNEL | PTESH(SHARE_INNER);
    1.13 	pe = PHYSDRAM + soc.dramsize;
    1.14 	if(pe > (uintptr)-KZERO)
    1.15 		pe = (uintptr)-KZERO;
    1.16-
    1.17-	for(pa = PHYSDRAM; pa < pe; pa += PGLSZ(1))
    1.18-		l1[PTL1X(pa, 1)] = pa | PTEVALID | PTEBLOCK | PTEWRITE | PTEAF
    1.19-			 | PTEKERNEL | PTESH(SHARE_INNER);
    1.20+	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){
    1.21+		if(pe - pa < PGLSZ(1)){
    1.22+			l1[PTL1X(va, 1)] = (uintptr)l1 | PTEVALID | PTETABLE;
    1.23+			l1[PTL1X(pa, 1)] = (uintptr)l1 | PTEVALID | PTETABLE;
    1.24+			for(; pa < pe; pa += PGLSZ(0), va += PGLSZ(0))
    1.25+				l1[PTLX(va, 0)] = pa | PTEVALID | PTEPAGE | attr;
    1.26+			break;
    1.27+		}
    1.28+		l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr;
    1.29+		l1[PTL1X(pa, 1)] = pa | PTEVALID | PTEBLOCK | attr;
    1.30+	}
    1.31+	pe = (uintptr)-KZERO;	/* populate top levels for mmukmap() */
    1.32 	if(PTLEVELS > 2)
    1.33-	for(pa = PHYSDRAM; pa < pe; pa += PGLSZ(2))
    1.34+	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2)){
    1.35+		l1[PTL1X(va, 2)] = (uintptr)&l1[L1TABLEX(va, 1)] | PTEVALID | PTETABLE;
    1.36 		l1[PTL1X(pa, 2)] = (uintptr)&l1[L1TABLEX(pa, 1)] | PTEVALID | PTETABLE;
    1.37+	}
    1.38 	if(PTLEVELS > 3)
    1.39-	for(pa = PHYSDRAM; pa < pe; pa += PGLSZ(3))
    1.40+	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3)){
    1.41+		l1[PTL1X(va, 3)] = (uintptr)&l1[L1TABLEX(va, 2)] | PTEVALID | PTETABLE;
    1.42 		l1[PTL1X(pa, 3)] = (uintptr)&l1[L1TABLEX(pa, 2)] | PTEVALID | PTETABLE;
    1.43-
    1.44-	/* KZERO */
    1.45-	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1))
    1.46-		l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | PTEWRITE | PTEAF
    1.47-			| PTEKERNEL | PTESH(SHARE_INNER);
    1.48-	if(PTLEVELS > 2)
    1.49-	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2))
    1.50-		l1[PTL1X(va, 2)] = (uintptr)&l1[L1TABLEX(va, 1)] | PTEVALID | PTETABLE;
    1.51-	if(PTLEVELS > 3)
    1.52-	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3))
    1.53-		l1[PTL1X(va, 3)] = (uintptr)&l1[L1TABLEX(va, 2)] | PTEVALID | PTETABLE;
    1.54+	}
    1.55 
    1.56 	/* VIRTIO */
    1.57-	pe = -VIRTIO + soc.physio;
    1.58-	for(pa = soc.physio, va = VIRTIO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1))
    1.59-		l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | PTEWRITE | PTEAF
    1.60-			| PTEKERNEL | PTESH(SHARE_OUTER) | PTEDEVICE;
    1.61+	attr = PTEWRITE | PTEAF | PTEKERNEL | PTESH(SHARE_OUTER) | PTEDEVICE;
    1.62+	pe = soc.physio + IOSIZE;
    1.63+	for(pa = soc.physio, va = VIRTIO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){
    1.64+		if(pe - pa < PGLSZ(1)){
    1.65+			l1[PTL1X(va, 1)] = (uintptr)l1 | PTEVALID | PTETABLE;
    1.66+			for(; pa < pe; pa += PGLSZ(0), va += PGLSZ(0))
    1.67+				l1[PTLX(va, 0)] = pa | PTEVALID | PTEPAGE | attr;
    1.68+			break;
    1.69+		}
    1.70+		l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr;
    1.71+	}
    1.72 	if(PTLEVELS > 2)
    1.73 	for(pa = soc.physio, va = VIRTIO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2))
    1.74 		l1[PTL1X(va, 2)] = (uintptr)&l1[L1TABLEX(va, 1)] | PTEVALID | PTETABLE;
    1.75 	if(PTLEVELS > 3)
    1.76 	for(pa = soc.physio, va = VIRTIO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3))
    1.77 		l1[PTL1X(va, 3)] = (uintptr)&l1[L1TABLEX(va, 2)] | PTEVALID | PTETABLE;
    1.78+
    1.79+	/* ARMLOCAL */
    1.80+	pe = soc.armlocal + MB;
    1.81+	for(pa = soc.armlocal, va = ARMLOCAL; pa < pe; pa += PGLSZ(1), va += PGLSZ(1))
    1.82+		l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr;
    1.83+	if(PTLEVELS > 2)
    1.84+	for(pa = soc.armlocal, va = ARMLOCAL; pa < pe; pa += PGLSZ(2), va += PGLSZ(2))
    1.85+		l1[PTL1X(va, 2)] = (uintptr)&l1[L1TABLEX(va, 1)] | PTEVALID | PTETABLE;
    1.86+	if(PTLEVELS > 3)
    1.87+	for(pa = soc.armlocal, va = ARMLOCAL; pa < pe; pa += PGLSZ(3), va += PGLSZ(3))
    1.88+		l1[PTL1X(va, 3)] = (uintptr)&l1[L1TABLEX(va, 2)] | PTEVALID | PTETABLE;
    1.89 }
    1.90 
    1.91 void
    1.92@@ -57,21 +77,17 @@ mmu0clear(uintptr *l1)
    1.93 	pe = PHYSDRAM + soc.dramsize;
    1.94 	if(pe > (uintptr)-KZERO)
    1.95 		pe = (uintptr)-KZERO;
    1.96-
    1.97-	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){
    1.98+	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1))
    1.99 		if(PTL1X(pa, 1) != PTL1X(va, 1))
   1.100 			l1[PTL1X(pa, 1)] = 0;
   1.101-	}
   1.102 	if(PTLEVELS > 2)
   1.103-	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2)){
   1.104+	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2))
   1.105 		if(PTL1X(pa, 2) != PTL1X(va, 2))
   1.106 			l1[PTL1X(pa, 2)] = 0;
   1.107-	}
   1.108 	if(PTLEVELS > 3)
   1.109-	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3)){
   1.110+	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3))
   1.111 		if(PTL1X(pa, 3) != PTL1X(va, 3))
   1.112 			l1[PTL1X(pa, 3)] = 0;
   1.113-	}
   1.114 }
   1.115 
   1.116 void
   1.117@@ -85,32 +101,24 @@ mmuidmap(uintptr *l1)
   1.118 	pe = PHYSDRAM + soc.dramsize;
   1.119 	if(pe > (uintptr)-KZERO)
   1.120 		pe = (uintptr)-KZERO;
   1.121-
   1.122-	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){
   1.123-		if(PTL1X(pa, 1) != PTL1X(va, 1))
   1.124-			l1[PTL1X(pa, 1)] = pa | PTEVALID | PTEBLOCK | PTEWRITE | PTEAF
   1.125-				 | PTEKERNEL | PTESH(SHARE_INNER);
   1.126-	}
   1.127+	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1))
   1.128+		l1[PTL1X(pa, 1)] = l1[PTL1X(va, 1)];
   1.129 	if(PTLEVELS > 2)
   1.130-	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2)){
   1.131-		if(PTL1X(pa, 2) != PTL1X(va, 2))
   1.132-			l1[PTL1X(pa, 2)] = PADDR(&l1[L1TABLEX(pa, 1)]) | PTEVALID | PTETABLE;
   1.133-	}
   1.134+	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2))
   1.135+		l1[PTL1X(pa, 2)] = l1[PTL1X(va, 2)];
   1.136 	if(PTLEVELS > 3)
   1.137-	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3)){
   1.138-		if(PTL1X(pa, 3) != PTL1X(va, 3))
   1.139-			l1[PTL1X(pa, 3)] = PADDR(&l1[L1TABLEX(pa, 2)]) | PTEVALID | PTETABLE;
   1.140-	}
   1.141+	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3))
   1.142+		l1[PTL1X(pa, 3)] = l1[PTL1X(va, 3)];
   1.143 	setttbr(PADDR(&l1[L1TABLEX(0, PTLEVELS-1)]));
   1.144 }
   1.145 
   1.146 void
   1.147 mmu1init(void)
   1.148 {
   1.149-	m->mmul1 = mallocalign(L1SIZE+L1TOPSIZE, BY2PG, L1SIZE, 0);
   1.150-	if(m->mmul1 == nil)
   1.151-		panic("mmu1init: no memory for mmul1");
   1.152-	memset(m->mmul1, 0, L1SIZE+L1TOPSIZE);
   1.153+	m->mmutop = mallocalign(L1TOPSIZE, BY2PG, 0, 0);
   1.154+	if(m->mmutop == nil)
   1.155+		panic("mmu1init: no memory for mmutop");
   1.156+	memset(m->mmutop, 0, L1TOPSIZE);
   1.157 	mmuswitch(nil);
   1.158 }
   1.159 
   1.160@@ -187,7 +195,7 @@ mmuwalk(uintptr va, int level)
   1.161 	int i, x;
   1.162 
   1.163 	x = PTLX(va, PTLEVELS-1);
   1.164-	table = &m->mmul1[L1TABLEX(va, PTLEVELS-1)];
   1.165+	table = m->mmutop;
   1.166 	for(i = PTLEVELS-2; i >= level; i--){
   1.167 		pte = table[x];
   1.168 		if(pte & PTEVALID) {
   1.169@@ -262,12 +270,12 @@ putasid(Proc *p)
   1.170 {
   1.171 	/*
   1.172 	 * Prevent the following scenario:
   1.173-	 *	pX sleeps on cpuA, leaving its page tables in mmul1
   1.174+	 *	pX sleeps on cpuA, leaving its page tables in mmutop
   1.175 	 *	pX wakes up on cpuB, and exits, freeing its page tables
   1.176 	 *  pY on cpuB allocates a freed page table page and overwrites with data
   1.177 	 *  cpuA takes an interrupt, and is now running with bad page tables
   1.178 	 * In theory this shouldn't hurt because only user address space tables
   1.179-	 * are affected, and mmuswitch will clear mmul1 before a user process is
   1.180+	 * are affected, and mmuswitch will clear mmutop before a user process is
   1.181 	 * dispatched.  But empirically it correlates with weird problems, eg
   1.182 	 * resetting of the core clock at 0x4000001C which confuses local timers.
   1.183 	 */
   1.184@@ -287,7 +295,6 @@ putmmu(uintptr va, uintptr pa, Page *pg)
   1.185 	s = splhi();
   1.186 	while((pte = mmuwalk(va, 0)) == nil){
   1.187 		spllo();
   1.188-		assert(up->mmufree == nil);
   1.189 		up->mmufree = newpage(0, nil, 0);
   1.190 		splhi();
   1.191 	}
   1.192@@ -330,10 +337,10 @@ mmuswitch(Proc *p)
   1.193 	Page *t;
   1.194 
   1.195 	for(va = UZERO; va < USTKTOP; va += PGLSZ(PTLEVELS-1))
   1.196-		m->mmul1[PTL1X(va, PTLEVELS-1)] = 0;
   1.197+		m->mmutop[PTLX(va, PTLEVELS-1)] = 0;
   1.198 
   1.199 	if(p == nil){
   1.200-		setttbr(PADDR(&m->mmul1[L1TABLEX(0, PTLEVELS-1)]));
   1.201+		setttbr(PADDR(m->mmutop));
   1.202 		return;
   1.203 	}
   1.204 
   1.205@@ -344,13 +351,13 @@ mmuswitch(Proc *p)
   1.206 
   1.207 	for(t = p->mmuhead[PTLEVELS-1]; t != nil; t = t->next){
   1.208 		va = t->va;
   1.209-		m->mmul1[PTL1X(va, PTLEVELS-1)] = t->pa | PTEVALID | PTETABLE;
   1.210+		m->mmutop[PTLX(va, PTLEVELS-1)] = t->pa | PTEVALID | PTETABLE;
   1.211 	}
   1.212 
   1.213 	if(allocasid(p))
   1.214 		flushasid((uvlong)p->asid<<48);
   1.215 
   1.216-	setttbr((uvlong)p->asid<<48 | PADDR(&m->mmul1[L1TABLEX(0, PTLEVELS-1)]));
   1.217+	setttbr((uvlong)p->asid<<48 | PADDR(m->mmutop));
   1.218 }
   1.219 
   1.220 void