changelog shortlog tags branches changeset files file revisions raw help

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

changeset 7238: 9fe2319844b6
parent: b1dc95374307
child: c0e23a8829f7
author: cinap_lenrek@felloff.net
date: Wed, 15 May 2019 13:24:34 +0200
permissions: -rw-r--r--
description: bcm64: fix mmu0clear() mistake from previous commit
cinap_lenrek@7199 1
 #include "u.h"
cinap_lenrek@7199 2
 #include "../port/lib.h"
cinap_lenrek@7199 3
 #include "mem.h"
cinap_lenrek@7199 4
 #include "dat.h"
cinap_lenrek@7199 5
 #include "fns.h"
cinap_lenrek@7199 6
 #include "sysreg.h"
cinap_lenrek@7199 7
 
cinap_lenrek@7199 8
 void
cinap_lenrek@7199 9
 mmu0init(uintptr *l1)
cinap_lenrek@7199 10
 {
cinap_lenrek@7199 11
 	uintptr va, pa, pe;
cinap_lenrek@7199 12
 
cinap_lenrek@7199 13
 	/* 0 identity map */
cinap_lenrek@7199 14
 	pe = PHYSDRAM + soc.dramsize;
cinap_lenrek@7199 15
 	for(pa = PHYSDRAM; pa < pe; pa += PGLSZ(1))
cinap_lenrek@7199 16
 		l1[PTL1X(pa, 1)] = pa | PTEVALID | PTEBLOCK | PTEWRITE | PTEAF
cinap_lenrek@7199 17
 			 | PTEKERNEL | PTESH(SHARE_INNER);
cinap_lenrek@7199 18
 	if(PTLEVELS > 2)
cinap_lenrek@7199 19
 	for(pa = PHYSDRAM; pa < pe; pa += PGLSZ(2))
cinap_lenrek@7199 20
 		l1[PTL1X(pa, 2)] = (uintptr)&l1[L1TABLEX(pa, 1)] | PTEVALID | PTETABLE;
cinap_lenrek@7199 21
 	if(PTLEVELS > 3)
cinap_lenrek@7199 22
 	for(pa = PHYSDRAM; pa < pe; pa += PGLSZ(3))
cinap_lenrek@7199 23
 		l1[PTL1X(pa, 3)] = (uintptr)&l1[L1TABLEX(pa, 2)] | PTEVALID | PTETABLE;
cinap_lenrek@7199 24
 
cinap_lenrek@7199 25
 	/* KZERO */
cinap_lenrek@7199 26
 	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1))
cinap_lenrek@7199 27
 		l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | PTEWRITE | PTEAF
cinap_lenrek@7199 28
 			| PTEKERNEL | PTESH(SHARE_INNER);
cinap_lenrek@7199 29
 	if(PTLEVELS > 2)
cinap_lenrek@7199 30
 	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2))
cinap_lenrek@7199 31
 		l1[PTL1X(va, 2)] = (uintptr)&l1[L1TABLEX(va, 1)] | PTEVALID | PTETABLE;
cinap_lenrek@7199 32
 	if(PTLEVELS > 3)
cinap_lenrek@7199 33
 	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3))
cinap_lenrek@7199 34
 		l1[PTL1X(va, 3)] = (uintptr)&l1[L1TABLEX(va, 2)] | PTEVALID | PTETABLE;
cinap_lenrek@7199 35
 
cinap_lenrek@7199 36
 	/* VIRTIO */
cinap_lenrek@7199 37
 	pe = -VIRTIO + soc.physio;
cinap_lenrek@7199 38
 	for(pa = soc.physio, va = VIRTIO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1))
cinap_lenrek@7199 39
 		l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | PTEWRITE | PTEAF
cinap_lenrek@7199 40
 			| PTEKERNEL | PTESH(SHARE_OUTER) | PTEDEVICE;
cinap_lenrek@7199 41
 	if(PTLEVELS > 2)
cinap_lenrek@7199 42
 	for(pa = soc.physio, va = VIRTIO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2))
cinap_lenrek@7199 43
 		l1[PTL1X(va, 2)] = (uintptr)&l1[L1TABLEX(va, 1)] | PTEVALID | PTETABLE;
