shithub: riscv

Download patch

ref: 9b194f23b2a544fab666e40f4f574c8fceb7601f
parent: b836802fe6c1327bc1947a560741f26aac6a7711
parent: 4c68cfa41226de2501c677e80e9e6932d1e39236
author: Alex Musolino <alex@musolino.id.au>
date: Wed Dec 12 07:51:29 EST 2018

merge

--- a/lib/theo
+++ b/lib/theo
@@ -905,3 +905,8 @@
 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.
--- a/sys/games/lib/fortunes
+++ b/sys/games/lib/fortunes
@@ -5248,3 +5248,4 @@
 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
--- a/sys/include/dtracy.h
+++ b/sys/include/dtracy.h
@@ -41,6 +41,8 @@
 /*
 	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 @@
 	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 dtcaggread(DTChan *, void *, int);
 void dtcreset(DTChan *);
 void dtcrun(DTChan *, int);
+int dtcfault(DTTrigInfo *, int, char *, ...);
 
 /* aggbuf functions */
 int dtaunpackid(DTAgg *);
--- a/sys/src/9/pc/l.s
+++ b/sys/src/9/pc/l.s
@@ -511,6 +511,17 @@
 	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
--- a/sys/src/9/pc/mkfile
+++ b/sys/src/9/pc/mkfile
@@ -67,6 +67,7 @@
 	/$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'}
--- a/sys/src/9/pc/pc
+++ b/sys/src/9/pc/pc
@@ -18,6 +18,7 @@
 	cap
 	kprof
 	fs
+	dtracy
 
 	ether		netif
 	bridge		netif log
@@ -137,6 +138,9 @@
 	vgatvp3026	=cur
 	vgavesa
 	vgavmware	+cur
+	
+	dtracysys
+	dtracytimer
 
 ip
 	tcp
--- a/sys/src/9/pc/trap.c
+++ b/sys/src/9/pc/trap.c
@@ -450,6 +450,7 @@
 			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 @@
 					ureg->pc += 2;
 					return;
 				}
+			} else if(pc == _peekinst){
+				if(vno == VectorGPF){
+					ureg->pc += 2;
+					return;
+				}
 			}
 		}
 
@@ -712,6 +718,13 @@
 	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)
--- a/sys/src/9/pc64/l.s
+++ b/sys/src/9/pc64/l.s
@@ -449,6 +449,18 @@
 	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
--- a/sys/src/9/pc64/mkfile
+++ b/sys/src/9/pc64/mkfile
@@ -65,6 +65,7 @@
 	/$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'}
--- a/sys/src/9/pc64/pc64
+++ b/sys/src/9/pc64/pc64
@@ -41,6 +41,7 @@
 	
 	segment
 	vmx
+	dtracy
 
 link
 #	devpccard
@@ -135,6 +136,9 @@
 #	vgatvp3026	=cur
 	vgavesa
 #	vgavmware	+cur
+
+	dtracysys
+	dtracytimer
 
 ip
 	tcp
--- a/sys/src/9/pc64/trap.c
+++ b/sys/src/9/pc64/trap.c
@@ -440,6 +440,7 @@
 
 			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 @@
 					ureg->pc += 2;
 					return;
 				}
+			} else if(pc == _peekinst){
+				if(vno == VectorGPF){
+					ureg->pc += 2;
+					return;
+				}
 			}
 		}
 
@@ -672,6 +678,14 @@
 	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)
--- a/sys/src/9/port/devdtracy.c
+++ b/sys/src/9/port/devdtracy.c
@@ -125,9 +125,13 @@
 	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 @@
 static Chan*
 dtracyattach(char *spec)
 {
+	if(!dtracyen)
+		error("*dtracy= not set");
 	return devattach(L'Δ', spec);
 }
 
@@ -512,67 +518,16 @@
 	}
 }
 
+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,
-};
-
--- a/sys/src/9/port/dtracysys.c
+++ b/sys/src/9/port/dtracysys.c
@@ -260,7 +260,7 @@
 		z = systab[i], systab[i] = wraptab[i], wraptab[i] = z;
 }
 
-DTProvider dtracyprov_sys = {
+DTProvider dtracysysprov = {
 	.name = "sys",
 	.provide = sysprovide,
 	.enable = sysenable,
--- /dev/null
+++ b/sys/src/9/port/dtracytimer.c
@@ -1,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,
+};
--- a/sys/src/9/port/mkdevc
+++ b/sys/src/9/port/mkdevc
@@ -58,7 +58,8 @@
 			if($i ~ "[+=]cur")
 				vgacur[nvgacur++] = $1;
 		}
-	}
+	}else if($1 ~ "^dtracy.*")
+		dtracyprov[ndtracyprov++] = $1;
 }
 
 collect && section == "port"{
@@ -189,6 +190,16 @@
 		for(i = 0; i < nport; i++)
 			printf "%s\n", port[i];
 		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];
--- a/sys/src/cmd/dtracy/act.c
+++ b/sys/src/cmd/dtracy/act.c
@@ -462,6 +462,34 @@
 	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 @@
 	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;
--- a/sys/src/cmd/sshfs.c
+++ b/sys/src/cmd/sshfs.c
@@ -1414,4 +1414,6 @@
 	passwdparse(gidtab, readfile(gidfile));
 	
 	threadpostmountsrv(&sshfssrv, svc, mtpt, MCREATE | mflag);
+
+	exits(nil);
 }
--- a/sys/src/libdtracy/prog.c
+++ b/sys/src/libdtracy/prog.c
@@ -230,6 +230,55 @@
 #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 @@
 			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;