This commit is contained in:
Alex Musolino 2018-12-12 12:51:29 +10:30
commit 9b194f23b2
18 changed files with 242 additions and 63 deletions

View file

@ -905,3 +905,8 @@ No.
No. No.
Not going to explain further. Not going to explain further.
Get your shit together 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.

View file

@ -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 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 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 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

View file

@ -41,6 +41,8 @@ struct DTName {
/* /*
we assign all pairs (probe,action-group) (called an enabling or DTEnab) a unique ID called EPID. 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. 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 { struct DTEnab {
u32int epid; u32int epid;
@ -235,6 +237,10 @@ struct DTTrigInfo {
DTChan *ch; 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 dtinit(int);
void dtsync(void); void dtsync(void);
@ -269,6 +275,7 @@ int dtcread(DTChan *, void *, int);
int dtcaggread(DTChan *, void *, int); int dtcaggread(DTChan *, void *, int);
void dtcreset(DTChan *); void dtcreset(DTChan *);
void dtcrun(DTChan *, int); void dtcrun(DTChan *, int);
int dtcfault(DTTrigInfo *, int, char *, ...);
/* aggbuf functions */ /* aggbuf functions */
int dtaunpackid(DTAgg *); int dtaunpackid(DTAgg *);

View file

@ -511,6 +511,17 @@ TEXT _wrmsrinst(SB), $0
MOVL BP, AX /* BP set to -1 if traped */ MOVL BP, AX /* BP set to -1 if traped */
RET 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. * 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 * If the Id bit can be toggled then the CPUID instruction can be used

View file

@ -67,6 +67,7 @@ LIB=\
/$objtype/lib/libmp.a\ /$objtype/lib/libmp.a\
/$objtype/lib/libfis.a\ /$objtype/lib/libfis.a\
/$objtype/lib/libaml.a\ /$objtype/lib/libaml.a\
/$objtype/lib/libdtracy.a\
ETHER=`{echo devether.c ether*.c | sed 's/\.c/.'$O'/g'} ETHER=`{echo devether.c ether*.c | sed 's/\.c/.'$O'/g'}
AUDIO=`{echo devaudio.c audio*.c | sed 's/\.c/.'$O'/g'} AUDIO=`{echo devaudio.c audio*.c | sed 's/\.c/.'$O'/g'}

View file

@ -18,6 +18,7 @@ dev
cap cap
kprof kprof
fs fs
dtracy
ether netif ether netif
bridge netif log bridge netif log
@ -138,6 +139,9 @@ misc
vgavesa vgavesa
vgavmware +cur vgavmware +cur
dtracysys
dtracytimer
ip ip
tcp tcp
udp udp

View file

@ -450,6 +450,7 @@ trap(Ureg* ureg)
extern void _forkretiret(void); extern void _forkretiret(void);
extern void _rdmsrinst(void); extern void _rdmsrinst(void);
extern void _wrmsrinst(void); extern void _wrmsrinst(void);
extern void _peekinst(void);
extern void load_fs(ulong); extern void load_fs(ulong);
extern void load_gs(ulong); extern void load_gs(ulong);
@ -478,6 +479,11 @@ trap(Ureg* ureg)
ureg->pc += 2; ureg->pc += 2;
return; return;
} }
} else if(pc == _peekinst){
if(vno == VectorGPF){
ureg->pc += 2;
return;
}
} }
} }
@ -712,6 +718,13 @@ fault386(Ureg* ureg, void*)
if(!user){ if(!user){
if(vmapsync(addr)) if(vmapsync(addr))
return; return;
{
extern void _peekinst(void);
if((void(*)(void))ureg->pc == _peekinst){
ureg->pc += 2;
return;
}
}
if(addr >= USTKTOP) if(addr >= USTKTOP)
panic("kernel fault: bad address pc=0x%.8lux addr=0x%.8lux", ureg->pc, addr); panic("kernel fault: bad address pc=0x%.8lux addr=0x%.8lux", ureg->pc, addr);
if(up == nil) if(up == nil)

View file

@ -449,6 +449,18 @@ TEXT _wrmsrinst(SB), $0
MOVQ BP, AX /* BP set to -1 if traped */ MOVQ BP, AX /* BP set to -1 if traped */
RET 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 TEXT invlpg(SB), 1, $-4
INVLPG (RARG) INVLPG (RARG)
RET RET

View file

@ -65,6 +65,7 @@ LIB=\
/$objtype/lib/libc.a\ /$objtype/lib/libc.a\
/$objtype/lib/libfis.a\ /$objtype/lib/libfis.a\
/$objtype/lib/libaml.a\ /$objtype/lib/libaml.a\
/$objtype/lib/libdtracy.a\
ETHER=`{cd ../pc; echo devether.c ether*.c | sed 's/\.c/.'$O'/g'} 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'} AUDIO=`{cd ../pc; echo devaudio.c audio*.c | sed 's/\.c/.'$O'/g'}

View file

@ -41,6 +41,7 @@ dev
segment segment
vmx vmx
dtracy
link link
# devpccard # devpccard
@ -136,6 +137,9 @@ misc
vgavesa vgavesa
# vgavmware +cur # vgavmware +cur
dtracysys
dtracytimer
ip ip
tcp tcp
udp udp

View file

@ -440,6 +440,7 @@ trap(Ureg *ureg)
extern void _rdmsrinst(void); extern void _rdmsrinst(void);
extern void _wrmsrinst(void); extern void _wrmsrinst(void);
extern void _peekinst(void);
pc = (void*)ureg->pc; pc = (void*)ureg->pc;
if(pc == _rdmsrinst || pc == _wrmsrinst){ if(pc == _rdmsrinst || pc == _wrmsrinst){
@ -448,6 +449,11 @@ trap(Ureg *ureg)
ureg->pc += 2; ureg->pc += 2;
return; return;
} }
} else if(pc == _peekinst){
if(vno == VectorGPF){
ureg->pc += 2;
return;
}
} }
} }
@ -672,6 +678,14 @@ faultamd64(Ureg* ureg, void*)
read = !(ureg->error & 2); read = !(ureg->error & 2);
user = userureg(ureg); user = userureg(ureg);
if(!user){ if(!user){
{
extern void _peekinst(void);
if((void(*)(void))ureg->pc == _peekinst){
ureg->pc += 2;
return;
}
}
if(addr >= USTKTOP) if(addr >= USTKTOP)
panic("kernel fault: bad address pc=%#p addr=%#p", ureg->pc, addr); panic("kernel fault: bad address pc=%#p addr=%#p", ureg->pc, addr);
if(up == nil) if(up == nil)

View file

@ -125,9 +125,13 @@ dtkfree(DTKChan *p)
dtktab[idx] = nil; dtktab[idx] = nil;
} }
static int dtracyen;
static void static void
dtracyinit(void) dtracyinit(void)
{ {
dtracyen = getconf("*dtracy") != nil;
if(!dtracyen) return;
machlocks = smalloc(sizeof(Lock) * conf.nmach); machlocks = smalloc(sizeof(Lock) * conf.nmach);
dtinit(conf.nmach); dtinit(conf.nmach);
} }
@ -135,6 +139,8 @@ dtracyinit(void)
static Chan* static Chan*
dtracyattach(char *spec) dtracyattach(char *spec)
{ {
if(!dtracyen)
error("*dtracy= not set");
return devattach(L'Δ', spec); return devattach(L'Δ', spec);
} }
@ -512,67 +518,16 @@ dtgetvar(int v)
} }
} }
int peek(char *, char *, int);
int int
dtpeek(uvlong addr, void *buf, int len) dtpeek(uvlong addr, void *buf, int len)
{ {
if((uintptr)addr != addr || up == nil || !okaddr((uintptr) addr, len, 0)) return -1; uintptr a;
memmove(buf, (void *) addr, len);
return 0; 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 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 dtracyprov_timer = {
.name = "timer",
.provide = timerprovide,
.enable = timerenable,
.disable = timerdisable,
};
extern DTProvider dtracyprov_sys;
DTProvider *dtproviders[] = {
&dtracyprov_timer,
&dtracyprov_sys,
nil,
};

View file

@ -260,7 +260,7 @@ sysdisable(DTProbe *p)
z = systab[i], systab[i] = wraptab[i], wraptab[i] = z; z = systab[i], systab[i] = wraptab[i], wraptab[i] = z;
} }
DTProvider dtracyprov_sys = { DTProvider dtracysysprov = {
.name = "sys", .name = "sys",
.provide = sysprovide, .provide = sysprovide,
.enable = sysenable, .enable = sysenable,

View file

@ -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 <dtracy.h>
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,
};

View file

@ -58,7 +58,8 @@ collect && section == "misc"{
if($i ~ "[+=]cur") if($i ~ "[+=]cur")
vgacur[nvgacur++] = $1; vgacur[nvgacur++] = $1;
} }
} }else if($1 ~ "^dtracy.*")
dtracyprov[ndtracyprov++] = $1;
} }
collect && section == "port"{ collect && section == "port"{
@ -191,6 +192,16 @@ END{
printf "\n"; printf "\n";
} }
if(ndtracyprov){
printf "#include <dtracy.h>\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 "char* conffile = \"%s/%s\";\n", pwd, ARGV[1];
printf "ulong kerndate = KERNDATE;\n"; printf "ulong kerndate = KERNDATE;\n";

View file

@ -462,6 +462,34 @@ parseclause(Clause *cl, uchar *p, uchar *e, Enab *en, Biobuf *bp)
return 0; 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 int
parsebuf(uchar *p, int n, Biobuf *bp) parsebuf(uchar *p, int n, Biobuf *bp)
{ {
@ -474,6 +502,11 @@ parsebuf(uchar *p, int n, Biobuf *bp)
while(p < e){ while(p < e){
p = unpack(p, e, "iv", &epid, &ts); p = unpack(p, e, "iv", &epid, &ts);
if(p == nil) goto err; if(p == nil) goto err;
if(epid == (u32int)-1){
p = parsefault(p, e);
if(p == nil) goto err;
continue;
}
en = epidlookup(epid); en = epidlookup(epid);
if(en == nil) goto err; if(en == nil) goto err;
if(parseclause(en->cl, p - 12, p + en->reclen - 12, en, bp) < 0) return -1; if(parseclause(en->cl, p - 12, p + en->reclen - 12, en, bp) < 0) return -1;

View file

@ -1414,4 +1414,6 @@ threadmain(int argc, char **argv)
passwdparse(gidtab, readfile(gidfile)); passwdparse(gidtab, readfile(gidfile));
threadpostmountsrv(&sshfssrv, svc, mtpt, MCREATE | mflag); threadpostmountsrv(&sshfssrv, svc, mtpt, MCREATE | mflag);
exits(nil);
} }

View file

@ -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 PUT4(c) *bp++ = c; *bp++ = c >> 8; *bp++ = c >> 16; *bp++ = c >> 24;
#define PUT8(c) PUT4(c); PUT4(c>>32); #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 static int
dtgexec(DTActGr *g, DTTrigInfo *info) dtgexec(DTActGr *g, DTTrigInfo *info)
{ {
@ -265,8 +314,8 @@ dtgexec(DTActGr *g, DTTrigInfo *info)
break; break;
case ACTTRACESTR: case ACTTRACESTR:
if(dtpeekstr(v, bp, g->acts[i].size) < 0){ if(dtpeekstr(v, bp, g->acts[i].size) < 0){
snprint(info->ch->errstr, sizeof(info->ch->errstr), "fault @ %#llux", v); dtcfault(info, DTFILL, "ip", dtgetvar(DTV_PID), v);
return -1; return 0;
} }
bp += g->acts[i].size; bp += g->acts[i].size;
break; break;