M bitsy/dat.h => bitsy/dat.h +10 -4
@@ 72,10 72,16 @@ struct Conf
/*
* MMU stuff in proc
*/
-#define NCOLOR 1
+enum
+{
+ NCOLOR= 1, /* 1 level cache, don't worry about VCE's */
+ Nmeg= 32, /* maximum size of user space */
+};
+
struct PMMU
{
- int dummy;
+ ulong pid; /* current pid (0 if none) */
+ Page *l1[Nmeg]; /* this's process' level 1 entries */
};
/*
@@ 159,11 165,11 @@ struct Cycintr
};
/*
- * Fake kmap
+ * Fake kmap since we direct map dram
*/
typedef void KMap;
#define VA(k) ((ulong)(k))
-#define kmap(p) (KMap*)((p)->pa|KZERO)
+#define kmap(p) (KMap*)((p)->pa)
#define kunmap(k)
struct
M bitsy/main.c => bitsy/main.c +91 -3
@@ 32,9 32,10 @@ main(void)
gpioinit();
trapinit();
clockinit();
- spllo();
- delay(1000);
- exit(1);
+ chandevreset();
+ pageinit();
+ userinit();
+ schedinit();
}
/*
@@ 55,6 56,93 @@ exit(int ispanic)
}
/*
+ * starting place for first process
+ */
+void
+init0(void)
+{
+ up->nerrlab = 0;
+
+ spllo();
+
+ /*
+ * These are o.k. because rootinit is null.
+ * Then early kproc's will have a root and dot.
+ */
+ up->slash = namec("#/", Atodir, 0, 0);
+ cnameclose(up->slash->name);
+ up->slash->name = newcname("/");
+ up->dot = cclone(up->slash, 0);
+
+ chandevinit();
+
+ if(!waserror()){
+ ksetenv("terminal", "bitsy");
+ ksetenv("cputype", "arm");
+ if(cpuserver)
+ ksetenv("service", "cpu");
+ else
+ ksetenv("service", "terminal");
+ poperror();
+ }
+ kproc("alarm", alarmkproc, 0);
+
+ touser();
+}
+
+/*
+ * create the first process
+ */
+void
+userinit(void)
+{
+ Proc *p;
+ Segment *s;
+ KMap *k;
+ Page *pg;
+
+ p = newproc();
+ p->pgrp = newpgrp();
+ p->egrp = smalloc(sizeof(Egrp));
+ p->egrp->ref = 1;
+ p->fgrp = dupfgrp(nil);
+ p->rgrp = newrgrp();
+ p->procmode = 0640;
+
+ strcpy(p->text, "*init*");
+ strcpy(p->user, eve);
+
+ /*
+ * Kernel Stack
+ */
+ p->sched.pc = (ulong)init0;
+ p->sched.sp = (ulong)p->kstack+KSTACK-(1+MAXSYSARG)*BY2WD;
+
+ /*
+ * User Stack
+ */
+ s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
+ p->seg[SSEG] = s;
+ pg = newpage(1, 0, USTKTOP-BY2PG);
+ segpage(s, pg);
+
+ /*
+ * Text
+ */
+ s = newseg(SG_TEXT, UTZERO, 1);
+ s->flushme++;
+ p->seg[TSEG] = s;
+ pg = newpage(1, 0, UTZERO);
+ memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
+ segpage(s, pg);
+ k = kmap(s->map[0]->pages[0]);
+ memmove((ulong*)VA(k), initcode, sizeof initcode);
+ kunmap(k);
+
+ ready(p);
+}
+
+/*
* set mach dependent process state for a new process
*/
void
M bitsy/mem.h => bitsy/mem.h +10 -5
@@ 45,11 45,16 @@
#define UTZERO (UZERO+BY2PG) /* first address in user text */
#define KZERO 0xC0000000 /* base of kernel address space */
#define KTZERO 0xC0008000 /* first address in kernel text */
-#define REGZERO 0xA0000000 /* 256 meg for special regs */
-#define REGTOP 0xB0000000 /* 256 meg for special regs */
-#define FLASHZERO 0xB0000000 /* 256 meg for flash */
-#define USTKTOP (REGZERO-BY2PG) /* byte just beyond user stack */
-#define USTKSIZE (16*1024*1024) /* size of user stack */
+#define REGZERO 0xA0000000 /* 256 meg for mapspecial regs */
+#define REGTOP 0xB0000000 /* ... */
+#define FLASHZERO 0xB0000000 /* 128 meg for flash */
+#define FLASHTOP 0xB8000000 /* ... */
+#define DRAMZERO 0xC0000000 /* 128 meg for memory */
+#define DRAMTOP 0xC8000000 /* ... */
+#define NULLZERO 0xE0000000 /* 128 meg for cache flush zeroes */
+#define NULLTOP 0xE8000000 /* ... */
+#define USTKTOP 0x2000000 /* byte just beyond user stack */
+#define USTKSIZE (8*1024*1024) /* size of user stack */
#define TSTKTOP (USTKTOP-USTKSIZE) /* end of new stack in sysexec */
#define TSTKSIZ 100
#define MACHADDR (KZERO+0x00001000)
M bitsy/mmu.c => bitsy/mmu.c +125 -36
@@ 7,6 7,14 @@
#include "ureg.h"
#include "../port/error.h"
+/*
+ * 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.
+ */
+
/* real protection bits */
enum
{
@@ 17,7 25,8 @@ enum
L1Section= (2<<0),
L1Cached= (1<<3),
L1Buffered= (1<<2),
- L1Domain0= (0<<5),
+ L1DomShift= 5,
+ L1Domain0= (0<<L1DomShift),
L1KernelRW= (0x1<<10),
L1UserRO= (0x2<<10),
L1UserRW= (0x3<<10),
@@ 34,22 43,11 @@ enum
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,
+ /* domain values */
+ Dnoaccess= 0,
+ Dclient= 1,
+ Dmanager= 3,
};
ulong *l1table;
@@ 62,27 60,35 @@ ulong *l1table;
void
mmuinit(void)
{
- ulong a, e;
+ ulong a, o;
ulong *t;
/* get a prototype level 1 page */
l1table = xspanalloc(16*1024, 16*1024, 0);
memset(l1table, 0, 16*1024);
- /* direct map DRAM */
- e = conf.base1 + BY2PG*conf.npage1;
- for(a = PHYSDRAM0; a < e; a += OneMeg)
- l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask) |
- L1Cached | L1Buffered;
+ /* map DRAM */
+ for(o = 0; o < DRAMTOP; o += OneMeg)
+ l1table[(DRAMZERO+o)>>20] = L1Section | L1KernelRW| L1Domain0
+ | L1Cached | L1Buffered
+ | ((PHYSDRAM0+o)&L1SectBaseMask);
+
+ /* map zeros area */
+ for(o = 0; o < 128 * OneMeg; o += OneMeg)
+ l1table[(NULLZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0
+ | ((PHYSNULL0+o)&L1SectBaseMask);
- /* direct map zeros area */
- for(a = PHYSNULL0; a < PHYSNULL0 + 128 * OneMeg; a += OneMeg)
- l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask);
+ /* map flash */
+ for(o = 0; o < 128 * OneMeg; o += OneMeg)
+ l1table[(FLASHZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0
+ | L1Cached | L1Buffered
+ | ((PHYSFLASH0+o)&L1SectBaseMask);
- /* direct map flash */
- for(a = PHYSFLASH0; a < PHYSFLASH0 + 128 * OneMeg; a += OneMeg)
- l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask) |
- L1Cached | L1Buffered;
+ /* map peripheral control module regs */
+ mapspecial(0x80000000, OneMeg);
+
+ /* map system control module regs */
+ mapspecial(0x90000000, OneMeg);
/*
* double map start of ram to exception vectors
@@ 95,7 101,7 @@ mmuinit(void)
/* set up the domain register to cause all domains to obey pte access bits */
iprint("setting up domain access\n");
- putdac(0xFFFFFFFF);
+ putdac(Dclient);
/* point to map */
iprint("setting tlb map %lux\n", (ulong)l1table);
@@ 137,7 143,7 @@ mapspecial(ulong pa, int len)
if(livelarge){
if(rv == nil)
rv = (ulong*)(va+off);
- l1table[va>>20] = L1Section | L1KernelRW |
+ l1table[va>>20] = L1Section | L1KernelRW | L1Domain0 |
(base & L1SectBaseMask);
base += OneMeg;
continue;
@@ 151,6 157,13 @@ mapspecial(ulong pa, int len)
}
break;
case L1Section:
+ /* 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)));
+
continue;
case L1PageTable:
if(livelarge)
@@ 182,20 195,96 @@ mapspecial(ulong pa, int len)
return rv;
}
+/*
+ * 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
+ */
void
putmmu(ulong va, ulong pa, Page*)
{
- USED(va, pa);
+ 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();
}
+/*
+ * this is called with palloc locked so the pagechainhead is kosher
+ */
void
-mmurelease(Proc* proc)
+mmurelease(Proc* p)
{
- USED(proc);
+ 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;
+ }
}
void
-mmuswitch(Proc* proc)
+mmuswitch(Proc* p)
{
- USED(proc);
+ /* 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);
}
M pc/ns16552.h => pc/ns16552.h +9 -3
@@ 104,7 104,7 @@ ns16552default(char *name, int port, int irq)
void
ns16552install(void)
{
- int i, j, port, nscard;
+ int i, j, port, nscard, baud;
char *p, *q;
Scard *sc;
char name[NAMELEN];
@@ 123,8 123,14 @@ ns16552install(void)
/* set up a serial console */
if(p = getconf("console")){
port = strtol(p, &q, 0);
- if(p != q && (port == 0 || port == 1))
- ns16552special(port, 9600, &kbdq, &printq, kbdcr2nl);
+ if(p != q && (port == 0 || port == 1)) {
+ baud = 0;
+ if(p = getconf("baud"))
+ baud = strtoul(p, 0, 0);
+ if(baud == 0)
+ baud = 9600;
+ ns16552special(port, baud, &kbdq, &printq, kbdcr2nl);
+ }
}
/* the rest come out of plan9.ini */