diff options
author | jhibbits <jhibbits@FreeBSD.org> | 2013-02-03 00:19:34 +0000 |
---|---|---|
committer | jhibbits <jhibbits@FreeBSD.org> | 2013-02-03 00:19:34 +0000 |
commit | afa4bf5e598e3361874f0345548e5e3865b05217 (patch) | |
tree | 17d55b32cd181a3f8ac709015e1f5a3607bb5be6 /sys/cddl | |
parent | 04d7d467d910ac1811db48a47e1294716f5f7ac2 (diff) | |
download | FreeBSD-src-afa4bf5e598e3361874f0345548e5e3865b05217.zip FreeBSD-src-afa4bf5e598e3361874f0345548e5e3865b05217.tar.gz |
Fix the PowerPC DTrace copy functions. The kernel doesn't hold the same view to
the user map, so use the md copy in/out functions provided by the kernel.
MFC with: r242723
Diffstat (limited to 'sys/cddl')
-rw-r--r-- | sys/cddl/dev/dtrace/powerpc/dtrace_asm.S | 44 | ||||
-rw-r--r-- | sys/cddl/dev/dtrace/powerpc/dtrace_isa.c | 83 |
2 files changed, 61 insertions, 66 deletions
diff --git a/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S b/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S index 9ff83db..8537e3c 100644 --- a/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S +++ b/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S @@ -19,6 +19,8 @@ * * CDDL HEADER END * + * Portions Copyright 2012,2013 Justin Hibbits <jhibbits@freebsd.org> + * * $FreeBSD$ */ /* @@ -114,48 +116,6 @@ ASENTRY_NOPROF(dtrace_fulword) END(dtrace_fulword) /* -uint8_t -dtrace_fuword8_nocheck(void *addr) -*/ -ASENTRY_NOPROF(dtrace_fuword8_nocheck) - lbz %r3,0(%r3) - blr -END(dtrace_fuword8_nocheck) - -/* -uint16_t -dtrace_fuword16_nocheck(void *addr) -*/ -ASENTRY_NOPROF(dtrace_fuword16_nocheck) - lhz %r3,0(%r3) - blr -END(dtrace_fuword16_nocheck) - -/* -uint32_t -dtrace_fuword32_nocheck(void *addr) -*/ -ASENTRY_NOPROF(dtrace_fuword32_nocheck) - lwz %r3,0(%r3) - blr -END(dtrace_fuword32_nocheck) - -/* -uint64_t -dtrace_fuword64_nocheck(void *addr) -*/ -ASENTRY_NOPROF(dtrace_fuword64_nocheck) -#if defined(__powerpc64__) - ld %r3,0(%r3) -#else - lwz %r5,0(%r3) - lwz %r4,4(%r3) - mr %r3,%r5 -#endif - blr -END(dtrace_fuword64_nocheck) - -/* XXX: unoptimized void dtrace_copy(uintptr_t src, uintptr_t dest, size_t size) diff --git a/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c b/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c index a697816..efbca6f 100644 --- a/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c +++ b/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c @@ -19,6 +19,8 @@ * * CDDL HEADER END * + * Portions Copyright 2012,2013 Justin Hibbits <jhibbits@freebsd.org> + * * $FreeBSD$ */ /* @@ -45,11 +47,6 @@ #include "regset.h" -uint8_t dtrace_fuword8_nocheck(void *); -uint16_t dtrace_fuword16_nocheck(void *); -uint32_t dtrace_fuword32_nocheck(void *); -uint64_t dtrace_fuword64_nocheck(void *); - /* Offset to the LR Save word (ppc32) */ #define RETURN_OFFSET 4 #define RETURN_OFFSET64 8 @@ -462,31 +459,63 @@ dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size, volatile uint16_t *flags) { if (dtrace_copycheck(uaddr, kaddr, size)) - dtrace_copy(uaddr, kaddr, size); + if (copyin((const void *)uaddr, (void *)kaddr, size)) { + DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); + cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; + } } void dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size, volatile uint16_t *flags) { - if (dtrace_copycheck(uaddr, kaddr, size)) - dtrace_copy(kaddr, uaddr, size); + if (dtrace_copycheck(uaddr, kaddr, size)) { + if (copyout((const void *)kaddr, (void *)uaddr, size)) { + DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); + cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; + } + } } void dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size, volatile uint16_t *flags) { - if (dtrace_copycheck(uaddr, kaddr, size)) - dtrace_copystr(uaddr, kaddr, size, flags); + size_t actual; + int error; + + if (dtrace_copycheck(uaddr, kaddr, size)) { + error = copyinstr((const void *)uaddr, (void *)kaddr, + size, &actual); + + /* ENAMETOOLONG is not a fault condition. */ + if (error && error != ENAMETOOLONG) { + DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); + cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; + } + } } +/* + * The bulk of this function could be replaced to match dtrace_copyinstr() + * if we ever implement a copyoutstr(). + */ void dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size, volatile uint16_t *flags) { - if (dtrace_copycheck(uaddr, kaddr, size)) - dtrace_copystr(kaddr, uaddr, size, flags); + size_t len; + + if (dtrace_copycheck(uaddr, kaddr, size)) { + len = strlen((const char *)kaddr); + if (len > size) + len = size; + + if (copyout((const void *)kaddr, (void *)uaddr, len)) { + DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); + cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; + } + } } uint8_t @@ -497,18 +526,21 @@ dtrace_fuword8(void *uaddr) cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; return (0); } - return (dtrace_fuword8_nocheck(uaddr)); + return (fubyte(uaddr)); } uint16_t dtrace_fuword16(void *uaddr) { - if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { - DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); - cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; - return (0); + uint16_t ret = 0; + + if (dtrace_copycheck((uintptr_t)uaddr, (uintptr_t)&ret, sizeof(ret))) { + if (copyin((const void *)uaddr, (void *)&ret, sizeof(ret))) { + DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); + cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; + } } - return (dtrace_fuword16_nocheck(uaddr)); + return ret; } uint32_t @@ -519,16 +551,19 @@ dtrace_fuword32(void *uaddr) cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; return (0); } - return (dtrace_fuword32_nocheck(uaddr)); + return (fuword32(uaddr)); } uint64_t dtrace_fuword64(void *uaddr) { - if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { - DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); - cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; - return (0); + uint64_t ret = 0; + + if (dtrace_copycheck((uintptr_t)uaddr, (uintptr_t)&ret, sizeof(ret))) { + if (copyin((const void *)uaddr, (void *)&ret, sizeof(ret))) { + DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); + cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; + } } - return (dtrace_fuword64_nocheck(uaddr)); + return ret; } |