|  | @@ -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.
 |