From 7e7a9efdb5d4dec51bd44fdb8535f16dd73a7b94 Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Sun, 3 Feb 2013 00:19:34 +0000 Subject: [PATCH] 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 --- sys/cddl/dev/dtrace/powerpc/dtrace_asm.S | 44 +------------ 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 9ff83db14d12..8537e3ca8a04 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 + * * $FreeBSD$ */ /* @@ -113,48 +115,6 @@ dtrace_fulword(void *addr) 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 diff --git a/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c b/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c index a697816475b6..efbca6fa9c08 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 + * * $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; }