summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraiju <devnull@localhost>2018-12-11 09:09:08 +0000
committeraiju <devnull@localhost>2018-12-11 09:09:08 +0000
commitcc066d813083789d76169720edbf7a3104538117 (patch)
tree718af5de9f51a6996d137ae591f9a2b7c46cd911
parent6f30420136d8f2a87790dbe826bc6800de74770a (diff)
downloadplan9front-cc066d813083789d76169720edbf7a3104538117.tar.xz
dtracy: catch page faults
-rw-r--r--sys/src/9/pc/l.s11
-rw-r--r--sys/src/9/pc/trap.c15
-rw-r--r--sys/src/9/pc64/l.s12
-rw-r--r--sys/src/9/pc64/trap.c16
-rw-r--r--sys/src/9/port/devdtracy.c12
5 files changed, 63 insertions, 3 deletions
diff --git a/sys/src/9/pc/l.s b/sys/src/9/pc/l.s
index 217088ecb..151985f3f 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 $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
diff --git a/sys/src/9/pc/trap.c b/sys/src/9/pc/trap.c
index b76afaff2..12d062adf 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,12 @@ trap(Ureg* ureg)
ureg->pc += 2;
return;
}
+ } else if(pc == _peekinst){
+ if(vno == VectorGPF){
+ ureg->ax = -1;
+ ureg->pc += 2;
+ return;
+ }
}
}
@@ -712,6 +719,14 @@ fault386(Ureg* ureg, void*)
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)
diff --git a/sys/src/9/pc64/l.s b/sys/src/9/pc64/l.s
index 7143d3b69..25d5c71e0 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 $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
diff --git a/sys/src/9/pc64/trap.c b/sys/src/9/pc64/trap.c
index 1944f43bd..17a356463 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,12 @@ trap(Ureg *ureg)
ureg->pc += 2;
return;
}
+ } else if(pc == _peekinst){
+ if(vno == VectorGPF){
+ ureg->ax = -1;
+ ureg->pc += 2;
+ return;
+ }
}
}
@@ -672,6 +679,15 @@ faultamd64(Ureg* ureg, void*)
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)
diff --git a/sys/src/9/port/devdtracy.c b/sys/src/9/port/devdtracy.c
index 53da2c46b..1d382f9f1 100644
--- a/sys/src/9/port/devdtracy.c
+++ b/sys/src/9/port/devdtracy.c
@@ -518,10 +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;
+ 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);
}