M carrera/devrtc.c => carrera/devrtc.c +9 -2
@@ 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:
M carrera/main.c => carrera/main.c +1 -1
@@ 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;
M mpc/devuart.c => mpc/devuart.c +0 -2
@@ 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);
M mpc/l.s => mpc/l.s +6 -2
@@ 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
M mpc/mmu.c => mpc/mmu.c +8 -1
@@ 14,6 14,13 @@ mmuinit(void)
}
void
+flushmmu(void)
+{
+// print("flushmmu()\n");
+ _flushmmu();
+}
+
+void
mmuswitch(Proc*)
{
flushmmu();
@@ 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);
A mpc/sh.c => mpc/sh.c +481 -0
@@ 0,0 1,481 @@
+/* sh - simple shell - great for early stages of porting */
+#include <u.h>
+#include <libc.h>
+
+#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;
+}
M mpc/trap.c => mpc/trap.c +79 -16
@@ 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);
+// }
+}
M port/devdraw.c => port/devdraw.c +34 -12
@@ 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<<screenimage.ldepth);
if(blank == 0) /* turn screen on */
@@ 1819,6 1840,7 @@ drawblankscreen(int blank)
setcolor(i, 0, 0, 0);
}
sdraw.blanked = blank;
+ qunlock(&sdraw);
}
/*