From 2f75edee410b6b9874fa5cd36888742a9bcab658 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 19 Jul 1991 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1991-07-19 --- gnot/fault68020.c | 9 ++++++--- gnot/l.s | 7 ++++--- gnot/main.c | 2 +- gnot/mem.h | 4 +++- gnot/trap.c | 1 + gnot/ureg.h | 3 ++- pc/clock.c | 14 ++++++++++++++ pc/fault386.c | 19 +++++++++++++++---- pc/fns.h | 1 + pc/headland.c | 41 ++++++++++++++++++++++++++++++++++++++++ pc/kbd.c | 2 +- pc/l.s | 5 +++-- pc/main.c | 32 +++++++++++++++++-------------- pc/mem.h | 8 ++------ pc/mmu.c | 46 ++++++++++++++++++++++----------------------- pc/trap.c | 48 +++++++++++++++++++++++------------------------ port/fault.c | 9 +++++++-- power/boot.c | 3 +-- 18 files changed, 166 insertions(+), 88 deletions(-) create mode 100644 pc/headland.c diff --git a/gnot/fault68020.c b/gnot/fault68020.c index c66fce4d3c5792c9fca0057d3821e2814907b966..4719c9608e8a5679876925b7cfa3da4a8fb3910e 100644 --- a/gnot/fault68020.c +++ b/gnot/fault68020.c @@ -47,6 +47,7 @@ fault68020(Ureg *ur, FFrame *f) { ulong addr, badvaddr; int user, read, insyscall; + char buf[ERRLEN]; if(u == 0){ dumpregs(ur); @@ -88,9 +89,11 @@ fault68020(Ureg *ur, FFrame *f) if(fault(addr, read) < 0){ if(user){ - pprint("user %s error addr=0x%lux\n", read? "read" : "write", badvaddr); - pprint("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->sr, ur->pc, ur->usp); - pexit("Suicide", 0); + sprint(buf, "sys: fault %s pc=0x%lux addr=0x%lux", + read? "read" : "write", ur->pc, badvaddr); + postnote(u->p, 1, buf, NDebug); + notify(ur); + return; } u->p->state = MMUing; dumpregs(ur); diff --git a/gnot/l.s b/gnot/l.s index fd4173f7ab0b43b6d770aa161f7cf78e0d74a093..db3da7f5f1f7642a80a8e88a648956643ce0d04c 100644 --- a/gnot/l.s +++ b/gnot/l.s @@ -29,16 +29,17 @@ dead: BRA dead /* - * Take first processor into user mode + * Take first processor into user mode. Leave enough room on the stack + * for a full-sized Ureg (including long bus error format) to fit */ TEXT touser(SB), $-4 - MOVL $(USERADDR+BY2PG), A7 + MOVL $(USERADDR+BY2PG-UREGVARSZ), A7 MOVW $0, -(A7) MOVL $(UTZERO+32), -(A7) /* header is in text */ MOVW $0, -(A7) - MOVL $(USTKTOP-4*BY2WD), A0 + MOVL $(USTKTOP-6*BY2WD), A0 /* MAXSYSARG=6 */ MOVL A0, USP MOVW $(SUPER|SPL(0)), SR MOVL $8, R0 diff --git a/gnot/main.c b/gnot/main.c index b822e5ecdf7d3f986d86364c568f5bc1ad2ec869..4d851fd538a7e1609a1cd4b2ec18c2bd4348883a 100644 --- a/gnot/main.c +++ b/gnot/main.c @@ -157,7 +157,7 @@ userinit(void) * Kernel Stack */ p->sched.pc = (ulong)init0; - p->sched.sp = USERADDR+BY2PG-MAXSYSARG*BY2WD; + p->sched.sp = USERADDR+BY2PG-5*BY2WD; p->sched.sr = SUPER|SPL(0); p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF)); diff --git a/gnot/mem.h b/gnot/mem.h index 8326620b909afaf96adf32a7bbddd2dbd664f66c..4b55c9af7509f3f00623cfa9a37afa556a9be25e 100644 --- a/gnot/mem.h +++ b/gnot/mem.h @@ -50,7 +50,9 @@ */ #define USERADDR 0x80000000 -#define UREGADDR (USERADDR+BY2PG-(2+4+2+(8+8+1+1)*BY2WD)) +/* assuming we're in a syscall, this is the address of the Ureg structure */ +#define UREGVARSZ (23*BY2WD) /* size of variable part of Ureg */ +#define UREGADDR (USERADDR+BY2PG-(UREGVARSZ+2+4+2+(8+8+1+1)*BY2WD)) /* * Devices poked during bootstrap diff --git a/gnot/trap.c b/gnot/trap.c index 4fbcff4017d62bb05730b736b166c316ca952141..a48ba88e884cdce08ead648c1f5b943033aa922e 100644 --- a/gnot/trap.c +++ b/gnot/trap.c @@ -172,6 +172,7 @@ notify(Ureg *ur) *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */ ur->usp = sp; ur->pc = (ulong)u->notify; + ur->vo = 0x0080; /* pretend we're returning from syscall */ u->notified = 1; u->nnote--; memmove(&u->lastnote, &u->note[0], sizeof(Note)); diff --git a/gnot/ureg.h b/gnot/ureg.h index f3ad7e1fe8243e0685857735a23a0957e1be4f77..737bac7daf7b318b4d32cbaa5e2dd3070ecf5f7a 100644 --- a/gnot/ureg.h +++ b/gnot/ureg.h @@ -17,8 +17,9 @@ struct Ureg ulong a6; ulong sp; ulong usp; - ulong magic; /* for db to find bottom of ureg */ + ulong magic; /* for db to find bottom of ureg */ ushort sr; ulong pc; ushort vo; + uchar microstate[UREGVARSZ]; /* variable-sized portion */ }; diff --git a/pc/clock.c b/pc/clock.c index 8e9aaba2515a5caacdc8641d9aa6016c7b71120b..4b58b2fc1a21d6b3e10405405f2fb66302064302 100644 --- a/pc/clock.c +++ b/pc/clock.c @@ -23,6 +23,20 @@ enum Freq= 1193182, /* Real clock frequency */ }; +/* + * delay for l milliseconds + */ +void +delay(int l) +{ + int i; + + while(--l){ + for(i=0; i < 404; i++) + ; + } +} + void clockinit(void) { diff --git a/pc/fault386.c b/pc/fault386.c index 4ea534eed3f439b7df948a59b2d6eae14597cf84..72ff0917e1cb9db26a5c4eb1db0746fdc90cd49e 100644 --- a/pc/fault386.c +++ b/pc/fault386.c @@ -6,20 +6,30 @@ #include "ureg.h" #include "io.h" +int faulting; + void fault386(Ureg *ur) { ulong addr; int read; int user; + int n; + static int times; -print("fault386\n"); -dumpregs(ur); -for(;;); addr = getcr2(); +print("fault386 %lux ur %lux\n", addr, ur); +dumpregs(ur); +if(++times==3) + panic("3rd time"); + if(faulting) + panic("double fault\n"); + faulting = 1; read = !(ur->ecode & 2); user = (ur->ecode & 4); - if(fault(addr, read) < 0){ + n = fault(addr, read); +print("fault returns %d\n", n); + if(n < 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); @@ -29,6 +39,7 @@ for(;;); dumpregs(ur); panic("fault: 0x%lux", addr); } + faulting = 0; } void diff --git a/pc/fns.h b/pc/fns.h index 694d08b63b523510498e078fc773797ca5c03c8a..2bcc0b7caef1227555502707c4b515dc0f51a0b8 100644 --- a/pc/fns.h +++ b/pc/fns.h @@ -1,5 +1,6 @@ #include "../port/portfns.h" +void a20enable(void); #define clearmmucache() /* 386 doesn't have one */ void clock(Ureg*); void clockinit(void); diff --git a/pc/headland.c b/pc/headland.c new file mode 100644 index 0000000000000000000000000000000000000000..12e875bc56c6d732619d25f7d34f496b4c847b7d --- /dev/null +++ b/pc/headland.c @@ -0,0 +1,41 @@ +#include "u.h" +#include "lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" + +/* + * headland hip set for the safari. + * + * serious magic!!! + */ + +enum +{ + Head= 0x92, /* control port */ + Reset= (1<<0), /* reset the 386 */ + A20ena= (1<<1), /* enable address line 20 */ +}; + +/* + * enable address bit 20 + */ +void +a20enable(void) +{ + outb(Head, A20ena); +} + +/* + * reset the chip + */ +void +exit(void) +{ + int i; + + u = 0; + print("exiting\n"); + delay(5000); + outb(Head, Reset); +} diff --git a/pc/kbd.c b/pc/kbd.c index 72e7c4d15d129b036759809a0eecd2f5e790c60f..d9dc7eadc89fffd6864307514312e973e01355a8 100644 --- a/pc/kbd.c +++ b/pc/kbd.c @@ -257,7 +257,7 @@ kbdintr(Ureg *ur) int keyup; /* - * get a character to be there + * get a character */ c = inb(Data); diff --git a/pc/l.s b/pc/l.s index 8b7a16167b2761b948c54c2096826848fbe54302..47df2b5024c5358a6fcd21a1c3ead7bd60819e98 100644 --- a/pc/l.s +++ b/pc/l.s @@ -432,12 +432,13 @@ TEXT setlabel(SB),$0 */ TEXT touser(SB),$0 PUSHL $(UDSEL) /* old ss */ - PUSHL $(USTKTOP-4*BY2WD) /* old sp */ + PUSHL $(USTKTOP-16) /* old sp */ PUSHFL /* old flags */ PUSHL $(UESEL) /* old cs */ PUSHL $(UTZERO+32) /* old pc */ - MOVL $(UDSEL),AX /* set up user's data segment */ + MOVL $(UDSEL),AX MOVW AX,DS + MOVW AX,ES IRETL /* diff --git a/pc/main.c b/pc/main.c index 3cfc95e93bc21e2e2ba344c9356b170f76532bb2..468e1253fd7cde063fc67d676a3333eeb6db807d 100644 --- a/pc/main.c +++ b/pc/main.c @@ -13,12 +13,14 @@ extern long edata; void main(void) { + a20enable(); machinit(); confinit(); screeninit(); printinit(); mmuinit(); trapinit(); + kbdinit(); clockinit(); faultinit(); procinit0(); @@ -31,7 +33,6 @@ main(void) swapinit(); pageinit(); userinit(); -print("user inited\n"); schedinit(); } @@ -52,7 +53,7 @@ machinit(void) active.machs = 1; } -long useless; +ulong garbage; void init0(void) @@ -64,9 +65,6 @@ init0(void) u->p->state = Running; u->p->mach = m; - spllo(); -print("interrupts on\n"); - /* * These are o.k. because rootinit is null. * Then early kproc's will have a root and dot. @@ -75,12 +73,18 @@ print("interrupts on\n"); u->dot = clone(u->slash, 0); chandevinit(); -print("going to user\n"); /* - * fault in the first executable page + * fault in the first executable page and user stack + */ + print("text is %lux\n", *((ulong *)(UTZERO+32))); + + /* fault in the first stack page */ - useless = *((ulong *)UTZERO); + print("stack is %lux\n", *((ulong *)(USTKTOP-4))); + *((ulong *)(USTKTOP-4)) = 0xdeadbeef; + print("stack is %lux\n", *((ulong *)(USTKTOP-4))); + delay(5000); touser(); } @@ -104,11 +108,12 @@ userinit(void) /* * Kernel Stack * - * N.B. The -4 for the stack pointer is important. Gotolabel - * uses the bottom 4 bytes of stack to store it's return pc. + * N.B. The -12 for the stack pointer is important. + * 4 bytes for gotolabel's return PC + * 8 bytes for optional sp and ss pushed during interrupts */ p->sched.pc = (ulong)init0; - p->sched.sp = USERADDR + BY2PG - 4; + p->sched.sp = USERADDR + BY2PG - 12; p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF)); /* @@ -182,13 +187,13 @@ confinit(void) * the last 128k belongs to the roms */ conf.npage1 = (i)*1024/4; - conf.base1 = 1024/4; + conf.base1 = 1024*1024; conf.npage = conf.npage0 + conf.npage1; conf.maxialloc = (conf.npage0*BY2PG-PGROUND((ulong)&end)); mul = 1; - conf.nproc = 20 + 50*mul; + conf.nproc = 20 + 20*mul; conf.npgrp = conf.nproc/2; conf.nseg = conf.nproc*3; conf.npagetab = (conf.nseg*14)/10; @@ -275,4 +280,3 @@ mouseputc(IOQ *q, int c) { return c; } - diff --git a/pc/mem.h b/pc/mem.h index 99de95e59783ed1065acc136824407743adcb8bd..1d0b12bf93a6b6f1379c1dec56d616b62d45a664 100644 --- a/pc/mem.h +++ b/pc/mem.h @@ -48,7 +48,7 @@ #define TSTKSIZ 10 #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 USTKBTM (USTKTOP - USTKSIZE) #define MACHSIZE 4096 @@ -63,9 +63,7 @@ #define UDSEG 3 /* user data/stack */ #define UESEG 4 /* user executable */ #define SYSGATE 5 /* system call gate */ -#define RDSEG 6 /* reboot data/stack */ -#define RESEG 7 /* reboot executable */ -#define TSSSEG 8 /* task segment */ +#define TSSSEG 6 /* task segment */ #define SELGDT (0<<3) /* selector is in gdt */ #define SELLDT (1<<3) /* selector is in ldt */ @@ -77,8 +75,6 @@ #define KDSEL SELECTOR(KDSEG, SELGDT, 0) #define UESEL SELECTOR(UESEG, SELGDT, 3) #define UDSEL SELECTOR(UDSEG, SELGDT, 3) -#define RDSEL SELECTOR(RDSEG, SELGDT, 0) -#define RESEL SELECTOR(RESEG, SELGDT, 0) #define TSSSEL SELECTOR(TSSSEG, SELGDT, 0) /* diff --git a/pc/mmu.c b/pc/mmu.c index b58f050f5276d42b4b2b7d2bb879e414fcf4a259..ffc66473c651df09976decce6e82d6b3282303be 100644 --- a/pc/mmu.c +++ b/pc/mmu.c @@ -66,8 +66,6 @@ Segdesc gdt[] = [UDSEG] DATASEGM(3), /* user data/stack */ [UESEG] EXECSEGM(3), /* user code */ [SYSGATE] CALLGATE(KESEL,0,3), /* call gate for system calls */ -[RDSEG] D16SEGM(0), /* reboot data/stack */ -[RESEG] E16SEGM(0), /* reboot code */ [TSSSEG] TSSSEGM(0,0), /* tss segment */ }; @@ -86,7 +84,20 @@ static ulong *upt; /* page table for struct User */ * offset of virtual address into * bottom level page table */ -#define BTMOFF(v) (((v)>>(PGSHIFT))&(BY2PG-1)) +#define BTMOFF(v) (((v)>>(PGSHIFT))&(WD2PG-1)) + +void +mmudump(void) +{ + int i; + ulong *z; + z = (ulong*)gdt; + for(i = 0; i < sizeof(gdt)/4; i+=2) + print("%8.8lux %8.8lux\n", *z++, *z++); + print("UESEL %lux UDSEL %lux\n", UESEL, UDSEL); + print("KESEL %lux KDSEL %lux\n", KESEL, KDSEL); + panic("done"); +} void mmuinit(void) @@ -112,12 +123,11 @@ mmuinit(void) * leave a map for a user area. */ - /* allocate and fill low level page tables for physical mem */ - nkpt = ROUNDUP(conf.npage0+conf.npage1, 4*1024*1024); - nkpt = nkpt/(4*1024*1024); + /* allocate and fill low level page tables for kernel mem */ + nkpt = ROUNDUP(conf.npage, 4*1024); + nkpt = nkpt/(4*1024); kpt = ialloc(nkpt*BY2PG, 1); - n = ROUNDUP(conf.npage0+conf.npage1, 1*1024*1024); - n = n/(4*1024); + n = ROUNDUP(conf.npage, 1024); for(i = 0; i < n; i++) kpt[i] = (i<upage->va != (USERADDR|(p->pid&0xFFFF))) panic("mapstack %d 0x%lux 0x%lux", p->pid, p->upage->pa, p->upage->va); @@ -210,7 +218,7 @@ putmmu(ulong va, ulong pa, Page *pg) Proc *p; int i; -print("putmmu %lux %lux USTKTOP %lux\n", va, pa, USTKTOP); /**/ +print("putmmu %lux %lux\n", va, pa); /**/ if(u==0) panic("putmmu"); p = u->p; @@ -232,8 +240,9 @@ print("putmmu %lux %lux USTKTOP %lux\n", va, pa, USTKTOP); /**/ pg = p->mmu[i]; if(pg == 0){ pg = p->mmu[i] = newpage(1, 0, 0); - p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEKERNEL | PTEWRITE; + p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE; toppt[topoff] = p->mmue[i]; +print("toppt[%d] = %lux\n", topoff, p->mmue[i]); } /* @@ -241,6 +250,7 @@ print("putmmu %lux %lux USTKTOP %lux\n", va, pa, USTKTOP); /**/ */ pt = (ulong*)(p->mmu[i]->pa|KZERO); pt[BTMOFF(va)] = pa | PTEUSER; +print("%lux[%d] = %lux\n", pt, BTMOFF(va), pa | PTEUSER); /* flush cached mmu entries */ putcr3(((ulong)toppt)&~KZERO); @@ -261,15 +271,3 @@ systrap(void) { panic("system trap from user"); } - -void -exit(void) -{ - int i; - - u = 0; - print("exiting\n"); - for(i = 0; i < WD2PG; i++) - toppt[i] = 0; - putcr3(((ulong)toppt)&~KZERO); -} diff --git a/pc/trap.c b/pc/trap.c index fffbd272a28c889ae2bc41409cda9ac3542fe92e..e2a81cc67aeea7f1fd1fc904dd0151304bdb5995 100644 --- a/pc/trap.c +++ b/pc/trap.c @@ -60,30 +60,30 @@ trapinit(void) /* * set the standard traps */ - sethvec(0, intr0, SEGTG, 0); - sethvec(1, intr1, SEGTG, 0); - sethvec(2, intr2, SEGTG, 0); - sethvec(3, intr3, SEGTG, 0); - sethvec(4, intr4, SEGTG, 0); - sethvec(5, intr5, SEGTG, 0); - sethvec(6, intr6, SEGTG, 0); - sethvec(7, intr7, SEGTG, 0); - sethvec(8, intr8, SEGTG, 0); - sethvec(9, intr9, SEGTG, 0); - sethvec(10, intr10, SEGTG, 0); - sethvec(11, intr11, SEGTG, 0); - sethvec(12, intr12, SEGTG, 0); - sethvec(13, intr13, SEGTG, 0); - sethvec(14, intr14, SEGTG, 0); - sethvec(15, intr15, SEGTG, 0); - sethvec(16, intr16, SEGTG, 0); - sethvec(17, intr17, SEGTG, 0); - sethvec(18, intr18, SEGTG, 0); - sethvec(19, intr19, SEGTG, 0); - sethvec(20, intr20, SEGTG, 0); - sethvec(21, intr21, SEGTG, 0); - sethvec(22, intr22, SEGTG, 0); - sethvec(23, intr23, SEGTG, 0); + sethvec(0, intr0, SEGIG, 0); + sethvec(1, intr1, SEGIG, 0); + sethvec(2, intr2, SEGIG, 0); + sethvec(3, intr3, SEGIG, 0); + sethvec(4, intr4, SEGIG, 0); + sethvec(5, intr5, SEGIG, 0); + sethvec(6, intr6, SEGIG, 0); + sethvec(7, intr7, SEGIG, 0); + sethvec(8, intr8, SEGIG, 0); + sethvec(9, intr9, SEGIG, 0); + sethvec(10, intr10, SEGIG, 0); + sethvec(11, intr11, SEGIG, 0); + sethvec(12, intr12, SEGIG, 0); + sethvec(13, intr13, SEGIG, 0); + sethvec(14, intr14, SEGIG, 0); + sethvec(15, intr15, SEGIG, 0); + sethvec(16, intr16, SEGIG, 0); + sethvec(17, intr17, SEGIG, 0); + sethvec(18, intr18, SEGIG, 0); + sethvec(19, intr19, SEGIG, 0); + sethvec(20, intr20, SEGIG, 0); + sethvec(21, intr21, SEGIG, 0); + sethvec(22, intr22, SEGIG, 0); + sethvec(23, intr23, SEGIG, 0); /* * set all others to unknown interrupts diff --git a/port/fault.c b/port/fault.c index 24046478823bbc15d7c9a8d59c4ea1c0425f5d1c..078cf4e2ac6506a73c8f8e131367aa369128b664 100644 --- a/port/fault.c +++ b/port/fault.c @@ -103,8 +103,13 @@ again: } qunlock(&s->lk); - if(new) /* A race may provide a page we never used when - putpage(new); * a fault is fixed while process slept in newpage */ + + /* + * A race may provide a page we never used when + * a fault is fixed while process slept in newpage + */ + if(new) + putpage(new); putmmu(addr, mmuphys, *pg); return 0; diff --git a/power/boot.c b/power/boot.c index 8785aae0fba83c7d87321c0bd4bf6490685485dc..7d2dd66dae35facd42c95980d3e635d3fee9552b 100644 --- a/power/boot.c +++ b/power/boot.c @@ -369,9 +369,8 @@ boot(int ask) Dir dir; char dirbuf[DIRLEN]; - if(ask){ + if(ask) outin("server", sys, sizeof(sys)); - } for(tries = 0; tries < 5; tries++){ fd = -1;