M gnot/lib.h => gnot/lib.h +1 -1
@@ 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;
M gnot/trap.c => gnot/trap.c +1 -1
@@ 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);
M pc/dat.h => pc/dat.h +5 -3
@@ 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
M pc/fault386.c => pc/fault386.c +23 -4
@@ 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);
}
M pc/fns.h => pc/fns.h +6 -4
@@ 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);
M pc/l.s => pc/l.s +25 -15
@@ 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
M pc/main.c => pc/main.c +12 -6
@@ 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();
}
M pc/mem.h => pc/mem.h +17 -12
@@ 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
M pc/mmu.c => pc/mmu.c +112 -18
@@ 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<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE;
- }
+ for(i = 0; i < n; i++)
+ kpt[i] = (i<<PGSHIFT) | PTEVALID | PTEKERNEL | PTEWRITE;
/* allocate page table for u-> */
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);
}
M pc/trap.c => pc/trap.c +24 -2
@@ 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.
@@ 137,11 137,33 @@ trap(Ureg *ur)
}
/*
+ * 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");
}
M port/fault.c => port/fault.c +2 -2
@@ 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;
M port/lib.h => port/lib.h +1 -1
@@ 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;
M port/page.c => port/page.c +1 -1
@@ 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;
M power/trap.c => power/trap.c +1 -1
@@ 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);
M ss/trap.c => ss/trap.c +1 -1
@@ 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);