}
 }
 
-static nokprobe_inline int read_mem_aligned(unsigned long *dest,
-                                           unsigned long ea, int nb,
-                                           struct pt_regs *regs)
+static __always_inline int
+__read_mem_aligned(unsigned long *dest, unsigned long ea, int nb, struct pt_regs *regs)
 {
-       int err = 0;
        unsigned long x = 0;
 
        switch (nb) {
        case 1:
-               err = __get_user(x, (unsigned char __user *) ea);
+               unsafe_get_user(x, (unsigned char __user *)ea, Efault);
                break;
        case 2:
-               err = __get_user(x, (unsigned short __user *) ea);
+               unsafe_get_user(x, (unsigned short __user *)ea, Efault);
                break;
        case 4:
-               err = __get_user(x, (unsigned int __user *) ea);
+               unsafe_get_user(x, (unsigned int __user *)ea, Efault);
                break;
 #ifdef __powerpc64__
        case 8:
-               err = __get_user(x, (unsigned long __user *) ea);
+               unsafe_get_user(x, (unsigned long __user *)ea, Efault);
                break;
 #endif
        }
-       if (!err)
-               *dest = x;
-       else
+       *dest = x;
+       return 0;
+
+Efault:
+       regs->dar = ea;
+       return -EFAULT;
+}
+
+static nokprobe_inline int
+read_mem_aligned(unsigned long *dest, unsigned long ea, int nb, struct pt_regs *regs)
+{
+       int err;
+
+       if (is_kernel_addr(ea))
+               return __read_mem_aligned(dest, ea, nb, regs);
+
+       if (user_read_access_begin((void __user *)ea, nb)) {
+               err = __read_mem_aligned(dest, ea, nb, regs);
+               user_read_access_end();
+       } else {
+               err = -EFAULT;
                regs->dar = ea;
+       }
+
        return err;
 }
 
  * Copy from userspace to a buffer, using the largest possible
  * aligned accesses, up to sizeof(long).
  */
-static nokprobe_inline int copy_mem_in(u8 *dest, unsigned long ea, int nb,
-                                      struct pt_regs *regs)
+static __always_inline int __copy_mem_in(u8 *dest, unsigned long ea, int nb, struct pt_regs *regs)
 {
-       int err = 0;
        int c;
 
        for (; nb > 0; nb -= c) {
                        c = max_align(nb);
                switch (c) {
                case 1:
-                       err = __get_user(*dest, (unsigned char __user *) ea);
+                       unsafe_get_user(*dest, (u8 __user *)ea, Efault);
                        break;
                case 2:
-                       err = __get_user(*(u16 *)dest,
-                                        (unsigned short __user *) ea);
+                       unsafe_get_user(*(u16 *)dest, (u16 __user *)ea, Efault);
                        break;
                case 4:
-                       err = __get_user(*(u32 *)dest,
-                                        (unsigned int __user *) ea);
+                       unsafe_get_user(*(u32 *)dest, (u32 __user *)ea, Efault);
                        break;
 #ifdef __powerpc64__
                case 8:
-                       err = __get_user(*(unsigned long *)dest,
-                                        (unsigned long __user *) ea);
+                       unsafe_get_user(*(u64 *)dest, (u64 __user *)ea, Efault);
                        break;
 #endif
                }
-               if (err) {
-                       regs->dar = ea;
-                       return err;
-               }
                dest += c;
                ea += c;
        }
        return 0;
+
+Efault:
+       regs->dar = ea;
+       return -EFAULT;
+}
+
+static nokprobe_inline int copy_mem_in(u8 *dest, unsigned long ea, int nb, struct pt_regs *regs)
+{
+       int err;
+
+       if (is_kernel_addr(ea))
+               return __copy_mem_in(dest, ea, nb, regs);
+
+       if (user_read_access_begin((void __user *)ea, nb)) {
+               err = __copy_mem_in(dest, ea, nb, regs);
+               user_read_access_end();
+       } else {
+               err = -EFAULT;
+               regs->dar = ea;
+       }
+
+       return err;
 }
 
 static nokprobe_inline int read_mem_unaligned(unsigned long *dest,
 }
 NOKPROBE_SYMBOL(read_mem);
 
