## diffname bitsy/mmu.c 2000/0902
## diff -e /dev/null /n/emeliedump/2000/0902/sys/src/9/bitsy/mmu.c
0a
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "../port/error.h"
void
putmmu(ulong va, ulong pa, Page*)
{
USED(va, pa);
}
void
mmurelease(Proc* proc)
{
USED(proc);
}
void
mmuswitch(Proc* proc)
{
USED(proc);
}
.
## diffname bitsy/mmu.c 2000/0905
## diff -e /n/emeliedump/2000/0902/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0905/sys/src/9/bitsy/mmu.c
10a
mmuinit(void)
{
}
void
.
## diffname bitsy/mmu.c 2000/0906
## diff -e /n/emeliedump/2000/0905/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0906/sys/src/9/bitsy/mmu.c
12a
ulong a, e;
/* set up the domain register to cause all domains to obey pte access bits */
putdac(0x55555555);
/* get a prototype level 1 page */
l1page = xspanalloc(BY2PG, 16*1024, 0);
memset(l1page, 0, BY2PG);
/* map DRAM */
e = PHYSDRAM0 + BY2PG*con
for(
/* map zeros */
/* map flash */
.
9a
/* real protection bits */
enum
{
Small_Page= (2<<0),
Large_Page= (1<<0),
Cached= (1<<3),
Buffered= (1<<2),
UserRO= (0xAA<<4),
UserRW= (0xFF<<4),
KernelRW= (0x55<<4),
};
/*
* table to map fault.c bits to physical bits
*/
static ulong phystrans[8] =
{
[PTEVALID] Small_Page|Cached|Buffered|UserRO,
[PTEVALID|PTEWRITE] Small_Page|Cached|Buffered|UserRW,
[PTEVALID|UNCACHED] Small_Page|UserRO,
[PTEVALID|UNCACHED|PTEWRITE] Small_Page|UserRW,
};
ulong *l1page;
/*
* We map all of memory, flash, and the zeros area with sections.
* Special use space is mapped on the fly with regmap.
*/
.
## diffname bitsy/mmu.c 2000/0907
## diff -e /n/emeliedump/2000/0906/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0907/sys/src/9/bitsy/mmu.c
52,56c
/* direct map DRAM */
e = conf.base1 + BY2PG*conf.npage2;
for(a = PHYSDRAM0; a < e; a += OneMeg)
l1table[a>>20] = L1Section | L1KernelRW |
L1Cached | L1Buffered | (a&L1SectBaseMask);
/* direct map zeros area */
for(a = PHYSNULL0; a < PHYSNULL0 + 128 * OneMeg; a += OneMeg)
l1table[a>>20] = L1Section | L1KernelRW |
L1Cached | L1Buffered | (a&L1SectBaseMask);
/* direct map flash */
for(a = PHYFLASH0; a < PHYFLASH0 + 128 * OneMeg; a += OneMeg)
l1table[a>>20] = L1Section | L1KernelRW |
L1Cached | L1Buffered | (a&L1SectBaseMask);
/* map the uart so that we can continue using iprint */
uart3regs = mapspecial(UART3REGS, 64);
}
/*
* map special use space
*/
ulong*
mapspecial(ulong addr, int len)
{
ulong *t;
ulong a, i;
/* first see if we've mapped it somewhere, the first hole means we're done */
for(a = REGZERO; a < REGTOP; a += OneMeg){
if((l1table[a>>20] & L1TypeMask) != L1PageTable){
/* create a page table and break */
t = xspanalloc(BY2PG, 1024, 0);
memzero(t, BY2PG, 0);
l1table[a>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask);
break;
}
t = (ulong*)(l1table[a>>20] & L1PTBaseMask);
for(i = 0; i < OneMeg; i += BY2PG){
if((t[a>>20] & L2TypeMask) != L2SmallPage)
break;
}
if(i < OneMeg){
a += i;
break;
}
}
.
49,50c
l1table = xspanalloc(BY2PG, 16*1024, 0);
memset(l1table, 0, BY2PG);
.
34c
ulong *l1table;
.
28,31c
[PTEVALID] L2SmallPage|L2Cached|L2Buffered|L2UserRO,
[PTEVALID|PTEWRITE] L2SmallPage|L2Cached|L2Buffered|L2UserRW,
[PTEVALID|PTEUNCACHED] L2SmallPage|L2UserRO,
[PTEVALID|PTEUNCACHED|PTEWRITE] L2SmallPage|L2UserRW,
[PTEKERNEL|PTEVALID] L2SmallPage|L2Cached|L2Buffered|L2KernelRW,
[PTEKERNEL|PTEVALID|PTEWRITE] L2SmallPage|L2Cached|L2Buffered|L2KernelRW,
[PTEKERNEL|PTEVALID|PTEUNCACHED] L2SmallPage|L2KernelRW,
[PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE] L2SmallPage|L2KernelRW,
.
26c
static ulong phystrans[16] =
.
22d
13,19c
/* level 1 descriptor bits */
L1TypeMask= (3<<0),
L1Invalid= (0<<0),
L1PageTable= (1<<0),
L1Section= (2<<0),
L1Cached= (1<<3),
L1Buffered= (1<<2),
L1Domain0= (0<<5),
L1KernelRW= (0x1<<10),
L1UserRO= (0x2<<10),
L1UserRW= (0x3<<10),
L1SectBaseMask= (0xFFF<<20),
L1PTBaseMask= (0x3FFFFF<<10),
/* level 2 descriptor bits */
L2TypeMask= (3<<0),
L2SmallPage= (2<<0),
L2LargePage= (1<<0),
L2Cached= (1<<3),
L2Buffered= (1<<2),
L2KernelRW= (0x55<<4),
L2UserRO= (0xAA<<4),
L2UserRW= (0xFF<<4),
L2PageBaseMask= (0xFFFFF<<12),
.
## diffname bitsy/mmu.c 2000/0909
## diff -e /n/emeliedump/2000/0907/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0909/sys/src/9/bitsy/mmu.c
120a
/* we get here if no entry was found mapping this physical address */
.
117c
virtaddr += i;
.
113c
if((t[virtaddr>>20] & L2TypeMask) != L2SmallPage)
.
111c
t = (ulong*)(l1table[virtaddr>>20] & L1PTBaseMask);
.
108c
l1table[virtaddr>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask);
.
103,104c
for(virtaddr = REGZERO; virtaddr < REGTOP; virtaddr += OneMeg){
if((l1table[virtaddr>>20] & L1TypeMask) != L1PageTable){
.
100c
ulong virtaddr, i;
.
97c
mapspecial(ulong physaddr, int len)
.
## diffname bitsy/mmu.c 2000/0920
## diff -e /n/emeliedump/2000/0909/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0920/sys/src/9/bitsy/mmu.c
122,123c
/* we get here if no entry was found mapping this physical range */
.
114a
.
113c
if((t[(virtaddr+i)>>20] & L2TypeMask) != L2SmallPage)
.
94c
* map special use space
.
## diffname bitsy/mmu.c 2000/0921
## diff -e /n/emeliedump/2000/0920/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0921/sys/src/9/bitsy/mmu.c
115c
if(candidate == 0){
/* look for start of range */
if((entry & L2PageBaseMask) != base)
continue;
candidate = virtaddr+i;
} else {
/* look for contiunued range */
if((entry & L2PageBaseMask) != base + off)
candidate = 0;
continue;
}
}
/* if we're at the end of the range, area is already mapped */
if((entry & L2PageBaseMask) == end)
return candidate + (physaddr-base);
.
113c
entry = t[(virtaddr+i)>>20];
/* first hole means nothing left, add map */
if((entry & L2TypeMask) != L2SmallPage)
.
108c
l1table[virtaddr>>20] = L1PageTable | L1Domain0 |
(((ulong)t) & L1PTBaseMask);
.
101a
base = physaddr & ~(BY2PG-1);
end = (physaddr+len-1) & ~(BY2PG-1);
if(len > 128*1024)
usemeg = 1;
off = 0;
candidate = 0;
.
100c
ulong virtaddr, i, base, end, off, entry, candidate;
.
94c
* map special space, assume that the space isn't already mapped
.
## diffname bitsy/mmu.c 2000/0923
## diff -e /n/emeliedump/2000/0921/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0923/sys/src/9/bitsy/mmu.c
134c
if((entry & L2PageBaseMask) != base + off){
.
96a
mapspecmeg(ulong physaddr, int len)
ulong*
.
94c
* map special space uncached, assume that the space isn't already mapped
.
## diffname bitsy/mmu.c 2000/0924
## diff -e /n/emeliedump/2000/0923/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0924/sys/src/9/bitsy/mmu.c
152c
/* didn't fit */
if(base <= end)
return nil;
return rv;
.
146,149d
141,144d
125,139c
/* found unused entry on level 2 table */
if((entry & L2TypeMask) != L2SmallPage){
if(rv == nil)
rv = (ulong*)(va+i*BY2PG+off);
t[i>>PGSHIFT] = L2SmallPage | L2KernelRW |
(base & L2PageBaseMask);
base += BY2PG;
continue;
.
123c
entry = t[i>>PGSHIFT];
.
121c
t = (ulong*)(l1table[va>>20] & L1PTBaseMask);
.
119d
117c
l1table[va>>20] = L1PageTable | L1Domain0 |
.
111,114c
for(va = REGZERO; va < REGTOP && base >= end; va += OneMeg){
if((l1table[va>>20] & L1TypeMask) != L1PageTable){
/* found unused entry on level 1 table */
if(livelarge){
if(rv == nil)
rv = (ulong*)(va+i*BY2PG+off);
l1table[va>>20] = L1Section | L1KernelRW |
(base&L1SectBaseMask);
base += OneMeg;
continue;
}
/* create a page table and keep going */
.
104,109c
rv = nil;
livelarge = len >= 128*1024;
if(livelarge){
base = pa & ~(OneMeg-1);
end = (pa+len-1) & ~(OneMeg-1);
} else {
base = pa & ~(BY2PG-1);
end = (pa+len-1) & ~(BY2PG-1);
}
off = pa - base;
.
102c
ulong va, i, base, end, off;
int livelarge;
ulong* rv;
.
97,99c
mapspecial(ulong pa, int len)
.
## diffname bitsy/mmu.c 2000/0928
## diff -e /n/emeliedump/2000/0924/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0928/sys/src/9/bitsy/mmu.c
130c
memset(t, 0, BY2PG);
.
100c
ulong va, i, base, end, off, entry;
.
90c
// uart3regs = mapspecial(UART3REGS, 64);
/* set up the domain register to cause all domains to obey pte access bits */
iprint("setting up domain access\n");
putdac(0x55555555);
/* point to map */
iprint("setting tlb map %lux\n", (ulong)l1table);
putttb((ulong)l1table);
.
85c
for(a = PHYSFLASH0; a < PHYSFLASH0 + 128 * OneMeg; a += OneMeg)
.
78a
/* direct map devs */
for(a = REGZERO; a < REGTOP; a += OneMeg)
l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask);
.
74c
e = conf.base1 + BY2PG*conf.npage1;
.
66,68d
## diffname bitsy/mmu.c 2000/0929
## diff -e /n/emeliedump/2000/0928/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0929/sys/src/9/bitsy/mmu.c
151c
rv = (ulong*)(va+i+off);
.
143a
/* here if we're using page maps instead of sections */
.
137,141c
/* create an L2 page table and keep going */
t = xspanalloc(BY2PG, 1024, 0);
memset(t, 0, BY2PG);
l1table[va>>20] = L1PageTable | L1Domain0 |
(((ulong)t) & L1PTBaseMask);
}
break;
case L1Section:
continue;
case L1PageTable:
if(livelarge)
continue;
break;
.
135c
} else {
.
132c
(base & L1SectBaseMask);
.
130c
rv = (ulong*)(va+off);
.
124,126c
for(va = REGZERO; va < REGTOP && base <= end; va += OneMeg){
switch(l1table[va>>20] & L1TypeMask){
default:
.
99a
/* map the uart so that we can continue using iprint */
uart3regs = (Uartregs*)mapspecial(UART3REGS, 64);
/* enable mmu, and make 0xFFFF0000 the virtual address of the exception vecs */
mmuenable();
iprint("uart3regs now at %lux\n", uart3regs);
.
95c
putdac(0xFFFFFFFF);
.
90,91c
/* map first page of DRAM also into 0xFFFF0000 for the interrupt vectors */
t = xspanalloc(BY2PG, 16*1024, 0);
memset(t, 0, BY2PG);
l1table[0xFFFF0000>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask);
t[0xF0000>>PGSHIFT] = L2SmallPage | L2KernelRW | PHYSDRAM0;
.
87,88c
l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask) |
L1Cached | L1Buffered;
.
82,83c
l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask);
.
76,79d
73,74c
l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask) |
L1Cached | L1Buffered;
.
64a
ulong *t;
.
## diffname bitsy/mmu.c 2000/1002
## diff -e /n/emeliedump/2000/0929/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1002/sys/src/9/bitsy/mmu.c
112c
void*
.
101c
uart3regs = mapspecial(UART3REGS, 64);
.
## diffname bitsy/mmu.c 2000/1006
## diff -e /n/emeliedump/2000/1002/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1006/sys/src/9/bitsy/mmu.c
105,106d
100,102d
## diffname bitsy/mmu.c 2000/1007
## diff -e /n/emeliedump/2000/1006/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1007/sys/src/9/bitsy/mmu.c
100c
/* enable mmu */
wbflush();
flushcache();
flushmmu();
.
89,90c
l1table[a>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask);
t[(a&0xfffff)>>PGSHIFT] = L2SmallPage | L2KernelRW | (PHYSDRAM0 & L2PageBaseMask);
.
86,87c
/*
* double map start of ram to exception vectors
*/
a = EVECTORS;
t = xspanalloc(BY2PG, 1024, 0);
.
68,69c
l1table = xspanalloc(16*1024, 16*1024, 0);
memset(l1table, 0, 16*1024);
.
56a
.
## diffname bitsy/mmu.c 2000/1011
## diff -e /n/emeliedump/2000/1007/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1011/sys/src/9/bitsy/mmu.c
200c
/* set pid */
if(p->pid <= 0)
p->pid = newtlbpid(p);
putpid(p->pid<<25);
/* set domain register to this + the kernel's domains */
putdac((Dclient<<(2*p->pid)) | Dclient);
.
198c
mmuswitch(Proc* p)
.
194c
Page *pg;
int i;
for(i = 0; i < nelem(p->l1); i++){
pg = p->l1[i];
if(pg == nil)
continue;
if(--pg->ref)
panic("mmurelease: pg->ref %d\n", pg->ref);
pagechainhead(pg);
p->l1[i] = nil;
}
.
192c
mmurelease(Proc* p)
.
190a
/*
* this is called with palloc locked so the pagechainhead is kosher
*/
.
188c
ulong pva;
Page *p;
ulong *t;
/* if user memory, offset by pid value */
if((va & 0xfe000000) == 0)
pva = va | (up->pid << 25);
else
pva = va;
/* always point L1 entry to L2 page, can't hurt */
p = up->l1[va>>20];
if(p == nil){
p = auxpage();
if(p == nil)
pexit("out of memory", 1);
p->va = VA(kmap(p));
up->l1[va>>20] = p;
}
l1table[pva>>20] = L1PageTable | L1Domain0 | (p->pa & L1PTBaseMask);
t = (ulong*)p->va;
/* set L2 entry */
t[(pva & (OneMeg-1))>>PGSHIFT] = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)]
| (pa & ~(PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE));
wbflush();
.
184a
/*
* find a new pid. If none exist, flush all pids, mmu, and caches.
*/
static Lock pidlock;
int
newtlbpid(Proc *p)
{
return p->pid;
}
/*
* table to map fault.c bits to physical bits
*/
static ulong mmubits[16] =
{
[PTEVALID] L2SmallPage|L2Cached|L2Buffered|L2UserRO,
[PTEVALID|PTEWRITE] L2SmallPage|L2Cached|L2Buffered|L2UserRW,
[PTEVALID|PTEUNCACHED] L2SmallPage|L2UserRO,
[PTEVALID|PTEUNCACHED|PTEWRITE] L2SmallPage|L2UserRW,
[PTEKERNEL|PTEVALID] L2SmallPage|L2Cached|L2Buffered|L2KernelRW,
[PTEKERNEL|PTEVALID|PTEWRITE] L2SmallPage|L2Cached|L2Buffered|L2KernelRW,
[PTEKERNEL|PTEVALID|PTEUNCACHED] L2SmallPage|L2KernelRW,
[PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE] L2SmallPage|L2KernelRW,
};
/*
* add an entry to the current map
*/
.
153a
/* if it's already mapped in a one meg area, don't remap */
entry = l1table[va>>20];
i = entry & L1SectBaseMask;
if(pa >= i && (pa+len) <= i + OneMeg)
if((entry & ~L1SectBaseMask) == (L1Section | L1KernelRW | L1Domain0))
return (void*)(va + (pa & (OneMeg-1)));
.
140c
l1table[va>>20] = L1Section | L1KernelRW | L1Domain0 |
.
98c
putdac(Dclient);
.
86a
/* map peripheral control module regs */
mapspecial(0x80000000, OneMeg);
/* map system control module regs */
mapspecial(0x90000000, OneMeg);
.
82,85c
/* map flash */
for(o = 0; o < 128 * OneMeg; o += OneMeg)
l1table[(FLASHZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0
| L1Cached | L1Buffered
| ((PHYSFLASH0+o)&L1SectBaseMask);
.
78,80c
/* map zeros area */
for(o = 0; o < 128 * OneMeg; o += OneMeg)
l1table[(NULLZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0
| ((PHYSNULL0+o)&L1SectBaseMask);
.
72,76c
/* map DRAM */
for(o = 0; o < DRAMTOP; o += OneMeg)
l1table[(DRAMZERO+o)>>20] = L1Section | L1KernelRW| L1Domain0
| L1Cached | L1Buffered
| ((PHYSDRAM0+o)&L1SectBaseMask);
.
65c
ulong a, o;
.
39,52c
/* domain values */
Dnoaccess= 0,
Dclient= 1,
Dmanager= 3,
.
37d
20c
L1DomShift= 5,
L1Domain0= (0<<L1DomShift),
.
9a
/*
* to avoid mmu and cash flushing, we use the pid register in the MMU
* to map all user addresses. Although there are 64 possible pids, we
* can only use 31 because there are only 32 protection domains and we
* need one for the kernel. Pid i is thus associated with domain i.
* Domain 0 is used for the kernel.
*/
.
## diffname bitsy/mmu.c 2000/1012
## diff -e /n/emeliedump/2000/1011/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1012/sys/src/9/bitsy/mmu.c
289c
putdac((Dclient<<(2*p->tlbpid)) | Dclient);
.
284,286c
if(p->tlbpid <= 0)
p->tlbpid = newtlbpid(p);
iprint("using tlbpid %d\n", p->tlbpid);
putpid(p->tlbpid<<25);
.
237c
pva = va | (up->tlbpid << 25);
.
235c
iprint("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa);
/* if user memory, add pid value */
.
206c
int i;
ilock(&pidlock);
i = ++(m->lastpid);
if(i >= nelem(m->pid2proc)){
flushpids();
i = m->lastpid = 0;
}
m->pid2proc[i] = p;
p->tlbpid = i+1;
iunlock(&pidlock);
return p->tlbpid;
.
202a
void
flushpids(void)
{
memset(l1table, 0, BY2WD*nelem(m->pid2proc)*32);
memset(m->pid2proc, 0, sizeof(m->pid2proc));
flushcache();
flushmmu();
}
.
199c
* maintain pids
.
107d
103d
## diffname bitsy/mmu.c 2000/1013
## diff -e /n/emeliedump/2000/1012/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1013/sys/src/9/bitsy/mmu.c
302,309c
// flushcache(); /* drain and flush the cache */
// flushmmu();
// memmove(l1table, p->l1table, sizeof(p->l1table));
.
295c
p->l1page[i] = nil;
.
288,289c
for(i = 0; i < nelem(p->l1page); i++){
pg = p->l1page[i];
.
276c
flushmmu();
.
274a
iprint("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]);
.
273c
t[(va & (OneMeg-1))>>PGSHIFT] = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)]
.
269c
l1table[va>>20] = L1PageTable | L1Domain0 | (p->pa & L1PTBaseMask);
iprint("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]);
up->l1table[va>>20] = l1table[va>>20];
.
267c
up->l1page[va>>20] = p;
.
261c
p = up->l1page[va>>20];
.
254,259d
249d
197,227d
71c
for(o = 0; o < 128*OneMeg; o += OneMeg)
.
69a
/* map low mem */
for(o = 0; o < 1*OneMeg; o += OneMeg)
l1table[(0+o)>>20] = L1Section | L1KernelRW| L1Domain0
| L1Cached | L1Buffered
| ((0+o)&L1SectBaseMask);
.
## diffname bitsy/mmu.c 2000/1014
## diff -e /n/emeliedump/2000/1013/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1014/sys/src/9/bitsy/mmu.c
273,275c
iprint("switching to proc %d\n", p->pid);
memmove(l1table, p->l1table, sizeof(p->l1table));
cleanaddr((ulong)l1table);
wbflush();
}
void
peekmmu(ulong va)
{
ulong e;
e = l1table[va>>20];
switch(e & L1TypeMask){
default:
iprint("l1: %lux invalid\n", e);
break;
case L1PageTable:
iprint("l1: %lux pt\n", e);
va &= OneMeg-1;
va >>= PGSHIFT;
e &= L1PTBaseMask;
e = ((ulong*)e)[va];
iprint("l2: %lux\n", e);
break;
case L1Section:
iprint("l1: %lux section\n", e);
break;
}
.
247c
wbflush();
.
245a
cleanaddr((ulong)&t[(va & (OneMeg-1))>>PGSHIFT]);
.
237a
cleanaddr((ulong)&l1table[va>>20]);
.
235a
memset((uchar*)(p->va), 0, BY2PG);
.
## diffname bitsy/mmu.c 2000/1015
## diff -e /n/emeliedump/2000/1014/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1015/sys/src/9/bitsy/mmu.c
279a
/* lose any possible stale tlb entries */
mmuinvalidate();
}
void
flushmmu(void)
{
int s;
s = splhi();
up->newtlb = 1;
mmuswitch(up);
splx(s);
.
278c
/* make sure map is in memory and drain write buffer */
cacheflushaddr((ulong)l1table);
.
276c
if(p->newtlb){
mmuptefree(p);
p->newtlb = 0;
}
/* write back dirty cache entries before changing map */
cacheflush();
/* move in new map */
.
270a
if(p->mmufree && palloc.r.p)
wakeup(&palloc.r);
p->mmufree = nil;
memset(l1table, 0, sizeof(p->l1table));
.
269d
265a
p->l1page[i] = nil;
pg->next = p->mmufree;
p->mmufree = pg;
}
memset(p->l1table, 0, sizeof(p->l1table));
}
/*
* this is called with palloc locked so the pagechainhead is kosher
*/
void
mmurelease(Proc* p)
{
Page *pg, *next;
/* write back dirty cache entries before changing map */
cacheflush();
mmuptefree(p);
for(pg = p->mmufree; pg; pg = next){
next = pg->next;
.
262c
for(i = 0; i < Nmeg; i++){
.
257c
mmuptefree(Proc *p)
.
254c
* free up all page tables for this proc
.
247,248c
//iprint("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]);
cacheflushaddr((ulong)&t[(va & (OneMeg-1))>>PGSHIFT]);
.
239,240c
cacheflushaddr((ulong)&l1table[va>>20]);
//iprint("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]);
.
227c
//iprint("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa);
.
118a
cacheflush();
.
116,117c
mmuinvalidate();
.
84a
| L1Cached | L1Buffered
.
## diffname bitsy/mmu.c 2000/1016
## diff -e /n/emeliedump/2000/1015/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1016/sys/src/9/bitsy/mmu.c
302a
if(m->mmupid == p->pid && p->newtlb == 0)
return;
m->mmupid = p->pid;
.
301c
mmuswitch(Proc *p)
.
248c
print("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]);
.
243c
t = (ulong*)pg->va;
.
241c
print("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]);
.
239c
l1table[va>>20] = L1PageTable | L1Domain0 | (pg->pa & L1PTBaseMask);
.
230,237c
pg = up->l1page[va>>20];
if(pg == nil){
pg = up->mmufree;
if(pg != nil){
up->mmufree = pg->next;
} else {
pg = auxpage();
if(pg == nil)
pexit("out of memory", 1);
}
pg->va = VA(kmap(pg));
up->l1page[va>>20] = pg;
memset((uchar*)(pg->va), 0, BY2PG);
.
228c
print("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa);
.
225c
Page *pg;
.
## diffname bitsy/mmu.c 2000/1018
## diff -e /n/emeliedump/2000/1016/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1018/sys/src/9/bitsy/mmu.c
323,325c
/* make sure map is in memory */
cachewbregion(l1table, sizeof(p->l1table));
.
317,319d
311a
/* write back dirty cache entries and invalidate all cache entries */
cacheflush();
.
302a
cachewbregion(l1table, sizeof(p->l1table));
.
256c
/* write back dirty entries - we need this because the pio() in
* fault.c is writing via a different virt addr and won't clean
* its changes out of the dcache. Page coloring doesn't work
* on this mmu because the virtual cache is set associative
* rather than direct mapped.
*/
cachewb();
if(pg->cachectl[0] == PG_TXTFLUSH){
/* pio() sets PG_TXTFLUSH whenever a text page has been written */
icacheinvalidate();
pg->cachectl[0] = PG_NOFLUSH;
}
splx(s);
.
253,254d
251c
l2p = &t[(va & (OneMeg-1))>>PGSHIFT];
*l2p = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)]
.
249a
/* always point L1 entry to L2 page, can't hurt */
l1p = &l1table[va>>20];
*l1p = L1PageTable | L1Domain0 | (l2pg->pa & L1PTBaseMask);
up->l1table[va>>20] = *l1p;
t = (ulong*)l2pg->va;
.
244,248d
240,242c
l2pg->va = VA(kmap(l2pg));
up->l1page[va>>20] = l2pg;
memset((uchar*)(l2pg->va), 0, BY2PG);
.
236,237c
l2pg = auxpage();
if(l2pg == nil)
.
228,234c
s = splhi();
/* clear out the current entry */
mmuinvalidateaddr(va);
l2pg = up->l1page[va>>20];
if(l2pg == nil){
l2pg = up->mmufree;
if(l2pg != nil){
up->mmufree = l2pg->next;
.
225,226c
Page *l2pg;
ulong *t, *l1p, *l2p;
int s;
.
223c
putmmu(ulong va, ulong pa, Page *pg)
.
## diffname bitsy/mmu.c 2000/1019
## diff -e /n/emeliedump/2000/1018/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1019/sys/src/9/bitsy/mmu.c
378c
iprint("l1: %lux[%lux] = %lux section\n", l1table, va>>20, e);
.
374,375c
d = ((ulong*)e)[va];
iprint("l2: %lux[%lux] = %lux\n", e, va, d);
.
370c
iprint("l1: %lux[%lux] = %lux pt\n", l1table, va>>20, e);
.
367c
iprint("l1: %lux[%lux] = %lux invalid\n", l1table, va>>20, e);
.
362c
ulong e, d;
.
198a
cacheflush();
.
181c
for(i = 0; i < OneMeg && base <= end; i += BY2PG){
.
174c
if(large)
.
148c
if(large){
.
134,135c
large = len >= 128*1024;
if(large){
.
130c
int large;
.
## diffname bitsy/mmu.c 2000/1106
## diff -e /n/emeliedump/2000/1019/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1106/sys/src/9/bitsy/mmu.c
343c
cachewbregion((ulong)l1table, sizeof(p->l1table));
.
321c
cachewbregion((ulong)l1table, sizeof(p->l1table));
.
## diffname bitsy/mmu.c 2000/1118
## diff -e /n/emeliedump/2000/1106/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1118/sys/src/9/bitsy/mmu.c
201a
}
/* map in i/o registers */
void*
mapspecial(ulong pa, int len)
{
return _map(pa, len, REGZERO, REGTOP, L1KernelRW, L2KernelRW);
}
/* map add on memory */
void*
mapmem(ulong pa, int len)
{
return _map(pa, len, EMEMZERO, EMEMTOP, L1KernelRW|L1Cached|L1Buffered,
L2KernelRW|L2Cached|L2Buffered);
}
/* map a virtual address to a physical one */
ulong
mmu_paddr(ulong va)
{
ulong entry;
ulong *t;
entry = l1table[va>>20];
switch(entry & L1TypeMask){
case L1Section:
return (entry & L1SectBaseMask) | (va & (OneMeg-1));
case L1PageTable:
t = (ulong*)(entry & L1PTBaseMask);
va &= OneMeg-1;
entry = t[va>>PGSHIFT];
switch(entry & L1TypeMask){
case L2SmallPage:
return (entry & L2PageBaseMask) | (va & (BY2PG-1));
}
}
return 0;
}
/* map a physical address to a virtual one */
static ulong
findva(ulong pa, ulong zero, ulong top)
{
int i;
ulong entry, va;
ulong start, end;
ulong *t;
for(va = zero; va < top; va += OneMeg){
/* search the L1 entry */
entry = l1table[va>>20];
switch(entry & L1TypeMask){
default:
return 0; /* no holes */
case L1Section:
start = entry & L1SectBaseMask;
end = start + OneMeg;
if(pa >= start && pa < end)
return va | (pa & (OneMeg-1));
continue;
case L1PageTable:
break;
}
/* search the L2 entry */
t = (ulong*)(l1table[va>>20] & L1PTBaseMask);
for(i = 0; i < OneMeg; i += BY2PG){
entry = t[i>>PGSHIFT];
/* found unused entry on level 2 table */
if((entry & L2TypeMask) != L2SmallPage)
break;
start = entry & L2PageBaseMask;
end = start + BY2PG;
if(pa >= start && pa < end)
return va | (BY2PG*i) | (pa & (BY2PG-1));
}
}
return 0;
}
ulong
mmu_kaddr(ulong pa)
{
ulong va;
/* try the easy stuff first (the first case is true most of the time) */
if(pa >= PHYSDRAM0 && pa <= PHYSDRAM0+(DRAMTOP-DRAMZERO))
return DRAMZERO+(pa-PHYSDRAM0);
if(pa >= PHYSFLASH0 && pa <= PHYSFLASH0+(FLASHTOP-FLASHZERO))
return FLASHZERO+(pa-PHYSFLASH0);
if(pa >= PHYSNULL0 && pa <= PHYSNULL0+(NULLTOP-NULLZERO))
return NULLZERO+(pa-PHYSNULL0);
if(!mmuinited)
return 0; /* this shouldn't happen */
/* walk the map for the special regs and extended memory */
va = findva(pa, EMEMZERO, EMEMTOP);
if(va != 0)
return va;
return findva(pa, REGZERO, REGTOP);
.
188c
t[i>>PGSHIFT] = L2SmallPage | l2prop |
.
169c
if((entry & ~L1SectBaseMask) == (L1Section | l1prop | L1Domain0))
.
151c
l1table[va>>20] = L1Section | l1prop | L1Domain0 |
.
144c
for(va = zero; va < top && base <= end; va += OneMeg){
.
125,126c
static void*
_map(ulong pa, int len, ulong zero, ulong top, ulong l1prop, ulong l2prop)
.
123c
* map on request
.
119a
mmuinited = 1;
.
91d
89c
for(o = 0; o < FLASHTOP-FLASHZERO; o += OneMeg)
.
83c
for(o = 0; o < NULLTOP-NULLZERO; o += OneMeg)
.
77c
for(o = 0; o < DRAMTOP-DRAMZERO; o += OneMeg)
.
70c
/* map low mem (I really don't know why I have to do this -- presotto) */
.
55d
53a
static int mmuinited;
.
## diffname bitsy/mmu.c 2000/1121
## diff -e /n/emeliedump/2000/1118/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1121/sys/src/9/bitsy/mmu.c
216,217c
ulong l1, l2;
if(cached){
l1 = L1KernelRW|L1Cached|L1Buffered;
l2 = L2KernelRW|L2Cached|L2Buffered;
} else {
l1 = L1KernelRW;
l2 = L2KernelRW;
}
return _map(pa, len, EMEMZERO, EMEMTOP, l1, l2);
.
214c
mapmem(ulong pa, int len, int cached)
.
## diffname bitsy/mmu.c 2000/1130
## diff -e /n/emeliedump/2000/1121/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1130/sys/src/9/bitsy/mmu.c
81a
/* uncached DRAM */
for(o = 0; o < UCDRAMTOP-UCDRAMZERO; o += OneMeg)
l1table[(UCDRAMZERO+o)>>20] = L1Section | L1KernelRW| L1Domain0
| ((PHYSDRAM0+o)&L1SectBaseMask);
.
## diffname bitsy/mmu.c 2001/0810
## diff -e /n/emeliedump/2000/1130/sys/src/9/bitsy/mmu.c /n/emeliedump/2001/0810/sys/src/9/bitsy/mmu.c
124,125d
112a
mmurestart();
mmuinited = 1;
}
void
mmurestart(void) {
.
## diffname bitsy/mmu.c 2001/0813
## diff -e /n/emeliedump/2001/0810/sys/src/9/bitsy/mmu.c /n/emeliedump/2001/0813/sys/src/9/bitsy/mmu.c
127a
icacheinvalidate(); /* you never know ... (sape) */
.
## diffname bitsy/mmu.c 2001/0814
## diff -e /n/emeliedump/2001/0813/sys/src/9/bitsy/mmu.c /n/emeliedump/2001/0814/sys/src/9/bitsy/mmu.c
128d
120a
.
## diffname bitsy/mmu.c 2001/0815
## diff -e /n/emeliedump/2001/0814/sys/src/9/bitsy/mmu.c /n/emeliedump/2001/0815/sys/src/9/bitsy/mmu.c
263c
ulong
.
|