M gnot/fault68020.c => gnot/fault68020.c +6 -3
@@ 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);
M gnot/l.s => gnot/l.s +4 -3
@@ 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
M gnot/main.c => gnot/main.c +1 -1
@@ 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));
M gnot/mem.h => gnot/mem.h +3 -1
@@ 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
M gnot/trap.c => gnot/trap.c +1 -0
@@ 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));
M gnot/ureg.h => gnot/ureg.h +2 -1
@@ 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 */
};
M pc/clock.c => pc/clock.c +14 -0
@@ 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)
{
M pc/fault386.c => pc/fault386.c +15 -4
@@ 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
M pc/fns.h => pc/fns.h +1 -0
@@ 1,5 1,6 @@
#include "../port/portfns.h"
+void a20enable(void);
#define clearmmucache() /* 386 doesn't have one */
void clock(Ureg*);
void clockinit(void);
A pc/headland.c => pc/headland.c +41 -0
@@ 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);
+}
M pc/kbd.c => pc/kbd.c +1 -1
@@ 257,7 257,7 @@ kbdintr(Ureg *ur)
int keyup;
/*
- * get a character to be there
+ * get a character
*/
c = inb(Data);
M pc/l.s => pc/l.s +3 -2
@@ 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
/*
M pc/main.c => pc/main.c +18 -14
@@ 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;
}
-
M pc/mem.h => pc/mem.h +2 -6
@@ 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)
/*
M pc/mmu.c => pc/mmu.c +22 -24
@@ 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<<PGSHIFT) | PTEVALID | PTEKERNEL | PTEWRITE;
@@ 150,8 160,6 @@ 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);
@@ 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);
-}
M pc/trap.c => pc/trap.c +24 -24
@@ 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
M port/fault.c => port/fault.c +7 -2
@@ 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;
M power/boot.c => power/boot.c +1 -2
@@ 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;