From c18632de75e162659987b1ccc4e5586de3fde01e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 11 Oct 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-10-11 --- bitsy/dat.h | 14 +++-- bitsy/main.c | 94 +++++++++++++++++++++++++++++- bitsy/mem.h | 15 +++-- bitsy/mmu.c | 161 +++++++++++++++++++++++++++++++++++++++------------ pc/ns16552.h | 12 +++- 5 files changed, 245 insertions(+), 51 deletions(-) diff --git a/bitsy/dat.h b/bitsy/dat.h index 1283184bfe313f8eddae1e076d1abe22779dbfe1..4b6bc9e443b559033c808dcc0cbd0ebd75baa40f 100644 --- a/bitsy/dat.h +++ b/bitsy/dat.h @@ -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 diff --git a/bitsy/main.c b/bitsy/main.c index e48f06796f81c61cff247bfe2e6685530d24e401..4f67b0224db04c17fb60032fdbd9573ad4b93907 100644 --- a/bitsy/main.c +++ b/bitsy/main.c @@ -32,9 +32,10 @@ main(void) gpioinit(); trapinit(); clockinit(); - spllo(); - delay(1000); - exit(1); + chandevreset(); + pageinit(); + userinit(); + schedinit(); } /* @@ -54,6 +55,93 @@ exit(int ispanic) (*f)(); } +/* + * 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 */ diff --git a/bitsy/mem.h b/bitsy/mem.h index 0a6108807d5bec0c47e22ba9df9db22bef27eb45..75a3a494870e5a98703a9ec2f4cc06d96bf62613 100644 --- a/bitsy/mem.h +++ b/bitsy/mem.h @@ -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) diff --git a/bitsy/mmu.c b/bitsy/mmu.c index cffe10a9bb6afd989fb5e82d1ca37acd7869b6bc..cbb325f9dbef49cba2332b063b3a8567fffc0a00 100644 --- a/bitsy/mmu.c +++ b/bitsy/mmu.c @@ -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<>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); } diff --git a/pc/ns16552.h b/pc/ns16552.h index 407067d37cf8aa82fd375e098b0066ad0adda0df..6a14f387db141221c771e2cdb1cd8161a8ec390b 100644 --- a/pc/ns16552.h +++ b/pc/ns16552.h @@ -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 */