|
@@ -266,3 +266,150 @@ do { \
|
|
|
" .long 1b,3b\n" \
|
|
|
".previous" \
|
|
|
: "=&r" (err), "=&r" (x) \
|
|
|
+ : "r" (addr), "i" (-EFAULT), "0" (err) \
|
|
|
+ : "r14", "memory")
|
|
|
+
|
|
|
+/**
|
|
|
+ * __put_user: - Write a simple value into user space, with less checking.
|
|
|
+ * @x: Value to copy to user space.
|
|
|
+ * @ptr: Destination address, in user space.
|
|
|
+ *
|
|
|
+ * Context: User context only. This function may sleep.
|
|
|
+ *
|
|
|
+ * This macro copies a single simple value from kernel space to user
|
|
|
+ * space. It supports simple types like char and int, but not larger
|
|
|
+ * data types like structures or arrays.
|
|
|
+ *
|
|
|
+ * @ptr must have pointer-to-simple-variable type, and @x must be assignable
|
|
|
+ * to the result of dereferencing @ptr.
|
|
|
+ *
|
|
|
+ * Caller must check the pointer with access_ok() before calling this
|
|
|
+ * function.
|
|
|
+ *
|
|
|
+ * Returns zero on success, or -EFAULT on error.
|
|
|
+ */
|
|
|
+#define __put_user(x,ptr) \
|
|
|
+ __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
|
|
|
+
|
|
|
+
|
|
|
+#define __put_user_nocheck(x,ptr,size) \
|
|
|
+({ \
|
|
|
+ long __pu_err; \
|
|
|
+ might_sleep(); \
|
|
|
+ __put_user_size((x),(ptr),(size),__pu_err); \
|
|
|
+ __pu_err; \
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+#define __put_user_check(x,ptr,size) \
|
|
|
+({ \
|
|
|
+ long __pu_err = -EFAULT; \
|
|
|
+ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
|
|
|
+ might_sleep(); \
|
|
|
+ if (access_ok(VERIFY_WRITE,__pu_addr,size)) \
|
|
|
+ __put_user_size((x),__pu_addr,(size),__pu_err); \
|
|
|
+ __pu_err; \
|
|
|
+})
|
|
|
+
|
|
|
+#if defined(__LITTLE_ENDIAN__)
|
|
|
+#define __put_user_u64(x, addr, err) \
|
|
|
+ __asm__ __volatile__( \
|
|
|
+ " .fillinsn\n" \
|
|
|
+ "1: st %L1,@%2\n" \
|
|
|
+ " .fillinsn\n" \
|
|
|
+ "2: st %H1,@(4,%2)\n" \
|
|
|
+ " .fillinsn\n" \
|
|
|
+ "3:\n" \
|
|
|
+ ".section .fixup,\"ax\"\n" \
|
|
|
+ " .balign 4\n" \
|
|
|
+ "4: ldi %0,%3\n" \
|
|
|
+ " seth r14,#high(3b)\n" \
|
|
|
+ " or3 r14,r14,#low(3b)\n" \
|
|
|
+ " jmp r14\n" \
|
|
|
+ ".previous\n" \
|
|
|
+ ".section __ex_table,\"a\"\n" \
|
|
|
+ " .balign 4\n" \
|
|
|
+ " .long 1b,4b\n" \
|
|
|
+ " .long 2b,4b\n" \
|
|
|
+ ".previous" \
|
|
|
+ : "=&r" (err) \
|
|
|
+ : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err) \
|
|
|
+ : "r14", "memory")
|
|
|
+
|
|
|
+#elif defined(__BIG_ENDIAN__)
|
|
|
+#define __put_user_u64(x, addr, err) \
|
|
|
+ __asm__ __volatile__( \
|
|
|
+ " .fillinsn\n" \
|
|
|
+ "1: st %H1,@%2\n" \
|
|
|
+ " .fillinsn\n" \
|
|
|
+ "2: st %L1,@(4,%2)\n" \
|
|
|
+ " .fillinsn\n" \
|
|
|
+ "3:\n" \
|
|
|
+ ".section .fixup,\"ax\"\n" \
|
|
|
+ " .balign 4\n" \
|
|
|
+ "4: ldi %0,%3\n" \
|
|
|
+ " seth r14,#high(3b)\n" \
|
|
|
+ " or3 r14,r14,#low(3b)\n" \
|
|
|
+ " jmp r14\n" \
|
|
|
+ ".previous\n" \
|
|
|
+ ".section __ex_table,\"a\"\n" \
|
|
|
+ " .balign 4\n" \
|
|
|
+ " .long 1b,4b\n" \
|
|
|
+ " .long 2b,4b\n" \
|
|
|
+ ".previous" \
|
|
|
+ : "=&r" (err) \
|
|
|
+ : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err) \
|
|
|
+ : "r14", "memory")
|
|
|
+#else
|
|
|
+#error no endian defined
|
|
|
+#endif
|
|
|
+
|
|
|
+extern void __put_user_bad(void);
|
|
|
+
|
|
|
+#define __put_user_size(x,ptr,size,retval) \
|
|
|
+do { \
|
|
|
+ retval = 0; \
|
|
|
+ __chk_user_ptr(ptr); \
|
|
|
+ switch (size) { \
|
|
|
+ case 1: __put_user_asm(x,ptr,retval,"b"); break; \
|
|
|
+ case 2: __put_user_asm(x,ptr,retval,"h"); break; \
|
|
|
+ case 4: __put_user_asm(x,ptr,retval,""); break; \
|
|
|
+ case 8: __put_user_u64((__typeof__(*ptr))(x),ptr,retval); break;\
|
|
|
+ default: __put_user_bad(); \
|
|
|
+ } \
|
|
|
+} while (0)
|
|
|
+
|
|
|
+struct __large_struct { unsigned long buf[100]; };
|
|
|
+#define __m(x) (*(struct __large_struct *)(x))
|
|
|
+
|
|
|
+/*
|
|
|
+ * Tell gcc we read from memory instead of writing: this is because
|
|
|
+ * we do not write to any memory gcc knows about, so there are no
|
|
|
+ * aliasing issues.
|
|
|
+ */
|
|
|
+#define __put_user_asm(x, addr, err, itype) \
|
|
|
+ __asm__ __volatile__( \
|
|
|
+ " .fillinsn\n" \
|
|
|
+ "1: st"itype" %1,@%2\n" \
|
|
|
+ " .fillinsn\n" \
|
|
|
+ "2:\n" \
|
|
|
+ ".section .fixup,\"ax\"\n" \
|
|
|
+ " .balign 4\n" \
|
|
|
+ "3: ldi %0,%3\n" \
|
|
|
+ " seth r14,#high(2b)\n" \
|
|
|
+ " or3 r14,r14,#low(2b)\n" \
|
|
|
+ " jmp r14\n" \
|
|
|
+ ".previous\n" \
|
|
|
+ ".section __ex_table,\"a\"\n" \
|
|
|
+ " .balign 4\n" \
|
|
|
+ " .long 1b,3b\n" \
|
|
|
+ ".previous" \
|
|
|
+ : "=&r" (err) \
|
|
|
+ : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err) \
|
|
|
+ : "r14", "memory")
|
|
|
+
|
|
|
+/*
|
|
|
+ * Here we special-case 1, 2 and 4-byte copy_*_user invocations. On a fault
|
|
|
+ * we return the initial request size (1, 2 or 4), as copy_*_user should do.
|
|
|
+ * If a store crosses a page boundary and gets a fault, the m32r will not write
|
|
|
+ * anything, so this is accurate.
|