cinap_lenrek@7199 44
 	if(PTLEVELS > 3)
cinap_lenrek@7199 45
 	for(pa = soc.physio, va = VIRTIO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3))
cinap_lenrek@7199 46
 		l1[PTL1X(va, 3)] = (uintptr)&l1[L1TABLEX(va, 2)] | PTEVALID | PTETABLE;
cinap_lenrek@7199 47
 }
cinap_lenrek@7199 48
 
cinap_lenrek@7199 49
 void
cinap_lenrek@7199 50
 mmu0clear(uintptr *l1)
cinap_lenrek@7199 51
 {
cinap_lenrek@7199 52
 	uintptr va, pa, pe;
cinap_lenrek@7199 53
 
cinap_lenrek@7199 54
 	pe = PHYSDRAM + soc.dramsize;
cinap_lenrek@7199 55
 
cinap_lenrek@7235 56
 	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){
cinap_lenrek@7235 57
 		if(PTL1X(pa, 1) != PTL1X(va, 1))
cinap_lenrek@7235 58
 			l1[PTL1X(pa, 1)] = 0;
cinap_lenrek@7199 59
 	}
cinap_lenrek@7199 60
 	if(PTLEVELS > 2)
cinap_lenrek@7199 61
 	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2)){
cinap_lenrek@7199 62
 		if(PTL1X(pa, 2) != PTL1X(va, 2))
cinap_lenrek@7199 63
 			l1[PTL1X(pa, 2)] = 0;
cinap_lenrek@7199 64
 	}
cinap_lenrek@7238 65
 	if(PTLEVELS > 3)
cinap_lenrek@7235 66
 	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3)){
cinap_lenrek@7235 67
 		if(PTL1X(pa, 3) != PTL1X(va, 3))
cinap_lenrek@7235 68
 			l1[PTL1X(pa, 3)] = 0;
cinap_lenrek@7235 69
 	}
cinap_lenrek@7235 70
 }
cinap_lenrek@7235 71
 
cinap_lenrek@7235 72
 void
cinap_lenrek@7235 73
 mmuidmap(uintptr *l1)
cinap_lenrek@7235 74
 {
cinap_lenrek@7235 75
 	uintptr va, pa, pe;
cinap_lenrek@7235 76
 
cinap_lenrek@7235 77
 	mmuswitch(nil);
cinap_lenrek@7235 78
 	flushtlb();
cinap_lenrek@7235 79
 
cinap_lenrek@7235 80
 	pe = PHYSDRAM + soc.dramsize;
cinap_lenrek@7235 81
 
cinap_lenrek@7199 82
 	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){
cinap_lenrek@7199 83
 		if(PTL1X(pa, 1) != PTL1X(va, 1))
cinap_lenrek@7235 84
 			l1[PTL1X(pa, 1)] = pa | PTEVALID | PTEBLOCK | PTEWRITE | PTEAF
cinap_lenrek@7235 85
 				 | PTEKERNEL | PTESH(SHARE_INNER);
cinap_lenrek@7199 86
 	}
cinap_lenrek@7235 87
 	if(PTLEVELS > 2)
cinap_lenrek@7235 88
 	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2)){
cinap_lenrek@7235 89
 		if(PTL1X(pa, 2) != PTL1X(va, 2))
cinap_lenrek@7235 90
 			l1[PTL1X(pa, 2)] = PADDR(&l1[L1TABLEX(pa, 1)]) | PTEVALID | PTETABLE;
cinap_lenrek@7235 91
 	}
cinap_lenrek@7235 92
 	if(PTLEVELS > 3)
cinap_lenrek@7235 93
 	for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3)){
cinap_lenrek@7235 94
 		if(PTL1X(pa, 3) != PTL1X(va, 3))
cinap_lenrek@7235 95
 			l1[PTL1X(pa, 3)] = PADDR(&l1[L1TABLEX(pa, 2)]) | PTEVALID | PTETABLE;
cinap_lenrek@7235 96
 	}
cinap_lenrek@7235 97
 	setttbr(PADDR(&l1[L1TABLEX(0, PTLEVELS-1)]));
