|
@@ -101,28 +101,39 @@ extern int __get_user_1(void *);
|
|
extern int __get_user_2(void *);
|
|
extern int __get_user_2(void *);
|
|
extern int __get_user_4(void *);
|
|
extern int __get_user_4(void *);
|
|
|
|
|
|
-#define __get_user_x(__r2,__p,__e,__s,__i...) \
|
|
|
|
|
|
+#define __GUP_CLOBBER_1 "lr", "cc"
|
|
|
|
+#ifdef CONFIG_CPU_USE_DOMAINS
|
|
|
|
+#define __GUP_CLOBBER_2 "ip", "lr", "cc"
|
|
|
|
+#else
|
|
|
|
+#define __GUP_CLOBBER_2 "lr", "cc"
|
|
|
|
+#endif
|
|
|
|
+#define __GUP_CLOBBER_4 "lr", "cc"
|
|
|
|
+
|
|
|
|
+#define __get_user_x(__r2,__p,__e,__l,__s) \
|
|
__asm__ __volatile__ ( \
|
|
__asm__ __volatile__ ( \
|
|
__asmeq("%0", "r0") __asmeq("%1", "r2") \
|
|
__asmeq("%0", "r0") __asmeq("%1", "r2") \
|
|
|
|
+ __asmeq("%3", "r1") \
|
|
"bl __get_user_" #__s \
|
|
"bl __get_user_" #__s \
|
|
: "=&r" (__e), "=r" (__r2) \
|
|
: "=&r" (__e), "=r" (__r2) \
|
|
- : "0" (__p) \
|
|
|
|
- : __i, "cc")
|
|
|
|
|
|
+ : "0" (__p), "r" (__l) \
|
|
|
|
+ : __GUP_CLOBBER_##__s)
|
|
|
|
|
|
-#define get_user(x,p) \
|
|
|
|
|
|
+#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 const typeof(*(p)) __user *__p asm("r0") = (p);\
|
|
register unsigned long __r2 asm("r2"); \
|
|
register unsigned long __r2 asm("r2"); \
|
|
|
|
+ register unsigned long __l asm("r1") = __limit; \
|
|
register int __e asm("r0"); \
|
|
register int __e asm("r0"); \
|
|
switch (sizeof(*(__p))) { \
|
|
switch (sizeof(*(__p))) { \
|
|
case 1: \
|
|
case 1: \
|
|
- __get_user_x(__r2, __p, __e, 1, "lr"); \
|
|
|
|
- break; \
|
|
|
|
|
|
+ __get_user_x(__r2, __p, __e, __l, 1); \
|
|
|
|
+ break; \
|
|
case 2: \
|
|
case 2: \
|
|
- __get_user_x(__r2, __p, __e, 2, "r3", "lr"); \
|
|
|
|
|
|
+ __get_user_x(__r2, __p, __e, __l, 2); \
|
|
break; \
|
|
break; \
|
|
case 4: \
|
|
case 4: \
|
|
- __get_user_x(__r2, __p, __e, 4, "lr"); \
|
|
|
|
|
|
+ __get_user_x(__r2, __p, __e, __l, 4); \
|
|
break; \
|
|
break; \
|
|
default: __e = __get_user_bad(); break; \
|
|
default: __e = __get_user_bad(); break; \
|
|
} \
|
|
} \
|
|
@@ -130,42 +141,57 @@ extern int __get_user_4(void *);
|
|
__e; \
|
|
__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_1(void *, unsigned int);
|
|
extern int __put_user_2(void *, unsigned int);
|
|
extern int __put_user_2(void *, unsigned int);
|
|
extern int __put_user_4(void *, unsigned int);
|
|
extern int __put_user_4(void *, unsigned int);
|
|
extern int __put_user_8(void *, unsigned long long);
|
|
extern int __put_user_8(void *, unsigned long long);
|
|
|
|
|
|
-#define __put_user_x(__r2,__p,__e,__s) \
|
|
|
|
|
|
+#define __put_user_x(__r2,__p,__e,__l,__s) \
|
|
__asm__ __volatile__ ( \
|
|
__asm__ __volatile__ ( \
|
|
__asmeq("%0", "r0") __asmeq("%2", "r2") \
|
|
__asmeq("%0", "r0") __asmeq("%2", "r2") \
|
|
|
|
+ __asmeq("%3", "r1") \
|
|
"bl __put_user_" #__s \
|
|
"bl __put_user_" #__s \
|
|
: "=&r" (__e) \
|
|
: "=&r" (__e) \
|
|
- : "0" (__p), "r" (__r2) \
|
|
|
|
|
|
+ : "0" (__p), "r" (__r2), "r" (__l) \
|
|
: "ip", "lr", "cc")
|
|
: "ip", "lr", "cc")
|
|
|
|
|
|
-#define put_user(x,p) \
|
|
|
|
|
|
+#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)) __r2 asm("r2") = (x); \
|
|
register const typeof(*(p)) __user *__p asm("r0") = (p);\
|
|
register const typeof(*(p)) __user *__p asm("r0") = (p);\
|
|
|
|
+ register unsigned long __l asm("r1") = __limit; \
|
|
register int __e asm("r0"); \
|
|
register int __e asm("r0"); \
|
|
switch (sizeof(*(__p))) { \
|
|
switch (sizeof(*(__p))) { \
|
|
case 1: \
|
|
case 1: \
|
|
- __put_user_x(__r2, __p, __e, 1); \
|
|
|
|
|
|
+ __put_user_x(__r2, __p, __e, __l, 1); \
|
|
break; \
|
|
break; \
|
|
case 2: \
|
|
case 2: \
|
|
- __put_user_x(__r2, __p, __e, 2); \
|
|
|
|
|
|
+ __put_user_x(__r2, __p, __e, __l, 2); \
|
|
break; \
|
|
break; \
|
|
case 4: \
|
|
case 4: \
|
|
- __put_user_x(__r2, __p, __e, 4); \
|
|
|
|
|
|
+ __put_user_x(__r2, __p, __e, __l, 4); \
|
|
break; \
|
|
break; \
|
|
case 8: \
|
|
case 8: \
|
|
- __put_user_x(__r2, __p, __e, 8); \
|
|
|
|
|
|
+ __put_user_x(__r2, __p, __e, __l, 8); \
|
|
break; \
|
|
break; \
|
|
default: __e = __put_user_bad(); break; \
|
|
default: __e = __put_user_bad(); break; \
|
|
} \
|
|
} \
|
|
__e; \
|
|
__e; \
|
|
})
|
|
})
|
|
|
|
|
|
|
|
+#define put_user(x,p) \
|
|
|
|
+ ({ \
|
|
|
|
+ might_fault(); \
|
|
|
|
+ __put_user_check(x,p); \
|
|
|
|
+ })
|
|
|
|
+
|
|
#else /* CONFIG_MMU */
|
|
#else /* CONFIG_MMU */
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -219,6 +245,7 @@ do { \
|
|
unsigned long __gu_addr = (unsigned long)(ptr); \
|
|
unsigned long __gu_addr = (unsigned long)(ptr); \
|
|
unsigned long __gu_val; \
|
|
unsigned long __gu_val; \
|
|
__chk_user_ptr(ptr); \
|
|
__chk_user_ptr(ptr); \
|
|
|
|
+ might_fault(); \
|
|
switch (sizeof(*(ptr))) { \
|
|
switch (sizeof(*(ptr))) { \
|
|
case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \
|
|
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 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \
|
|
@@ -300,6 +327,7 @@ do { \
|
|
unsigned long __pu_addr = (unsigned long)(ptr); \
|
|
unsigned long __pu_addr = (unsigned long)(ptr); \
|
|
__typeof__(*(ptr)) __pu_val = (x); \
|
|
__typeof__(*(ptr)) __pu_val = (x); \
|
|
__chk_user_ptr(ptr); \
|
|
__chk_user_ptr(ptr); \
|
|
|
|
+ might_fault(); \
|
|
switch (sizeof(*(ptr))) { \
|
|
switch (sizeof(*(ptr))) { \
|
|
case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \
|
|
case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \
|
|
case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \
|
|
case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \
|