shithub: riscv

Download patch

ref: cc066d813083789d76169720edbf7a3104538117
parent: 6f30420136d8f2a87790dbe826bc6800de74770a
author: aiju <devnull@localhost>
date: Tue Dec 11 04:09:08 EST 2018

dtracy: catch page faults

--- 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	$0, AX				/* AX set to -1 if traped */
+	MOVL	src+0(FP), SI
+	MOVL	dst+4(FP), DI
+	MOVL	cnt+8(FP), CX
+	CLD
+TEXT _peekinst(SB), $0
+	REP; MOVSB
+	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/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,12 @@
 					ureg->pc += 2;
 					return;
 				}
+			} else if(pc == _peekinst){
+				if(vno == VectorGPF){
+					ureg->ax = -1;
+					ureg->pc += 2;
+					return;
+				}
 			}
 		}
 
@@ -712,6 +719,14 @@
 	if(!user){
 		if(vmapsync(addr))
 			return;
+		{
+			extern void _peekinst(void);
+			if((void(*)(void))ureg->pc == _peekinst){
+				ureg->ax = -1;
+				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	$0, AX
+	MOVQ	RARG, SI
+	MOVQ	dst+8(FP), DI
+	MOVL	cnt+16(FP), CX
+	CLD
+TEXT _peekinst(SB), $0
+	REP; MOVSB
+	RET
+	
+
 TEXT invlpg(SB), 1, $-4
 	INVLPG	(RARG)
 	RET
--- 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,12 @@
 					ureg->pc += 2;
 					return;
 				}
+			} else if(pc == _peekinst){
+				if(vno == VectorGPF){
+					ureg->ax = -1;
+					ureg->pc += 2;
+					return;
+				}
 			}
 		}
 
@@ -672,6 +679,15 @@
 	read = !(ureg->error & 2);
 	user = userureg(ureg);
 	if(!user){
+		{
+			extern void _peekinst(void);
+			
+			if((void(*)(void))ureg->pc == _peekinst){
+				ureg->ax = -1;
+				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
@@ -518,10 +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;
+	uintptr a;
+	
+	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);
 }