diff --git a/arch/sparc64/lib/copy_in_user.S b/arch/sparc64/lib/copy_in_user.S
index 650af3f..ba91c3e 100644
--- a/arch/sparc64/lib/copy_in_user.S
+++ b/arch/sparc64/lib/copy_in_user.S
@@ -105,15 +105,24 @@ ___copy_in_user:	/* %o0=dst, %o1=src, %o2=len */
 	/* Act like copy_{to,in}_user(), ie. return zero instead
 	 * of original destination pointer.  This is invoked when
 	 * copy_{to,in}_user() finds that %asi is kernel space.
+	 *
+	 * We can't quite use memcpy directly since we are supposed
+	 * to return nonzero on faults.  Could optimize these, but
+	 * this is used extremely rarely (probe_kernel_read/write).
 	 */
 	.globl		memcpy_user_stub
 	.type		memcpy_user_stub,#function
 memcpy_user_stub:
-	save		%sp, -192, %sp
-	mov		%i0, %o0
-	mov		%i1, %o1
-	call		memcpy
-	 mov		%i2, %o2
-	ret
-	 restore	%g0, %g0, %o0
+	brz,pn		%o2, 2f
+	 clr		%o3
+1:
+	EX(ldub [%o1 + %o3], %g1)
+	EX(stb %g1, [%o0 + %o3])
+	deccc		%o2
+	bgu,pt		%XCC, 1b
+	 inc		%o3
+2:
+	retl
+	 clr		%o0
+
 	.size		memcpy_user_stub, .-memcpy_user_stub