cinap_lenrek@7199 98
 }
cinap_lenrek@7199 99
 
cinap_lenrek@7199 100
 void
cinap_lenrek@7199 101
 mmu1init(void)
cinap_lenrek@7199 102
 {
cinap_lenrek@7199 103
 	m->mmul1 = mallocalign(L1SIZE+L1TOPSIZE, BY2PG, L1SIZE, 0);
cinap_lenrek@7199 104
 	if(m->mmul1 == nil)
cinap_lenrek@7199 105
 		panic("mmu1init: no memory for mmul1");
cinap_lenrek@7199 106
 	memset(m->mmul1, 0, L1SIZE+L1TOPSIZE);
cinap_lenrek@7199 107
 	mmuswitch(nil);
cinap_lenrek@7199 108
 }
cinap_lenrek@7199 109
 
cinap_lenrek@7199 110
 uintptr
cinap_lenrek@7199 111
 paddr(void *va)
cinap_lenrek@7199 112
 {
cinap_lenrek@7199 113
 	if((uintptr)va >= KZERO)
cinap_lenrek@7199 114
 		return (uintptr)va-KZERO;
cinap_lenrek@7199 115
 	panic("paddr: va=%#p pc=%#p", va, getcallerpc(&va));
cinap_lenrek@7199 116
 	return 0;
cinap_lenrek@7199 117
 }
cinap_lenrek@7199 118
 
cinap_lenrek@7199 119
 uintptr
cinap_lenrek@7199 120
 cankaddr(uintptr pa)
cinap_lenrek@7199 121
 {
cinap_lenrek@7199 122
 	if(pa < (uintptr)-KZERO)
cinap_lenrek@7199 123
 		return -KZERO - pa;
cinap_lenrek@7199 124
 	return 0;
cinap_lenrek@7199 125
 }
cinap_lenrek@7199 126
 
cinap_lenrek@7199 127
 void*
cinap_lenrek@7199 128
 kaddr(uintptr pa)
cinap_lenrek@7199 129
 {
cinap_lenrek@7199 130
 	if(pa < (uintptr)-KZERO)
cinap_lenrek@7199 131
 		return (void*)(pa + KZERO);
cinap_lenrek@7199 132
 	panic("kaddr: pa=%#p pc=%#p", pa, getcallerpc(&pa));
cinap_lenrek@7199 133
 	return nil;
cinap_lenrek@7199 134
 }
cinap_lenrek@7199 135
 
cinap_lenrek@7199 136
 void
cinap_lenrek@7199 137
 kmapinval(void)
cinap_lenrek@7199 138
 {
cinap_lenrek@7199 139
 }
cinap_lenrek@7199 140
 
cinap_lenrek@7199 141
 KMap*
cinap_lenrek@7199 142
 kmap(Page *p)
cinap_lenrek@7199 143
 {
cinap_lenrek@7199 144
 	return kaddr(p->pa);
cinap_lenrek@7199 145
 }
cinap_lenrek@7199 146
 
cinap_lenrek@7199 147
 void
cinap_lenrek@7199 148
 kunmap(KMap*)
cinap_lenrek@7199 149
 {
cinap_lenrek@7199 150
 }
cinap_lenrek@7199 151
 
cinap_lenrek@7199 152
 uintptr
cinap_lenrek@7199 153
 mmukmap(uintptr va, uintptr pa, usize size)
