| 
					
				 | 
			
			
				@@ -113,3 +113,161 @@ extern int __get_user_4(void *); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	   __asm__ __volatile__ (					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		__asmeq("%0", "r0") __asmeq("%1", "r2")			\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		__asmeq("%3", "r1")					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		"bl	__get_user_" #__s				\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		: "=&r" (__e), "=r" (__r2)				\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		: "0" (__p), "r" (__l)					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		: __GUP_CLOBBER_##__s) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define __get_user_check(x,p)							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	({								\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		unsigned long __limit = current_thread_info()->addr_limit - 1; \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		register const typeof(*(p)) __user *__p asm("r0") = (p);\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		register unsigned long __r2 asm("r2");			\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		register unsigned long __l asm("r1") = __limit;		\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		register int __e asm("r0");				\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		switch (sizeof(*(__p))) {				\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 1:							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			__get_user_x(__r2, __p, __e, __l, 1);		\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break;						\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 2:							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			__get_user_x(__r2, __p, __e, __l, 2);		\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break;						\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 4:							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			__get_user_x(__r2, __p, __e, __l, 4);		\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break;						\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		default: __e = __get_user_bad(); break;			\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		x = (typeof(*(p))) __r2;				\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		__e;							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define get_user(x,p)							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	({								\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		might_fault();						\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		__get_user_check(x,p);					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+extern int __put_user_1(void *, unsigned int); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+extern int __put_user_2(void *, unsigned int); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+extern int __put_user_4(void *, unsigned int); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+extern int __put_user_8(void *, unsigned long long); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define __put_user_x(__r2,__p,__e,__l,__s)				\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	   __asm__ __volatile__ (					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		__asmeq("%0", "r0") __asmeq("%2", "r2")			\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		__asmeq("%3", "r1")					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		"bl	__put_user_" #__s				\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		: "=&r" (__e)						\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		: "0" (__p), "r" (__r2), "r" (__l)			\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		: "ip", "lr", "cc") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define __put_user_check(x,p)							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	({								\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		unsigned long __limit = current_thread_info()->addr_limit - 1; \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		register const typeof(*(p)) __r2 asm("r2") = (x);	\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		register const typeof(*(p)) __user *__p asm("r0") = (p);\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		register unsigned long __l asm("r1") = __limit;		\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		register int __e asm("r0");				\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		switch (sizeof(*(__p))) {				\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 1:							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			__put_user_x(__r2, __p, __e, __l, 1);		\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break;						\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 2:							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			__put_user_x(__r2, __p, __e, __l, 2);		\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break;						\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 4:							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			__put_user_x(__r2, __p, __e, __l, 4);		\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break;						\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 8:							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			__put_user_x(__r2, __p, __e, __l, 8);		\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break;						\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		default: __e = __put_user_bad(); break;			\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		__e;							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define put_user(x,p)							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	({								\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		might_fault();						\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		__put_user_check(x,p);					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#else /* CONFIG_MMU */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * uClinux has only one addr space, so has simplified address limits. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define USER_DS			KERNEL_DS 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define segment_eq(a,b)		(1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define __addr_ok(addr)		((void)(addr),1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define __range_ok(addr,size)	((void)(addr),0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define get_fs()		(KERNEL_DS) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static inline void set_fs(mm_segment_t fs) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define get_user(x,p)	__get_user(x,p) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define put_user(x,p)	__put_user(x,p) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif /* CONFIG_MMU */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define access_ok(type,addr,size)	(__range_ok(addr,size) == 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define user_addr_max() \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	(segment_eq(get_fs(), USER_DS) ? TASK_SIZE : ~0UL) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * The "__xxx" versions of the user access functions do not verify the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * address space - it must have been done previously with a separate 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * "access_ok()" call. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * The "xxx_error" versions set the third argument to EFAULT if an 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * error occurs, and leave it unchanged on success.  Note that these 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * versions are void (ie, don't return a value as such). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define __get_user(x,ptr)						\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+({									\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	long __gu_err = 0;						\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	__get_user_err((x),(ptr),__gu_err);				\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	__gu_err;							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define __get_user_error(x,ptr,err)					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+({									\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	__get_user_err((x),(ptr),err);					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	(void) 0;							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define __get_user_err(x,ptr,err)					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+do {									\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long __gu_addr = (unsigned long)(ptr);			\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long __gu_val;						\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	__chk_user_ptr(ptr);						\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	might_fault();							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	switch (sizeof(*(ptr))) {					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case 1:	__get_user_asm_byte(__gu_val,__gu_addr,err);	break;	\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case 2:	__get_user_asm_half(__gu_val,__gu_addr,err);	break;	\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case 4:	__get_user_asm_word(__gu_val,__gu_addr,err);	break;	\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	default: (__gu_val) = __get_user_bad();				\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	}								\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	(x) = (__typeof__(*(ptr)))__gu_val;				\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} while (0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define __get_user_asm_byte(x,addr,err)				\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	__asm__ __volatile__(					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"1:	" TUSER(ldrb) "	%1,[%2],#0\n"			\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"2:\n"							\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"	.pushsection .fixup,\"ax\"\n"			\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"	.align	2\n"					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"3:	mov	%0, %3\n"				\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"	mov	%1, #0\n"				\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"	b	2b\n"					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"	.popsection\n"					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"	.pushsection __ex_table,\"a\"\n"		\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"	.align	3\n"					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"	.long	1b, 3b\n"				\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"	.popsection"					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	: "+r" (err), "=&r" (x)					\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	: "r" (addr), "i" (-EFAULT)				\ 
			 |