-static nokprobe_inline int write_mem_aligned(unsigned long val,
-                                            unsigned long ea, int nb,
-                                            struct pt_regs *regs)
+static __always_inline int
+__write_mem_aligned(unsigned long val, unsigned long ea, int nb, struct pt_regs *regs)
 {
-       int err = 0;
-
        switch (nb) {
        case 1:
-               err = __put_user(val, (unsigned char __user *) ea);
+               unsafe_put_user(val, (unsigned char __user *)ea, Efault);
                break;
        case 2:
-               err = __put_user(val, (unsigned short __user *) ea);
+               unsafe_put_user(val, (unsigned short __user *)ea, Efault);
                break;
        case 4:
-               err = __put_user(val, (unsigned int __user *) ea);
+               unsafe_put_user(val, (unsigned int __user *)ea, Efault);
                break;
 #ifdef __powerpc64__
        case 8:
-               err = __put_user(val, (unsigned long __user *) ea);
+               unsafe_put_user(val, (unsigned long __user *)ea, Efault);
                break;
 #endif
        }
-       if (err)
+       return 0;
+
+Efault:
+       regs->dar = ea;
+       return -EFAULT;
+}
+
+static nokprobe_inline int
+write_mem_aligned(unsigned long val, unsigned long ea, int nb, struct pt_regs *regs)
+{
+       int err;
+
+       if (is_kernel_addr(ea))
+               return __write_mem_aligned(val, ea, nb, regs);
+
+       if (user_write_access_begin((void __user *)ea, nb)) {
+               err = __write_mem_aligned(val, ea, nb, regs);
+               user_write_access_end();
+       } else {
+               err = -EFAULT;
                regs->dar = ea;
+       }
+
        return err;
 }
 
  * Copy from a buffer to userspace, using the largest possible
  * aligned accesses, up to sizeof(long).
  */
-static nokprobe_inline int copy_mem_out(u8 *dest, unsigned long ea, int nb,
-                                       struct pt_regs *regs)
+static nokprobe_inline int __copy_mem_out(u8 *dest, unsigned long ea, int nb, struct pt_regs *regs)
 {
-       int err = 0;
        int c;
 
        for (; nb > 0; nb -= c) {
                        c = max_align(nb);
                switch (c) {
                case 1:
-                       err = __put_user(*dest, (unsigned char __user *) ea);
+                       unsafe_put_user(*dest, (u8 __user *)ea, Efault);
                        break;
                case 2:
-                       err = __put_user(*(u16 *)dest,
-                                        (unsigned short __user *) ea);
+                       unsafe_put_user(*(u16 *)dest, (u16 __user *)ea, Efault);
                        break;
                case 4:
-                       err = __put_user(*(u32 *)dest,
-                                        (unsigned int __user *) ea);
+                       unsafe_put_user(*(u32 *)dest, (u32 __user *)ea, Efault);
                        break;
 #ifdef __powerpc64__
                case 8:
-                       err = __put_user(*(unsigned long *)dest,
-                                        (unsigned long __user *) ea);
+                       unsafe_put_user(*(u64 *)dest, (u64 __user *)ea, Efault);
                        break;
 #endif
                }
-               if (err) {
-                       regs->dar = ea;
-                       return err;
-               }
                dest += c;
                ea += c;
        }
        return 0;
+
+Efault:
+       regs->dar = ea;
+       return -EFAULT;
+}
+
+static nokprobe_inline int copy_mem_out(u8 *dest, unsigned long ea, int nb, struct pt_regs *regs)
+{
+       int err;
+
+       if (is_kernel_addr(ea))
+               return __copy_mem_out(dest, ea, nb, regs);
+
+       if (user_write_access_begin((void __user *)ea, nb)) {
+               err = __copy_mem_out(dest, ea, nb, regs);
+               user_write_access_end();
+       } else {
+               err = -EFAULT;
+               regs->dar = ea;
+       }
+
+       return err;
 }
 
 static nokprobe_inline int write_mem_unaligned(unsigned long val,
 }
 #endif /* CONFIG_VSX */
 
+static int __emulate_dcbz(unsigned long ea)
+{
+       unsigned long i;
+       unsigned long size = l1_dcache_bytes();
+
+       for (i = 0; i < size; i += sizeof(long))
+               unsafe_put_user(0, (unsigned long __user *)(ea + i), Efault);
+
+       return 0;
+
+Efault:
+       return -EFAULT;
+}
+
 int emulate_dcbz(unsigned long ea, struct pt_regs *regs)
 {
        int err;
-       unsigned long i, size;
+       unsigned long size;
 
 #ifdef __powerpc64__
        size = ppc64_caches.l1d.block_size;
        ea &= ~(size - 1);
        if (!address_ok(regs, ea, size))
                return -EFAULT;
-       for (i = 0; i < size; i += sizeof(long)) {
-               err = __put_user(0, (unsigned long __user *) (ea + i));
-               if (err) {
-                       regs->dar = ea;
-                       return err;
-               }
+
+       if (is_kernel_addr(ea)) {
+               err = __emulate_dcbz(ea);
+       } else if (user_write_access_begin((void __user *)ea, size)) {
+               err = __emulate_dcbz(ea);
+               user_write_access_end();
+       } else {
+               err = -EFAULT;
        }
-       return 0;
+
+       if (err)
+               regs->dar = ea;
+
+
+       return err;
 }
 NOKPROBE_SYMBOL(emulate_dcbz);