diff options
author | cinap_lenrek <cinap_lenrek@localhost> | 2011-07-12 15:46:22 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@localhost> | 2011-07-12 15:46:22 +0200 |
commit | c6c2e04d4a700fe3982a4a72e768c69d6ace08a6 (patch) | |
tree | d64dc55189b55da8c7d01be1c981dda6dcab76dd /sys | |
parent | b429f72eaedff27b43c4ac951cea62f574e6fb23 (diff) |
segdesc: add /dev/^(ldt gdt) support
Diffstat (limited to 'sys')
-rw-r--r-- | sys/src/9/alphapc/fns.h | 1 | ||||
-rw-r--r-- | sys/src/9/alphapc/main.c | 5 | ||||
-rw-r--r-- | sys/src/9/bitsy/fns.h | 1 | ||||
-rw-r--r-- | sys/src/9/bitsy/main.c | 5 | ||||
-rw-r--r-- | sys/src/9/kw/arch.c | 5 | ||||
-rw-r--r-- | sys/src/9/kw/fns.h | 1 | ||||
-rw-r--r-- | sys/src/9/mtx/fns.h | 1 | ||||
-rw-r--r-- | sys/src/9/mtx/main.c | 5 | ||||
-rw-r--r-- | sys/src/9/omap/arch.c | 5 | ||||
-rw-r--r-- | sys/src/9/omap/fns.h | 1 | ||||
-rw-r--r-- | sys/src/9/pc/dat.h | 16 | ||||
-rw-r--r-- | sys/src/9/pc/fns.h | 4 | ||||
-rw-r--r-- | sys/src/9/pc/io.h | 2 | ||||
-rw-r--r-- | sys/src/9/pc/l.s | 16 | ||||
-rw-r--r-- | sys/src/9/pc/main.c | 21 | ||||
-rw-r--r-- | sys/src/9/pc/mem.h | 9 | ||||
-rw-r--r-- | sys/src/9/pc/mmu.c | 15 | ||||
-rw-r--r-- | sys/src/9/pc/pccpuf | 1 | ||||
-rw-r--r-- | sys/src/9/pc/pcf | 1 | ||||
-rw-r--r-- | sys/src/9/pc/segdesc.c | 261 | ||||
-rw-r--r-- | sys/src/9/pc/trap.c | 93 | ||||
-rw-r--r-- | sys/src/9/port/sysproc.c | 16 | ||||
-rw-r--r-- | sys/src/9/ppc/fns.h | 1 | ||||
-rw-r--r-- | sys/src/9/ppc/main.c | 5 |
24 files changed, 440 insertions, 51 deletions
diff --git a/sys/src/9/alphapc/fns.h b/sys/src/9/alphapc/fns.h index 05fd83914..6470d40c9 100644 --- a/sys/src/9/alphapc/fns.h +++ b/sys/src/9/alphapc/fns.h @@ -88,6 +88,7 @@ void printinit(void); #define procrestore(p) void procsave(Proc*); void procsetup(Proc*); +void procfork(Proc*); void restfpregs(FPsave*); uvlong rpcc(uvlong*); void screeninit(void); diff --git a/sys/src/9/alphapc/main.c b/sys/src/9/alphapc/main.c index 600e0a5c8..2940c567b 100644 --- a/sys/src/9/alphapc/main.c +++ b/sys/src/9/alphapc/main.c @@ -272,6 +272,11 @@ procsetup(Proc *p) } void +procfork(Proc *) +{ +} + +void procsave(Proc *p) { if(p->fpstate == FPactive){ diff --git a/sys/src/9/bitsy/fns.h b/sys/src/9/bitsy/fns.h index 08aff860a..f7bece5c3 100644 --- a/sys/src/9/bitsy/fns.h +++ b/sys/src/9/bitsy/fns.h @@ -85,6 +85,7 @@ void powerkproc(void*); #define procrestore(p) void procsave(Proc*); void procsetup(Proc*); +void procfork(Proc*); void putdac(ulong); void putttb(ulong); void putpid(ulong); diff --git a/sys/src/9/bitsy/main.c b/sys/src/9/bitsy/main.c index 041b780c1..ac5e9caf8 100644 --- a/sys/src/9/bitsy/main.c +++ b/sys/src/9/bitsy/main.c @@ -243,6 +243,11 @@ procsetup(Proc *p) p->fpstate = FPinit; } +void +procfork(Proc*) +{ +} + /* * Save the mach dependent part of the process state. */ diff --git a/sys/src/9/kw/arch.c b/sys/src/9/kw/arch.c index c800ffc77..e481d5c58 100644 --- a/sys/src/9/kw/arch.c +++ b/sys/src/9/kw/arch.c @@ -126,6 +126,11 @@ procsetup(Proc* p) fpusysprocsetup(p); } +void +procfork(Proc *) +{ +} + /* * Save the mach dependent part of the process state. */ diff --git a/sys/src/9/kw/fns.h b/sys/src/9/kw/fns.h index fcaa647da..18ea068e9 100644 --- a/sys/src/9/kw/fns.h +++ b/sys/src/9/kw/fns.h @@ -68,6 +68,7 @@ extern void pidput(u32int); void procrestore(Proc *); void procsave(Proc*); void procsetup(Proc*); +void procfork(Proc*); extern void _reset(void); extern void setr13(int, u32int*); extern void syscallfmt(int syscallno, ulong pc, va_list list); diff --git a/sys/src/9/mtx/fns.h b/sys/src/9/mtx/fns.h index b4cc6e02b..f03e79e3a 100644 --- a/sys/src/9/mtx/fns.h +++ b/sys/src/9/mtx/fns.h @@ -85,6 +85,7 @@ void pcisetbme(Pcidev*); #define procrestore(p) void procsave(Proc*); void procsetup(Proc*); +void procfork(Proc*); void putdec(ulong); void puthid0(ulong); void puthid1(ulong); diff --git a/sys/src/9/mtx/main.c b/sys/src/9/mtx/main.c index cde420688..92c8787e9 100644 --- a/sys/src/9/mtx/main.c +++ b/sys/src/9/mtx/main.c @@ -259,6 +259,11 @@ procsetup(Proc *p) p->fpstate = FPinit; } +void +procfork(Proc *) +{ +} + /* * Save the mach dependent part of the process state. */ diff --git a/sys/src/9/omap/arch.c b/sys/src/9/omap/arch.c index a9b9537a9..53fb71e85 100644 --- a/sys/src/9/omap/arch.c +++ b/sys/src/9/omap/arch.c @@ -126,6 +126,11 @@ procsetup(Proc* p) fpusysprocsetup(p); } +void +procfork(Proc*) +{ +} + /* * Save the mach dependent part of the process state. */ diff --git a/sys/src/9/omap/fns.h b/sys/src/9/omap/fns.h index 3f7bbfedc..342af1604 100644 --- a/sys/src/9/omap/fns.h +++ b/sys/src/9/omap/fns.h @@ -70,6 +70,7 @@ extern vlong probeaddr(uintptr); extern void procrestore(Proc *); extern void procsave(Proc*); extern void procsetup(Proc*); +extern void procfork(Proc*); extern void _reset(void); extern void screenclockson(void); extern void screeninit(void); diff --git a/sys/src/9/pc/dat.h b/sys/src/9/pc/dat.h index 4786d8967..13c8a2a80 100644 --- a/sys/src/9/pc/dat.h +++ b/sys/src/9/pc/dat.h @@ -108,6 +108,12 @@ struct Conf int nuart; /* number of uart devices */ }; +struct Segdesc +{ + ulong d0; + ulong d1; +}; + /* * MMU stuff in proc */ @@ -120,6 +126,10 @@ struct PMMU Page* kmaptable; /* page table used by kmap */ uint lastkmap; /* last entry used by kmap */ int nkmap; /* number of current kmaps */ + + Segdesc gdt[NPROCSEG]; /* per process descriptors */ + Segdesc *ldt; /* local descriptor table */ + int nldt; /* number of ldt descriptors allocated */ }; /* @@ -163,12 +173,6 @@ typedef struct { ulong iomap; /* I/O map base address + T-bit */ } Tss; -struct Segdesc -{ - ulong d0; - ulong d1; -}; - struct Mach { int machno; /* physical id of processor (KNOWN TO ASSEMBLY) */ diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h index e376e7280..c612a2c59 100644 --- a/sys/src/9/pc/fns.h +++ b/sys/src/9/pc/fns.h @@ -87,6 +87,7 @@ void kbdenable(void); void kbdinit(void); #define kmapinval() void lgdt(ushort[3]); +void lldt(ulong); void lidt(ushort[3]); void links(void); void ltr(ulong); @@ -147,6 +148,7 @@ int pdbmap(ulong*, ulong, ulong, int); void procrestore(Proc*); void procsave(Proc*); void procsetup(Proc*); +void procfork(Proc*); void putcr0(ulong); void putcr3(ulong); void putcr4(ulong); @@ -173,7 +175,6 @@ void umbrwfree(ulong, int); ulong upaalloc(int, int); void upafree(ulong, int); void upareserve(ulong, int); -#define userureg(ur) (((ur)->cs & 0xFFFF) == UESEL) void vectortable(void); void* vmap(ulong, int); int vmapsync(ulong); @@ -182,6 +183,7 @@ void wbinvd(void); void wrmsr(int, vlong); int xchgw(ushort*, int); +#define userureg(ur) (((ur)->cs & 3) == 3) #define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1])) #define KADDR(a) kaddr(a) #define PADDR(a) paddr((void*)(a)) diff --git a/sys/src/9/pc/io.h b/sys/src/9/pc/io.h index eb8dac7e8..197a91799 100644 --- a/sys/src/9/pc/io.h +++ b/sys/src/9/pc/io.h @@ -10,6 +10,8 @@ enum { VectorCNA = 7, /* coprocessor not available */ Vector2F = 8, /* double fault */ VectorCSO = 9, /* coprocessor segment overrun */ + VectorSNP = 11, /* segment not present */ + VectorGPF = 13, /* general protection fault */ VectorPF = 14, /* page fault */ Vector15 = 15, /* reserved */ VectorCERR = 16, /* coprocessor error */ diff --git a/sys/src/9/pc/l.s b/sys/src/9/pc/l.s index 7d971a9ad..3cc9170dc 100644 --- a/sys/src/9/pc/l.s +++ b/sys/src/9/pc/l.s @@ -243,6 +243,17 @@ _idle: HLT JMP _idle + +TEXT load_fs(SB), $0 + MOVW fs+0(FP), AX + MOVW AX, FS + RET + +TEXT load_gs(SB), $0 + MOVW gs+0(FP), AX + MOVW AX, GS + RET + /* * Save registers. */ @@ -601,6 +612,11 @@ TEXT lgdt(SB), $0 /* GDTR - global descriptor table */ MOVL (AX), GDTR RET +TEXT lldt(SB), $0 /* LDTR - local descriptor table */ + MOVL sel+0(FP), AX + BYTE $0x0F; BYTE $0x00; BYTE $0xD0 /* LLDT AX */ + RET + TEXT lidt(SB), $0 /* IDTR - interrupt descriptor table */ MOVL idtptr+0(FP), AX MOVL (AX), IDTR diff --git a/sys/src/9/pc/main.c b/sys/src/9/pc/main.c index d82dacf36..ff928af2e 100644 --- a/sys/src/9/pc/main.c +++ b/sys/src/9/pc/main.c @@ -225,8 +225,7 @@ userinit(void) kstrdup(&p->text, "*init*"); kstrdup(&p->user, eve); - p->fpstate = FPinit; - fpoff(); + procsetup(p); /* * Kernel Stack @@ -585,6 +584,24 @@ procsetup(Proc*p) { p->fpstate = FPinit; fpoff(); + + memset(p->gdt, 0, sizeof(p->gdt)); + p->ldt = nil; + p->nldt = 0; +} + +void +procfork(Proc *p) +{ + /* inherit user descriptors */ + memmove(p->gdt, up->gdt, sizeof(p->gdt)); + + /* copy local descriptor table */ + if(up->ldt != nil && up->nldt > 0){ + p->ldt = malloc(sizeof(Segdesc) * up->nldt); + memmove(p->ldt, up->ldt, sizeof(Segdesc) * up->nldt); + p->nldt = up->nldt; + } } void diff --git a/sys/src/9/pc/mem.h b/sys/src/9/pc/mem.h index 184e86c72..24b8260b3 100644 --- a/sys/src/9/pc/mem.h +++ b/sys/src/9/pc/mem.h @@ -92,8 +92,10 @@ #define APMCSEG16 7 /* APM 16-bit code segment */ #define APMDSEG 8 /* APM data segment */ #define KESEG16 9 /* kernel executable 16-bit */ -#define NGDT 10 /* number of GDT entries required */ -/* #define APM40SEG 8 /* APM segment 0x40 */ +#define LDTSEG 10 /* local descriptor table */ +#define PROCSEG0 11 /* per process descriptor0 */ +#define NPROCSEG 3 /* number of per process descriptors */ +#define NGDT 14 /* number of GDT entries required */ #define SELGDT (0<<2) /* selector is in gdt */ #define SELLDT (1<<2) /* selector is in ldt */ @@ -109,7 +111,7 @@ #define APMCSEL SELECTOR(APMCSEG, SELGDT, 0) #define APMCSEL16 SELECTOR(APMCSEG16, SELGDT, 0) #define APMDSEL SELECTOR(APMDSEG, SELGDT, 0) -/* #define APM40SEL SELECTOR(APM40SEG, SELGDT, 0) */ +#define LDTSEL SELECTOR(LDTSEG, SELGDT, 0) /* * fields in segment descriptors @@ -120,6 +122,7 @@ #define SEGCG (0x0C<<8) /* call gate */ #define SEGIG (0x0E<<8) /* interrupt gate */ #define SEGTG (0x0F<<8) /* trap gate */ +#define SEGLDT (0x02<<8) /* local descriptor table */ #define SEGTYPE (0x1F<<8) #define SEGP (1<<15) /* segment present */ diff --git a/sys/src/9/pc/mmu.c b/sys/src/9/pc/mmu.c index 823c9a6d8..8e7506f7a 100644 --- a/sys/src/9/pc/mmu.c +++ b/sys/src/9/pc/mmu.c @@ -294,6 +294,8 @@ void mmuswitch(Proc* proc) { ulong *pdb; + ulong x; + int n; if(proc->newtlb){ mmuptefree(proc); @@ -307,6 +309,14 @@ mmuswitch(Proc* proc) taskswitch(proc->mmupdb->pa, (ulong)(proc->kstack+KSTACK)); }else taskswitch(PADDR(m->pdb), (ulong)(proc->kstack+KSTACK)); + + memmove(&m->gdt[PROCSEG0], proc->gdt, sizeof(proc->gdt)); + if((x = (ulong)proc->ldt) && (n = proc->nldt) > 0){ + m->gdt[LDTSEG].d0 = (x<<16)|((n * sizeof(Segdesc)) - 1); + m->gdt[LDTSEG].d1 = (x&0xFF000000)|((x>>16)&0xFF)|SEGLDT|SEGPL(0)|SEGP; + lldt(LDTSEL); + } else + lldt(NULLSEL); } /* @@ -366,6 +376,11 @@ mmurelease(Proc* proc) if(proc->mmufree && palloc.r.p) wakeup(&palloc.r); proc->mmufree = 0; + if(proc->ldt){ + free(proc->ldt); + proc->ldt = nil; + proc->nldt = 0; + } } /* diff --git a/sys/src/9/pc/pccpuf b/sys/src/9/pc/pccpuf index 6b5c4281e..f480af1d8 100644 --- a/sys/src/9/pc/pccpuf +++ b/sys/src/9/pc/pccpuf @@ -35,6 +35,7 @@ dev usb link + segdesc realmode devpccard devi82365 diff --git a/sys/src/9/pc/pcf b/sys/src/9/pc/pcf index 1d8ece9cb..24019ee18 100644 --- a/sys/src/9/pc/pcf +++ b/sys/src/9/pc/pcf @@ -37,6 +37,7 @@ dev usb link + segdesc realmode devpccard devi82365 diff --git a/sys/src/9/pc/segdesc.c b/sys/src/9/pc/segdesc.c new file mode 100644 index 000000000..5fcdde7df --- /dev/null +++ b/sys/src/9/pc/segdesc.c @@ -0,0 +1,261 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + +/* + * flags: + * P = present + * A = accessed (for code/data) + * E = expand down (for data) + * W = writable (for data) + * R = readable (for code) + * C = conforming (for code) + * G = limit granularity in pages (for code/data) + * D = 32 bit operand size (for code) + * B = 32 bit stack pointer (for data) + * Y = busy (for tss and tss16) + * U = available for use by system software + */ + +static struct { + char *name; + char *flags; +} descrtypes[] = { + "data", "--------AWE01--P----U.BG--------", + "code", "--------ARC11--P----U.DG--------", + "tss16", "--------1Y000--P----U..G--------", + "ldt", "--------01000--P----U..G--------", + "callg16", "--------00100--P----U..G--------", + "taskg", "--------10100--P----U..G--------", + "intrg16", "--------01100--P----U..G--------", + "trapg16", "--------11100--P----U..G--------", + "tss", "--------1Y010--P----U..G--------", + "callg", "--------00110--P----U..G--------", + "intrg", "--------01110--P----U..G--------", + "trapg", "--------11110--P----U..G--------", +}; + +/* + * format: + * idx[4] type[8] flags[8] dpl[1] base[8] limit[5]\n + */ + +enum +{ + RECLEN = 4+1 + 8+1 + 8+1 + 1+1 + 8+1 + 5+1, +}; + +static long +descwrite(Proc *proc, int local, void *v, long n, vlong) +{ + int i, j, t; + char buf[RECLEN+1]; + char c, *p, *s, *e, *f[6]; + Segdesc d; + + int dpl; + ulong base; + ulong limit; + + s = (char*)v; + e = s + n; + + if(waserror()){ + if(proc == up) + flushmmu(); + nexterror(); + } + + while(s < e){ + for(p = s; p < e && *p != '\n'; p++); + ; + if((p - s) > RECLEN) + error(Ebadarg); + memmove(buf, s, p - s); + buf[p-s] = 0; + s = p+1; + + if(getfields(buf, f, nelem(f), 1, " ") != nelem(f)) + error(Ebadarg); + + i = strtoul(f[0], nil, 16); + + for(t=0; t<nelem(descrtypes); t++) + if(strcmp(descrtypes[t].name, f[1]) == 0) + break; + if(t == nelem(descrtypes)) + error(Ebadarg); + + dpl = atoi(f[3]); + base = strtoul(f[4], nil, 16); + limit = strtoul(f[5], nil, 16); + + d.d0 = ((base & 0xFFFF)<<16) | (limit & 0xFFFF); + d.d1 = (base & 0xFF000000) | (limit & 0xF0000) | ((dpl & 3)<<13) | ((base & 0xFF0000)>>16); + + for(j=0; c = descrtypes[t].flags[j]; j++){ + switch(c){ + default: + if(strchr(f[2], c) == nil){ + case '0': + case '.': + d.d1 &= ~(1<<j); + break; + } else { + case '1': + d.d1 |= (1<<j); + break; + } + case '-': + continue; + } + } + + /* dont allow system segments */ + if((d.d1 & SEGP) && ((dpl != 3) || !(d.d1 & (1<<12)))) + error(Eperm); + + if(local){ + Segdesc *new, *old; + int c; + + if(i < 0 || i >= 8192) + error(Ebadarg); + if(i >= (c = ((old = proc->ldt) ? proc->nldt : 0))){ + if((new = malloc(sizeof(Segdesc) * (i+1))) == nil) + error(Enomem); + if(c > 0) + memmove(new, old, sizeof(Segdesc) * c); + memset(new + c, 0, sizeof(Segdesc) * ((i+1) - c)); + proc->ldt = new; + proc->nldt = i+1; + free(old); + } + proc->ldt[i] = d; + } else { + if(i < PROCSEG0 || i >= PROCSEG0 + NPROCSEG) + error(Ebadarg); + proc->gdt[i - PROCSEG0] = d; + } + } + poperror(); + + if(proc == up) + flushmmu(); + + return n; +} + +static long +descread(Proc *proc, int local, void *v, long n, vlong o) +{ + int i, j, k, t; + char *s; + + int dpl; + ulong base; + ulong limit; + + s = v; + for(i = 0;;i++){ + Segdesc d; + + if(local){ + if(proc->ldt == nil || i >= proc->nldt) + break; + d = proc->ldt[i]; + } else { + if(i < PROCSEG0) + i = PROCSEG0; + if(i >= PROCSEG0 + NPROCSEG) + break; + d = proc->gdt[i - PROCSEG0]; + } + + if(o >= RECLEN){ + o -= RECLEN; + continue; + } + + if(s + RECLEN+1 >= (char*)v + n) + break; + + for(t=0; t<nelem(descrtypes); t++){ + for(j=0; descrtypes[t].flags[j]; j++){ + if(descrtypes[t].flags[j]=='0' && (d.d1 & (1<<j)) != 0) + break; + if(descrtypes[t].flags[j]=='1' && (d.d1 & (1<<j)) == 0) + break; + } + if(descrtypes[t].flags[j] == 0) + break; + } + if(t == nelem(descrtypes)) + t = 0; + + s += sprint(s, "%.4lux ", (ulong)i); + s += sprint(s, "%-8s ", descrtypes[t].name); + + k = 0; + for(j=0; descrtypes[t].flags[j]; j++){ + switch(descrtypes[t].flags[j]){ + case '-': + case '.': + case '0': + case '1': + continue; + } + if(d.d1 & (1 << j)) + s[k++] = descrtypes[t].flags[j]; + } + if(k == 0) + s[k++] = '-'; + while(k < 9) + s[k++] = ' '; + s += k; + + dpl = (d.d1 & 0x6000)>>13; + base = ((d.d0 & 0xFFFF0000)>>16) | ((d.d1 & 0xFF)<<16) | (d.d1 & 0xFF000000); + limit = (d.d1 & 0xF0000) | (d.d0 & 0xFFFF); + + s += sprint(s, "%.1d ", dpl); + s += sprint(s, "%.8lux ", base); + s += sprint(s, "%.5lux\n", limit); + } + + return s-(char*)v; +} + +static long +gdtread(Chan*, void *v, long n, vlong o) +{ + return descread(up, 0, v, n, o); +} + +static long +gdtwrite(Chan*, void *v, long n, vlong o) +{ + return descwrite(up, 0, v, n, o); +} + +static long +ldtread(Chan*, void *v, long n, vlong o) +{ + return descread(up, 1, v, n, o); +} + +static long +ldtwrite(Chan*, void *v, long n, vlong o) +{ + return descwrite(up, 1, v, n, o); +} + +void +segdesclink(void) +{ + addarchfile("gdt", 0666, gdtread, gdtwrite); + addarchfile("ldt", 0666, ldtread, ldtwrite); +} diff --git a/sys/src/9/pc/trap.c b/sys/src/9/pc/trap.c index 17ca545c5..08033a9ee 100644 --- a/sys/src/9/pc/trap.c +++ b/sys/src/9/pc/trap.c @@ -326,7 +326,7 @@ trap(Ureg* ureg) } m->perf.intrts = perfticks(); - user = (ureg->cs & 0xFFFF) == UESEL; + user = userureg(ureg); if(user){ up->dbgreg = ureg; cycles(&up->kentry); @@ -424,6 +424,48 @@ trap(Ureg* ureg) while(m->machno != 0) ; } + + if(vno == VectorGPF || vno == VectorSNP){ + ulong *sp; + uchar *pc; + + /* l.s */ + extern void load_fs(ulong); + extern void load_gs(ulong); + + /* + * CS, SS, DS and ES are initialized by strayintr + * in l.s. initialize the others too so we dont trap + * again when restoring the old context. + */ + load_fs(NULLSEL); + load_gs(NULLSEL); + + pc = (uchar*)ureg->pc; + sp = (ulong*)&ureg->sp; + + /* + * we test for the instructions used by forkret() + * to load the segments. this needs to be changed + * if forkret changes! + */ + + /* POP */ + if((pc[0] == 0x0f && (pc[1] == 0xa9 /*GS*/ || + pc[1] == 0xa1 /*FS*/)) || (pc[0] == 0x07) /*ES*/ || + (pc[0] == 0x1f) /*DS*/){ + sp[0] = NULLSEL; + return; + } + + /* IRET */ + if(pc[0] == 0xcf){ + sp[1] = UESEL; /*CS*/ + sp[4] = UDSEL; /*SS*/ + return; + } + } + dumpregs(ureg); if(!user){ ureg->sp = (ulong)&ureg->sp; @@ -461,7 +503,10 @@ dumpregs2(Ureg* ureg) iprint("cpu%d: registers for kernel\n", m->machno); iprint("FLAGS=%luX TRAP=%luX ECODE=%luX PC=%luX", ureg->flags, ureg->trap, ureg->ecode, ureg->pc); - iprint(" SS=%4.4luX USP=%luX\n", ureg->ss & 0xFFFF, ureg->usp); + if(userureg(ureg)) + iprint(" SS=%4.4luX USP=%luX\n", ureg->ss & 0xFFFF, ureg->usp); + else + iprint(" SP=%luX\n", (ulong)&ureg->sp); iprint(" AX %8.8luX BX %8.8luX CX %8.8luX DX %8.8luX\n", ureg->ax, ureg->bx, ureg->cx, ureg->dx); iprint(" SI %8.8luX DI %8.8luX BP %8.8luX\n", @@ -619,7 +664,7 @@ fault386(Ureg* ureg, void*) addr = getcr2(); read = !(ureg->ecode & 2); - user = (ureg->cs & 0xFFFF) == UESEL; + user = userureg(ureg); if(!user){ if(vmapsync(addr)) return; @@ -666,7 +711,7 @@ syscall(Ureg* ureg) ulong scallnr; vlong startns, stopns; - if((ureg->cs & 0xFFFF) != UESEL) + if(!userureg(ureg)) panic("syscall: cs 0x%4.4luX", ureg->cs); cycles(&up->kentry); @@ -850,6 +895,8 @@ if(0) print("%s %lud: notify %.8lux %.8lux %.8lux %s\n", *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */ ureg->usp = sp; ureg->pc = (ulong)up->notify; + ureg->cs = UESEL; + ureg->ss = ureg->ds = ureg->es = UDSEL; up->notified = 1; up->nnote--; memmove(&up->lastnote, &up->note[0], sizeof(Note)); @@ -889,23 +936,10 @@ noted(Ureg* ureg, ulong arg0) pexit("Suicide", 0); } - /* - * Check the segment selectors are all valid, otherwise - * a fault will be taken on attempting to return to the - * user process. - * Take care with the comparisons as different processor - * generations push segment descriptors in different ways. - */ - if((nureg->cs & 0xFFFF) != UESEL || (nureg->ss & 0xFFFF) != UDSEL - || (nureg->ds & 0xFFFF) != UDSEL || (nureg->es & 0xFFFF) != UDSEL - || (nureg->fs & 0xFFFF) != UDSEL || (nureg->gs & 0xFFFF) != UDSEL){ - qunlock(&up->debug); - pprint("bad segment selector in noted\n"); - pexit("Suicide", 0); - } - /* don't let user change system flags */ nureg->flags = (ureg->flags & ~0xCD5) | (nureg->flags & 0xCD5); + nureg->cs |= 3; + nureg->ss |= 3; memmove(ureg, nureg, sizeof(Ureg)); @@ -968,6 +1002,9 @@ execregs(ulong entry, ulong ssize, ulong nargs) ureg = up->dbgreg; ureg->usp = (ulong)sp; ureg->pc = entry; + ureg->cs = UESEL; + ureg->ss = ureg->ds = ureg->es = UDSEL; + ureg->fs = ureg->gs = NULLSEL; return USTKTOP-sizeof(Tos); /* address of kernel/user shared data */ } @@ -989,23 +1026,13 @@ userpc(void) void setregisters(Ureg* ureg, char* pureg, char* uva, int n) { - ulong cs, ds, es, flags, fs, gs, ss; + ulong flags; - ss = ureg->ss; flags = ureg->flags; - cs = ureg->cs; - ds = ureg->ds; - es = ureg->es; - fs = ureg->fs; - gs = ureg->gs; memmove(pureg, uva, n); - ureg->gs = gs; - ureg->fs = fs; - ureg->es = es; - ureg->ds = ds; - ureg->cs = cs; - ureg->flags = (ureg->flags & 0x00FF) | (flags & 0xFF00); - ureg->ss = ss; + ureg->flags = (ureg->flags & 0xCD5) | (flags & ~0xCD5); + ureg->cs |= 3; + ureg->ss |= 3; } static void diff --git a/sys/src/9/port/sysproc.c b/sys/src/9/port/sysproc.c index 0048dc0b9..b49410d26 100644 --- a/sys/src/9/port/sysproc.c +++ b/sys/src/9/port/sysproc.c @@ -187,6 +187,9 @@ sysrfork(ulong *arg) kstrdup(&p->text, up->text); kstrdup(&p->user, up->user); + + procfork(p); + /* * since the bss/data segments are now shareable, * any mmu info about this process is now stale @@ -472,11 +475,6 @@ sysexec(ulong *arg) poperror(); cclose(tc); - /* - * At this point, the mmu contains info about the old address - * space and needs to be flushed - */ - flushmmu(); qlock(&up->debug); up->nnote = 0; up->notify = 0; @@ -484,9 +482,15 @@ sysexec(ulong *arg) up->privatemem = 0; procsetup(up); qunlock(&up->debug); + + /* + * At this point, the mmu contains info about the old address + * space and needs to be flushed + */ + flushmmu(); + if(up->hang) up->procctl = Proc_stopme; - return execregs(entry, ssize, nargs); } diff --git a/sys/src/9/ppc/fns.h b/sys/src/9/ppc/fns.h index 56b6aceab..d338f02fc 100644 --- a/sys/src/9/ppc/fns.h +++ b/sys/src/9/ppc/fns.h @@ -77,6 +77,7 @@ void pcicfgw32(Pcidev*, int, int); void pcicfgw8(Pcidev*, int, int); void procsave(Proc*); void procsetup(Proc*); +void procfork(Proc*); void putdcmp(ulong); void putdec(ulong); void puthash1(ulong); diff --git a/sys/src/9/ppc/main.c b/sys/src/9/ppc/main.c index 380d6fd6f..311d83105 100644 --- a/sys/src/9/ppc/main.c +++ b/sys/src/9/ppc/main.c @@ -287,6 +287,11 @@ procsetup(Proc *p) } void +procfork(Proc *) +{ +} + +void procrestore(Proc *p) { uvlong t; |