summaryrefslogtreecommitdiffstats
path: root/sys/cddl
diff options
context:
space:
mode:
authorjhibbits <jhibbits@FreeBSD.org>2013-02-03 00:19:34 +0000
committerjhibbits <jhibbits@FreeBSD.org>2013-02-03 00:19:34 +0000
commitafa4bf5e598e3361874f0345548e5e3865b05217 (patch)
tree17d55b32cd181a3f8ac709015e1f5a3607bb5be6 /sys/cddl
parent04d7d467d910ac1811db48a47e1294716f5f7ac2 (diff)
downloadFreeBSD-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.S44
-rw-r--r--sys/cddl/dev/dtrace/powerpc/dtrace_isa.c83
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;
}
OpenPOWER on IntegriCloud