M pc/dat.h => pc/dat.h +3 -2
@@ 165,8 165,9 @@ struct User
Note lastnote;
int (*notify)(void*, char*);
void *ureg;
- ushort svvo;
- ushort svsr;
+ ulong svcs; /* cs before a notify */
+ ulong svss; /* ss before a notify */
+ ulong svflags; /* flags before a notify */
};
/*
M pc/fault386.c => pc/fault386.c +9 -5
@@ 15,24 15,27 @@ fault386(Ureg *ur)
int read;
int user;
int n;
+ int insyscall;
static int times;
+ insyscall = u->p->insyscall;
+ u->p->insyscall = 1;
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);
n = fault(addr, read);
-print("fault returns %d\n", n);
+if(++times==3)
+ panic("3rd time in fault");
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);
+ 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;
@@ 40,6 43,7 @@ print("fault returns %d\n", n);
panic("fault: 0x%lux", addr);
}
faulting = 0;
+ u->p->insyscall = insyscall;
}
void
M pc/headland.c => pc/headland.c +0 -1
@@ 36,6 36,5 @@ exit(void)
u = 0;
print("exiting\n");
- delay(5000);
outb(Head, Reset);
}
M pc/l.s => pc/l.s +10 -5
@@ 9,6 9,11 @@ TEXT origin(SB),$0
#ifdef BOOT
/*
+ * This part of l.s is used only in the boot kernel.
+ * It assumes that we are in real address mode, i.e.,
+ * that we look like an 8086.
+ */
+/*
* relocate everything to a half meg and jump there
* - looks wierd because it is being assembled by a 32 bit
* assembler for a 16 bit world
@@ 431,11 436,11 @@ TEXT setlabel(SB),$0
* Set up an interrupt return frame and IRET to user level.
*/
TEXT touser(SB),$0
- PUSHL $(UDSEL) /* old ss */
- PUSHL $(USTKTOP-16) /* old sp */
- PUSHFL /* old flags */
- PUSHL $(UESEL) /* old cs */
- PUSHL $(UTZERO+32) /* old pc */
+ PUSHL $(UDSEL) /* old ss */
+ PUSHL $(USTKTOP) /* old sp */
+ PUSHFL /* old flags */
+ PUSHL $(UESEL) /* old cs */
+ PUSHL $(UTZERO+32) /* old pc */
MOVL $(UDSEL),AX
MOVW AX,DS
MOVW AX,ES
M pc/main.c => pc/main.c +6 -13
@@ 65,6 65,9 @@ init0(void)
u->p->state = Running;
u->p->mach = m;
+print("go low\n");
+ spllo();
+
/*
* These are o.k. because rootinit is null.
* Then early kproc's will have a root and dot.
@@ 74,17 77,8 @@ init0(void)
chandevinit();
- /*
- * fault in the first executable page and user stack
- */
- print("text is %lux\n", *((ulong *)(UTZERO+32)));
-
- /* fault in the first stack page
- */
- print("stack is %lux\n", *((ulong *)(USTKTOP-4)));
- *((ulong *)(USTKTOP-4)) = 0xdeadbeef;
- print("stack is %lux\n", *((ulong *)(USTKTOP-4)));
- delay(5000);
+print("going to user\n");
+delay(1000);
touser();
}
@@ 110,10 104,9 @@ userinit(void)
*
* 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 - 12;
+ p->sched.sp = USERADDR + BY2PG - 4;
p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF));
/*
M pc/mmu.c => pc/mmu.c +3 -2
@@ 242,15 242,16 @@ print("putmmu %lux %lux\n", va, pa); /**/
pg = p->mmu[i] = newpage(1, 0, 0);
p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE;
toppt[topoff] = p->mmue[i];
-print("toppt[%d] = %lux\n", topoff, p->mmue[i]);
+print("toppt[%d] = %lux\n", topoff, toppt[topoff]);
}
/*
* fill in the bottom level page table
*/
+print("%lux[%d] was %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]);
pt = (ulong*)(p->mmu[i]->pa|KZERO);
pt[BTMOFF(va)] = pa | PTEUSER;
-print("%lux[%d] = %lux\n", pt, BTMOFF(va), pa | PTEUSER);
+print("%lux[%d] now %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]);
/* flush cached mmu entries */
putcr3(((ulong)toppt)&~KZERO);
M pc/trap.c => pc/trap.c +194 -4
@@ 5,6 5,10 @@
#include "fns.h"
#include "io.h"
#include "ureg.h"
+#include "errno.h"
+
+void noted(Ureg*, ulong);
+void notify(Ureg*);
/*
* 8259 interrupt controllers
@@ 155,25 159,211 @@ dumpregs(Ureg *ur)
ur->si, ur->di, ur->bp, ur->ds);
}
+void
+dumpstack(void)
+{
+}
+
+void
+execpc(ulong entry)
+{
+ ((Ureg*)UREGADDR)->pc = entry;
+}
+
/*
* system calls
*/
+#undef CHDIR /* BUG */
+#include "/sys/src/libc/9syscall/sys.h"
+
+typedef long Syscall(ulong*);
+Syscall sysr1, sysfork, sysexec, sysgetpid, syssleep, sysexits, sysdeath, syswait;
+Syscall sysopen, sysclose, sysread, syswrite, sysseek, syserrstr, sysaccess, sysstat, sysfstat;
+Syscall sysdup, syschdir, sysforkpgrp, sysbind, sysmount, syspipe, syscreate;
+Syscall sysbrk_, sysremove, syswstat, sysfwstat, sysnotify, sysnoted, sysalarm;
+
+Syscall *systab[]={
+ sysr1,
+ syserrstr,
+ sysbind,
+ syschdir,
+ sysclose,
+ sysdup,
+ sysalarm,
+ sysexec,
+ sysexits,
+ sysfork,
+ sysforkpgrp,
+ sysfstat,
+ sysdeath,
+ sysmount,
+ sysopen,
+ sysread,
+ sysseek,
+ syssleep,
+ sysstat,
+ syswait,
+ syswrite,
+ syspipe,
+ syscreate,
+ sysdeath,
+ sysbrk_,
+ sysremove,
+ syswstat,
+ sysfwstat,
+ sysnotify,
+ sysnoted,
+ sysdeath, /* sysfilsys */
+};
+
long
syscall(Ureg *ur)
{
+ ulong ax;
+ ulong sp;
+ long ret;
+ int i;
+ static int times;
+ulong *z;
+
u->p->insyscall = 1;
u->p->pc = ur->pc;
+ if((ur->cs)&0xffff == KESEL)
+ panic("recursive system call");
+ u->p->insyscall = 0;
+
+ /*
+ * do something about floating point!!!
+ */
- panic("syscall");
+ ax = ur->ax;
+ sp = ur->usp;
+ u->nerrlab = 0;
+ ret = -1;
+z = (ulong *)sp;
+print("syscall %lux %lux %lux %lux\n", *z, *(z+1), *(z+2), *(z+3));
+dumpregs(ur);
+if(++times==3)
+ panic("3rd time in syscall");
+ if(!waserror()){
+ if(ax >= sizeof systab/BY2WD){
+ pprint("bad sys call number %d pc %lux\n", ax, ur->pc);
+ postnote(u->p, 1, "sys: bad sys call", NDebug);
+ error(Ebadarg);
+ }
+ if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-(1+MAXSYSARG)*BY2WD))
+ validaddr(sp, (1+MAXSYSARG)*BY2WD, 0);
+ ret = (*systab[ax])((ulong*)(sp+BY2WD));
+ poperror();
+ }
+print("return from syscall\n");
+ if(u->nerrlab){
+ print("bad errstack [%d]: %d extra\n", ax, u->nerrlab);
+ for(i = 0; i < NERR; i++)
+ print("sp=%lux pc=%lux\n", u->errlab[i].sp, u->errlab[i].pc);
+ panic("error stack");
+ }
+ u->p->insyscall = 0;
+ if(ax == NOTED){
+ noted(ur, *(ulong*)(sp+BY2WD));
+ ret = -1;
+ } else if(u->nnote){
+ ur->ax = ret;
+ notify(ur);
+ }
+ return ret;
}
+/*
+ * Call user, if necessary, with note.
+ * Pass user the Ureg struct and the note on his stack.
+ */
void
-dumpstack(void)
+notify(Ureg *ur)
{
+ ulong sp;
+
+ lock(&u->p->debug);
+ if(u->nnote==0){
+ unlock(&u->p->debug);
+ return;
+ }
+ if(u->note[0].flag!=NUser && (u->notified || u->notify==0)){
+ if(u->note[0].flag == NDebug)
+ pprint("suicide: %s\n", u->note[0].msg);
+ Die:
+ unlock(&u->p->debug);
+ pexit(u->note[0].msg, u->note[0].flag!=NDebug);
+ }
+ if(!u->notified){
+ if(!u->notify)
+ goto Die;
+ u->svcs = ur->cs;
+ u->svss = ur->ss;
+ u->svflags = ur->flags;
+ sp = ur->usp;
+ sp -= sizeof(Ureg);
+ u->ureg = (void*)sp;
+ memmove((Ureg*)sp, ur, sizeof(Ureg));
+ sp -= ERRLEN;
+ memmove((char*)sp, u->note[0].msg, ERRLEN);
+ sp -= 3*BY2WD;
+ *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD; /* arg 2 is string */
+ *(ulong*)(sp+1*BY2WD) = (ulong)u->ureg; /* arg 1 is ureg* */
+ *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */
+ ur->usp = sp;
+ ur->pc = (ulong)u->notify;
+ u->notified = 1;
+ u->nnote--;
+ memmove(&u->lastnote, &u->note[0], sizeof(Note));
+ memmove(&u->note[0], &u->note[1], u->nnote*sizeof(Note));
+ }
+ unlock(&u->p->debug);
}
+/*
+ * Return user to state before notify()
+ */
void
-execpc(ulong entry)
+noted(Ureg *ur, ulong arg0)
{
- ((Ureg*)UREGADDR)->pc = entry;
+ Ureg *nur;
+
+ nur = u->ureg;
+ validaddr(nur->pc, 1, 0);
+ validaddr(nur->usp, BY2WD, 0);
+ if(nur->cs!=u->svcs || nur->ss!=u->svss
+ || (nur->flags&0xff)!=(u->svflags&0xff)){
+ pprint("bad noted ureg cs %ux ss %ux flags %ux\n", nur->cs, nur->ss,
+ nur->flags);
+ pexit("Suicide", 0);
+ }
+ lock(&u->p->debug);
+ if(!u->notified){
+ unlock(&u->p->debug);
+ return;
+ }
+ u->notified = 0;
+ nur->flags = (u->svflags&0xffffff00) | (ur->flags&0xff);
+ memmove(ur, u->ureg, sizeof(Ureg));
+ ur->ax = -1; /* return error from the interrupted call */
+ switch(arg0){
+ case NCONT:
+ splhi();
+ unlock(&u->p->debug);
+ rfnote(ur);
+ break;
+ /* never returns */
+
+ default:
+ pprint("unknown noted arg 0x%lux\n", arg0);
+ u->lastnote.flag = NDebug;
+ /* fall through */
+
+ case NDFLT:
+ if(u->lastnote.flag == NDebug)
+ pprint("suicide: %s\n", u->lastnote.msg);
+ unlock(&u->p->debug);
+ pexit(u->lastnote.msg, u->lastnote.flag!=NDebug);
+ }
}
M port/devcons.c => port/devcons.c +6 -1
@@ 159,6 159,9 @@ pprint(char *fmt, ...)
Chan *c;
int n;
+ if(u->p->fgrp == 0)
+ return 0;
+
c = u->p->fgrp->fd[2];
if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR))
return 0;
@@ 418,6 421,9 @@ consopen(Chan *c, int omode)
unlock(&lineq);
}
break;
+ case Qswap:
+ kickpager(); /* start a pager if not already started */
+ break;
}
return devopen(c, omode, consdir, NCONS, devgen);
}
@@ 727,7 733,6 @@ conswrite(Chan *c, void *va, long n, ulong offset)
fd = strtoul(buf, 0, 0);
swc = fdtochan(fd, -1);
setswapchan(swc);
- kickpager();
return n;
default:
M port/proc.c => port/proc.c +3 -2
@@ 634,15 634,16 @@ procdump(void)
int i;
Proc *p;
- print("process table:\n");
+ print("process table %d:\n", conf.nproc);
for(i=0; i<conf.nproc; i++){
p = procalloc.arena+i;
if(p->state != Dead){
print("%d:%s %s upc %lux %s ut %ld st %ld r %lux\n",
- p->pid, p->text, p->pgrp->user, p->pc,
+ p->pid, p->text, p->pgrp ? p->pgrp->user : "pgrp=0", p->pc,
statename[p->state], p->time[0], p->time[1], p->r);
}
}
+ print("procdump: ret\n");
}
void
M port/swap.c => port/swap.c +0 -1
@@ 124,7 124,6 @@ pager(void *junk)
else {
/* Emulate the old system if no swap channel */
print("no physical memory\n");
- pprint("no physical memory\n");
tsleep(&swapalloc.r, return0, 0, 1000);
wakeup(&palloc.r);
}