diff --git a/lib/theo b/lib/theo index 8c1cf546a..1a4b71a26 100644 --- a/lib/theo +++ b/lib/theo @@ -905,3 +905,8 @@ No. No. Not going to explain further. Get your shit together +oh my, the moral outrage +Let it go, and consider leaving for good. +Do you have evidence? +Diffs are welcome. +Please don't do that. diff --git a/sys/games/lib/fortunes b/sys/games/lib/fortunes index adb2e9ff5..e5d2e27a2 100644 --- a/sys/games/lib/fortunes +++ b/sys/games/lib/fortunes @@ -5248,3 +5248,4 @@ I've been looking into running Plan 9 in JSLinux -- Skip Tavakkolian i have been looking for an excuse to install 9front. I'm beginning to wonder if anyone is left that isn't part of 9front? -- Steve Stallion Having a public mailing list is an invitation for discussion amongst likeminded individuals, not elitist fuckery. -- Steve Stallion, talking about 9fans +[9fans] ..... UNSUBSCRIBE_HELP NEEDED diff --git a/sys/include/dtracy.h b/sys/include/dtracy.h index 3e2ff81f1..cd8d577b3 100644 --- a/sys/include/dtracy.h +++ b/sys/include/dtracy.h @@ -41,6 +41,8 @@ struct DTName { /* we assign all pairs (probe,action-group) (called an enabling or DTEnab) a unique ID called EPID. we could also use probe IDs and action group IDs but using a single 32-bit ID for both is more flexible/efficient. + + epid == -1 indicates a fault record (see below) */ struct DTEnab { u32int epid; @@ -235,6 +237,10 @@ struct DTTrigInfo { DTChan *ch; }; +/* fault records are used to note when a probe had to be aborted (e.g. because of a page fault) */ +enum { + DTFILL = 1, /* illegal address */ +}; void dtinit(int); void dtsync(void); @@ -269,6 +275,7 @@ int dtcread(DTChan *, void *, int); int dtcaggread(DTChan *, void *, int); void dtcreset(DTChan *); void dtcrun(DTChan *, int); +int dtcfault(DTTrigInfo *, int, char *, ...); /* aggbuf functions */ int dtaunpackid(DTAgg *); diff --git a/sys/src/9/pc/l.s b/sys/src/9/pc/l.s index 217088ecb..5f40295ef 100644 --- a/sys/src/9/pc/l.s +++ b/sys/src/9/pc/l.s @@ -511,6 +511,17 @@ TEXT _wrmsrinst(SB), $0 MOVL BP, AX /* BP set to -1 if traped */ RET +/* fault-proof memcpy */ +TEXT peek(SB), $0 + MOVL src+0(FP), SI + MOVL dst+4(FP), DI + MOVL cnt+8(FP), CX + CLD +TEXT _peekinst(SB), $0 + REP; MOVSB + MOVL CX, AX + RET + /* * Try to determine the CPU type which requires fiddling with EFLAGS. * If the Id bit can be toggled then the CPUID instruction can be used diff --git a/sys/src/9/pc/mkfile b/sys/src/9/pc/mkfile index ee05c3a29..6b43feddc 100644 --- a/sys/src/9/pc/mkfile +++ b/sys/src/9/pc/mkfile @@ -67,6 +67,7 @@ LIB=\ /$objtype/lib/libmp.a\ /$objtype/lib/libfis.a\ /$objtype/lib/libaml.a\ + /$objtype/lib/libdtracy.a\ ETHER=`{echo devether.c ether*.c | sed 's/\.c/.'$O'/g'} AUDIO=`{echo devaudio.c audio*.c | sed 's/\.c/.'$O'/g'} diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc index ffdb41a4a..86c5c8b1e 100644 --- a/sys/src/9/pc/pc +++ b/sys/src/9/pc/pc @@ -18,6 +18,7 @@ dev cap kprof fs + dtracy ether netif bridge netif log @@ -137,6 +138,9 @@ misc vgatvp3026 =cur vgavesa vgavmware +cur + + dtracysys + dtracytimer ip tcp diff --git a/sys/src/9/pc/trap.c b/sys/src/9/pc/trap.c index b76afaff2..0d74f0a98 100644 --- a/sys/src/9/pc/trap.c +++ b/sys/src/9/pc/trap.c @@ -450,6 +450,7 @@ trap(Ureg* ureg) extern void _forkretiret(void); extern void _rdmsrinst(void); extern void _wrmsrinst(void); + extern void _peekinst(void); extern void load_fs(ulong); extern void load_gs(ulong); @@ -478,6 +479,11 @@ trap(Ureg* ureg) ureg->pc += 2; return; } + } else if(pc == _peekinst){ + if(vno == VectorGPF){ + ureg->pc += 2; + return; + } } } @@ -712,6 +718,13 @@ fault386(Ureg* ureg, void*) if(!user){ if(vmapsync(addr)) return; + { + extern void _peekinst(void); + if((void(*)(void))ureg->pc == _peekinst){ + ureg->pc += 2; + return; + } + } if(addr >= USTKTOP) panic("kernel fault: bad address pc=0x%.8lux addr=0x%.8lux", ureg->pc, addr); if(up == nil) diff --git a/sys/src/9/pc64/l.s b/sys/src/9/pc64/l.s index 7143d3b69..c00a24fc7 100644 --- a/sys/src/9/pc64/l.s +++ b/sys/src/9/pc64/l.s @@ -449,6 +449,18 @@ TEXT _wrmsrinst(SB), $0 MOVQ BP, AX /* BP set to -1 if traped */ RET +/* fault-proof memcpy */ +TEXT peek(SB), 1, $-4 + MOVQ RARG, SI + MOVQ dst+8(FP), DI + MOVL cnt+16(FP), CX + CLD +TEXT _peekinst(SB), $0 + REP; MOVSB + MOVL CX, AX + RET + + TEXT invlpg(SB), 1, $-4 INVLPG (RARG) RET diff --git a/sys/src/9/pc64/mkfile b/sys/src/9/pc64/mkfile index 51204dcee..fc0b5af09 100644 --- a/sys/src/9/pc64/mkfile +++ b/sys/src/9/pc64/mkfile @@ -65,6 +65,7 @@ LIB=\ /$objtype/lib/libc.a\ /$objtype/lib/libfis.a\ /$objtype/lib/libaml.a\ + /$objtype/lib/libdtracy.a\ ETHER=`{cd ../pc; echo devether.c ether*.c | sed 's/\.c/.'$O'/g'} AUDIO=`{cd ../pc; echo devaudio.c audio*.c | sed 's/\.c/.'$O'/g'} diff --git a/sys/src/9/pc64/pc64 b/sys/src/9/pc64/pc64 index ca464f96b..e3ce365d9 100644 --- a/sys/src/9/pc64/pc64 +++ b/sys/src/9/pc64/pc64 @@ -41,6 +41,7 @@ dev segment vmx + dtracy link # devpccard @@ -136,6 +137,9 @@ misc vgavesa # vgavmware +cur + dtracysys + dtracytimer + ip tcp udp diff --git a/sys/src/9/pc64/trap.c b/sys/src/9/pc64/trap.c index 1944f43bd..23c1e9b69 100644 --- a/sys/src/9/pc64/trap.c +++ b/sys/src/9/pc64/trap.c @@ -440,6 +440,7 @@ trap(Ureg *ureg) extern void _rdmsrinst(void); extern void _wrmsrinst(void); + extern void _peekinst(void); pc = (void*)ureg->pc; if(pc == _rdmsrinst || pc == _wrmsrinst){ @@ -448,6 +449,11 @@ trap(Ureg *ureg) ureg->pc += 2; return; } + } else if(pc == _peekinst){ + if(vno == VectorGPF){ + ureg->pc += 2; + return; + } } } @@ -672,6 +678,14 @@ faultamd64(Ureg* ureg, void*) read = !(ureg->error & 2); user = userureg(ureg); if(!user){ + { + extern void _peekinst(void); + + if((void(*)(void))ureg->pc == _peekinst){ + ureg->pc += 2; + return; + } + } if(addr >= USTKTOP) panic("kernel fault: bad address pc=%#p addr=%#p", ureg->pc, addr); if(up == nil) diff --git a/sys/src/9/port/devdtracy.c b/sys/src/9/port/devdtracy.c index 82d2d0a27..4bd47ca0e 100644 --- a/sys/src/9/port/devdtracy.c +++ b/sys/src/9/port/devdtracy.c @@ -125,9 +125,13 @@ dtkfree(DTKChan *p) dtktab[idx] = nil; } +static int dtracyen; + static void dtracyinit(void) { + dtracyen = getconf("*dtracy") != nil; + if(!dtracyen) return; machlocks = smalloc(sizeof(Lock) * conf.nmach); dtinit(conf.nmach); } @@ -135,6 +139,8 @@ dtracyinit(void) static Chan* dtracyattach(char *spec) { + if(!dtracyen) + error("*dtracy= not set"); return devattach(L'Δ', spec); } @@ -512,67 +518,16 @@ dtgetvar(int v) } } +int peek(char *, char *, int); + int dtpeek(uvlong addr, void *buf, int len) { - if((uintptr)addr != addr || up == nil || !okaddr((uintptr) addr, len, 0)) return -1; - memmove(buf, (void *) addr, len); - return 0; -} - -static DTProbe *timerprobe; - -static void -dtracytimer(void *) -{ - DTTrigInfo info; - - memset(&info, 0, sizeof(info)); - for(;;){ - tsleep(&up->sleep, return0, nil, 1000); - dtptrigger(timerprobe, m->machno, &info); - } -} - -static void -timerprovide(DTProvider *prov, DTName) -{ - static int provided; + uintptr a; - if(provided) return; - provided = 1; - timerprobe = dtpnew((DTName){"timer", "", "1s"}, prov, nil); + a = addr; + if(len == 0) return 0; + if(a != addr || a > -(uintptr)len || len < 0) return -1; + if(up == nil || up->privatemem || a >= KZERO) return -1; + return peek((void *)a, buf, len) > 0 ? -1 : 0; } - -static int -timerenable(DTProbe *) -{ - static int gotkproc; - - if(!gotkproc){ - kproc("dtracytimer", dtracytimer, nil); - gotkproc=1; - } - return 0; -} - -static void -timerdisable(DTProbe *) -{ -} - -DTProvider dtracyprov_timer = { - .name = "timer", - .provide = timerprovide, - .enable = timerenable, - .disable = timerdisable, -}; - -extern DTProvider dtracyprov_sys; - -DTProvider *dtproviders[] = { - &dtracyprov_timer, - &dtracyprov_sys, - nil, -}; - diff --git a/sys/src/9/port/dtracysys.c b/sys/src/9/port/dtracysys.c index c9e0f4e5a..859dd9f84 100644 --- a/sys/src/9/port/dtracysys.c +++ b/sys/src/9/port/dtracysys.c @@ -260,7 +260,7 @@ sysdisable(DTProbe *p) z = systab[i], systab[i] = wraptab[i], wraptab[i] = z; } -DTProvider dtracyprov_sys = { +DTProvider dtracysysprov = { .name = "sys", .provide = sysprovide, .enable = sysenable, diff --git a/sys/src/9/port/dtracytimer.c b/sys/src/9/port/dtracytimer.c new file mode 100644 index 000000000..cb3b636f6 --- /dev/null +++ b/sys/src/9/port/dtracytimer.c @@ -0,0 +1,56 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + +#include + +static DTProbe *timerprobe; + +static void +dtracytimer(void *) +{ + DTTrigInfo info; + + memset(&info, 0, sizeof(info)); + for(;;){ + tsleep(&up->sleep, return0, nil, 1000); + dtptrigger(timerprobe, m->machno, &info); + } +} + +static void +timerprovide(DTProvider *prov, DTName) +{ + static int provided; + + if(provided) return; + provided = 1; + timerprobe = dtpnew((DTName){"timer", "", "1s"}, prov, nil); +} + +static int +timerenable(DTProbe *) +{ + static int gotkproc; + + if(!gotkproc){ + kproc("dtracytimer", dtracytimer, nil); + gotkproc=1; + } + return 0; +} + +static void +timerdisable(DTProbe *) +{ +} + +DTProvider dtracytimerprov = { + .name = "timer", + .provide = timerprovide, + .enable = timerenable, + .disable = timerdisable, +}; diff --git a/sys/src/9/port/mkdevc b/sys/src/9/port/mkdevc index 283c69a27..8e87636d8 100755 --- a/sys/src/9/port/mkdevc +++ b/sys/src/9/port/mkdevc @@ -58,7 +58,8 @@ collect && section == "misc"{ if($i ~ "[+=]cur") vgacur[nvgacur++] = $1; } - } + }else if($1 ~ "^dtracy.*") + dtracyprov[ndtracyprov++] = $1; } collect && section == "port"{ @@ -190,6 +191,16 @@ END{ printf "%s\n", port[i]; printf "\n"; } + + if(ndtracyprov){ + printf "#include \n"; + for(i = 0; i < ndtracyprov; i++) + printf "extern DTProvider %sprov;\n", dtracyprov[i] + printf "DTProvider *dtproviders[] = {\n" + for(i = 0; i < ndtracyprov; i++) + printf "\t&%sprov,\n", dtracyprov[i] + printf "\tnil,\n};\n\n" + } printf "char* conffile = \"%s/%s\";\n", pwd, ARGV[1]; printf "ulong kerndate = KERNDATE;\n"; diff --git a/sys/src/cmd/dtracy/act.c b/sys/src/cmd/dtracy/act.c index 063be6cb9..3412382c3 100644 --- a/sys/src/cmd/dtracy/act.c +++ b/sys/src/cmd/dtracy/act.c @@ -462,6 +462,34 @@ parseclause(Clause *cl, uchar *p, uchar *e, Enab *en, Biobuf *bp) return 0; } +uchar * +parsefault(uchar *p0, uchar *e) +{ + uchar *p; + u32int epid; + u8int type, dummy; + u16int n; + Enab *en; + + p = unpack(p0, e, "csci", &type, &n, &dummy, &epid); + if(p == nil) return nil; + en = epidlookup(epid); + switch(type){ + case DTFILL: { + u32int pid; + u64int addr; + + p = unpack(p, e, "iv", &pid, &addr); + if(p == nil) return nil; + fprint(2, "dtracy: illegal access: probe=%s, pid=%d, addr=%#llx\n", en != nil ? en->probe : nil, pid, addr); + break; + } + default: + fprint(2, "dtracy: unknown fault type %#.2ux\n", type); + } + return p0 + n - 12; +} + int parsebuf(uchar *p, int n, Biobuf *bp) { @@ -474,6 +502,11 @@ parsebuf(uchar *p, int n, Biobuf *bp) while(p < e){ p = unpack(p, e, "iv", &epid, &ts); if(p == nil) goto err; + if(epid == (u32int)-1){ + p = parsefault(p, e); + if(p == nil) goto err; + continue; + } en = epidlookup(epid); if(en == nil) goto err; if(parseclause(en->cl, p - 12, p + en->reclen - 12, en, bp) < 0) return -1; diff --git a/sys/src/cmd/sshfs.c b/sys/src/cmd/sshfs.c index f85c72dae..d0c21ec74 100644 --- a/sys/src/cmd/sshfs.c +++ b/sys/src/cmd/sshfs.c @@ -1414,4 +1414,6 @@ threadmain(int argc, char **argv) passwdparse(gidtab, readfile(gidfile)); threadpostmountsrv(&sshfssrv, svc, mtpt, MCREATE | mflag); + + exits(nil); } diff --git a/sys/src/libdtracy/prog.c b/sys/src/libdtracy/prog.c index f0637acad..402638f13 100644 --- a/sys/src/libdtracy/prog.c +++ b/sys/src/libdtracy/prog.c @@ -230,6 +230,55 @@ dtpeekstr(uvlong addr, u8int *v, int len) #define PUT4(c) *bp++ = c; *bp++ = c >> 8; *bp++ = c >> 16; *bp++ = c >> 24; #define PUT8(c) PUT4(c); PUT4(c>>32); +int +dtcfault(DTTrigInfo *info, int type, char *fmt, ...) +{ + DTBuf *b; + va_list va; + int n; + char *s; + u8int *bp; + u32int l; + uvlong q; + + b = info->ch->wrbufs[info->machno]; + n = 20; + va_start(va, fmt); + for(s = fmt; *s != 0; s++) + switch(*s){ + case 'i': n += 4; break; + case 'p': n += 8; break; + default: + assert(0); + } + va_end(va); + if(b->wr + n > DTBUFSZ) + return -1; + bp = &b->data[b->wr]; + PUT4(-1); + PUT8(info->ts); + PUT1(type); + PUT2(n); + PUT1(0); + PUT4(info->epid); + va_start(va, fmt); + for(s = fmt; *s != 0; s++) + switch(*s){ + case 'i': + l = va_arg(va, int); + PUT4(l); + break; + case 'p': + q = (uintptr) va_arg(va, void *); + PUT8(q); + break; + } + va_end(va); + assert(bp - b->data - b->wr == n); + b->wr = bp - b->data; + return 0; +} + static int dtgexec(DTActGr *g, DTTrigInfo *info) { @@ -265,8 +314,8 @@ dtgexec(DTActGr *g, DTTrigInfo *info) break; case ACTTRACESTR: if(dtpeekstr(v, bp, g->acts[i].size) < 0){ - snprint(info->ch->errstr, sizeof(info->ch->errstr), "fault @ %#llux", v); - return -1; + dtcfault(info, DTFILL, "ip", dtgetvar(DTV_PID), v); + return 0; } bp += g->acts[i].size; break;