cinap_lenrek@7199 154
 {
cinap_lenrek@7217 155
 	uintptr a, pe, off, attr;
cinap_lenrek@7199 156
 
cinap_lenrek@7199 157
 	if(va == 0)
cinap_lenrek@7199 158
 		return 0;
cinap_lenrek@7199 159
 
cinap_lenrek@7217 160
 	attr = va & PTEMA(7);
cinap_lenrek@7217 161
 	va &= -PGLSZ(1);
cinap_lenrek@7199 162
 	off = pa % PGLSZ(1);
cinap_lenrek@7199 163
 	a = va + off;
cinap_lenrek@7199 164
 	pe = (pa + size + (PGLSZ(1)-1)) & -PGLSZ(1);
cinap_lenrek@7199 165
 	while(pa < pe){
cinap_lenrek@7199 166
 		((uintptr*)L1)[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | PTEWRITE | PTEAF
cinap_lenrek@7217 167
 			| PTEKERNEL | PTESH(SHARE_OUTER) | attr;
cinap_lenrek@7199 168
 		pa += PGLSZ(1);
cinap_lenrek@7199 169
 		va += PGLSZ(1);
cinap_lenrek@7199 170
 	}
cinap_lenrek@7199 171
 	flushtlb();
cinap_lenrek@7199 172
 	return a;
cinap_lenrek@7199 173
 }
cinap_lenrek@7199 174
 
cinap_lenrek@7199 175
 static uintptr*
cinap_lenrek@7199 176
 mmuwalk(uintptr va, int level)
cinap_lenrek@7199 177
 {
cinap_lenrek@7199 178
 	uintptr *table, pte;
cinap_lenrek@7199 179
 	Page *pg;
cinap_lenrek@7199 180
 	int i, x;
cinap_lenrek@7199 181
 
cinap_lenrek@7199 182
 	x = PTLX(va, PTLEVELS-1);
cinap_lenrek@7199 183
 	table = &m->mmul1[L1TABLEX(va, PTLEVELS-1)];
cinap_lenrek@7199 184
 	for(i = PTLEVELS-2; i >= level; i--){
cinap_lenrek@7199 185
 		pte = table[x];
cinap_lenrek@7199 186
 		if(pte & PTEVALID) {
cinap_lenrek@7199 187
 			if(pte & (0xFFFFULL<<48))
cinap_lenrek@7199 188
 				iprint("strange pte %#p va %#p\n", pte, va);
cinap_lenrek@7199 189
 			pte &= ~(0xFFFFULL<<48 | BY2PG-1);
cinap_lenrek@7199 190
 			table = KADDR(pte);
cinap_lenrek@7199 191
 		} else {
cinap_lenrek@7199 192
 			if(i < 2){
cinap_lenrek@7199 193
 				pg = up->mmufree;
cinap_lenrek@7199 194
 				if(pg == nil)
cinap_lenrek@7199 195
 					return nil;
cinap_lenrek@7199 196
 				up->mmufree = pg->next;
cinap_lenrek@7199 197
 				switch(i){
cinap_lenrek@7199 198
 				case 0:
cinap_lenrek@7199 199
 					pg->va = va & -PGLSZ(1);
cinap_lenrek@7199 200
 					if((pg->next = up->mmul1) == nil)
cinap_lenrek@7199 201
 						up->mmul1tail = pg;
cinap_lenrek@7199 202
 					up->mmul1 = pg;
cinap_lenrek@7199 203
 					break;
cinap_lenrek@7199 204
 				case 1:
cinap_lenrek@7199 205
 					pg->va = va & -PGLSZ(2);
cinap_lenrek@7199 206
 					if((pg->next = up->mmul2) == nil)
cinap_lenrek@7199 207
 						up->mmul2tail = pg;
cinap_lenrek@7199 208
 					up->mmul2 = pg;
cinap_lenrek@7199 209
 					break;
cinap_lenrek@7199 210
 				}
cinap_lenrek@7199 211
 				memset(KADDR(pg->pa), 0, BY2PG);
cinap_lenrek@7199 212
 				coherence();
cinap_lenrek@7199 213
 				table[x] = pg->pa | PTEVALID | PTETABLE;
cinap_lenrek@7199 214
 				table = KADDR(pg->pa);
cinap_lenrek@7199 215
 			} else {
cinap_lenrek@7199 216
 				table[x] = PADDR(&m->mmul1[L1TABLEX(va, 2)]) | PTEVALID | PTETABLE;
cinap_lenrek@7199 217
 				table = &m->mmul1[L1TABLEX(va, 2)];
cinap_lenrek@7199 218
 			}
cinap_lenrek@7199 219
 		}
cinap_lenrek@7199 220
 		x = PTLX(va, (uintptr)i);
cinap_lenrek@7199 221
 	}
cinap_lenrek@7199 222
 	return &table[x];
cinap_lenrek@7199 223
 }
cinap_lenrek@7199 224
 
cinap_lenrek@7199 225
 static Proc *asidlist[256];
cinap_lenrek@7199 226
 
cinap_lenrek@7199 227
 static int
cinap_lenrek@7199 228
 allocasid(Proc *p)
cinap_lenrek@7199 229
 {
cinap_lenrek@7199 230
 	static Lock lk;
cinap_lenrek@7199 231
 	Proc *x;
cinap_lenrek@7199 232
 	int a;
cinap_lenrek@7199 233
 
cinap_lenrek@7199 234
 	lock(&lk);
cinap_lenrek@7199 235
 	a = p->asid;
cinap_lenrek@7199 236
 	if(a < 0)
cinap_lenrek@7199 237
 		a = -a;
cinap_lenrek@7199 238
 	if(a == 0)
cinap_lenrek@7199 239
 		a = p->pid;
cinap_lenrek@7199 240
 	for(;; a++){
cinap_lenrek@7199 241
 		a %= nelem(asidlist);
cinap_lenrek@7199 242
 		if(a == 0)
cinap_lenrek@7199 243
 			continue;	// reserved
cinap_lenrek@7199 244
 		x = asidlist[a];
cinap_lenrek@7199 245
 		if(x == p || x == nil || (x->asid < 0 && x->mach == nil))
cinap_lenrek@7199 246
 			break;
cinap_lenrek@7199 247
 	}
cinap_lenrek@7199 248
 	p->asid = a;
cinap_lenrek@7199 249
 	asidlist[a] = p;
cinap_lenrek@7199 250
 	unlock(&lk);
cinap_lenrek@7199 251
 
cinap_lenrek@7199 252
 	return x != p;
cinap_lenrek@7199 253
 }
cinap_lenrek@7199 254
 
cinap_lenrek@7199 255
 static void
cinap_lenrek@7199 256
 freeasid(Proc *p)
cinap_lenrek@7199 257
 {
cinap_lenrek@7199 258
 	int a;
cinap_lenrek@7199 259
 
cinap_lenrek@7199 260
 	a = p->asid;
cinap_lenrek@7199 261
 	if(a < 0)
cinap_lenrek@7199 262
 		a = -a;
cinap_lenrek@7199 263
 	if(a > 0 && asidlist[a] == p)
cinap_lenrek@7199 264
 		asidlist[a] = nil;
cinap_lenrek@7199 265
 	p->asid = 0;
cinap_lenrek@7199 266
 }
cinap_lenrek@7199 267
 
cinap_lenrek@7199 268
 void
cinap_lenrek@7199 269
 putasid(Proc *p)
cinap_lenrek@7199 270
 {
cinap_lenrek@7199 271
 	/*
cinap_lenrek@7199 272
 	 * Prevent the following scenario:
cinap_lenrek@7199 273
 	 *	pX sleeps on cpuA, leaving its page tables in mmul1
cinap_lenrek@7199 274
 	 *	pX wakes up on cpuB, and exits, freeing its page tables
cinap_lenrek@7199 275
 	 *  pY on cpuB allocates a freed page table page and overwrites with data
cinap_lenrek@7199 276
 	 *  cpuA takes an interrupt, and is now running with bad page tables
cinap_lenrek@7199 277
 	 * In theory this shouldn't hurt because only user address space tables
cinap_lenrek@7199 278
 	 * are affected, and mmuswitch will clear mmul1 before a user process is
cinap_lenrek@7199 279
 	 * dispatched.  But empirically it correlates with weird problems, eg
cinap_lenrek@7199 280
 	 * resetting of the core clock at 0x4000001C which confuses local timers.
cinap_lenrek@7199 281
 	 */
cinap_lenrek@7199 282
 	if(conf.nmach > 1)
cinap_lenrek@7199 283
 		mmuswitch(nil);
cinap_lenrek@7199 284
 
cinap_lenrek@7199 285
 	if(p->asid > 0)
cinap_lenrek@7199 286
 		p->asid = -p->asid;
cinap_lenrek@7199 287
 }
cinap_lenrek@7199 288
 
cinap_lenrek@7199 289
 void
cinap_lenrek@7199 290
 putmmu(uintptr va, uintptr pa, Page *pg)
cinap_lenrek@7199 291
 {
cinap_lenrek@7199 292
 	uintptr *pte, old;
cinap_lenrek@7199 293
 	int s;
cinap_lenrek@7199 294
 
cinap_lenrek@7199 295
 	s = splhi();
cinap_lenrek@7199 296
 	while((pte = mmuwalk(va, 0)) == nil){
cinap_lenrek@7199 297
 		spllo();
cinap_lenrek@7199 298
 		assert(up->mmufree == nil);
cinap_lenrek@7199 299
 		up->mmufree = newpage(0, nil, 0);
cinap_lenrek@7199 300
 		splhi();
cinap_lenrek@7199 301
 	}
cinap_lenrek@7199 302
 	old = *pte;
cinap_lenrek@7199 303
 	*pte = 0;
cinap_lenrek@7199 304
 	if((old & PTEVALID) != 0)
cinap_lenrek@7199 305
 		flushasidvall((uvlong)up->asid<<48 | va>>12);
cinap_lenrek@7199 306
 	else
cinap_lenrek@7199 307
 		flushasidva((uvlong)up->asid<<48 | va>>12);
cinap_lenrek@7199 308
 	*pte = pa | PTEPAGE | PTEUSER | PTENG | PTEAF | PTESH(SHARE_INNER);
cinap_lenrek@7199 309
 	if(pg->txtflush & (1UL<<m->machno)){
cinap_lenrek@7199 310
 		/* pio() sets PG_TXTFLUSH whenever a text pg has been written */
cinap_lenrek@7199 311
 		cachedwbinvse((void*)KADDR(pg->pa), BY2PG);
cinap_lenrek@7199 312
 		cacheiinvse((void*)va, BY2PG);
cinap_lenrek@7199 313
 		pg->txtflush &= ~(1UL<<m->machno);
cinap_lenrek@7199 314
 	}
cinap_lenrek@7199 315
 	splx(s);
cinap_lenrek@7199 316
 }
cinap_lenrek@7199 317
 
cinap_lenrek@7199 318
 static void
cinap_lenrek@7199 319
 mmufree(Proc *p)
cinap_lenrek@7199 320
 {
cinap_lenrek@7199 321
 	freeasid(p);
cinap_lenrek@7199 322
 
cinap_lenrek@7199 323
 	if(p->mmul1 == nil){
cinap_lenrek@7199 324
 		assert(p->mmul2 == nil);
cinap_lenrek@7199 325
 		return;
cinap_lenrek@7199 326
 	}
cinap_lenrek@7199 327
 	p->mmul1tail->next = p->mmufree;
cinap_lenrek@7199 328
 	p->mmufree = p->mmul1;
cinap_lenrek@7199 329
 	p->mmul1 = p->mmul1tail = nil;
cinap_lenrek@7199 330
 
cinap_lenrek@7199 331
 	if(PTLEVELS > 2){
cinap_lenrek@7199 332
 		p->mmul2tail->next = p->mmufree;
cinap_lenrek@7199 333
 		p->mmufree = p->mmul2;
cinap_lenrek@7199 334
 		p->mmul2 = p->mmul2tail = nil;
cinap_lenrek@7199 335
 	}
cinap_lenrek@7199 336
 }
cinap_lenrek@7199 337
 
cinap_lenrek@7199 338
 void
cinap_lenrek@7199 339
 mmuswitch(Proc *p)
cinap_lenrek@7199 340
 {
cinap_lenrek@7199 341
 	uintptr va;
cinap_lenrek@7199 342
 	Page *t;
cinap_lenrek@7199 343
 
cinap_lenrek@7199 344
 	for(va = UZERO; va < USTKTOP; va += PGLSZ(PTLEVELS-1))
cinap_lenrek@7199 345
 		m->mmul1[PTL1X(va, PTLEVELS-1)] = 0;
cinap_lenrek@7199 346
 
cinap_lenrek@7199 347
 	if(p == nil){
cinap_lenrek@7199 348
 		setttbr(PADDR(&m->mmul1[L1TABLEX(0, PTLEVELS-1)]));
cinap_lenrek@7199 349
 		return;
cinap_lenrek@7199 350
 	}
cinap_lenrek@7199 351
 
cinap_lenrek@7199 352
 	if(p->newtlb){
cinap_lenrek@7199 353
 		mmufree(p);
cinap_lenrek@7199 354
 		p->newtlb = 0;
cinap_lenrek@7199 355
 	}
cinap_lenrek@7199 356
 
cinap_lenrek@7199 357
 	if(PTLEVELS == 2){
cinap_lenrek@7199 358
 		for(t = p->mmul1; t != nil; t = t->next){
cinap_lenrek@7199 359
 			va = t->va;
cinap_lenrek@7199 360
 			m->mmul1[PTL1X(va, 1)] = t->pa | PTEVALID | PTETABLE;
cinap_lenrek@7199 361
 		}
cinap_lenrek@7199 362
 	} else {
cinap_lenrek@7199 363
 		for(t = p->mmul2; t != nil; t = t->next){
cinap_lenrek@7199 364
 			va = t->va;
cinap_lenrek@7199 365
 			m->mmul1[PTL1X(va, 2)] = t->pa | PTEVALID | PTETABLE;
cinap_lenrek@7199 366
 			if(PTLEVELS > 3)
cinap_lenrek@7199 367
 				m->mmul1[PTL1X(va, 3)] = PADDR(&m->mmul1[L1TABLEX(va, 2)]) |
cinap_lenrek@7199 368
 					PTEVALID | PTETABLE;
cinap_lenrek@7199 369
 		}
cinap_lenrek@7199 370
 	}
cinap_lenrek@7199 371
 
cinap_lenrek@7199 372
 	if(allocasid(p))
cinap_lenrek@7199 373
 		flushasid((uvlong)p->asid<<48);
cinap_lenrek@7199 374
 
cinap_lenrek@7199 375
 	setttbr((uvlong)p->asid<<48 | PADDR(&m->mmul1[L1TABLEX(0, PTLEVELS-1)]));
cinap_lenrek@7199 376
 }
cinap_lenrek@7199 377
 
cinap_lenrek@7199 378
 void
cinap_lenrek@7199 379
 mmurelease(Proc *p)
cinap_lenrek@7199 380
 {
cinap_lenrek@7199 381
 	Page *t;
cinap_lenrek@7199 382
 
cinap_lenrek@7199 383
 	mmuswitch(nil);
cinap_lenrek@7199 384
 	mmufree(p);
cinap_lenrek@7199 385
 
cinap_lenrek@7199 386
 	if((t = p->mmufree) != nil){
cinap_lenrek@7199 387
 		do {
cinap_lenrek@7199 388
 			p->mmufree = t->next;
cinap_lenrek@7199 389
 			if(--t->ref != 0)
cinap_lenrek@7199 390
 				panic("mmurelease: bad page ref");
cinap_lenrek@7199 391
 			pagechainhead(t);
cinap_lenrek@7199 392
 		} while((t = p->mmufree) != nil);
cinap_lenrek@7199 393
 		pagechaindone();
cinap_lenrek@7199 394
 	}
cinap_lenrek@7199 395
 }
cinap_lenrek@7199 396
 
cinap_lenrek@7199 397
 void
cinap_lenrek@7199 398
 flushmmu(void)
cinap_lenrek@7199 399
 {
cinap_lenrek@7199 400
 	int x;
cinap_lenrek@7199 401
 
cinap_lenrek@7199 402
 	x = splhi();
cinap_lenrek@7199 403
 	up->newtlb = 1;
cinap_lenrek@7199 404
 	mmuswitch(up);
cinap_lenrek@7199 405
 	splx(x);
cinap_lenrek@7199 406
 }
cinap_lenrek@7199 407
 
cinap_lenrek@7199 408
 void
cinap_lenrek@7199 409
 checkmmu(uintptr, uintptr)
cinap_lenrek@7199 410
 {
cinap_lenrek@7199 411
 }