#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"
/* real protection bits */
enum
{
/* 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),
};
/*
* table to map fault.c bits to physical bits
*/
static ulong phystrans[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,
};
ulong *l1table;
/*
* We map all of memory, flash, and the zeros area with sections.
* Special use space is mapped on the fly with regmap.
*/
void
mmuinit(void)
{
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 */
l1table = xspanalloc(BY2PG, 16*1024, 0);
memset(l1table, 0, BY2PG);
/* 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 physaddr, int len)
{
ulong *t;
ulong virtaddr, i;
/* first see if we've mapped it somewhere, the first hole means we're done */
for(virtaddr = REGZERO; virtaddr < REGTOP; virtaddr += OneMeg){
if((l1table[virtaddr>>20] & L1TypeMask) != L1PageTable){
/* create a page table and break */
t = xspanalloc(BY2PG, 1024, 0);
memzero(t, BY2PG, 0);
l1table[virtaddr>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask);
break;
}
t = (ulong*)(l1table[virtaddr>>20] & L1PTBaseMask);
for(i = 0; i < OneMeg; i += BY2PG){
if((t[virtaddr>>20] & L2TypeMask) != L2SmallPage)
break;
}
if(i < OneMeg){
virtaddr += i;
break;
}
}
/* we get here if no entry was found mapping this physical address */
}
void
putmmu(ulong va, ulong pa, Page*)
{
USED(va, pa);
}
void
mmurelease(Proc* proc)
{
USED(proc);
}
void
mmuswitch(Proc* proc)
{
USED(proc);
}