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