diff options
-rw-r--r-- | arch/arm/lib/uaccess_with_memcpy.c | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c index bf987b4a2571..92838e79654d 100644 --- a/arch/arm/lib/uaccess_with_memcpy.c +++ b/arch/arm/lib/uaccess_with_memcpy.c | |||
@@ -49,14 +49,11 @@ pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp) | |||
49 | return 1; | 49 | return 1; |
50 | } | 50 | } |
51 | 51 | ||
52 | unsigned long | 52 | static unsigned long noinline |
53 | __copy_to_user(void __user *to, const void *from, unsigned long n) | 53 | __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n) |
54 | { | 54 | { |
55 | int atomic; | 55 | int atomic; |
56 | 56 | ||
57 | if (n < 1024) | ||
58 | return __copy_to_user_std(to, from, n); | ||
59 | |||
60 | if (unlikely(segment_eq(get_fs(), KERNEL_DS))) { | 57 | if (unlikely(segment_eq(get_fs(), KERNEL_DS))) { |
61 | memcpy((void *)to, from, n); | 58 | memcpy((void *)to, from, n); |
62 | return 0; | 59 | return 0; |
@@ -99,11 +96,24 @@ out: | |||
99 | return n; | 96 | return n; |
100 | } | 97 | } |
101 | 98 | ||
102 | unsigned long __clear_user(void __user *addr, unsigned long n) | 99 | unsigned long |
100 | __copy_to_user(void __user *to, const void *from, unsigned long n) | ||
101 | { | ||
102 | /* | ||
103 | * This test is stubbed out of the main function above to keep | ||
104 | * the overhead for small copies low by avoiding a large | ||
105 | * register dump on the stack just to reload them right away. | ||
106 | * With frame pointer disabled, tail call optimization kicks in | ||
107 | * as well making this test almost invisible. | ||
108 | */ | ||
109 | if (n < 1024) | ||
110 | return __copy_to_user_std(to, from, n); | ||
111 | return __copy_to_user_memcpy(to, from, n); | ||
112 | } | ||
113 | |||
114 | static unsigned long noinline | ||
115 | __clear_user_memset(void __user *addr, unsigned long n) | ||
103 | { | 116 | { |
104 | if (n < 256) | ||
105 | return __clear_user_std(addr, n); | ||
106 | |||
107 | if (unlikely(segment_eq(get_fs(), KERNEL_DS))) { | 117 | if (unlikely(segment_eq(get_fs(), KERNEL_DS))) { |
108 | memset((void *)addr, 0, n); | 118 | memset((void *)addr, 0, n); |
109 | return 0; | 119 | return 0; |
@@ -137,3 +147,11 @@ unsigned long __clear_user(void __user *addr, unsigned long n) | |||
137 | out: | 147 | out: |
138 | return n; | 148 | return n; |
139 | } | 149 | } |
150 | |||
151 | unsigned long __clear_user(void __user *addr, unsigned long n) | ||
152 | { | ||
153 | /* See rational for this in __copy_to_user() above. */ | ||
154 | if (n < 256) | ||
155 | return __clear_user_std(addr, n); | ||
156 | return __clear_user_memset(addr, n); | ||
157 | } | ||