From fcf95869e73b7416517583b51bbf3e9694beb5f4 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 18 Jul 1991 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1991-07-18 --- gnot/lib.h | 2 +- gnot/trap.c | 2 +- pc/dat.h | 8 ++-- pc/fault386.c | 27 +++++++++-- pc/fns.h | 10 ++-- pc/l.s | 40 ++++++++++------ pc/main.c | 18 ++++--- pc/mem.h | 29 ++++++----- pc/mmu.c | 130 +++++++++++++++++++++++++++++++++++++++++++------- pc/trap.c | 26 +++++++++- port/fault.c | 4 +- port/lib.h | 2 +- port/page.c | 2 +- power/trap.c | 2 +- ss/trap.c | 2 +- 15 files changed, 232 insertions(+), 72 deletions(-) diff --git a/gnot/lib.h b/gnot/lib.h index 6c6a30ddadc54aa4b368979a58a37aed8433f95c..a0a615a37d63ff35c2cd70adf1ffcc9bf47a3f01 100644 --- a/gnot/lib.h +++ b/gnot/lib.h @@ -75,7 +75,7 @@ extern long end; #define ORCLOSE 64 /* or'ed in, remove on close */ #define NCONT 0 /* continue after note */ -#define NTERM 1 /* terminate after note */ +#define NDFLT 1 /* terminate after note */ typedef struct Qid Qid; typedef struct Dir Dir; diff --git a/gnot/trap.c b/gnot/trap.c index 21661c136f1ad08d40963a87a56e90d82aa588a1..4fbcff4017d62bb05730b736b166c316ca952141 100644 --- a/gnot/trap.c +++ b/gnot/trap.c @@ -216,7 +216,7 @@ noted(Ureg *ur, ulong arg0) u->lastnote.flag = NDebug; /* fall through */ - case NTERM: + case NDFLT: if(u->lastnote.flag == NDebug) pprint("suicide: %s\n", u->lastnote.msg); unlock(&u->p->debug); diff --git a/pc/dat.h b/pc/dat.h index 98a43e6d521c6ed9a94e6b769f4c05e7394ba175..b445a294d057253d9867f84954e4d1bb46434922 100644 --- a/pc/dat.h +++ b/pc/dat.h @@ -98,10 +98,12 @@ struct Conf * MMU stuff in proc */ #define MAXMMU 4 +#define MAXSMMU 1 struct PMMU { - ulong mmuent[MAXMMU]; /* a process' mmu entries */ - Page *mmupg[MAXMMU]; /* mmu pages */ + int mmuvalid; + Page *mmu[MAXMMU+MAXSMMU]; /* bottom level page tables */ + ulong mmue[MAXMMU+MAXSMMU]; /* top level pointers to mmup pages */ }; #include "../port/portdat.h" @@ -138,7 +140,7 @@ struct Mach */ typedef void KMap; #define VA(k) ((ulong)(k)) -#define kmap(p) (KMap*)(p->pa|KZERO) +#define kmap(p) (KMap*)((p)->pa|KZERO) #define kunmap(k) #define NERR 15 diff --git a/pc/fault386.c b/pc/fault386.c index 10693c08494a51a88e3801307cb8418dd122d965..4ea534eed3f439b7df948a59b2d6eae14597cf84 100644 --- a/pc/fault386.c +++ b/pc/fault386.c @@ -7,13 +7,32 @@ #include "io.h" void -faultinit(void) +fault386(Ureg *ur) { - setvec(Faultvec, fault386); + ulong addr; + int read; + int user; + +print("fault386\n"); +dumpregs(ur); +for(;;); + addr = getcr2(); + read = !(ur->ecode & 2); + user = (ur->ecode & 4); + if(fault(addr, read) < 0){ + if(user){ + pprint("user %s error addr=0x%lux\n", read? "read" : "write", addr); + pprint("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->flags, ur->pc, ur->usp); + pexit("Suicide", 0); + } + u->p->state = MMUing; + dumpregs(ur); + panic("fault: 0x%lux", addr); + } } void -fault386(Ureg *ur) +faultinit(void) { - panic("fault"); + setvec(Faultvec, fault386); } diff --git a/pc/fns.h b/pc/fns.h index dc98a71f75862f07572c506edfbad63d478398bc..694d08b63b523510498e078fc773797ca5c03c8a 100644 --- a/pc/fns.h +++ b/pc/fns.h @@ -6,6 +6,7 @@ void clockinit(void); void delay(int); #define evenaddr(x) /* 386 doesn't care */ void fault386(Ureg*); +void faultinit(void); void floppyinit(void); void floppyintr(Ureg*); long floppyseek(int, long); @@ -13,6 +14,7 @@ long floppyread(int, void*, long); #define flushvirt(); void fpsave(FPsave*); void fprestore(FPsave*); +ulong getcr2(void); void idle(void); int inb(int); void intr0(void); @@ -43,16 +45,16 @@ void intr64(void); void intrbad(void); void kbdinit(void); void kbdintr(Ureg*); -void lgdt(Segdesc*, int); -void lidt(Segdesc*, int); -void lcr3(ulong); -void ltr(ulong); void mmuinit(void); void outb(int, int); void prhex(ulong); void procrestore(Proc*, uchar*); void procsave(uchar*, int); void procsetup(Proc*); +void putgdt(Segdesc*, int); +void putidt(Segdesc*, int); +void putcr3(ulong); +void puttr(ulong); void screeninit(void); void screenputc(int); void screenputs(char*, int); diff --git a/pc/l.s b/pc/l.s index ca822f1750f3d3802a9bceb0b6c91ec5d81618d2..8b7a16167b2761b948c54c2096826848fbe54302 100644 --- a/pc/l.s +++ b/pc/l.s @@ -215,10 +215,10 @@ TEXT tas(SB),$0 RET /* - * routines to load various system registers + * routines to load/read various system registers */ GLOBL idtptr(SB),$6 -TEXT lidt(SB),$0 +TEXT putidt(SB),$0 /* interrupt descriptor table */ MOVL t+0(FP),AX MOVL AX,idtptr+2(SB) MOVL l+4(FP),AX @@ -227,7 +227,7 @@ TEXT lidt(SB),$0 RET GLOBL gdtptr(SB),$6 -TEXT lgdt(SB),$0 +TEXT putgdt(SB),$0 /* global descriptor table */ MOVL t+0(FP),AX MOVL AX,gdtptr+2(SB) MOVL l+4(FP),AX @@ -235,16 +235,20 @@ TEXT lgdt(SB),$0 MOVL gdtptr(SB),GDTR RET -TEXT lcr3(SB),$0 +TEXT putcr3(SB),$0 /* top level page table pointer */ MOVL t+0(FP),AX MOVL AX,CR3 RET -TEXT ltr(SB),$0 +TEXT puttr(SB),$0 /* task register */ MOVL t+0(FP),AX MOVW AX,TASK RET +TEXT getcr2(SB),$0 /* fault address */ + MOVL CR2,AX + RET + /* * special traps */ @@ -350,6 +354,8 @@ TEXT intrbad(SB),$0 intrcommon: PUSHL DS PUSHAL + MOVL $(KDSEL),AX + MOVW AX,DS LEAL 0(SP),AX PUSHL AX CALL trap(SB) @@ -358,11 +364,12 @@ intrcommon: POPL DS ADDL $8,SP /* error code and trap type */ IRETL - RET /* this has to be here because of ken */ intrscommon: PUSHL DS PUSHAL + MOVL $(KDSEL),AX + MOVW AX,DS LEAL 0(SP),AX PUSHL AX CALL trap(SB) @@ -371,7 +378,6 @@ intrscommon: POPL DS ADDL $8,SP /* error code and trap type */ IRETL - RET /* this has to be here because of ken */ /* * interrupt level is interrupts on or off @@ -409,6 +415,7 @@ TEXT gotolabel(SB),$0 MOVL 0(AX),SP /* restore sp */ MOVL 4(AX),AX /* put return pc on the stack */ MOVL AX,0(SP) + MOVL $1,AX /* return 1 */ RET TEXT setlabel(SB),$0 @@ -416,17 +423,20 @@ TEXT setlabel(SB),$0 MOVL SP,0(AX) /* store sp */ MOVL 0(SP),BX /* store return pc */ MOVL BX,4(AX) + MOVL $0,AX /* return 0 */ RET +/* + * Used to get to the first process. + * Set up an interrupt return frame and IRET to user level. + */ TEXT touser(SB),$0 - MOVL $(USERADDR+BY2PG-6*BY2WD),AX - MOVL $(UTZERO+32),0(AX) /* header is in text */ - MOVL $(UESEL),4(AX) - MOVL $(IFLAG|2),8(AX) - MOVL $(USTKTOP-4*BY2WD),12(AX) - MOVL $(UDSEL),16(AX) - MOVL AX,SP - MOVL $(UDSEL),AX /* set up data segment */ + PUSHL $(UDSEL) /* old ss */ + PUSHL $(USTKTOP-4*BY2WD) /* old sp */ + PUSHFL /* old flags */ + PUSHL $(UESEL) /* old cs */ + PUSHL $(UTZERO+32) /* old pc */ + MOVL $(UDSEL),AX /* set up user's data segment */ MOVW AX,DS IRETL diff --git a/pc/main.c b/pc/main.c index fe241f4ee27becaccdd34d557c65c7917020a3e9..3cfc95e93bc21e2e2ba344c9356b170f76532bb2 100644 --- a/pc/main.c +++ b/pc/main.c @@ -17,19 +17,17 @@ main(void) confinit(); screeninit(); printinit(); - print("%d pages in bank0, %d pages in bank1\n", conf.npage0, conf.npage1); - print("edata == %lux, end == %lux\n", &edata, &end); mmuinit(); -print("mmu inited\n"); + trapinit(); + clockinit(); + faultinit(); procinit0(); -print("proc inited\n"); initseg(); grpinit(); chaninit(); alarminit(); chandevreset(); streaminit(); - trapinit(); swapinit(); pageinit(); userinit(); @@ -54,6 +52,8 @@ machinit(void) active.machs = 1; } +long useless; + void init0(void) { @@ -65,6 +65,7 @@ init0(void) u->p->mach = m; spllo(); +print("interrupts on\n"); /* * These are o.k. because rootinit is null. @@ -74,8 +75,13 @@ init0(void) u->dot = clone(u->slash, 0); chandevinit(); +print("going to user\n"); + + /* + * fault in the first executable page + */ + useless = *((ulong *)UTZERO); -/* kickpager(); /* BUG */ touser(); } diff --git a/pc/mem.h b/pc/mem.h index 3b0a78f9ad0f3f8faea3dc310dec4bdfe58b848d..99de95e59783ed1065acc136824407743adcb8bd 100644 --- a/pc/mem.h +++ b/pc/mem.h @@ -27,23 +27,28 @@ /* * Fundamental addresses */ -#define USERADDR 0xC0000000 -#define UREGADDR (USERADDR+BY2PG-4*16) /* - * Address spaces + * Address spaces * - * User is at 0-2GB - * Kernel is at 2GB-4GB + * User is at 0-2GB + * Kernel is at 2GB-4GB + * + * To avoid an extra page map, both the user stack (USTKTOP) and + * the temporary user stack (TSTKTOP) should be in the the same + * 4 meg. */ -#define UZERO 0 /* base of user address space */ -#define UTZERO (UZERO+BY2PG) /* first address in user text */ -#define TSTKTOP USERADDR /* end of new stack in sysexec */ +#define UZERO 0 /* base of user address space */ +#define UTZERO (UZERO+BY2PG) /* first address in user text */ +#define KZERO 0x80000000 /* base of kernel address space */ +#define KTZERO KZERO /* first address in kernel text */ +#define USERADDR 0xC0000000 /* struct User */ +#define UREGADDR (USERADDR+BY2PG-4*16) +#define TSTKTOP USERADDR /* end of new stack in sysexec */ #define TSTKSIZ 10 -#define USTKTOP (TSTKTOP-TSTKSIZ*BY2PG) /* byte just beyond user stack */ -#define KZERO 0x80000000 /* base of kernel address space */ -#define KTZERO KZERO /* first address in kernel text */ -#define USTKSIZE (4*1024*1024) /* size of user stack */ +#define USTKTOP (TSTKTOP-TSTKSIZ*BY2PG) /* byte just beyond user stack */ +#define USTKSIZE (4*1024*1024 - TSTKSIZ*BY2PG) /* size of user stack */ +#define USTKBTM USTKTOP - USTKSIZE #define MACHSIZE 4096 diff --git a/pc/mmu.c b/pc/mmu.c index 35197efb75febbf88f009564e086ac45a8026f79..b58f050f5276d42b4b2b7d2bb879e414fcf4a259 100644 --- a/pc/mmu.c +++ b/pc/mmu.c @@ -76,6 +76,17 @@ static ulong *kpt; /* kernel level page tables */ static ulong *upt; /* page table for struct User */ #define ROUNDUP(s,v) (((s)+(v-1))&~(v-1)) +/* + * offset of virtual address into + * top level page table + */ +#define TOPOFF(v) ((v)>>(2*PGSHIFT-2)) + +/* + * offset of virtual address into + * bottom level page table + */ +#define BTMOFF(v) (((v)>>(PGSHIFT))&(BY2PG-1)) void mmuinit(void) @@ -90,10 +101,10 @@ mmuinit(void) x = (ulong)systrap; gdt[SYSGATE].d0 = (x&0xFFFF)|(KESEL<<16); gdt[SYSGATE].d1 = (x&0xFFFF0000)|SEGP|SEGPL(3)|SEGCG; - x = (long)&tss; + x = (ulong)&tss; gdt[TSSSEG].d0 = (x<<16)|sizeof(Tss); gdt[TSSSEG].d1 = (x&0xFF000000)|((x>>16)&0xFF)|SEGTSS|SEGPL(0)|SEGP; - lgdt(gdt, sizeof gdt); + putgdt(gdt, sizeof gdt); /* * set up system page tables. @@ -107,59 +118,142 @@ mmuinit(void) kpt = ialloc(nkpt*BY2PG, 1); n = ROUNDUP(conf.npage0+conf.npage1, 1*1024*1024); n = n/(4*1024); - for(i = 0; i < n; i++){ - kpt[i] = (i< */ upt = ialloc(BY2PG, 1); /* allocate top level table and put pointers to lower tables in it */ toppt = ialloc(BY2PG, 1); - x = KZERO>>(2*PGSHIFT-2); + x = TOPOFF(KZERO); y = ((ulong)kpt)&~KZERO; - for(i = 0; i < nkpt; i++){ -/* toppt[i] = (y+i*BY2PG)|PTEVALID|PTEKERNEL|PTEWRITE;/**/ - toppt[x+i] = (y+i*BY2PG)|PTEVALID|PTEKERNEL|PTEWRITE; - } - x = USERADDR>>(2*PGSHIFT-2); + for(i = 0; i < nkpt; i++) + toppt[x+i] = (y+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE; + x = TOPOFF(USERADDR); y = ((ulong)upt)&~KZERO; - toppt[x] = y|PTEVALID|PTEKERNEL|PTEWRITE; - lcr3(((ulong)toppt)&~KZERO); + toppt[x] = y | PTEVALID | PTEKERNEL | PTEWRITE; + putcr3(((ulong)toppt)&~KZERO); /* * set up the task segment */ - tss.sp0 = USERADDR; + tss.sp0 = USERADDR+BY2PG; tss.ss0 = KDSEL; tss.cr3 = (ulong)toppt; - ltr(TSSSEL); + puttr(TSSSEL); } void mapstack(Proc *p) { - + ulong tlbphys; + int i; + +print("mapstack\n"); + + if(p->upage->va != (USERADDR|(p->pid&0xFFFF))) + panic("mapstack %d 0x%lux 0x%lux", p->pid, p->upage->pa, p->upage->va); + + /* + * dump any invalid mappings + */ + if(p->mmuvalid == 0){ + for(i = 0; i < MAXMMU+MAXSMMU; i++){ + if(p->mmu[i]==0) + continue; + memset(kmap(p->mmu[i]), 0, BY2PG); + } + p->mmuvalid = 1; + } + + /* + * point top level page table to bottom level ones + */ + memmove(toppt, p->mmu, MAXMMU*sizeof(ulong)); + memmove(&toppt[TOPOFF(USTKBTM)], &p->mmu[MAXMMU], MAXSMMU*sizeof(ulong)); + + /* map in u area */ + upt[0] = PPN(p->upage->pa) | PTEVALID | PTEKERNEL | PTEWRITE; + + /* flush cached mmu entries */ + putcr3(((ulong)toppt)&~KZERO); + + u = (User*)USERADDR; } void flushmmu(void) { + int s; + + if(u == 0) + return; + + u->p->mmuvalid = 0; + s = splhi(); + mapstack(u->p); + splx(s); } void mmurelease(Proc *p) { + p->mmuvalid = 0; } void -putmmu(ulong x, ulong y, Page *z) +putmmu(ulong va, ulong pa, Page *pg) { + int topoff; + ulong *pt; + Proc *p; + int i; + +print("putmmu %lux %lux USTKTOP %lux\n", va, pa, USTKTOP); /**/ + if(u==0) + panic("putmmu"); + p = u->p; + + /* + * check for exec/data vs stack vs illegal + */ + topoff = TOPOFF(va); + if(topoff < TOPOFF(TSTKTOP) && topoff >= TOPOFF(USTKBTM)) + i = MAXMMU + topoff - TOPOFF(USTKBTM); + else if(topoff < MAXMMU) + i = topoff; + else + panic("putmmu bad addr %lux", va); + + /* + * if bottom level page table missing, allocate one + */ + pg = p->mmu[i]; + if(pg == 0){ + pg = p->mmu[i] = newpage(1, 0, 0); + p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEKERNEL | PTEWRITE; + toppt[topoff] = p->mmue[i]; + } + + /* + * fill in the bottom level page table + */ + pt = (ulong*)(p->mmu[i]->pa|KZERO); + pt[BTMOFF(va)] = pa | PTEUSER; + + /* flush cached mmu entries */ + putcr3(((ulong)toppt)&~KZERO); } void invalidateu(void) { + /* unmap u area */ + upt[0] = 0; + + /* flush cached mmu entries */ + putcr3(((ulong)toppt)&~KZERO); } void @@ -177,5 +271,5 @@ exit(void) print("exiting\n"); for(i = 0; i < WD2PG; i++) toppt[i] = 0; - lcr3(((ulong)toppt)&~KZERO); + putcr3(((ulong)toppt)&~KZERO); } diff --git a/pc/trap.c b/pc/trap.c index 7ef58567c6fa250d05e3a79a90fe3d947ed94ff7..fffbd272a28c889ae2bc41409cda9ac3542fe92e 100644 --- a/pc/trap.c +++ b/pc/trap.c @@ -86,7 +86,7 @@ trapinit(void) sethvec(23, intr23, SEGTG, 0); /* - * set all others to unknown + * set all others to unknown interrupts */ for(i = 24; i < 256; i++) sethvec(i, intrbad, SEGIG, 0); @@ -100,7 +100,7 @@ trapinit(void) /* * tell the hardware where the table is (and how long) */ - lidt(ilt, sizeof(ilt)); + putidt(ilt, sizeof(ilt)); /* * Set up the first 8259 interrupt processor. @@ -136,12 +136,34 @@ trap(Ureg *ur) outb(Int0ctl, EOI); } +/* + * dump registers + */ +void +dumpregs(Ureg *ur) +{ + if(u) + print("registers for %s %d\n", u->p->text, u->p->pid); + else + print("registers for kernel\n"); + print("FLAGS=%lux ECODE=%lux CS=%lux PC=%lux SS=%lux USP=%lux\n", ur->flags, + ur->ecode, ur->cs, ur->pc, ur->ss, ur->usp); + + print(" AX %8.8lux BX %8.8lux CX %8.8lux DX %8.8lux\n", + ur->ax, ur->bx, ur->cx, ur->dx); + print(" SI %8.8lux DI %8.8lux BP %8.8lux DS %8.8lux\n", + ur->si, ur->di, ur->bp, ur->ds); +} + /* * system calls */ long syscall(Ureg *ur) { + u->p->insyscall = 1; + u->p->pc = ur->pc; + panic("syscall"); } diff --git a/port/fault.c b/port/fault.c index 11084e93a33146371721812dbc8186c219fa4fc4..24046478823bbc15d7c9a8d59c4ea1c0425f5d1c 100644 --- a/port/fault.c +++ b/port/fault.c @@ -103,8 +103,8 @@ again: } qunlock(&s->lk); - if(new) - putpage(new); + if(new) /* A race may provide a page we never used when + putpage(new); * a fault is fixed while process slept in newpage */ putmmu(addr, mmuphys, *pg); return 0; diff --git a/port/lib.h b/port/lib.h index d7be09489f12e9bf2285007a52b3a3a5890c5dd8..22773873ff3042156fda719b525babc5fd739dc5 100644 --- a/port/lib.h +++ b/port/lib.h @@ -75,7 +75,7 @@ extern long end; #define ORCLOSE 64 /* or'ed in, remove on close */ #define NCONT 0 /* continue after note */ -#define NTERM 1 /* terminate after note */ +#define NDFLT 1 /* terminate after note */ typedef struct Qid Qid; typedef struct Dir Dir; diff --git a/port/page.c b/port/page.c index 7715e37497350b529918a9ec55f84afba13bc311..2299aabb6cc0fba69895f916d7502b8f1dc98211 100644 --- a/port/page.c +++ b/port/page.c @@ -296,7 +296,7 @@ copypage(Page *f, Page *t) } void -uncachepage(Page *p) /* Alway called with a locked page */ +uncachepage(Page *p) /* Always called with a locked page */ { Page **l, *f; diff --git a/power/trap.c b/power/trap.c index ad93269b9099df2ff7bd48582fd56ace8fd48d55..b5ae91d6f027d1eaca4d20a1e9a714b5b6759c56 100644 --- a/power/trap.c +++ b/power/trap.c @@ -451,7 +451,7 @@ noted(Ureg **urp, ulong arg0) u->lastnote.flag = NDebug; /* fall through */ - case NTERM: + case NDFLT: if(u->lastnote.flag == NDebug) pprint("suicide: %s\n", u->lastnote.msg); unlock(&u->p->debug); diff --git a/ss/trap.c b/ss/trap.c index 671219b6771b86ff2ef34d71799ee26207e3122b..846d4708b05406da5fda29c16925a4a53352e4f5 100644 --- a/ss/trap.c +++ b/ss/trap.c @@ -290,7 +290,7 @@ noted(Ureg **urp, ulong arg0) u->lastnote.flag = NDebug; /* fall through */ - case NTERM: + case NDFLT: if(u->lastnote.flag == NDebug) pprint("suicide: %s\n", u->lastnote.msg); unlock(&u->p->debug);