aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/lib/uaccess_with_memcpy.c36
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
52unsigned long 52static 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
102unsigned long __clear_user(void __user *addr, unsigned long n) 99unsigned 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
114static 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)
137out: 147out:
138 return n; 148 return n;
139} 149}
150
151unsigned 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}