From 75093007b62c58ba3da073f70424df0c78302331 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 28 Jan 1999 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1999-01-28 --- carrera/devrtc.c | 11 +- carrera/main.c | 2 +- mpc/devuart.c | 2 - mpc/l.s | 8 +- mpc/mmu.c | 9 +- mpc/sh.c | 481 +++++++++++++++++++++++++++++++++++++++++++++++ mpc/trap.c | 95 ++++++++-- port/devdraw.c | 46 +++-- 8 files changed, 618 insertions(+), 36 deletions(-) create mode 100644 mpc/sh.c diff --git a/carrera/devrtc.c b/carrera/devrtc.c index 4fc429c5d2a2ef21b091c44cb39154e401bfba4f..811b8e01020492392c2612cd1e3ac99cec7c030d 100644 --- a/carrera/devrtc.c +++ b/carrera/devrtc.c @@ -10,6 +10,8 @@ * real time clock and non-volatile ram */ +extern ulong boottime; + typedef struct Rtc Rtc; struct Rtc { @@ -192,8 +194,6 @@ rtctime(void) return t; #else - extern ulong boottime; - return boottime+TK2SEC(MACHP(0)->ticks); #endif /* notdef */ } @@ -264,6 +264,8 @@ rtcwrite(Chan *c, void *buf, long n, vlong off) rtc.year = PUTBCD(rtc.year); } +/* disgusting hack because RTC doesn't work and m->ticks drifts */ +if(boottime == 0){ ilock(&rtclock); /* set clock values */ x = (*(uchar*)Rtcindex)&~0x7f; @@ -280,6 +282,11 @@ rtcwrite(Chan *c, void *buf, long n, vlong off) *(uchar*)Rtcindex = x|Year; *(uchar*)Rtcdata = rtc.year; iunlock(&rtclock); +}else{ + splhi(); + MACHP(0)->ticks = HZ*(secs - boottime); /* inverse of SEC2TK() */ + spllo(); +} return n; case Qnvram: diff --git a/carrera/main.c b/carrera/main.c index 490651a5638e9bba5a613d35a9694b0d733b8781..b839f0ae7fe2f7a2b78fd065611ec06a95122c7a 100644 --- a/carrera/main.c +++ b/carrera/main.c @@ -472,7 +472,7 @@ confinit(void) if(top > 16*MB/BY2PG){ conf.upages = (conf.npage*60)/100; - poolsetparam("Image", 0, 0, 4*1024*1024); + poolsetparam("Image", 0, 0, 4*1024*1024, nil); }else conf.upages = (conf.npage*40)/100; conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG; diff --git a/mpc/devuart.c b/mpc/devuart.c index 74df9c4b0cd9c167d1fa861b61f5f5a72c97c266..98acfa89e82ee537e791b6872b7da38fdeb5b573 100644 --- a/mpc/devuart.c +++ b/mpc/devuart.c @@ -997,7 +997,6 @@ uartintr(Uart *p, int events) p->overrun++; p->interrupts++; dokick = 0; -/* while(p->rxb != nil && ((bd = &p->rxb[p->rdrx])->status & BDEmpty) == 0){ if(p->mode) framedinput(p, bd); @@ -1008,7 +1007,6 @@ uartintr(Uart *p, int events) bd->status = (bd->status & BDWrap) | BDEmpty|BDInt; p->rdrx ^= 1; } -*/ if((bd = p->txb) != nil){ if((bd->status & BDReady) == 0){ ilock(&p->plock); diff --git a/mpc/l.s b/mpc/l.s index 9dd8ce99450412e0cd5c350c5aabedef1a8540ac..bdbdb8e067b09e56a3e475a1a8655b9689f977ee 100644 --- a/mpc/l.s +++ b/mpc/l.s @@ -60,7 +60,7 @@ /* special instruction definitions */ #define BDNZ BC 16,0, #define BDNE BC 0,2, -#define TLBIA WORD $(31<<26) +#define TLBIA WORD $((31<<26)|(370<<1)) #define MFTB(tbr,d) WORD $((31<<26)|((d)<<21)|((tbr&0x1f)<<16)|(((tbr>>5)&0x1f)<<11)|(371<<1)) /* on some models mtmsr doesn't synchronise enough (eg, 603e) */ @@ -427,7 +427,7 @@ TEXT eieio(SB), $0 EIEIO RETURN -TEXT flushmmu(SB), $0 +TEXT _flushmmu(SB), $0 TLBIA RETURN @@ -639,6 +639,9 @@ TEXT intrvec(SB), $-4 /* * restore state from Ureg and return from trap/interrupt */ +TEXT forkret(SB), $0 + BR restoreureg + restoreureg: MOVMW 48(R1), R2 /* r2:r31 */ /* defer R1 */ @@ -664,6 +667,7 @@ restoreureg: MOVW SPR(SAVER0), R0 RFI + GLOBL mach0+0(SB), $MACHSIZE GLOBL spltbl+0(SB), $4 GLOBL intrtbl+0(SB), $4 diff --git a/mpc/mmu.c b/mpc/mmu.c index e581bf41123c656afc1c9e2ecbab698d9ca18d93..24576e7aff6cfc5d226f3c1f931972b1388b55a0 100644 --- a/mpc/mmu.c +++ b/mpc/mmu.c @@ -13,6 +13,13 @@ mmuinit(void) kernelmmu(); } +void +flushmmu(void) +{ +// print("flushmmu()\n"); + _flushmmu(); +} + void mmuswitch(Proc*) { @@ -30,7 +37,7 @@ void putmmu(ulong va, ulong pa, Page*) { int x, r; -print("putmmu va=%ux pa=%ux\n", va, pa); +//print("putmmu va=%ux pa=%ux\n", va, pa); x = splhi(); r = _putmmu(va, pa); splx(x); diff --git a/mpc/sh.c b/mpc/sh.c new file mode 100644 index 0000000000000000000000000000000000000000..36de6460a74e51f929c95121db96ea82b06d939e --- /dev/null +++ b/mpc/sh.c @@ -0,0 +1,481 @@ +/* sh - simple shell - great for early stages of porting */ +#include +#include + +#define MAXLINE 200 /* maximum line length */ +#define WORD 256 /* token code for words */ +#define EOF -1 /* token code for end of file */ +#define ispunct(c) (c=='|' || c=='&' || c==';' || c=='<' || \ + c=='>' || c=='(' || c==')' || c=='\n') +#define isspace(c) (c==' ' || c=='\t') +#define execute(np) (np? (*(np)->op)(np) : 0) + +typedef struct Node Node; +struct Node{ /* parse tree node */ + int (*op)(Node *); /* operator function */ + Node *args[2]; /* argument nodes */ + char *argv[100]; /* argument pointers */ + char *io[3]; /* i/o redirection */ +}; + +Node nodes[25]; /* node pool */ +Node *nfree; /* next available node */ +char strspace[10*MAXLINE]; /* string storage */ +char *sfree; /* next free character in strspace */ +int t; /* current token code */ +char *token; /* current token text (in strspace) */ +int putback = 0; /* lookahead */ +Waitmsg status; /* exit status of most recent command */ +int cflag = 0; /* command is argument to sh */ +int tflag = 0; /* read only one line */ +int interactive = 0; /* prompt */ +char *cflagp; /* command line for cflag */ +char *path[] ={"/bin", 0}; + +Node *alloc(int (*op)(Node *)); +int builtin(Node *np); +Node *command(void); +int getch(void); +int gettoken(void); +Node *list(void); +void error(char *s, char *t); +Node *pipeline(void); +void redirect(Node *np); +int setio(Node *np); +Node *simple(void); +int xpipeline(Node *np); +int xsimple(Node *np); +int xsubshell(Node *np); +int xnowait(Node *np); +int xwait(Node *np); + +main(int argc, char *argv[]) +{ + Node *np; + + open("#c/cons", OREAD); + open("#c/cons", OWRITE); + open("#c/cons", OWRITE); + + print("hello world\n"); + + if(argc>1 && strcmp(argv[1], "-t")==0) + tflag++; + else if(argc>2 && strcmp(argv[1], "-c")==0){ + cflag++; + cflagp = argv[2]; + }else if(argc>1){ + close(0); + if(open(argv[1], 0) != 0){ + error(": can't open", argv[1]); + exits("argument"); + } + }else + interactive = 1; + for(;;){ + if(interactive) + fprint(2, "%d$ ", getpid()); + nfree = nodes; + sfree = strspace; + if((t=gettoken()) == EOF) + break; + if(t != '\n') + if(np = list()) + execute(np); + else + error("syntax error", ""); + while(t!=EOF && t!='\n') /* flush syntax errors */ + t = gettoken(); + } + exits(status.msg); +} + +/* alloc - allocate for op and return a node */ +Node* +alloc(int (*op)(Node *)) +{ + if(nfree < nodes+sizeof(nodes)){ + nfree->op = op; + nfree->args[0] = nfree->args[1] = 0; + nfree->argv[0] = nfree->argv[1] = 0; + nfree->io[0] = nfree->io[1] = nfree->io[2] = 0; + return nfree++; + } + error("node storage overflow", ""); + exits("node storage overflow"); +} + +/* builtin - check np for builtin command and, if found, execute it */ +int +builtin(Node *np) +{ + int n = 0; + char *s, name[MAXLINE]; + + if(np->argv[1]) + n = strtoul(np->argv[1], 0, 0); + if(strcmp(np->argv[0], "cd") == 0){ + if(chdir(np->argv[1]? np->argv[1] : "/") == -1) + error(": bad directory", np->argv[0]); + return 1; + }else if(strcmp(np->argv[0], "exit") == 0) + exits(np->argv[1]? np->argv[1] : status.msg); + else if(strcmp(np->argv[0], "bind") == 0){ + if(np->argv[1]==0 || np->argv[2]==0) + error("usage: bind new old", ""); + else if(bind(np->argv[1], np->argv[2], 0)==-1) + error("bind failed", ""); + return 1; +#ifdef asdf + }else if(strcmp(np->argv[0], "unmount") == 0){ + if(np->argv[1] == 0) + error("usage: unmount [new] old", ""); + else if(np->argv[2] == 0){ + if(unmount((char *)0, np->argv[1]) == -1) + error("unmount:", ""); + }else if(unmount(np->argv[1], np->argv[2]) == -1) + error("unmount", ""); + return 1; +#endif + }else if(strcmp(np->argv[0], "wait") == 0){ + while(wait(&status) != -1) + if(n && atoi(status.pid)==n){ + n = 0; + break; + } + if(n) + error("wait error", ""); + return 1; + }else if(strcmp(np->argv[0], "newpgrp") == 0){ + int i; + i = rfork(RFNAMEG|RFENVG); + if(i < 0) + error("rfork error", ""); + else + fprint(2, "%d\n", i); + return 1; + }else if(strcmp(np->argv[0], "exec") == 0){ + redirect(np); + if(np->argv[1] == (char *) 0) + return 1; + exec(np->argv[1], &np->argv[1]); + n = np->argv[1][0]; + if(n!='/' && n!='#' && (n!='.' || np->argv[1][1]!='/')) + for(n = 0; path[n]; n++){ + sprint(name, "%s/%s", path[n], np->argv[1]); + exec(name, &np->argv[1]); + } + error(": not found", np->argv[1]); + return 1; + } + return 0; +} + +/* command - ( list ) [ ( < | > | >> ) word ]* | simple */ +Node* +command(void) +{ + Node *np; + + if(t != '(') + return simple(); + np = alloc(xsubshell); + t = gettoken(); + if((np->args[0]=list())==0 || t!=')') + return 0; + while((t=gettoken())=='<' || t=='>') + if(!setio(np)) + return 0; + return np; +} + +/* getch - get next, possibly pushed back, input character */ +int +getch(void) +{ + unsigned char c; + static done=0; + + if(putback){ + c = putback; + putback = 0; + }else if(tflag){ + if(done || read(0, &c, 1)!=1){ + done = 1; + return EOF; + } + if(c == '\n') + done = 1; + }else if(cflag){ + if(done) + return EOF; + if((c=*cflagp++) == 0){ + done = 1; + c = '\n'; + } + }else if(read(0, &c, 1) != 1) + return EOF; + return c; +} + +/* gettoken - get next token into string space, return token code */ +int +gettoken(void) +{ + int c; + + while((c = getch()) != EOF) + if(!isspace(c)) + break; + if(c==EOF || ispunct(c)) + return c; + token = sfree; + do{ + if(sfree >= strspace+sizeof(strspace) - 1){ + error("string storage overflow", ""); + exits("string storage overflow"); + } + *sfree++ = c; + }while((c=getch()) != EOF && !ispunct(c) && !isspace(c)); + *sfree++ = 0; + putback = c; + return WORD; +} + +/* list - pipeline ( ( ; | & ) pipeline )* [ ; | & ] (not LL(1), but ok) */ +Node* +list(void) +{ + Node *np, *np1; + + np = alloc(0); + if((np->args[1]=pipeline()) == 0) + return 0; + while(t==';' || t=='&'){ + np->op = (t==';')? xwait : xnowait; + t = gettoken(); + if(t==')' || t=='\n') /* tests ~first(pipeline) */ + break; + np1 = alloc(0); + np1->args[0] = np; + if((np1->args[1]=pipeline()) == 0) + return 0; + np = np1; + } + if(np->op == 0) + np->op = xwait; + return np; +} + +/* error - print error message s, prefixed by t */ +void +error(char *s, char *t) +{ + char buf[ERRLEN]; + + fprint(2, "%s%s", t, s); + errstr(buf); + fprint(2, ": %s\n", buf); +} + +/* pipeline - command ( | command )* */ +Node* +pipeline(void) +{ + Node *np, *np1; + + if((np=command()) == 0) + return 0; + while(t == '|'){ + np1 = alloc(xpipeline); + np1->args[0] = np; + t = gettoken(); + if((np1->args[1]=command()) == 0) + return 0; + np = np1; + } + return np; +} + +/* redirect - redirect i/o according to np->io[] values */ +void +redirect(Node *np) +{ + int fd; + + if(np->io[0]){ + if((fd = open(np->io[0], 0)) < 0){ + error(": can't open", np->io[0]); + exits("open"); + } + dup(fd, 0); + close(fd); + } + if(np->io[1]){ + if((fd = create(np->io[1], 1, 0666L)) < 0){ + error(": can't create", np->io[1]); + exits("create"); + } + dup(fd, 1); + close(fd); + } + if(np->io[2]){ + if((fd = open(np->io[2], 1)) < 0 && (fd = create(np->io[2], 1, 0666L)) < 0){ + error(": can't write", np->io[2]); + exits("write"); + } + dup(fd, 1); + close(fd); + seek(1, 0, 2); + } +} + +/* setio - ( < | > | >> ) word; fill in np->io[] */ +int +setio(Node *np) +{ + if(t == '<'){ + t = gettoken(); + np->io[0] = token; + }else if(t == '>'){ + t = gettoken(); + if(t == '>'){ + t = gettoken(); + np->io[2] = token; + }else + np->io[1] = token; + }else + return 0; + if(t != WORD) + return 0; + return 1; +} + +/* simple - word ( [ < | > | >> ] word )* */ +Node* +simple(void) +{ + Node *np; + int n = 1; + + if(t != WORD) + return 0; + np = alloc(xsimple); + np->argv[0] = token; + while((t = gettoken())==WORD || t=='<' || t=='>') + if(t == WORD) + np->argv[n++] = token; + else if(!setio(np)) + return 0; + np->argv[n] = 0; + return np; +} + +/* xpipeline - execute cmd | cmd */ +int +xpipeline(Node *np) +{ + int pid, fd[2]; + + if(pipe(fd) < 0){ + error("can't create pipe", ""); + return 0; + } + if((pid=fork()) == 0){ /* left side; redirect stdout */ + dup(fd[1], 1); + close(fd[0]); + close(fd[1]); + execute(np->args[0]); + exits(status.msg); + }else if(pid == -1){ + error("can't create process", ""); + return 0; + } + if((pid=fork()) == 0){ /* right side; redirect stdin */ + dup(fd[0], 0); + close(fd[0]); + close(fd[1]); + pid = execute(np->args[1]); /*BUG: this is wrong sometimes*/ + if(pid > 0) + while(wait(&status)!=-1 && atoi(status.pid)!=pid) + ; + exits(0); + }else if(pid == -1){ + error("can't create process", ""); + return 0; + } + close(fd[0]); /* avoid using up fd's */ + close(fd[1]); + return pid; +} + +/* xsimple - execute a simple command */ +int +xsimple(Node *np) +{ + char name[MAXLINE]; + int pid, i; + + if(builtin(np)) + return 0; + if(pid = fork()){ + if(pid == -1) + error(": can't create process", np->argv[0]); + return pid; + } + redirect(np); /* child process */ + exec(np->argv[0], &np->argv[0]); + i = np->argv[0][0]; + if(i!='/' && i!='#' && (i!='.' || np->argv[0][1]!='/')) + for(i = 0; path[i]; i++){ + sprint(name, "%s/%s", path[i], np->argv[0]); + exec(name, &np->argv[0]); + } + error(": not found", np->argv[0]); + exits("not found"); +} + +/* xsubshell - execute (cmd) */ +int +xsubshell(Node *np) +{ + int pid; + + if(pid = fork()){ + if(pid == -1) + error("can't create process", ""); + return pid; + } + redirect(np); /* child process */ + execute(np->args[0]); + exits(status.msg); +} + +/* xnowait - execute cmd & */ +int +xnowait(Node *np) +{ + int pid; + + execute(np->args[0]); + pid = execute(np->args[1]); + if(interactive) + fprint(2, "%d\n", pid); + return 0; +} + +/* xwait - execute cmd ; */ +int xwait(Node *np) +{ + int pid; + + execute(np->args[0]); + pid = execute(np->args[1]); + if(pid > 0){ + while(wait(&status) != -1 && atoi(status.pid) != pid) + ; + if(atoi(status.pid) != pid) + error("wait error", ""); + } + return 0; +} diff --git a/mpc/trap.c b/mpc/trap.c index 1ac2dc92c234acb2172a96cbaf9f1cb5c093cf62..8b1c26073c143b8ebb097f40f3ada90a633439c2 100644 --- a/mpc/trap.c +++ b/mpc/trap.c @@ -33,6 +33,7 @@ struct void faultpower(Ureg *ur, ulong addr, int read); void kernfault(Ureg*, int); +void syscall(Ureg* ureg); char *excname[] = { @@ -179,11 +180,7 @@ trap(Ureg *ur) break; case CSYSCALL: - spllo(); - print("syscall!\n"); - dumpregs(ur); - delay(100); - splhi(); + syscall(ur); break; case CPROG: @@ -214,7 +211,7 @@ faultpower(Ureg *ureg, ulong addr, int read) char buf[ERRLEN]; user = (ureg->srr1 & MSR_PR) != 0; -print("fault: pc = %ux, addr = %ux read = %d user = %d stack=%ux\n", ureg->pc, addr, read, user, &ureg); +//print("fault: pc = %ux, addr = %ux read = %d user = %d stack=%ux\n", ureg->pc, addr, read, user, &ureg); insyscall = up->insyscall; up->insyscall = 1; spllo(); @@ -229,7 +226,6 @@ print("fault: pc = %ux, addr = %ux read = %d user = %d stack=%ux\n", ureg->pc, a postnote(up, 1, buf, NDebug); } up->insyscall = insyscall; - splhi(); } void @@ -540,9 +536,8 @@ forkchild(Proc *p, Ureg *ur) cur = (Ureg*)(p->sched.sp+2*BY2WD); memmove(cur, ur, sizeof(Ureg)); - - cur->pc += 4; - + cur->r3 = 0; + /* Things from bottom of syscall we never got to execute */ p->psstate = 0; p->insyscall = 0; @@ -558,12 +553,6 @@ userpc(void) } -// need to be in l.s -void -forkret(void) -{ - panic("forkret"); -} /* This routine must save the values of registers the user is not * permitted to write from devproc and then restore the saved values * before returning @@ -599,3 +588,77 @@ dbgpc(Proc *p) return ureg->pc; } + +/* + * system calls + */ +#include "../port/systab.h" + +/* + * Syscall should be called directly from assembler without going through trap(). + */ +void +syscall(Ureg* ureg) +{ + ulong sp; + long ret; + int i, scallnr; + + if((ureg->srr1 & MSR_PR) == 0) + panic("syscall: srr1 0x%4.4uX\n", ureg->srr1); + + m->syscall++; + up->insyscall = 1; + up->pc = ureg->pc; + up->dbgreg = ureg; + + scallnr = ureg->r3; +//print("scall %s\n", sysctab[scallnr]); + up->scallnr = scallnr; + spllo(); + + sp = ureg->usp; + up->nerrlab = 0; + ret = -1; + if(!waserror()){ + if(scallnr >= nsyscall){ + pprint("bad sys call number %d pc %lux\n", scallnr, ureg->pc); + postnote(up, 1, "sys: bad sys call", NDebug); + error(Ebadarg); + } + + if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD)) + validaddr(sp, sizeof(Sargs)+BY2WD, 0); + + up->s = *((Sargs*)(sp+BY2WD)); + up->psstate = sysctab[scallnr]; + + ret = systab[scallnr](up->s.args); + poperror(); + } + if(up->nerrlab){ + print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab); + for(i = 0; i < NERR; i++) + print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc); + panic("error stack"); + } + + up->insyscall = 0; + up->psstate = 0; + + /* + * Put return value in frame. On the x86 the syscall is + * just another trap and the return value from syscall is + * ignored. On other machines the return value is put into + * the results register by caller of syscall. + */ + ureg->r3 = ret; +//print("ret = %d\n", ret); +// if(scallnr == NOTED) +// noted(ureg, *(ulong*)(sp+BY2WD)); + +// if(scallnr!=RFORK && (up->procctl || up->nnote)){ +// splhi(); +// notify(ureg); +// } +} diff --git a/port/devdraw.c b/port/devdraw.c index 38d1338fcfa604815571ec3430352f4ff5f3aa57..f3a62c6c26d3dedf0a9fcfb77aa0455f59127e39 100644 --- a/port/devdraw.c +++ b/port/devdraw.c @@ -787,21 +787,37 @@ drawchar(Memimage *dst, Point p, Memimage *src, Point *sp, DImage *font, int ind return p; } -Chan* -drawattach(char *spec) +static int +initscreenimage(void) { int width; - if(screendata.data == nil){ - screendata.base = nil; - screendata.data = attachscreen(&screenimage.r, &screenimage.ldepth, &width, &sdraw.softscreen); - if(screendata.data != nil){ - screendata.ref = 1; - screenimage.data = &screendata; - screenimage.width = width; - screenimage.clipr = screenimage.r; - } + if(screendata.data != nil) + return 1; + screendata.data = attachscreen(&screenimage.r, &screenimage.ldepth, &width, &sdraw.softscreen); + if(screendata.data == nil) + return 0; + + screendata.base = nil; + if(screendata.data != nil){ + screendata.ref = 1; + screenimage.data = &screendata; + screenimage.width = width; + screenimage.clipr = screenimage.r; } + + return 1; +} + +Chan* +drawattach(char *spec) +{ + qlock(&sdraw); + if(!initscreenimage()){ + qunlock(&sdraw); + error("no frame buffer"); + } + qunlock(&sdraw); return devattach('i', spec); } @@ -1606,7 +1622,6 @@ drawmesg(Client *client, void *av, int n) if(n < m) error(Eshortdraw); - CaseS: dst = drawimage(client, a+1); dstid = BGLONG(a+1); src = drawimage(client, a+5); @@ -1808,6 +1823,12 @@ drawblankscreen(int blank) if(blank == sdraw.blanked) return; + if(!canqlock(&sdraw)) + return; + if(!initscreenimage()){ + qunlock(&sdraw); + return; + } p = sdraw.savemap; nc = 1<<(1<