Commit 47d632f9f8f3ed62b21f725e98b726d65769b6d7
1 parent
1efea40d41
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
arch/tile: optimize get_user/put_user and friends
Use direct load/store for the get_user/put_user. Previously, we would call out to a helper routine that would do the appropriate thing and then return, handling the possible exception internally. Now we inline the load or store, along with a "we succeeded" indication in a register; if the load or store faults, we write a "we failed" indication into the same register and then return to the following instruction. This is more efficient and gives us more compact code, as well as being more in line with what other architectures do. The special futex assembly source file for TILE-Gx also disappears in this change; we just use the same inlining idiom there as well, putting the appropriate atomic operations directly into futex_atomic_op_inuser() (and thus into the FUTEX_WAIT function). The underlying atomic copy_from_user, copy_to_user functions were renamed using the (cryptic) x86 convention as copy_from_user_ll and copy_to_user_ll. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Showing 8 changed files with 241 additions and 315 deletions Inline Diff
arch/tile/include/asm/atomic_32.h
1 | /* | 1 | /* |
2 | * Copyright 2010 Tilera Corporation. All Rights Reserved. | 2 | * Copyright 2010 Tilera Corporation. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU General Public License | 5 | * modify it under the terms of the GNU General Public License |
6 | * as published by the Free Software Foundation, version 2. | 6 | * as published by the Free Software Foundation, version 2. |
7 | * | 7 | * |
8 | * This program is distributed in the hope that it will be useful, but | 8 | * This program is distributed in the hope that it will be useful, but |
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 9 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | 10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or |
11 | * NON INFRINGEMENT. See the GNU General Public License for | 11 | * NON INFRINGEMENT. See the GNU General Public License for |
12 | * more details. | 12 | * more details. |
13 | * | 13 | * |
14 | * Do not include directly; use <linux/atomic.h>. | 14 | * Do not include directly; use <linux/atomic.h>. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifndef _ASM_TILE_ATOMIC_32_H | 17 | #ifndef _ASM_TILE_ATOMIC_32_H |
18 | #define _ASM_TILE_ATOMIC_32_H | 18 | #define _ASM_TILE_ATOMIC_32_H |
19 | 19 | ||
20 | #include <asm/barrier.h> | 20 | #include <asm/barrier.h> |
21 | #include <arch/chip.h> | 21 | #include <arch/chip.h> |
22 | 22 | ||
23 | #ifndef __ASSEMBLY__ | 23 | #ifndef __ASSEMBLY__ |
24 | 24 | ||
25 | /* Tile-specific routines to support <linux/atomic.h>. */ | 25 | /* Tile-specific routines to support <linux/atomic.h>. */ |
26 | int _atomic_xchg(atomic_t *v, int n); | 26 | int _atomic_xchg(atomic_t *v, int n); |
27 | int _atomic_xchg_add(atomic_t *v, int i); | 27 | int _atomic_xchg_add(atomic_t *v, int i); |
28 | int _atomic_xchg_add_unless(atomic_t *v, int a, int u); | 28 | int _atomic_xchg_add_unless(atomic_t *v, int a, int u); |
29 | int _atomic_cmpxchg(atomic_t *v, int o, int n); | 29 | int _atomic_cmpxchg(atomic_t *v, int o, int n); |
30 | 30 | ||
31 | /** | 31 | /** |
32 | * atomic_xchg - atomically exchange contents of memory with a new value | 32 | * atomic_xchg - atomically exchange contents of memory with a new value |
33 | * @v: pointer of type atomic_t | 33 | * @v: pointer of type atomic_t |
34 | * @i: integer value to store in memory | 34 | * @i: integer value to store in memory |
35 | * | 35 | * |
36 | * Atomically sets @v to @i and returns old @v | 36 | * Atomically sets @v to @i and returns old @v |
37 | */ | 37 | */ |
38 | static inline int atomic_xchg(atomic_t *v, int n) | 38 | static inline int atomic_xchg(atomic_t *v, int n) |
39 | { | 39 | { |
40 | smp_mb(); /* barrier for proper semantics */ | 40 | smp_mb(); /* barrier for proper semantics */ |
41 | return _atomic_xchg(v, n); | 41 | return _atomic_xchg(v, n); |
42 | } | 42 | } |
43 | 43 | ||
44 | /** | 44 | /** |
45 | * atomic_cmpxchg - atomically exchange contents of memory if it matches | 45 | * atomic_cmpxchg - atomically exchange contents of memory if it matches |
46 | * @v: pointer of type atomic_t | 46 | * @v: pointer of type atomic_t |
47 | * @o: old value that memory should have | 47 | * @o: old value that memory should have |
48 | * @n: new value to write to memory if it matches | 48 | * @n: new value to write to memory if it matches |
49 | * | 49 | * |
50 | * Atomically checks if @v holds @o and replaces it with @n if so. | 50 | * Atomically checks if @v holds @o and replaces it with @n if so. |
51 | * Returns the old value at @v. | 51 | * Returns the old value at @v. |
52 | */ | 52 | */ |
53 | static inline int atomic_cmpxchg(atomic_t *v, int o, int n) | 53 | static inline int atomic_cmpxchg(atomic_t *v, int o, int n) |
54 | { | 54 | { |
55 | smp_mb(); /* barrier for proper semantics */ | 55 | smp_mb(); /* barrier for proper semantics */ |
56 | return _atomic_cmpxchg(v, o, n); | 56 | return _atomic_cmpxchg(v, o, n); |
57 | } | 57 | } |
58 | 58 | ||
59 | /** | 59 | /** |
60 | * atomic_add - add integer to atomic variable | 60 | * atomic_add - add integer to atomic variable |
61 | * @i: integer value to add | 61 | * @i: integer value to add |
62 | * @v: pointer of type atomic_t | 62 | * @v: pointer of type atomic_t |
63 | * | 63 | * |
64 | * Atomically adds @i to @v. | 64 | * Atomically adds @i to @v. |
65 | */ | 65 | */ |
66 | static inline void atomic_add(int i, atomic_t *v) | 66 | static inline void atomic_add(int i, atomic_t *v) |
67 | { | 67 | { |
68 | _atomic_xchg_add(v, i); | 68 | _atomic_xchg_add(v, i); |
69 | } | 69 | } |
70 | 70 | ||
71 | /** | 71 | /** |
72 | * atomic_add_return - add integer and return | 72 | * atomic_add_return - add integer and return |
73 | * @v: pointer of type atomic_t | 73 | * @v: pointer of type atomic_t |
74 | * @i: integer value to add | 74 | * @i: integer value to add |
75 | * | 75 | * |
76 | * Atomically adds @i to @v and returns @i + @v | 76 | * Atomically adds @i to @v and returns @i + @v |
77 | */ | 77 | */ |
78 | static inline int atomic_add_return(int i, atomic_t *v) | 78 | static inline int atomic_add_return(int i, atomic_t *v) |
79 | { | 79 | { |
80 | smp_mb(); /* barrier for proper semantics */ | 80 | smp_mb(); /* barrier for proper semantics */ |
81 | return _atomic_xchg_add(v, i) + i; | 81 | return _atomic_xchg_add(v, i) + i; |
82 | } | 82 | } |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * __atomic_add_unless - add unless the number is already a given value | 85 | * __atomic_add_unless - add unless the number is already a given value |
86 | * @v: pointer of type atomic_t | 86 | * @v: pointer of type atomic_t |
87 | * @a: the amount to add to v... | 87 | * @a: the amount to add to v... |
88 | * @u: ...unless v is equal to u. | 88 | * @u: ...unless v is equal to u. |
89 | * | 89 | * |
90 | * Atomically adds @a to @v, so long as @v was not already @u. | 90 | * Atomically adds @a to @v, so long as @v was not already @u. |
91 | * Returns the old value of @v. | 91 | * Returns the old value of @v. |
92 | */ | 92 | */ |
93 | static inline int __atomic_add_unless(atomic_t *v, int a, int u) | 93 | static inline int __atomic_add_unless(atomic_t *v, int a, int u) |
94 | { | 94 | { |
95 | smp_mb(); /* barrier for proper semantics */ | 95 | smp_mb(); /* barrier for proper semantics */ |
96 | return _atomic_xchg_add_unless(v, a, u); | 96 | return _atomic_xchg_add_unless(v, a, u); |
97 | } | 97 | } |
98 | 98 | ||
99 | /** | 99 | /** |
100 | * atomic_set - set atomic variable | 100 | * atomic_set - set atomic variable |
101 | * @v: pointer of type atomic_t | 101 | * @v: pointer of type atomic_t |
102 | * @i: required value | 102 | * @i: required value |
103 | * | 103 | * |
104 | * Atomically sets the value of @v to @i. | 104 | * Atomically sets the value of @v to @i. |
105 | * | 105 | * |
106 | * atomic_set() can't be just a raw store, since it would be lost if it | 106 | * atomic_set() can't be just a raw store, since it would be lost if it |
107 | * fell between the load and store of one of the other atomic ops. | 107 | * fell between the load and store of one of the other atomic ops. |
108 | */ | 108 | */ |
109 | static inline void atomic_set(atomic_t *v, int n) | 109 | static inline void atomic_set(atomic_t *v, int n) |
110 | { | 110 | { |
111 | _atomic_xchg(v, n); | 111 | _atomic_xchg(v, n); |
112 | } | 112 | } |
113 | 113 | ||
114 | /* A 64bit atomic type */ | 114 | /* A 64bit atomic type */ |
115 | 115 | ||
116 | typedef struct { | 116 | typedef struct { |
117 | u64 __aligned(8) counter; | 117 | u64 __aligned(8) counter; |
118 | } atomic64_t; | 118 | } atomic64_t; |
119 | 119 | ||
120 | #define ATOMIC64_INIT(val) { (val) } | 120 | #define ATOMIC64_INIT(val) { (val) } |
121 | 121 | ||
122 | u64 _atomic64_xchg(atomic64_t *v, u64 n); | 122 | u64 _atomic64_xchg(atomic64_t *v, u64 n); |
123 | u64 _atomic64_xchg_add(atomic64_t *v, u64 i); | 123 | u64 _atomic64_xchg_add(atomic64_t *v, u64 i); |
124 | u64 _atomic64_xchg_add_unless(atomic64_t *v, u64 a, u64 u); | 124 | u64 _atomic64_xchg_add_unless(atomic64_t *v, u64 a, u64 u); |
125 | u64 _atomic64_cmpxchg(atomic64_t *v, u64 o, u64 n); | 125 | u64 _atomic64_cmpxchg(atomic64_t *v, u64 o, u64 n); |
126 | 126 | ||
127 | /** | 127 | /** |
128 | * atomic64_read - read atomic variable | 128 | * atomic64_read - read atomic variable |
129 | * @v: pointer of type atomic64_t | 129 | * @v: pointer of type atomic64_t |
130 | * | 130 | * |
131 | * Atomically reads the value of @v. | 131 | * Atomically reads the value of @v. |
132 | */ | 132 | */ |
133 | static inline u64 atomic64_read(const atomic64_t *v) | 133 | static inline u64 atomic64_read(const atomic64_t *v) |
134 | { | 134 | { |
135 | /* | 135 | /* |
136 | * Requires an atomic op to read both 32-bit parts consistently. | 136 | * Requires an atomic op to read both 32-bit parts consistently. |
137 | * Casting away const is safe since the atomic support routines | 137 | * Casting away const is safe since the atomic support routines |
138 | * do not write to memory if the value has not been modified. | 138 | * do not write to memory if the value has not been modified. |
139 | */ | 139 | */ |
140 | return _atomic64_xchg_add((atomic64_t *)v, 0); | 140 | return _atomic64_xchg_add((atomic64_t *)v, 0); |
141 | } | 141 | } |
142 | 142 | ||
143 | /** | 143 | /** |
144 | * atomic64_xchg - atomically exchange contents of memory with a new value | 144 | * atomic64_xchg - atomically exchange contents of memory with a new value |
145 | * @v: pointer of type atomic64_t | 145 | * @v: pointer of type atomic64_t |
146 | * @i: integer value to store in memory | 146 | * @i: integer value to store in memory |
147 | * | 147 | * |
148 | * Atomically sets @v to @i and returns old @v | 148 | * Atomically sets @v to @i and returns old @v |
149 | */ | 149 | */ |
150 | static inline u64 atomic64_xchg(atomic64_t *v, u64 n) | 150 | static inline u64 atomic64_xchg(atomic64_t *v, u64 n) |
151 | { | 151 | { |
152 | smp_mb(); /* barrier for proper semantics */ | 152 | smp_mb(); /* barrier for proper semantics */ |
153 | return _atomic64_xchg(v, n); | 153 | return _atomic64_xchg(v, n); |
154 | } | 154 | } |
155 | 155 | ||
156 | /** | 156 | /** |
157 | * atomic64_cmpxchg - atomically exchange contents of memory if it matches | 157 | * atomic64_cmpxchg - atomically exchange contents of memory if it matches |
158 | * @v: pointer of type atomic64_t | 158 | * @v: pointer of type atomic64_t |
159 | * @o: old value that memory should have | 159 | * @o: old value that memory should have |
160 | * @n: new value to write to memory if it matches | 160 | * @n: new value to write to memory if it matches |
161 | * | 161 | * |
162 | * Atomically checks if @v holds @o and replaces it with @n if so. | 162 | * Atomically checks if @v holds @o and replaces it with @n if so. |
163 | * Returns the old value at @v. | 163 | * Returns the old value at @v. |
164 | */ | 164 | */ |
165 | static inline u64 atomic64_cmpxchg(atomic64_t *v, u64 o, u64 n) | 165 | static inline u64 atomic64_cmpxchg(atomic64_t *v, u64 o, u64 n) |
166 | { | 166 | { |
167 | smp_mb(); /* barrier for proper semantics */ | 167 | smp_mb(); /* barrier for proper semantics */ |
168 | return _atomic64_cmpxchg(v, o, n); | 168 | return _atomic64_cmpxchg(v, o, n); |
169 | } | 169 | } |
170 | 170 | ||
171 | /** | 171 | /** |
172 | * atomic64_add - add integer to atomic variable | 172 | * atomic64_add - add integer to atomic variable |
173 | * @i: integer value to add | 173 | * @i: integer value to add |
174 | * @v: pointer of type atomic64_t | 174 | * @v: pointer of type atomic64_t |
175 | * | 175 | * |
176 | * Atomically adds @i to @v. | 176 | * Atomically adds @i to @v. |
177 | */ | 177 | */ |
178 | static inline void atomic64_add(u64 i, atomic64_t *v) | 178 | static inline void atomic64_add(u64 i, atomic64_t *v) |
179 | { | 179 | { |
180 | _atomic64_xchg_add(v, i); | 180 | _atomic64_xchg_add(v, i); |
181 | } | 181 | } |
182 | 182 | ||
183 | /** | 183 | /** |
184 | * atomic64_add_return - add integer and return | 184 | * atomic64_add_return - add integer and return |
185 | * @v: pointer of type atomic64_t | 185 | * @v: pointer of type atomic64_t |
186 | * @i: integer value to add | 186 | * @i: integer value to add |
187 | * | 187 | * |
188 | * Atomically adds @i to @v and returns @i + @v | 188 | * Atomically adds @i to @v and returns @i + @v |
189 | */ | 189 | */ |
190 | static inline u64 atomic64_add_return(u64 i, atomic64_t *v) | 190 | static inline u64 atomic64_add_return(u64 i, atomic64_t *v) |
191 | { | 191 | { |
192 | smp_mb(); /* barrier for proper semantics */ | 192 | smp_mb(); /* barrier for proper semantics */ |
193 | return _atomic64_xchg_add(v, i) + i; | 193 | return _atomic64_xchg_add(v, i) + i; |
194 | } | 194 | } |
195 | 195 | ||
196 | /** | 196 | /** |
197 | * atomic64_add_unless - add unless the number is already a given value | 197 | * atomic64_add_unless - add unless the number is already a given value |
198 | * @v: pointer of type atomic64_t | 198 | * @v: pointer of type atomic64_t |
199 | * @a: the amount to add to v... | 199 | * @a: the amount to add to v... |
200 | * @u: ...unless v is equal to u. | 200 | * @u: ...unless v is equal to u. |
201 | * | 201 | * |
202 | * Atomically adds @a to @v, so long as @v was not already @u. | 202 | * Atomically adds @a to @v, so long as @v was not already @u. |
203 | * Returns non-zero if @v was not @u, and zero otherwise. | 203 | * Returns non-zero if @v was not @u, and zero otherwise. |
204 | */ | 204 | */ |
205 | static inline u64 atomic64_add_unless(atomic64_t *v, u64 a, u64 u) | 205 | static inline u64 atomic64_add_unless(atomic64_t *v, u64 a, u64 u) |
206 | { | 206 | { |
207 | smp_mb(); /* barrier for proper semantics */ | 207 | smp_mb(); /* barrier for proper semantics */ |
208 | return _atomic64_xchg_add_unless(v, a, u) != u; | 208 | return _atomic64_xchg_add_unless(v, a, u) != u; |
209 | } | 209 | } |
210 | 210 | ||
211 | /** | 211 | /** |
212 | * atomic64_set - set atomic variable | 212 | * atomic64_set - set atomic variable |
213 | * @v: pointer of type atomic64_t | 213 | * @v: pointer of type atomic64_t |
214 | * @i: required value | 214 | * @i: required value |
215 | * | 215 | * |
216 | * Atomically sets the value of @v to @i. | 216 | * Atomically sets the value of @v to @i. |
217 | * | 217 | * |
218 | * atomic64_set() can't be just a raw store, since it would be lost if it | 218 | * atomic64_set() can't be just a raw store, since it would be lost if it |
219 | * fell between the load and store of one of the other atomic ops. | 219 | * fell between the load and store of one of the other atomic ops. |
220 | */ | 220 | */ |
221 | static inline void atomic64_set(atomic64_t *v, u64 n) | 221 | static inline void atomic64_set(atomic64_t *v, u64 n) |
222 | { | 222 | { |
223 | _atomic64_xchg(v, n); | 223 | _atomic64_xchg(v, n); |
224 | } | 224 | } |
225 | 225 | ||
226 | #define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0) | 226 | #define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0) |
227 | #define atomic64_inc(v) atomic64_add(1LL, (v)) | 227 | #define atomic64_inc(v) atomic64_add(1LL, (v)) |
228 | #define atomic64_inc_return(v) atomic64_add_return(1LL, (v)) | 228 | #define atomic64_inc_return(v) atomic64_add_return(1LL, (v)) |
229 | #define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0) | 229 | #define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0) |
230 | #define atomic64_sub_return(i, v) atomic64_add_return(-(i), (v)) | 230 | #define atomic64_sub_return(i, v) atomic64_add_return(-(i), (v)) |
231 | #define atomic64_sub_and_test(a, v) (atomic64_sub_return((a), (v)) == 0) | 231 | #define atomic64_sub_and_test(a, v) (atomic64_sub_return((a), (v)) == 0) |
232 | #define atomic64_sub(i, v) atomic64_add(-(i), (v)) | 232 | #define atomic64_sub(i, v) atomic64_add(-(i), (v)) |
233 | #define atomic64_dec(v) atomic64_sub(1LL, (v)) | 233 | #define atomic64_dec(v) atomic64_sub(1LL, (v)) |
234 | #define atomic64_dec_return(v) atomic64_sub_return(1LL, (v)) | 234 | #define atomic64_dec_return(v) atomic64_sub_return(1LL, (v)) |
235 | #define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0) | 235 | #define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0) |
236 | #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1LL, 0LL) | 236 | #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1LL, 0LL) |
237 | 237 | ||
238 | /* | 238 | /* |
239 | * We need to barrier before modifying the word, since the _atomic_xxx() | 239 | * We need to barrier before modifying the word, since the _atomic_xxx() |
240 | * routines just tns the lock and then read/modify/write of the word. | 240 | * routines just tns the lock and then read/modify/write of the word. |
241 | * But after the word is updated, the routine issues an "mf" before returning, | 241 | * But after the word is updated, the routine issues an "mf" before returning, |
242 | * and since it's a function call, we don't even need a compiler barrier. | 242 | * and since it's a function call, we don't even need a compiler barrier. |
243 | */ | 243 | */ |
244 | #define smp_mb__before_atomic_dec() smp_mb() | 244 | #define smp_mb__before_atomic_dec() smp_mb() |
245 | #define smp_mb__before_atomic_inc() smp_mb() | 245 | #define smp_mb__before_atomic_inc() smp_mb() |
246 | #define smp_mb__after_atomic_dec() do { } while (0) | 246 | #define smp_mb__after_atomic_dec() do { } while (0) |
247 | #define smp_mb__after_atomic_inc() do { } while (0) | 247 | #define smp_mb__after_atomic_inc() do { } while (0) |
248 | 248 | ||
249 | #endif /* !__ASSEMBLY__ */ | 249 | #endif /* !__ASSEMBLY__ */ |
250 | 250 | ||
251 | /* | 251 | /* |
252 | * Internal definitions only beyond this point. | 252 | * Internal definitions only beyond this point. |
253 | */ | 253 | */ |
254 | 254 | ||
255 | #define ATOMIC_LOCKS_FOUND_VIA_TABLE() \ | 255 | #define ATOMIC_LOCKS_FOUND_VIA_TABLE() \ |
256 | (!CHIP_HAS_CBOX_HOME_MAP() && defined(CONFIG_SMP)) | 256 | (!CHIP_HAS_CBOX_HOME_MAP() && defined(CONFIG_SMP)) |
257 | 257 | ||
258 | #if ATOMIC_LOCKS_FOUND_VIA_TABLE() | 258 | #if ATOMIC_LOCKS_FOUND_VIA_TABLE() |
259 | 259 | ||
260 | /* Number of entries in atomic_lock_ptr[]. */ | 260 | /* Number of entries in atomic_lock_ptr[]. */ |
261 | #define ATOMIC_HASH_L1_SHIFT 6 | 261 | #define ATOMIC_HASH_L1_SHIFT 6 |
262 | #define ATOMIC_HASH_L1_SIZE (1 << ATOMIC_HASH_L1_SHIFT) | 262 | #define ATOMIC_HASH_L1_SIZE (1 << ATOMIC_HASH_L1_SHIFT) |
263 | 263 | ||
264 | /* Number of locks in each struct pointed to by atomic_lock_ptr[]. */ | 264 | /* Number of locks in each struct pointed to by atomic_lock_ptr[]. */ |
265 | #define ATOMIC_HASH_L2_SHIFT (CHIP_L2_LOG_LINE_SIZE() - 2) | 265 | #define ATOMIC_HASH_L2_SHIFT (CHIP_L2_LOG_LINE_SIZE() - 2) |
266 | #define ATOMIC_HASH_L2_SIZE (1 << ATOMIC_HASH_L2_SHIFT) | 266 | #define ATOMIC_HASH_L2_SIZE (1 << ATOMIC_HASH_L2_SHIFT) |
267 | 267 | ||
268 | #else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ | 268 | #else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ |
269 | 269 | ||
270 | /* | 270 | /* |
271 | * Number of atomic locks in atomic_locks[]. Must be a power of two. | 271 | * Number of atomic locks in atomic_locks[]. Must be a power of two. |
272 | * There is no reason for more than PAGE_SIZE / 8 entries, since that | 272 | * There is no reason for more than PAGE_SIZE / 8 entries, since that |
273 | * is the maximum number of pointer bits we can use to index this. | 273 | * is the maximum number of pointer bits we can use to index this. |
274 | * And we cannot have more than PAGE_SIZE / 4, since this has to | 274 | * And we cannot have more than PAGE_SIZE / 4, since this has to |
275 | * fit on a single page and each entry takes 4 bytes. | 275 | * fit on a single page and each entry takes 4 bytes. |
276 | */ | 276 | */ |
277 | #define ATOMIC_HASH_SHIFT (PAGE_SHIFT - 3) | 277 | #define ATOMIC_HASH_SHIFT (PAGE_SHIFT - 3) |
278 | #define ATOMIC_HASH_SIZE (1 << ATOMIC_HASH_SHIFT) | 278 | #define ATOMIC_HASH_SIZE (1 << ATOMIC_HASH_SHIFT) |
279 | 279 | ||
280 | #ifndef __ASSEMBLY__ | 280 | #ifndef __ASSEMBLY__ |
281 | extern int atomic_locks[]; | 281 | extern int atomic_locks[]; |
282 | #endif | 282 | #endif |
283 | 283 | ||
284 | #endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ | 284 | #endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ |
285 | 285 | ||
286 | /* | 286 | /* |
287 | * All the code that may fault while holding an atomic lock must | 287 | * All the code that may fault while holding an atomic lock must |
288 | * place the pointer to the lock in ATOMIC_LOCK_REG so the fault code | 288 | * place the pointer to the lock in ATOMIC_LOCK_REG so the fault code |
289 | * can correctly release and reacquire the lock. Note that we | 289 | * can correctly release and reacquire the lock. Note that we |
290 | * mention the register number in a comment in "lib/atomic_asm.S" to help | 290 | * mention the register number in a comment in "lib/atomic_asm.S" to help |
291 | * assembly coders from using this register by mistake, so if it | 291 | * assembly coders from using this register by mistake, so if it |
292 | * is changed here, change that comment as well. | 292 | * is changed here, change that comment as well. |
293 | */ | 293 | */ |
294 | #define ATOMIC_LOCK_REG 20 | 294 | #define ATOMIC_LOCK_REG 20 |
295 | #define ATOMIC_LOCK_REG_NAME r20 | 295 | #define ATOMIC_LOCK_REG_NAME r20 |
296 | 296 | ||
297 | #ifndef __ASSEMBLY__ | 297 | #ifndef __ASSEMBLY__ |
298 | /* Called from setup to initialize a hash table to point to per_cpu locks. */ | 298 | /* Called from setup to initialize a hash table to point to per_cpu locks. */ |
299 | void __init_atomic_per_cpu(void); | 299 | void __init_atomic_per_cpu(void); |
300 | 300 | ||
301 | #ifdef CONFIG_SMP | 301 | #ifdef CONFIG_SMP |
302 | /* Support releasing the atomic lock in do_page_fault_ics(). */ | 302 | /* Support releasing the atomic lock in do_page_fault_ics(). */ |
303 | void __atomic_fault_unlock(int *lock_ptr); | 303 | void __atomic_fault_unlock(int *lock_ptr); |
304 | #endif | 304 | #endif |
305 | 305 | ||
306 | /* Return a pointer to the lock for the given address. */ | ||
307 | int *__atomic_hashed_lock(volatile void *v); | ||
308 | |||
306 | /* Private helper routines in lib/atomic_asm_32.S */ | 309 | /* Private helper routines in lib/atomic_asm_32.S */ |
310 | struct __get_user { | ||
311 | unsigned long val; | ||
312 | int err; | ||
313 | }; | ||
307 | extern struct __get_user __atomic_cmpxchg(volatile int *p, | 314 | extern struct __get_user __atomic_cmpxchg(volatile int *p, |
308 | int *lock, int o, int n); | 315 | int *lock, int o, int n); |
309 | extern struct __get_user __atomic_xchg(volatile int *p, int *lock, int n); | 316 | extern struct __get_user __atomic_xchg(volatile int *p, int *lock, int n); |
310 | extern struct __get_user __atomic_xchg_add(volatile int *p, int *lock, int n); | 317 | extern struct __get_user __atomic_xchg_add(volatile int *p, int *lock, int n); |
311 | extern struct __get_user __atomic_xchg_add_unless(volatile int *p, | 318 | extern struct __get_user __atomic_xchg_add_unless(volatile int *p, |
312 | int *lock, int o, int n); | 319 | int *lock, int o, int n); |
313 | extern struct __get_user __atomic_or(volatile int *p, int *lock, int n); | 320 | extern struct __get_user __atomic_or(volatile int *p, int *lock, int n); |
314 | extern struct __get_user __atomic_andn(volatile int *p, int *lock, int n); | 321 | extern struct __get_user __atomic_andn(volatile int *p, int *lock, int n); |
315 | extern struct __get_user __atomic_xor(volatile int *p, int *lock, int n); | 322 | extern struct __get_user __atomic_xor(volatile int *p, int *lock, int n); |
316 | extern u64 __atomic64_cmpxchg(volatile u64 *p, int *lock, u64 o, u64 n); | 323 | extern u64 __atomic64_cmpxchg(volatile u64 *p, int *lock, u64 o, u64 n); |
317 | extern u64 __atomic64_xchg(volatile u64 *p, int *lock, u64 n); | 324 | extern u64 __atomic64_xchg(volatile u64 *p, int *lock, u64 n); |
318 | extern u64 __atomic64_xchg_add(volatile u64 *p, int *lock, u64 n); | 325 | extern u64 __atomic64_xchg_add(volatile u64 *p, int *lock, u64 n); |
319 | extern u64 __atomic64_xchg_add_unless(volatile u64 *p, | 326 | extern u64 __atomic64_xchg_add_unless(volatile u64 *p, |
320 | int *lock, u64 o, u64 n); | 327 | int *lock, u64 o, u64 n); |
328 | |||
329 | /* Return failure from the atomic wrappers. */ | ||
330 | struct __get_user __atomic_bad_address(int __user *addr); | ||
321 | 331 | ||
322 | #endif /* !__ASSEMBLY__ */ | 332 | #endif /* !__ASSEMBLY__ */ |
323 | 333 | ||
324 | #endif /* _ASM_TILE_ATOMIC_32_H */ | 334 | #endif /* _ASM_TILE_ATOMIC_32_H */ |
325 | 335 |
arch/tile/include/asm/futex.h
1 | /* | 1 | /* |
2 | * Copyright 2010 Tilera Corporation. All Rights Reserved. | 2 | * Copyright 2010 Tilera Corporation. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU General Public License | 5 | * modify it under the terms of the GNU General Public License |
6 | * as published by the Free Software Foundation, version 2. | 6 | * as published by the Free Software Foundation, version 2. |
7 | * | 7 | * |
8 | * This program is distributed in the hope that it will be useful, but | 8 | * This program is distributed in the hope that it will be useful, but |
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 9 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | 10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or |
11 | * NON INFRINGEMENT. See the GNU General Public License for | 11 | * NON INFRINGEMENT. See the GNU General Public License for |
12 | * more details. | 12 | * more details. |
13 | * | 13 | * |
14 | * These routines make two important assumptions: | 14 | * These routines make two important assumptions: |
15 | * | 15 | * |
16 | * 1. atomic_t is really an int and can be freely cast back and forth | 16 | * 1. atomic_t is really an int and can be freely cast back and forth |
17 | * (validated in __init_atomic_per_cpu). | 17 | * (validated in __init_atomic_per_cpu). |
18 | * | 18 | * |
19 | * 2. userspace uses sys_cmpxchg() for all atomic operations, thus using | 19 | * 2. userspace uses sys_cmpxchg() for all atomic operations, thus using |
20 | * the same locking convention that all the kernel atomic routines use. | 20 | * the same locking convention that all the kernel atomic routines use. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #ifndef _ASM_TILE_FUTEX_H | 23 | #ifndef _ASM_TILE_FUTEX_H |
24 | #define _ASM_TILE_FUTEX_H | 24 | #define _ASM_TILE_FUTEX_H |
25 | 25 | ||
26 | #ifndef __ASSEMBLY__ | 26 | #ifndef __ASSEMBLY__ |
27 | 27 | ||
28 | #include <linux/futex.h> | 28 | #include <linux/futex.h> |
29 | #include <linux/uaccess.h> | 29 | #include <linux/uaccess.h> |
30 | #include <linux/errno.h> | 30 | #include <linux/errno.h> |
31 | #include <asm/atomic.h> | ||
31 | 32 | ||
32 | extern struct __get_user futex_set(u32 __user *v, int i); | 33 | /* |
33 | extern struct __get_user futex_add(u32 __user *v, int n); | 34 | * Support macros for futex operations. Do not use these macros directly. |
34 | extern struct __get_user futex_or(u32 __user *v, int n); | 35 | * They assume "ret", "val", "oparg", and "uaddr" in the lexical context. |
35 | extern struct __get_user futex_andn(u32 __user *v, int n); | 36 | * __futex_cmpxchg() additionally assumes "oldval". |
36 | extern struct __get_user futex_cmpxchg(u32 __user *v, int o, int n); | 37 | */ |
37 | 38 | ||
38 | #ifndef __tilegx__ | 39 | #ifdef __tilegx__ |
39 | extern struct __get_user futex_xor(u32 __user *v, int n); | 40 | |
41 | #define __futex_asm(OP) \ | ||
42 | asm("1: {" #OP " %1, %3, %4; movei %0, 0 }\n" \ | ||
43 | ".pushsection .fixup,\"ax\"\n" \ | ||
44 | "0: { movei %0, %5; j 9f }\n" \ | ||
45 | ".section __ex_table,\"a\"\n" \ | ||
46 | ".quad 1b, 0b\n" \ | ||
47 | ".popsection\n" \ | ||
48 | "9:" \ | ||
49 | : "=r" (ret), "=r" (val), "+m" (*(uaddr)) \ | ||
50 | : "r" (uaddr), "r" (oparg), "i" (-EFAULT)) | ||
51 | |||
52 | #define __futex_set() __futex_asm(exch4) | ||
53 | #define __futex_add() __futex_asm(fetchadd4) | ||
54 | #define __futex_or() __futex_asm(fetchor4) | ||
55 | #define __futex_andn() ({ oparg = ~oparg; __futex_asm(fetchand4); }) | ||
56 | #define __futex_cmpxchg() \ | ||
57 | ({ __insn_mtspr(SPR_CMPEXCH_VALUE, oldval); __futex_asm(cmpexch4); }) | ||
58 | |||
59 | #define __futex_xor() \ | ||
60 | ({ \ | ||
61 | u32 oldval, n = oparg; \ | ||
62 | if ((ret = __get_user(oldval, uaddr)) == 0) { \ | ||
63 | do { \ | ||
64 | oparg = oldval ^ n; \ | ||
65 | __futex_cmpxchg(); \ | ||
66 | } while (ret == 0 && oldval != val); \ | ||
67 | } \ | ||
68 | }) | ||
69 | |||
70 | /* No need to prefetch, since the atomic ops go to the home cache anyway. */ | ||
71 | #define __futex_prolog() | ||
72 | |||
40 | #else | 73 | #else |
41 | static inline struct __get_user futex_xor(u32 __user *uaddr, int n) | 74 | |
42 | { | 75 | #define __futex_call(FN) \ |
43 | struct __get_user asm_ret = __get_user_4(uaddr); | 76 | { \ |
44 | if (!asm_ret.err) { | 77 | struct __get_user gu = FN((u32 __force *)uaddr, lock, oparg); \ |
45 | int oldval, newval; | 78 | val = gu.val; \ |
46 | do { | 79 | ret = gu.err; \ |
47 | oldval = asm_ret.val; | ||
48 | newval = oldval ^ n; | ||
49 | asm_ret = futex_cmpxchg(uaddr, oldval, newval); | ||
50 | } while (asm_ret.err == 0 && oldval != asm_ret.val); | ||
51 | } | 80 | } |
52 | return asm_ret; | 81 | |
53 | } | 82 | #define __futex_set() __futex_call(__atomic_xchg) |
83 | #define __futex_add() __futex_call(__atomic_xchg_add) | ||
84 | #define __futex_or() __futex_call(__atomic_or) | ||
85 | #define __futex_andn() __futex_call(__atomic_andn) | ||
86 | #define __futex_xor() __futex_call(__atomic_xor) | ||
87 | |||
88 | #define __futex_cmpxchg() \ | ||
89 | { \ | ||
90 | struct __get_user gu = __atomic_cmpxchg((u32 __force *)uaddr, \ | ||
91 | lock, oldval, oparg); \ | ||
92 | val = gu.val; \ | ||
93 | ret = gu.err; \ | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Find the lock pointer for the atomic calls to use, and issue a | ||
98 | * prefetch to the user address to bring it into cache. Similar to | ||
99 | * __atomic_setup(), but we can't do a read into the L1 since it might | ||
100 | * fault; instead we do a prefetch into the L2. | ||
101 | */ | ||
102 | #define __futex_prolog() \ | ||
103 | int *lock; \ | ||
104 | __insn_prefetch(uaddr); \ | ||
105 | lock = __atomic_hashed_lock((int __force *)uaddr) | ||
54 | #endif | 106 | #endif |
55 | 107 | ||
56 | static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) | 108 | static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) |
57 | { | 109 | { |
58 | int op = (encoded_op >> 28) & 7; | 110 | int op = (encoded_op >> 28) & 7; |
59 | int cmp = (encoded_op >> 24) & 15; | 111 | int cmp = (encoded_op >> 24) & 15; |
60 | int oparg = (encoded_op << 8) >> 20; | 112 | int oparg = (encoded_op << 8) >> 20; |
61 | int cmparg = (encoded_op << 20) >> 20; | 113 | int cmparg = (encoded_op << 20) >> 20; |
62 | int ret; | 114 | int uninitialized_var(val), ret; |
63 | struct __get_user asm_ret; | ||
64 | 115 | ||
116 | __futex_prolog(); | ||
117 | |||
118 | /* The 32-bit futex code makes this assumption, so validate it here. */ | ||
119 | BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int)); | ||
120 | |||
65 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 121 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
66 | oparg = 1 << oparg; | 122 | oparg = 1 << oparg; |
67 | 123 | ||
68 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) | 124 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) |
69 | return -EFAULT; | 125 | return -EFAULT; |
70 | 126 | ||
71 | pagefault_disable(); | 127 | pagefault_disable(); |
72 | switch (op) { | 128 | switch (op) { |
73 | case FUTEX_OP_SET: | 129 | case FUTEX_OP_SET: |
74 | asm_ret = futex_set(uaddr, oparg); | 130 | __futex_set(); |
75 | break; | 131 | break; |
76 | case FUTEX_OP_ADD: | 132 | case FUTEX_OP_ADD: |
77 | asm_ret = futex_add(uaddr, oparg); | 133 | __futex_add(); |
78 | break; | 134 | break; |
79 | case FUTEX_OP_OR: | 135 | case FUTEX_OP_OR: |
80 | asm_ret = futex_or(uaddr, oparg); | 136 | __futex_or(); |
81 | break; | 137 | break; |
82 | case FUTEX_OP_ANDN: | 138 | case FUTEX_OP_ANDN: |
83 | asm_ret = futex_andn(uaddr, oparg); | 139 | __futex_andn(); |
84 | break; | 140 | break; |
85 | case FUTEX_OP_XOR: | 141 | case FUTEX_OP_XOR: |
86 | asm_ret = futex_xor(uaddr, oparg); | 142 | __futex_xor(); |
87 | break; | 143 | break; |
88 | default: | 144 | default: |
89 | asm_ret.err = -ENOSYS; | 145 | ret = -ENOSYS; |
146 | break; | ||
90 | } | 147 | } |
91 | pagefault_enable(); | 148 | pagefault_enable(); |
92 | 149 | ||
93 | ret = asm_ret.err; | ||
94 | |||
95 | if (!ret) { | 150 | if (!ret) { |
96 | switch (cmp) { | 151 | switch (cmp) { |
97 | case FUTEX_OP_CMP_EQ: | 152 | case FUTEX_OP_CMP_EQ: |
98 | ret = (asm_ret.val == cmparg); | 153 | ret = (val == cmparg); |
99 | break; | 154 | break; |
100 | case FUTEX_OP_CMP_NE: | 155 | case FUTEX_OP_CMP_NE: |
101 | ret = (asm_ret.val != cmparg); | 156 | ret = (val != cmparg); |
102 | break; | 157 | break; |
103 | case FUTEX_OP_CMP_LT: | 158 | case FUTEX_OP_CMP_LT: |
104 | ret = (asm_ret.val < cmparg); | 159 | ret = (val < cmparg); |
105 | break; | 160 | break; |
106 | case FUTEX_OP_CMP_GE: | 161 | case FUTEX_OP_CMP_GE: |
107 | ret = (asm_ret.val >= cmparg); | 162 | ret = (val >= cmparg); |
108 | break; | 163 | break; |
109 | case FUTEX_OP_CMP_LE: | 164 | case FUTEX_OP_CMP_LE: |
110 | ret = (asm_ret.val <= cmparg); | 165 | ret = (val <= cmparg); |
111 | break; | 166 | break; |
112 | case FUTEX_OP_CMP_GT: | 167 | case FUTEX_OP_CMP_GT: |
113 | ret = (asm_ret.val > cmparg); | 168 | ret = (val > cmparg); |
114 | break; | 169 | break; |
115 | default: | 170 | default: |
116 | ret = -ENOSYS; | 171 | ret = -ENOSYS; |
117 | } | 172 | } |
118 | } | 173 | } |
119 | return ret; | 174 | return ret; |
120 | } | 175 | } |
121 | 176 | ||
122 | static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, | 177 | static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, |
123 | u32 oldval, u32 newval) | 178 | u32 oldval, u32 oparg) |
124 | { | 179 | { |
125 | struct __get_user asm_ret; | 180 | int ret, val; |
126 | 181 | ||
182 | __futex_prolog(); | ||
183 | |||
127 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) | 184 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) |
128 | return -EFAULT; | 185 | return -EFAULT; |
129 | 186 | ||
130 | asm_ret = futex_cmpxchg(uaddr, oldval, newval); | 187 | __futex_cmpxchg(); |
131 | *uval = asm_ret.val; | ||
132 | return asm_ret.err; |
arch/tile/include/asm/uaccess.h
1 | /* | 1 | /* |
2 | * Copyright 2010 Tilera Corporation. All Rights Reserved. | 2 | * Copyright 2010 Tilera Corporation. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU General Public License | 5 | * modify it under the terms of the GNU General Public License |
6 | * as published by the Free Software Foundation, version 2. | 6 | * as published by the Free Software Foundation, version 2. |
7 | * | 7 | * |
8 | * This program is distributed in the hope that it will be useful, but | 8 | * This program is distributed in the hope that it will be useful, but |
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 9 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | 10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or |
11 | * NON INFRINGEMENT. See the GNU General Public License for | 11 | * NON INFRINGEMENT. See the GNU General Public License for |
12 | * more details. | 12 | * more details. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #ifndef _ASM_TILE_UACCESS_H | 15 | #ifndef _ASM_TILE_UACCESS_H |
16 | #define _ASM_TILE_UACCESS_H | 16 | #define _ASM_TILE_UACCESS_H |
17 | 17 | ||
18 | /* | 18 | /* |
19 | * User space memory access functions | 19 | * User space memory access functions |
20 | */ | 20 | */ |
21 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
22 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
23 | #include <asm-generic/uaccess-unaligned.h> | 23 | #include <asm-generic/uaccess-unaligned.h> |
24 | #include <asm/processor.h> | 24 | #include <asm/processor.h> |
25 | #include <asm/page.h> | 25 | #include <asm/page.h> |
26 | 26 | ||
27 | #define VERIFY_READ 0 | 27 | #define VERIFY_READ 0 |
28 | #define VERIFY_WRITE 1 | 28 | #define VERIFY_WRITE 1 |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * The fs value determines whether argument validity checking should be | 31 | * The fs value determines whether argument validity checking should be |
32 | * performed or not. If get_fs() == USER_DS, checking is performed, with | 32 | * performed or not. If get_fs() == USER_DS, checking is performed, with |
33 | * get_fs() == KERNEL_DS, checking is bypassed. | 33 | * get_fs() == KERNEL_DS, checking is bypassed. |
34 | * | 34 | * |
35 | * For historical reasons, these macros are grossly misnamed. | 35 | * For historical reasons, these macros are grossly misnamed. |
36 | */ | 36 | */ |
37 | #define MAKE_MM_SEG(a) ((mm_segment_t) { (a) }) | 37 | #define MAKE_MM_SEG(a) ((mm_segment_t) { (a) }) |
38 | 38 | ||
39 | #define KERNEL_DS MAKE_MM_SEG(-1UL) | 39 | #define KERNEL_DS MAKE_MM_SEG(-1UL) |
40 | #define USER_DS MAKE_MM_SEG(PAGE_OFFSET) | 40 | #define USER_DS MAKE_MM_SEG(PAGE_OFFSET) |
41 | 41 | ||
42 | #define get_ds() (KERNEL_DS) | 42 | #define get_ds() (KERNEL_DS) |
43 | #define get_fs() (current_thread_info()->addr_limit) | 43 | #define get_fs() (current_thread_info()->addr_limit) |
44 | #define set_fs(x) (current_thread_info()->addr_limit = (x)) | 44 | #define set_fs(x) (current_thread_info()->addr_limit = (x)) |
45 | 45 | ||
46 | #define segment_eq(a, b) ((a).seg == (b).seg) | 46 | #define segment_eq(a, b) ((a).seg == (b).seg) |
47 | 47 | ||
48 | #ifndef __tilegx__ | 48 | #ifndef __tilegx__ |
49 | /* | 49 | /* |
50 | * We could allow mapping all 16 MB at 0xfc000000, but we set up a | 50 | * We could allow mapping all 16 MB at 0xfc000000, but we set up a |
51 | * special hack in arch_setup_additional_pages() to auto-create a mapping | 51 | * special hack in arch_setup_additional_pages() to auto-create a mapping |
52 | * for the first 16 KB, and it would seem strange to have different | 52 | * for the first 16 KB, and it would seem strange to have different |
53 | * user-accessible semantics for memory at 0xfc000000 and above 0xfc004000. | 53 | * user-accessible semantics for memory at 0xfc000000 and above 0xfc004000. |
54 | */ | 54 | */ |
55 | static inline int is_arch_mappable_range(unsigned long addr, | 55 | static inline int is_arch_mappable_range(unsigned long addr, |
56 | unsigned long size) | 56 | unsigned long size) |
57 | { | 57 | { |
58 | return (addr >= MEM_USER_INTRPT && | 58 | return (addr >= MEM_USER_INTRPT && |
59 | addr < (MEM_USER_INTRPT + INTRPT_SIZE) && | 59 | addr < (MEM_USER_INTRPT + INTRPT_SIZE) && |
60 | size <= (MEM_USER_INTRPT + INTRPT_SIZE) - addr); | 60 | size <= (MEM_USER_INTRPT + INTRPT_SIZE) - addr); |
61 | } | 61 | } |
62 | #define is_arch_mappable_range is_arch_mappable_range | 62 | #define is_arch_mappable_range is_arch_mappable_range |
63 | #else | 63 | #else |
64 | #define is_arch_mappable_range(addr, size) 0 | 64 | #define is_arch_mappable_range(addr, size) 0 |
65 | #endif | 65 | #endif |
66 | 66 | ||
67 | /* | 67 | /* |
68 | * Test whether a block of memory is a valid user space address. | 68 | * Test whether a block of memory is a valid user space address. |
69 | * Returns 0 if the range is valid, nonzero otherwise. | 69 | * Returns 0 if the range is valid, nonzero otherwise. |
70 | */ | 70 | */ |
71 | int __range_ok(unsigned long addr, unsigned long size); | 71 | int __range_ok(unsigned long addr, unsigned long size); |
72 | 72 | ||
73 | /** | 73 | /** |
74 | * access_ok: - Checks if a user space pointer is valid | 74 | * access_ok: - Checks if a user space pointer is valid |
75 | * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that | 75 | * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that |
76 | * %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe | 76 | * %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe |
77 | * to write to a block, it is always safe to read from it. | 77 | * to write to a block, it is always safe to read from it. |
78 | * @addr: User space pointer to start of block to check | 78 | * @addr: User space pointer to start of block to check |
79 | * @size: Size of block to check | 79 | * @size: Size of block to check |
80 | * | 80 | * |
81 | * Context: User context only. This function may sleep. | 81 | * Context: User context only. This function may sleep. |
82 | * | 82 | * |
83 | * Checks if a pointer to a block of memory in user space is valid. | 83 | * Checks if a pointer to a block of memory in user space is valid. |
84 | * | 84 | * |
85 | * Returns true (nonzero) if the memory block may be valid, false (zero) | 85 | * Returns true (nonzero) if the memory block may be valid, false (zero) |
86 | * if it is definitely invalid. | 86 | * if it is definitely invalid. |
87 | * | 87 | * |
88 | * Note that, depending on architecture, this function probably just | 88 | * Note that, depending on architecture, this function probably just |
89 | * checks that the pointer is in the user space range - after calling | 89 | * checks that the pointer is in the user space range - after calling |
90 | * this function, memory access functions may still return -EFAULT. | 90 | * this function, memory access functions may still return -EFAULT. |
91 | */ | 91 | */ |
92 | #define access_ok(type, addr, size) ({ \ | 92 | #define access_ok(type, addr, size) ({ \ |
93 | __chk_user_ptr(addr); \ | 93 | __chk_user_ptr(addr); \ |
94 | likely(__range_ok((unsigned long)(addr), (size)) == 0); \ | 94 | likely(__range_ok((unsigned long)(addr), (size)) == 0); \ |
95 | }) | 95 | }) |
96 | 96 | ||
97 | /* | 97 | /* |
98 | * The exception table consists of pairs of addresses: the first is the | 98 | * The exception table consists of pairs of addresses: the first is the |
99 | * address of an instruction that is allowed to fault, and the second is | 99 | * address of an instruction that is allowed to fault, and the second is |
100 | * the address at which the program should continue. No registers are | 100 | * the address at which the program should continue. No registers are |
101 | * modified, so it is entirely up to the continuation code to figure out | 101 | * modified, so it is entirely up to the continuation code to figure out |
102 | * what to do. | 102 | * what to do. |
103 | * | 103 | * |
104 | * All the routines below use bits of fixup code that are out of line | 104 | * All the routines below use bits of fixup code that are out of line |
105 | * with the main instruction path. This means when everything is well, | 105 | * with the main instruction path. This means when everything is well, |
106 | * we don't even have to jump over them. Further, they do not intrude | 106 | * we don't even have to jump over them. Further, they do not intrude |
107 | * on our cache or tlb entries. | 107 | * on our cache or tlb entries. |
108 | */ | 108 | */ |
109 | 109 | ||
110 | struct exception_table_entry { | 110 | struct exception_table_entry { |
111 | unsigned long insn, fixup; | 111 | unsigned long insn, fixup; |
112 | }; | 112 | }; |
113 | 113 | ||
114 | extern int fixup_exception(struct pt_regs *regs); | 114 | extern int fixup_exception(struct pt_regs *regs); |
115 | 115 | ||
116 | /* | 116 | /* |
117 | * We return the __get_user_N function results in a structure, | 117 | * Support macros for __get_user(). |
118 | * thus in r0 and r1. If "err" is zero, "val" is the result | ||
119 | * of the read; otherwise, "err" is -EFAULT. | ||
120 | * | 118 | * |
121 | * We rarely need 8-byte values on a 32-bit architecture, but | 119 | * Implementation note: The "case 8" logic of casting to the type of |
122 | * we size the structure to accommodate. In practice, for the | 120 | * the result of subtracting the value from itself is basically a way |
123 | * the smaller reads, we can zero the high word for free, and | 121 | * of keeping all integer types the same, but casting any pointers to |
124 | * the caller will ignore it by virtue of casting anyway. | 122 | * ptrdiff_t, i.e. also an integer type. This way there are no |
123 | * questionable casts seen by the compiler on an ILP32 platform. | ||
124 | * | ||
125 | * Note that __get_user() and __put_user() assume proper alignment. | ||
125 | */ | 126 | */ |
126 | struct __get_user { | ||
127 | unsigned long long val; | ||
128 | int err; | ||
129 | }; | ||
130 | 127 | ||
131 | /* | 128 | #ifdef __LP64__ |
132 | * FIXME: we should express these as inline extended assembler, since | 129 | #define _ASM_PTR ".quad" |
133 | * they're fundamentally just a variable dereference and some | 130 | #else |
134 | * supporting exception_table gunk. Note that (a la i386) we can | 131 | #define _ASM_PTR ".long" |
135 | * extend the copy_to_user and copy_from_user routines to call into | 132 | #endif |
136 | * such extended assembler routines, though we will have to use a | ||
137 | * different return code in that case (1, 2, or 4, rather than -EFAULT). | ||
138 | */ | ||
139 | extern struct __get_user __get_user_1(const void __user *); | ||
140 | extern struct __get_user __get_user_2(const void __user *); | ||
141 | extern struct __get_user __get_user_4(const void __user *); | ||
142 | extern struct __get_user __get_user_8(const void __user *); | ||
143 | extern int __put_user_1(long, void __user *); | ||
144 | extern int __put_user_2(long, void __user *); | ||
145 | extern int __put_user_4(long, void __user *); | ||
146 | extern int __put_user_8(long long, void __user *); | ||
147 | 133 | ||
148 | /* Unimplemented routines to cause linker failures */ | 134 | #define __get_user_asm(OP, x, ptr, ret) \ |
149 | extern struct __get_user __get_user_bad(void); | 135 | asm volatile("1: {" #OP " %1, %2; movei %0, 0 }\n" \ |
150 | extern int __put_user_bad(void); | 136 | ".pushsection .fixup,\"ax\"\n" \ |
137 | "0: { movei %1, 0; movei %0, %3 }\n" \ | ||
138 | "j 9f\n" \ | ||
139 | ".section __ex_table,\"a\"\n" \ | ||
140 | _ASM_PTR " 1b, 0b\n" \ | ||
141 | ".popsection\n" \ | ||
142 | "9:" \ | ||
143 | : "=r" (ret), "=r" (x) \ | ||
144 | : "r" (ptr), "i" (-EFAULT)) | ||
151 | 145 | ||
152 | /* | 146 | #ifdef __tilegx__ |
153 | * Careful: we have to cast the result to the type of the pointer | 147 | #define __get_user_1(x, ptr, ret) __get_user_asm(ld1u, x, ptr, ret) |
154 | * for sign reasons. | 148 | #define __get_user_2(x, ptr, ret) __get_user_asm(ld2u, x, ptr, ret) |
155 | */ | 149 | #define __get_user_4(x, ptr, ret) __get_user_asm(ld4u, x, ptr, ret) |
150 | #define __get_user_8(x, ptr, ret) __get_user_asm(ld, x, ptr, ret) | ||
151 | #else | ||
152 | #define __get_user_1(x, ptr, ret) __get_user_asm(lb_u, x, ptr, ret) | ||
153 | #define __get_user_2(x, ptr, ret) __get_user_asm(lh_u, x, ptr, ret) | ||
154 | #define __get_user_4(x, ptr, ret) __get_user_asm(lw, x, ptr, ret) | ||
155 | #ifdef __LITTLE_ENDIAN | ||
156 | #define __lo32(a, b) a | ||
157 | #define __hi32(a, b) b | ||
158 | #else | ||
159 | #define __lo32(a, b) b | ||
160 | #define __hi32(a, b) a | ||
161 | #endif | ||
162 | #define __get_user_8(x, ptr, ret) \ | ||
163 | ({ \ | ||
164 | unsigned int __a, __b; \ | ||
165 | asm volatile("1: { lw %1, %3; addi %2, %3, 4 }\n" \ | ||
166 | "2: { lw %2, %2; movei %0, 0 }\n" \ | ||
167 | ".pushsection .fixup,\"ax\"\n" \ | ||
168 | "0: { movei %1, 0; movei %2, 0 }\n" \ | ||
169 | "{ movei %0, %4; j 9f }\n" \ | ||
170 | ".section __ex_table,\"a\"\n" \ | ||
171 | ".word 1b, 0b\n" \ | ||
172 | ".word 2b, 0b\n" \ | ||
173 | ".popsection\n" \ | ||
174 | "9:" \ | ||
175 | : "=r" (ret), "=r" (__a), "=&r" (__b) \ | ||
176 | : "r" (ptr), "i" (-EFAULT)); \ | ||
177 | (x) = (__typeof(x))(__typeof((x)-(x))) \ | ||
178 | (((u64)__hi32(__a, __b) << 32) | \ | ||
179 | __lo32(__a, __b)); \ | ||
180 | }) | ||
181 | #endif | ||
182 | |||
183 | extern int __get_user_bad(void) | ||
184 | __attribute__((warning("sizeof __get_user argument not 1, 2, 4 or 8"))); | ||
185 | |||
156 | /** | 186 | /** |
157 | * __get_user: - Get a simple variable from user space, with less checking. | 187 | * __get_user: - Get a simple variable from user space, with less checking. |
158 | * @x: Variable to store result. | 188 | * @x: Variable to store result. |
159 | * @ptr: Source address, in user space. | 189 | * @ptr: Source address, in user space. |
160 | * | 190 | * |
161 | * Context: User context only. This function may sleep. | 191 | * Context: User context only. This function may sleep. |
162 | * | 192 | * |
163 | * This macro copies a single simple variable from user space to kernel | 193 | * This macro copies a single simple variable from user space to kernel |
164 | * space. It supports simple types like char and int, but not larger | 194 | * space. It supports simple types like char and int, but not larger |
165 | * data types like structures or arrays. | 195 | * data types like structures or arrays. |
166 | * | 196 | * |
167 | * @ptr must have pointer-to-simple-variable type, and the result of | 197 | * @ptr must have pointer-to-simple-variable type, and the result of |
168 | * dereferencing @ptr must be assignable to @x without a cast. | 198 | * dereferencing @ptr must be assignable to @x without a cast. |
169 | * | 199 | * |
170 | * Returns zero on success, or -EFAULT on error. | 200 | * Returns zero on success, or -EFAULT on error. |
171 | * On error, the variable @x is set to zero. | 201 | * On error, the variable @x is set to zero. |
172 | * | 202 | * |
173 | * Caller must check the pointer with access_ok() before calling this | 203 | * Caller must check the pointer with access_ok() before calling this |
174 | * function. | 204 | * function. |
175 | */ | 205 | */ |
176 | #define __get_user(x, ptr) \ | 206 | #define __get_user(x, ptr) \ |
177 | ({ struct __get_user __ret; \ | 207 | ({ \ |
178 | __typeof__(*(ptr)) const __user *__gu_addr = (ptr); \ | 208 | int __ret; \ |
179 | __chk_user_ptr(__gu_addr); \ | 209 | __chk_user_ptr(ptr); \ |
180 | switch (sizeof(*(__gu_addr))) { \ | 210 | switch (sizeof(*(ptr))) { \ |
181 | case 1: \ | 211 | case 1: __get_user_1(x, ptr, __ret); break; \ |
182 | __ret = __get_user_1(__gu_addr); \ | 212 | case 2: __get_user_2(x, ptr, __ret); break; \ |
183 | break; \ | 213 | case 4: __get_user_4(x, ptr, __ret); break; \ |
184 | case 2: \ | 214 | case 8: __get_user_8(x, ptr, __ret); break; \ |
185 | __ret = __get_user_2(__gu_addr); \ | 215 | default: __ret = __get_user_bad(); break; \ |
186 | break; \ | 216 | } \ |
187 | case 4: \ | 217 | __ret; \ |
188 | __ret = __get_user_4(__gu_addr); \ | 218 | }) |
189 | break; \ | ||
190 | case 8: \ | ||
191 | __ret = __get_user_8(__gu_addr); \ | ||
192 | break; \ | ||
193 | default: \ | ||
194 | __ret = __get_user_bad(); \ | ||
195 | break; \ | ||
196 | } \ | ||
197 | (x) = (__typeof__(*__gu_addr)) (__typeof__(*__gu_addr - *__gu_addr)) \ | ||
198 | __ret.val; \ | ||
199 | __ret.err; \ | ||
200 | }) | ||
201 | 219 | ||
220 | /* Support macros for __put_user(). */ | ||
221 | |||
222 | #define __put_user_asm(OP, x, ptr, ret) \ | ||
223 | asm volatile("1: {" #OP " %1, %2; movei %0, 0 }\n" \ | ||
224 | ".pushsection .fixup,\"ax\"\n" \ | ||
225 | "0: { movei %0, %3; j 9f }\n" \ | ||
226 | ".section __ex_table,\"a\"\n" \ | ||
227 | _ASM_PTR " 1b, 0b\n" \ | ||
228 | ".popsection\n" \ | ||
229 | "9:" \ | ||
230 | : "=r" (ret) \ | ||
231 | : "r" (ptr), "r" (x), "i" (-EFAULT)) | ||
232 | |||
233 | #ifdef __tilegx__ | ||
234 | #define __put_user_1(x, ptr, ret) __put_user_asm(st1, x, ptr, ret) | ||
235 | #define __put_user_2(x, ptr, ret) __put_user_asm(st2, x, ptr, ret) | ||
236 | #define __put_user_4(x, ptr, ret) __put_user_asm(st4, x, ptr, ret) | ||
237 | #define __put_user_8(x, ptr, ret) __put_user_asm(st, x, ptr, ret) | ||
238 | #else | ||
239 | #define __put_user_1(x, ptr, ret) __put_user_asm(sb, x, ptr, ret) | ||
240 | #define __put_user_2(x, ptr, ret) __put_user_asm(sh, x, ptr, ret) | ||
241 | #define __put_user_4(x, ptr, ret) __put_user_asm(sw, x, ptr, ret) | ||
242 | #define __put_user_8(x, ptr, ret) \ | ||
243 | ({ \ | ||
244 | u64 __x = (__typeof((x)-(x)))(x); \ | ||
245 | int __lo = (int) __x, __hi = (int) (__x >> 32); \ | ||
246 | asm volatile("1: { sw %1, %2; addi %0, %1, 4 }\n" \ | ||
247 | "2: { sw %0, %3; movei %0, 0 }\n" \ | ||
248 | ".pushsection .fixup,\"ax\"\n" \ | ||
249 | "0: { movei %0, %4; j 9f }\n" \ | ||
250 | ".section __ex_table,\"a\"\n" \ | ||
251 | ".word 1b, 0b\n" \ | ||
252 | ".word 2b, 0b\n" \ | ||
253 | ".popsection\n" \ | ||
254 | "9:" \ | ||
255 | : "=&r" (ret) \ | ||
256 | : "r" (ptr), "r" (__lo32(__lo, __hi)), \ | ||
257 | "r" (__hi32(__lo, __hi)), "i" (-EFAULT)); \ | ||
258 | }) | ||
259 | #endif | ||
260 | |||
261 | extern int __put_user_bad(void) | ||
262 | __attribute__((warning("sizeof __put_user argument not 1, 2, 4 or 8"))); | ||
263 | |||
202 | /** | 264 | /** |
203 | * __put_user: - Write a simple value into user space, with less checking. | 265 | * __put_user: - Write a simple value into user space, with less checking. |
204 | * @x: Value to copy to user space. | 266 | * @x: Value to copy to user space. |
205 | * @ptr: Destination address, in user space. | 267 | * @ptr: Destination address, in user space. |
206 | * | 268 | * |
207 | * Context: User context only. This function may sleep. | 269 | * Context: User context only. This function may sleep. |
208 | * | 270 | * |
209 | * This macro copies a single simple value from kernel space to user | 271 | * This macro copies a single simple value from kernel space to user |
210 | * space. It supports simple types like char and int, but not larger | 272 | * space. It supports simple types like char and int, but not larger |
211 | * data types like structures or arrays. | 273 | * data types like structures or arrays. |
212 | * | 274 | * |
213 | * @ptr must have pointer-to-simple-variable type, and @x must be assignable | 275 | * @ptr must have pointer-to-simple-variable type, and @x must be assignable |
214 | * to the result of dereferencing @ptr. | 276 | * to the result of dereferencing @ptr. |
215 | * | 277 | * |
216 | * Caller must check the pointer with access_ok() before calling this | 278 | * Caller must check the pointer with access_ok() before calling this |
217 | * function. | 279 | * function. |
218 | * | 280 | * |
219 | * Returns zero on success, or -EFAULT on error. | 281 | * Returns zero on success, or -EFAULT on error. |
220 | * | ||
221 | * Implementation note: The "case 8" logic of casting to the type of | ||
222 | * the result of subtracting the value from itself is basically a way | ||
223 | * of keeping all integer types the same, but casting any pointers to | ||
224 | * ptrdiff_t, i.e. also an integer type. This way there are no | ||
225 | * questionable casts seen by the compiler on an ILP32 platform. | ||
226 | */ | 282 | */ |
227 | #define __put_user(x, ptr) \ | 283 | #define __put_user(x, ptr) \ |
228 | ({ \ | 284 | ({ \ |
229 | int __pu_err = 0; \ | 285 | int __ret; \ |
230 | __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ | 286 | __chk_user_ptr(ptr); \ |
231 | typeof(*__pu_addr) __pu_val = (x); \ | 287 | switch (sizeof(*(ptr))) { \ |
232 | __chk_user_ptr(__pu_addr); \ | 288 | case 1: __put_user_1(x, ptr, __ret); break; \ |
233 | switch (sizeof(__pu_val)) { \ | 289 | case 2: __put_user_2(x, ptr, __ret); break; \ |
234 | case 1: \ | 290 | case 4: __put_user_4(x, ptr, __ret); break; \ |
235 | __pu_err = __put_user_1((long)__pu_val, __pu_addr); \ | 291 | case 8: __put_user_8(x, ptr, __ret); break; \ |
236 | break; \ | 292 | default: __ret = __put_user_bad(); break; \ |
237 | case 2: \ | ||
238 | __pu_err = __put_user_2((long)__pu_val, __pu_addr); \ | ||
239 | break; \ | ||
240 | case 4: \ | ||
241 | __pu_err = __put_user_4((long)__pu_val, __pu_addr); \ | ||
242 | break; \ | ||
243 | case 8: \ | ||
244 | __pu_err = \ | ||
245 | __put_user_8((__typeof__(__pu_val - __pu_val))__pu_val,\ | ||
246 | __pu_addr); \ | ||
247 | break; \ | ||
248 | default: \ | ||
249 | __pu_err = __put_user_bad(); \ | ||
250 | break; \ | ||
251 | } \ | 293 | } \ |
252 | __pu_err; \ | 294 | __ret; \ |
253 | }) | 295 | }) |
254 | 296 | ||
255 | /* | 297 | /* |
256 | * The versions of get_user and put_user without initial underscores | 298 | * The versions of get_user and put_user without initial underscores |
257 | * check the address of their arguments to make sure they are not | 299 | * check the address of their arguments to make sure they are not |
258 | * in kernel space. | 300 | * in kernel space. |
259 | */ | 301 | */ |
260 | #define put_user(x, ptr) \ | 302 | #define put_user(x, ptr) \ |
261 | ({ \ | 303 | ({ \ |
262 | __typeof__(*(ptr)) __user *__Pu_addr = (ptr); \ | 304 | __typeof__(*(ptr)) __user *__Pu_addr = (ptr); \ |
263 | access_ok(VERIFY_WRITE, (__Pu_addr), sizeof(*(__Pu_addr))) ? \ | 305 | access_ok(VERIFY_WRITE, (__Pu_addr), sizeof(*(__Pu_addr))) ? \ |
264 | __put_user((x), (__Pu_addr)) : \ | 306 | __put_user((x), (__Pu_addr)) : \ |
265 | -EFAULT; \ | 307 | -EFAULT; \ |
266 | }) | 308 | }) |
267 | 309 | ||
268 | #define get_user(x, ptr) \ | 310 | #define get_user(x, ptr) \ |
269 | ({ \ | 311 | ({ \ |
270 | __typeof__(*(ptr)) const __user *__Gu_addr = (ptr); \ | 312 | __typeof__(*(ptr)) const __user *__Gu_addr = (ptr); \ |
271 | access_ok(VERIFY_READ, (__Gu_addr), sizeof(*(__Gu_addr))) ? \ | 313 | access_ok(VERIFY_READ, (__Gu_addr), sizeof(*(__Gu_addr))) ? \ |
272 | __get_user((x), (__Gu_addr)) : \ | 314 | __get_user((x), (__Gu_addr)) : \ |
273 | ((x) = 0, -EFAULT); \ | 315 | ((x) = 0, -EFAULT); \ |
274 | }) | 316 | }) |
275 | 317 | ||
276 | /** | 318 | /** |
277 | * __copy_to_user() - copy data into user space, with less checking. | 319 | * __copy_to_user() - copy data into user space, with less checking. |
278 | * @to: Destination address, in user space. | 320 | * @to: Destination address, in user space. |
279 | * @from: Source address, in kernel space. | 321 | * @from: Source address, in kernel space. |
280 | * @n: Number of bytes to copy. | 322 | * @n: Number of bytes to copy. |
281 | * | 323 | * |
282 | * Context: User context only. This function may sleep. | 324 | * Context: User context only. This function may sleep. |
283 | * | 325 | * |
284 | * Copy data from kernel space to user space. Caller must check | 326 | * Copy data from kernel space to user space. Caller must check |
285 | * the specified block with access_ok() before calling this function. | 327 | * the specified block with access_ok() before calling this function. |
286 | * | 328 | * |
287 | * Returns number of bytes that could not be copied. | 329 | * Returns number of bytes that could not be copied. |
288 | * On success, this will be zero. | 330 | * On success, this will be zero. |
289 | * | 331 | * |
290 | * An alternate version - __copy_to_user_inatomic() - is designed | 332 | * An alternate version - __copy_to_user_inatomic() - is designed |
291 | * to be called from atomic context, typically bracketed by calls | 333 | * to be called from atomic context, typically bracketed by calls |
292 | * to pagefault_disable() and pagefault_enable(). | 334 | * to pagefault_disable() and pagefault_enable(). |
293 | */ | 335 | */ |
294 | extern unsigned long __must_check __copy_to_user_inatomic( | 336 | extern unsigned long __must_check __copy_to_user_inatomic( |
295 | void __user *to, const void *from, unsigned long n); | 337 | void __user *to, const void *from, unsigned long n); |
296 | 338 | ||
297 | static inline unsigned long __must_check | 339 | static inline unsigned long __must_check |
298 | __copy_to_user(void __user *to, const void *from, unsigned long n) | 340 | __copy_to_user(void __user *to, const void *from, unsigned long n) |
299 | { | 341 | { |
300 | might_fault(); | 342 | might_fault(); |
301 | return __copy_to_user_inatomic(to, from, n); | 343 | return __copy_to_user_inatomic(to, from, n); |
302 | } | 344 | } |
303 | 345 | ||
304 | static inline unsigned long __must_check | 346 | static inline unsigned long __must_check |
305 | copy_to_user(void __user *to, const void *from, unsigned long n) | 347 | copy_to_user(void __user *to, const void *from, unsigned long n) |
306 | { | 348 | { |
307 | if (access_ok(VERIFY_WRITE, to, n)) | 349 | if (access_ok(VERIFY_WRITE, to, n)) |
308 | n = __copy_to_user(to, from, n); | 350 | n = __copy_to_user(to, from, n); |
309 | return n; | 351 | return n; |
310 | } | 352 | } |
311 | 353 | ||
312 | /** | 354 | /** |
313 | * __copy_from_user() - copy data from user space, with less checking. | 355 | * __copy_from_user() - copy data from user space, with less checking. |
314 | * @to: Destination address, in kernel space. | 356 | * @to: Destination address, in kernel space. |
315 | * @from: Source address, in user space. | 357 | * @from: Source address, in user space. |
316 | * @n: Number of bytes to copy. | 358 | * @n: Number of bytes to copy. |
317 | * | 359 | * |
318 | * Context: User context only. This function may sleep. | 360 | * Context: User context only. This function may sleep. |
319 | * | 361 | * |
320 | * Copy data from user space to kernel space. Caller must check | 362 | * Copy data from user space to kernel space. Caller must check |
321 | * the specified block with access_ok() before calling this function. | 363 | * the specified block with access_ok() before calling this function. |
322 | * | 364 | * |
323 | * Returns number of bytes that could not be copied. | 365 | * Returns number of bytes that could not be copied. |
324 | * On success, this will be zero. | 366 | * On success, this will be zero. |
325 | * | 367 | * |
326 | * If some data could not be copied, this function will pad the copied | 368 | * If some data could not be copied, this function will pad the copied |
327 | * data to the requested size using zero bytes. | 369 | * data to the requested size using zero bytes. |
328 | * | 370 | * |
329 | * An alternate version - __copy_from_user_inatomic() - is designed | 371 | * An alternate version - __copy_from_user_inatomic() - is designed |
330 | * to be called from atomic context, typically bracketed by calls | 372 | * to be called from atomic context, typically bracketed by calls |
331 | * to pagefault_disable() and pagefault_enable(). This version | 373 | * to pagefault_disable() and pagefault_enable(). This version |
332 | * does *NOT* pad with zeros. | 374 | * does *NOT* pad with zeros. |
333 | */ | 375 | */ |
334 | extern unsigned long __must_check __copy_from_user_inatomic( | 376 | extern unsigned long __must_check __copy_from_user_inatomic( |
335 | void *to, const void __user *from, unsigned long n); | 377 | void *to, const void __user *from, unsigned long n); |
336 | extern unsigned long __must_check __copy_from_user_zeroing( | 378 | extern unsigned long __must_check __copy_from_user_zeroing( |
337 | void *to, const void __user *from, unsigned long n); | 379 | void *to, const void __user *from, unsigned long n); |
338 | 380 | ||
339 | static inline unsigned long __must_check | 381 | static inline unsigned long __must_check |
340 | __copy_from_user(void *to, const void __user *from, unsigned long n) | 382 | __copy_from_user(void *to, const void __user *from, unsigned long n) |
341 | { | 383 | { |
342 | might_fault(); | 384 | might_fault(); |
343 | return __copy_from_user_zeroing(to, from, n); | 385 | return __copy_from_user_zeroing(to, from, n); |
344 | } | 386 | } |
345 | 387 | ||
346 | static inline unsigned long __must_check | 388 | static inline unsigned long __must_check |
347 | _copy_from_user(void *to, const void __user *from, unsigned long n) | 389 | _copy_from_user(void *to, const void __user *from, unsigned long n) |
348 | { | 390 | { |
349 | if (access_ok(VERIFY_READ, from, n)) | 391 | if (access_ok(VERIFY_READ, from, n)) |
350 | n = __copy_from_user(to, from, n); | 392 | n = __copy_from_user(to, from, n); |
351 | else | 393 | else |
352 | memset(to, 0, n); | 394 | memset(to, 0, n); |
353 | return n; | 395 | return n; |
354 | } | 396 | } |
355 | 397 | ||
356 | #ifdef CONFIG_DEBUG_COPY_FROM_USER | 398 | #ifdef CONFIG_DEBUG_COPY_FROM_USER |
357 | extern void copy_from_user_overflow(void) | 399 | extern void copy_from_user_overflow(void) |
358 | __compiletime_warning("copy_from_user() size is not provably correct"); | 400 | __compiletime_warning("copy_from_user() size is not provably correct"); |
359 | 401 | ||
360 | static inline unsigned long __must_check copy_from_user(void *to, | 402 | static inline unsigned long __must_check copy_from_user(void *to, |
361 | const void __user *from, | 403 | const void __user *from, |
362 | unsigned long n) | 404 | unsigned long n) |
363 | { | 405 | { |
364 | int sz = __compiletime_object_size(to); | 406 | int sz = __compiletime_object_size(to); |
365 | 407 | ||
366 | if (likely(sz == -1 || sz >= n)) | 408 | if (likely(sz == -1 || sz >= n)) |
367 | n = _copy_from_user(to, from, n); | 409 | n = _copy_from_user(to, from, n); |
368 | else | 410 | else |
369 | copy_from_user_overflow(); | 411 | copy_from_user_overflow(); |
370 | 412 | ||
371 | return n; | 413 | return n; |
372 | } | 414 | } |
373 | #else | 415 | #else |
374 | #define copy_from_user _copy_from_user | 416 | #define copy_from_user _copy_from_user |
375 | #endif | 417 | #endif |
376 | 418 | ||
377 | #ifdef __tilegx__ | 419 | #ifdef __tilegx__ |
378 | /** | 420 | /** |
379 | * __copy_in_user() - copy data within user space, with less checking. | 421 | * __copy_in_user() - copy data within user space, with less checking. |
380 | * @to: Destination address, in user space. | 422 | * @to: Destination address, in user space. |
381 | * @from: Source address, in kernel space. | 423 | * @from: Source address, in user space. |
382 | * @n: Number of bytes to copy. | 424 | * @n: Number of bytes to copy. |
383 | * | 425 | * |
384 | * Context: User context only. This function may sleep. | 426 | * Context: User context only. This function may sleep. |
385 | * | 427 | * |
386 | * Copy data from user space to user space. Caller must check | 428 | * Copy data from user space to user space. Caller must check |
387 | * the specified blocks with access_ok() before calling this function. | 429 | * the specified blocks with access_ok() before calling this function. |
388 | * | 430 | * |
389 | * Returns number of bytes that could not be copied. | 431 | * Returns number of bytes that could not be copied. |
390 | * On success, this will be zero. | 432 | * On success, this will be zero. |
391 | */ | 433 | */ |
392 | extern unsigned long __copy_in_user_inatomic( | 434 | extern unsigned long __copy_in_user_inatomic( |
393 | void __user *to, const void __user *from, unsigned long n); | 435 | void __user *to, const void __user *from, unsigned long n); |
394 | 436 | ||
395 | static inline unsigned long __must_check | 437 | static inline unsigned long __must_check |
396 | __copy_in_user(void __user *to, const void __user *from, unsigned long n) | 438 | __copy_in_user(void __user *to, const void __user *from, unsigned long n) |
397 | { | 439 | { |
398 | might_sleep(); | 440 | might_sleep(); |
399 | return __copy_in_user_inatomic(to, from, n); | 441 | return __copy_in_user_inatomic(to, from, n); |
400 | } | 442 | } |
401 | 443 | ||
402 | static inline unsigned long __must_check | 444 | static inline unsigned long __must_check |
403 | copy_in_user(void __user *to, const void __user *from, unsigned long n) | 445 | copy_in_user(void __user *to, const void __user *from, unsigned long n) |
404 | { | 446 | { |
405 | if (access_ok(VERIFY_WRITE, to, n) && access_ok(VERIFY_READ, from, n)) | 447 | if (access_ok(VERIFY_WRITE, to, n) && access_ok(VERIFY_READ, from, n)) |
406 | n = __copy_in_user(to, from, n); | 448 | n = __copy_in_user(to, from, n); |
407 | return n; | 449 | return n; |
408 | } | 450 | } |
409 | #endif | 451 | #endif |
410 | 452 | ||
411 | 453 | ||
412 | /** | 454 | /** |
413 | * strlen_user: - Get the size of a string in user space. | 455 | * strlen_user: - Get the size of a string in user space. |
414 | * @str: The string to measure. | 456 | * @str: The string to measure. |
415 | * | 457 | * |
416 | * Context: User context only. This function may sleep. | 458 | * Context: User context only. This function may sleep. |
417 | * | 459 | * |
418 | * Get the size of a NUL-terminated string in user space. | 460 | * Get the size of a NUL-terminated string in user space. |
419 | * | 461 | * |
420 | * Returns the size of the string INCLUDING the terminating NUL. | 462 | * Returns the size of the string INCLUDING the terminating NUL. |
421 | * On exception, returns 0. | 463 | * On exception, returns 0. |
422 | * | 464 | * |
423 | * If there is a limit on the length of a valid string, you may wish to | 465 | * If there is a limit on the length of a valid string, you may wish to |
424 | * consider using strnlen_user() instead. | 466 | * consider using strnlen_user() instead. |
425 | */ | 467 | */ |
426 | extern long strnlen_user_asm(const char __user *str, long n); | 468 | extern long strnlen_user_asm(const char __user *str, long n); |
427 | static inline long __must_check strnlen_user(const char __user *str, long n) | 469 | static inline long __must_check strnlen_user(const char __user *str, long n) |
428 | { | 470 | { |
429 | might_fault(); | 471 | might_fault(); |
430 | return strnlen_user_asm(str, n); | 472 | return strnlen_user_asm(str, n); |
431 | } | 473 | } |
432 | #define strlen_user(str) strnlen_user(str, LONG_MAX) | 474 | #define strlen_user(str) strnlen_user(str, LONG_MAX) |
433 | 475 | ||
434 | /** | 476 | /** |
435 | * strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking. | 477 | * strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking. |
436 | * @dst: Destination address, in kernel space. This buffer must be at | 478 | * @dst: Destination address, in kernel space. This buffer must be at |
437 | * least @count bytes long. | 479 | * least @count bytes long. |
438 | * @src: Source address, in user space. | 480 | * @src: Source address, in user space. |
439 | * @count: Maximum number of bytes to copy, including the trailing NUL. | 481 | * @count: Maximum number of bytes to copy, including the trailing NUL. |
440 | * | 482 | * |
441 | * Copies a NUL-terminated string from userspace to kernel space. | 483 | * Copies a NUL-terminated string from userspace to kernel space. |
442 | * Caller must check the specified block with access_ok() before calling | 484 | * Caller must check the specified block with access_ok() before calling |
443 | * this function. | 485 | * this function. |
444 | * | 486 | * |
445 | * On success, returns the length of the string (not including the trailing | 487 | * On success, returns the length of the string (not including the trailing |
446 | * NUL). | 488 | * NUL). |
447 | * | 489 | * |
448 | * If access to userspace fails, returns -EFAULT (some data may have been | 490 | * If access to userspace fails, returns -EFAULT (some data may have been |
449 | * copied). | 491 | * copied). |
450 | * | 492 | * |
451 | * If @count is smaller than the length of the string, copies @count bytes | 493 | * If @count is smaller than the length of the string, copies @count bytes |
452 | * and returns @count. | 494 | * and returns @count. |
453 | */ | 495 | */ |
454 | extern long strncpy_from_user_asm(char *dst, const char __user *src, long); | 496 | extern long strncpy_from_user_asm(char *dst, const char __user *src, long); |
455 | static inline long __must_check __strncpy_from_user( | 497 | static inline long __must_check __strncpy_from_user( |
456 | char *dst, const char __user *src, long count) | 498 | char *dst, const char __user *src, long count) |
457 | { | 499 | { |
458 | might_fault(); | 500 | might_fault(); |
459 | return strncpy_from_user_asm(dst, src, count); | 501 | return strncpy_from_user_asm(dst, src, count); |
460 | } | 502 | } |
461 | static inline long __must_check strncpy_from_user( | 503 | static inline long __must_check strncpy_from_user( |
462 | char *dst, const char __user *src, long count) | 504 | char *dst, const char __user *src, long count) |
463 | { | 505 | { |
464 | if (access_ok(VERIFY_READ, src, 1)) | 506 | if (access_ok(VERIFY_READ, src, 1)) |
465 | return __strncpy_from_user(dst, src, count); | 507 | return __strncpy_from_user(dst, src, count); |
466 | return -EFAULT; | 508 | return -EFAULT; |
467 | } | 509 | } |
468 | 510 | ||
469 | /** | 511 | /** |
470 | * clear_user: - Zero a block of memory in user space. | 512 | * clear_user: - Zero a block of memory in user space. |
471 | * @mem: Destination address, in user space. | 513 | * @mem: Destination address, in user space. |
472 | * @len: Number of bytes to zero. | 514 | * @len: Number of bytes to zero. |
473 | * | 515 | * |
474 | * Zero a block of memory in user space. | 516 | * Zero a block of memory in user space. |
475 | * | 517 | * |
476 | * Returns number of bytes that could not be cleared. | 518 | * Returns number of bytes that could not be cleared. |
477 | * On success, this will be zero. | 519 | * On success, this will be zero. |
478 | */ | 520 | */ |
479 | extern unsigned long clear_user_asm(void __user *mem, unsigned long len); | 521 | extern unsigned long clear_user_asm(void __user *mem, unsigned long len); |
480 | static inline unsigned long __must_check __clear_user( | 522 | static inline unsigned long __must_check __clear_user( |
481 | void __user *mem, unsigned long len) | 523 | void __user *mem, unsigned long len) |
482 | { | 524 | { |
483 | might_fault(); | 525 | might_fault(); |
484 | return clear_user_asm(mem, len); | 526 | return clear_user_asm(mem, len); |
485 | } | 527 | } |
486 | static inline unsigned long __must_check clear_user( | 528 | static inline unsigned long __must_check clear_user( |
487 | void __user *mem, unsigned long len) | 529 | void __user *mem, unsigned long len) |
488 | { | 530 | { |
489 | if (access_ok(VERIFY_WRITE, mem, len)) | 531 | if (access_ok(VERIFY_WRITE, mem, len)) |
490 | return __clear_user(mem, len); | 532 | return __clear_user(mem, len); |
491 | return len; | 533 | return len; |
492 | } | 534 | } |
493 | 535 | ||
494 | /** | 536 | /** |
495 | * flush_user: - Flush a block of memory in user space from cache. | 537 | * flush_user: - Flush a block of memory in user space from cache. |
496 | * @mem: Destination address, in user space. | 538 | * @mem: Destination address, in user space. |
497 | * @len: Number of bytes to flush. | 539 | * @len: Number of bytes to flush. |
498 | * | 540 | * |
499 | * Returns number of bytes that could not be flushed. | 541 | * Returns number of bytes that could not be flushed. |
500 | * On success, this will be zero. | 542 | * On success, this will be zero. |
501 | */ | 543 | */ |
502 | extern unsigned long flush_user_asm(void __user *mem, unsigned long len); | 544 | extern unsigned long flush_user_asm(void __user *mem, unsigned long len); |
503 | static inline unsigned long __must_check __flush_user( | 545 | static inline unsigned long __must_check __flush_user( |
504 | void __user *mem, unsigned long len) | 546 | void __user *mem, unsigned long len) |
505 | { | 547 | { |
506 | int retval; | 548 | int retval; |
507 | 549 | ||
508 | might_fault(); | 550 | might_fault(); |
509 | retval = flush_user_asm(mem, len); | 551 | retval = flush_user_asm(mem, len); |
510 | mb_incoherent(); | 552 | mb_incoherent(); |
511 | return retval; | 553 | return retval; |
512 | } | 554 | } |
513 | 555 | ||
514 | static inline unsigned long __must_check flush_user( | 556 | static inline unsigned long __must_check flush_user( |
515 | void __user *mem, unsigned long len) | 557 | void __user *mem, unsigned long len) |
516 | { | 558 | { |
517 | if (access_ok(VERIFY_WRITE, mem, len)) | 559 | if (access_ok(VERIFY_WRITE, mem, len)) |
518 | return __flush_user(mem, len); | 560 | return __flush_user(mem, len); |
519 | return len; | 561 | return len; |
520 | } | 562 | } |
521 | 563 | ||
522 | /** | 564 | /** |
523 | * inv_user: - Invalidate a block of memory in user space from cache. | 565 | * inv_user: - Invalidate a block of memory in user space from cache. |
524 | * @mem: Destination address, in user space. | 566 | * @mem: Destination address, in user space. |
525 | * @len: Number of bytes to invalidate. | 567 | * @len: Number of bytes to invalidate. |
526 | * | 568 | * |
527 | * Returns number of bytes that could not be invalidated. | 569 | * Returns number of bytes that could not be invalidated. |
528 | * On success, this will be zero. | 570 | * On success, this will be zero. |
529 | * | 571 | * |
530 | * Note that on Tile64, the "inv" operation is in fact a | 572 | * Note that on Tile64, the "inv" operation is in fact a |
531 | * "flush and invalidate", so cache write-backs will occur prior | 573 | * "flush and invalidate", so cache write-backs will occur prior |
532 | * to the cache being marked invalid. | 574 | * to the cache being marked invalid. |
arch/tile/kernel/Makefile
1 | # | 1 | # |
2 | # Makefile for the Linux/TILE kernel. | 2 | # Makefile for the Linux/TILE kernel. |
3 | # | 3 | # |
4 | 4 | ||
5 | extra-y := vmlinux.lds head_$(BITS).o | 5 | extra-y := vmlinux.lds head_$(BITS).o |
6 | obj-y := backtrace.o entry.o init_task.o irq.o messaging.o \ | 6 | obj-y := backtrace.o entry.o init_task.o irq.o messaging.o \ |
7 | pci-dma.o proc.o process.o ptrace.o reboot.o \ | 7 | pci-dma.o proc.o process.o ptrace.o reboot.o \ |
8 | setup.o signal.o single_step.o stack.o sys.o sysfs.o time.o traps.o \ | 8 | setup.o signal.o single_step.o stack.o sys.o sysfs.o time.o traps.o \ |
9 | intvec_$(BITS).o regs_$(BITS).o tile-desc_$(BITS).o | 9 | intvec_$(BITS).o regs_$(BITS).o tile-desc_$(BITS).o |
10 | 10 | ||
11 | obj-$(CONFIG_HARDWALL) += hardwall.o | 11 | obj-$(CONFIG_HARDWALL) += hardwall.o |
12 | obj-$(CONFIG_TILEGX) += futex_64.o | ||
13 | obj-$(CONFIG_COMPAT) += compat.o compat_signal.o | 12 | obj-$(CONFIG_COMPAT) += compat.o compat_signal.o |
14 | obj-$(CONFIG_SMP) += smpboot.o smp.o tlb.o | 13 | obj-$(CONFIG_SMP) += smpboot.o smp.o tlb.o |
15 | obj-$(CONFIG_MODULES) += module.o | 14 | obj-$(CONFIG_MODULES) += module.o |
16 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 15 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
17 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o | 16 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o |
18 | obj-$(CONFIG_PCI) += pci.o | 17 | obj-$(CONFIG_PCI) += pci.o |
19 | 18 |
arch/tile/lib/atomic_32.c
1 | /* | 1 | /* |
2 | * Copyright 2010 Tilera Corporation. All Rights Reserved. | 2 | * Copyright 2010 Tilera Corporation. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU General Public License | 5 | * modify it under the terms of the GNU General Public License |
6 | * as published by the Free Software Foundation, version 2. | 6 | * as published by the Free Software Foundation, version 2. |
7 | * | 7 | * |
8 | * This program is distributed in the hope that it will be useful, but | 8 | * This program is distributed in the hope that it will be useful, but |
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 9 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | 10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or |
11 | * NON INFRINGEMENT. See the GNU General Public License for | 11 | * NON INFRINGEMENT. See the GNU General Public License for |
12 | * more details. | 12 | * more details. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/cache.h> | 15 | #include <linux/cache.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/uaccess.h> | 17 | #include <linux/uaccess.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
20 | #include <linux/atomic.h> | 20 | #include <linux/atomic.h> |
21 | #include <asm/futex.h> | ||
22 | #include <arch/chip.h> | 21 | #include <arch/chip.h> |
23 | 22 | ||
24 | /* See <asm/atomic_32.h> */ | 23 | /* See <asm/atomic_32.h> */ |
25 | #if ATOMIC_LOCKS_FOUND_VIA_TABLE() | 24 | #if ATOMIC_LOCKS_FOUND_VIA_TABLE() |
26 | 25 | ||
27 | /* | 26 | /* |
28 | * A block of memory containing locks for atomic ops. Each instance of this | 27 | * A block of memory containing locks for atomic ops. Each instance of this |
29 | * struct will be homed on a different CPU. | 28 | * struct will be homed on a different CPU. |
30 | */ | 29 | */ |
31 | struct atomic_locks_on_cpu { | 30 | struct atomic_locks_on_cpu { |
32 | int lock[ATOMIC_HASH_L2_SIZE]; | 31 | int lock[ATOMIC_HASH_L2_SIZE]; |
33 | } __attribute__((aligned(ATOMIC_HASH_L2_SIZE * 4))); | 32 | } __attribute__((aligned(ATOMIC_HASH_L2_SIZE * 4))); |
34 | 33 | ||
35 | static DEFINE_PER_CPU(struct atomic_locks_on_cpu, atomic_lock_pool); | 34 | static DEFINE_PER_CPU(struct atomic_locks_on_cpu, atomic_lock_pool); |
36 | 35 | ||
37 | /* The locks we'll use until __init_atomic_per_cpu is called. */ | 36 | /* The locks we'll use until __init_atomic_per_cpu is called. */ |
38 | static struct atomic_locks_on_cpu __initdata initial_atomic_locks; | 37 | static struct atomic_locks_on_cpu __initdata initial_atomic_locks; |
39 | 38 | ||
40 | /* Hash into this vector to get a pointer to lock for the given atomic. */ | 39 | /* Hash into this vector to get a pointer to lock for the given atomic. */ |
41 | struct atomic_locks_on_cpu *atomic_lock_ptr[ATOMIC_HASH_L1_SIZE] | 40 | struct atomic_locks_on_cpu *atomic_lock_ptr[ATOMIC_HASH_L1_SIZE] |
42 | __write_once = { | 41 | __write_once = { |
43 | [0 ... ATOMIC_HASH_L1_SIZE-1] (&initial_atomic_locks) | 42 | [0 ... ATOMIC_HASH_L1_SIZE-1] (&initial_atomic_locks) |
44 | }; | 43 | }; |
45 | 44 | ||
46 | #else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ | 45 | #else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ |
47 | 46 | ||
48 | /* This page is remapped on startup to be hash-for-home. */ | 47 | /* This page is remapped on startup to be hash-for-home. */ |
49 | int atomic_locks[PAGE_SIZE / sizeof(int)] __page_aligned_bss; | 48 | int atomic_locks[PAGE_SIZE / sizeof(int)] __page_aligned_bss; |
50 | 49 | ||
51 | #endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ | 50 | #endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ |
52 | 51 | ||
53 | static inline int *__atomic_hashed_lock(volatile void *v) | 52 | int *__atomic_hashed_lock(volatile void *v) |
54 | { | 53 | { |
55 | /* NOTE: this code must match "sys_cmpxchg" in kernel/intvec_32.S */ | 54 | /* NOTE: this code must match "sys_cmpxchg" in kernel/intvec_32.S */ |
56 | #if ATOMIC_LOCKS_FOUND_VIA_TABLE() | 55 | #if ATOMIC_LOCKS_FOUND_VIA_TABLE() |
57 | unsigned long i = | 56 | unsigned long i = |
58 | (unsigned long) v & ((PAGE_SIZE-1) & -sizeof(long long)); | 57 | (unsigned long) v & ((PAGE_SIZE-1) & -sizeof(long long)); |
59 | unsigned long n = __insn_crc32_32(0, i); | 58 | unsigned long n = __insn_crc32_32(0, i); |
60 | 59 | ||
61 | /* Grab high bits for L1 index. */ | 60 | /* Grab high bits for L1 index. */ |
62 | unsigned long l1_index = n >> ((sizeof(n) * 8) - ATOMIC_HASH_L1_SHIFT); | 61 | unsigned long l1_index = n >> ((sizeof(n) * 8) - ATOMIC_HASH_L1_SHIFT); |
63 | /* Grab low bits for L2 index. */ | 62 | /* Grab low bits for L2 index. */ |
64 | unsigned long l2_index = n & (ATOMIC_HASH_L2_SIZE - 1); | 63 | unsigned long l2_index = n & (ATOMIC_HASH_L2_SIZE - 1); |
65 | 64 | ||
66 | return &atomic_lock_ptr[l1_index]->lock[l2_index]; | 65 | return &atomic_lock_ptr[l1_index]->lock[l2_index]; |
67 | #else | 66 | #else |
68 | /* | 67 | /* |
69 | * Use bits [3, 3 + ATOMIC_HASH_SHIFT) as the lock index. | 68 | * Use bits [3, 3 + ATOMIC_HASH_SHIFT) as the lock index. |
70 | * Using mm works here because atomic_locks is page aligned. | 69 | * Using mm works here because atomic_locks is page aligned. |
71 | */ | 70 | */ |
72 | unsigned long ptr = __insn_mm((unsigned long)v >> 1, | 71 | unsigned long ptr = __insn_mm((unsigned long)v >> 1, |
73 | (unsigned long)atomic_locks, | 72 | (unsigned long)atomic_locks, |
74 | 2, (ATOMIC_HASH_SHIFT + 2) - 1); | 73 | 2, (ATOMIC_HASH_SHIFT + 2) - 1); |
75 | return (int *)ptr; | 74 | return (int *)ptr; |
76 | #endif | 75 | #endif |
77 | } | 76 | } |
78 | 77 | ||
79 | #ifdef CONFIG_SMP | 78 | #ifdef CONFIG_SMP |
80 | /* Return whether the passed pointer is a valid atomic lock pointer. */ | 79 | /* Return whether the passed pointer is a valid atomic lock pointer. */ |
81 | static int is_atomic_lock(int *p) | 80 | static int is_atomic_lock(int *p) |
82 | { | 81 | { |
83 | #if ATOMIC_LOCKS_FOUND_VIA_TABLE() | 82 | #if ATOMIC_LOCKS_FOUND_VIA_TABLE() |
84 | int i; | 83 | int i; |
85 | for (i = 0; i < ATOMIC_HASH_L1_SIZE; ++i) { | 84 | for (i = 0; i < ATOMIC_HASH_L1_SIZE; ++i) { |
86 | 85 | ||
87 | if (p >= &atomic_lock_ptr[i]->lock[0] && | 86 | if (p >= &atomic_lock_ptr[i]->lock[0] && |
88 | p < &atomic_lock_ptr[i]->lock[ATOMIC_HASH_L2_SIZE]) { | 87 | p < &atomic_lock_ptr[i]->lock[ATOMIC_HASH_L2_SIZE]) { |
89 | return 1; | 88 | return 1; |
90 | } | 89 | } |
91 | } | 90 | } |
92 | return 0; | 91 | return 0; |
93 | #else | 92 | #else |
94 | return p >= &atomic_locks[0] && p < &atomic_locks[ATOMIC_HASH_SIZE]; | 93 | return p >= &atomic_locks[0] && p < &atomic_locks[ATOMIC_HASH_SIZE]; |
95 | #endif | 94 | #endif |
96 | } | 95 | } |
97 | 96 | ||
98 | void __atomic_fault_unlock(int *irqlock_word) | 97 | void __atomic_fault_unlock(int *irqlock_word) |
99 | { | 98 | { |
100 | BUG_ON(!is_atomic_lock(irqlock_word)); | 99 | BUG_ON(!is_atomic_lock(irqlock_word)); |
101 | BUG_ON(*irqlock_word != 1); | 100 | BUG_ON(*irqlock_word != 1); |
102 | *irqlock_word = 0; | 101 | *irqlock_word = 0; |
103 | } | 102 | } |
104 | 103 | ||
105 | #endif /* CONFIG_SMP */ | 104 | #endif /* CONFIG_SMP */ |
106 | 105 | ||
107 | static inline int *__atomic_setup(volatile void *v) | 106 | static inline int *__atomic_setup(volatile void *v) |
108 | { | 107 | { |
109 | /* Issue a load to the target to bring it into cache. */ | 108 | /* Issue a load to the target to bring it into cache. */ |
110 | *(volatile int *)v; | 109 | *(volatile int *)v; |
111 | return __atomic_hashed_lock(v); | 110 | return __atomic_hashed_lock(v); |
112 | } | 111 | } |
113 | 112 | ||
114 | int _atomic_xchg(atomic_t *v, int n) | 113 | int _atomic_xchg(atomic_t *v, int n) |
115 | { | 114 | { |
116 | return __atomic_xchg(&v->counter, __atomic_setup(v), n).val; | 115 | return __atomic_xchg(&v->counter, __atomic_setup(v), n).val; |
117 | } | 116 | } |
118 | EXPORT_SYMBOL(_atomic_xchg); | 117 | EXPORT_SYMBOL(_atomic_xchg); |
119 | 118 | ||
120 | int _atomic_xchg_add(atomic_t *v, int i) | 119 | int _atomic_xchg_add(atomic_t *v, int i) |
121 | { | 120 | { |
122 | return __atomic_xchg_add(&v->counter, __atomic_setup(v), i).val; | 121 | return __atomic_xchg_add(&v->counter, __atomic_setup(v), i).val; |
123 | } | 122 | } |
124 | EXPORT_SYMBOL(_atomic_xchg_add); | 123 | EXPORT_SYMBOL(_atomic_xchg_add); |
125 | 124 | ||
126 | int _atomic_xchg_add_unless(atomic_t *v, int a, int u) | 125 | int _atomic_xchg_add_unless(atomic_t *v, int a, int u) |
127 | { | 126 | { |
128 | /* | 127 | /* |
129 | * Note: argument order is switched here since it is easier | 128 | * Note: argument order is switched here since it is easier |
130 | * to use the first argument consistently as the "old value" | 129 | * to use the first argument consistently as the "old value" |
131 | * in the assembly, as is done for _atomic_cmpxchg(). | 130 | * in the assembly, as is done for _atomic_cmpxchg(). |
132 | */ | 131 | */ |
133 | return __atomic_xchg_add_unless(&v->counter, __atomic_setup(v), u, a) | 132 | return __atomic_xchg_add_unless(&v->counter, __atomic_setup(v), u, a) |
134 | .val; | 133 | .val; |
135 | } | 134 | } |
136 | EXPORT_SYMBOL(_atomic_xchg_add_unless); | 135 | EXPORT_SYMBOL(_atomic_xchg_add_unless); |
137 | 136 | ||
138 | int _atomic_cmpxchg(atomic_t *v, int o, int n) | 137 | int _atomic_cmpxchg(atomic_t *v, int o, int n) |
139 | { | 138 | { |
140 | return __atomic_cmpxchg(&v->counter, __atomic_setup(v), o, n).val; | 139 | return __atomic_cmpxchg(&v->counter, __atomic_setup(v), o, n).val; |
141 | } | 140 | } |
142 | EXPORT_SYMBOL(_atomic_cmpxchg); | 141 | EXPORT_SYMBOL(_atomic_cmpxchg); |
143 | 142 | ||
144 | unsigned long _atomic_or(volatile unsigned long *p, unsigned long mask) | 143 | unsigned long _atomic_or(volatile unsigned long *p, unsigned long mask) |
145 | { | 144 | { |
146 | return __atomic_or((int *)p, __atomic_setup(p), mask).val; | 145 | return __atomic_or((int *)p, __atomic_setup(p), mask).val; |
147 | } | 146 | } |
148 | EXPORT_SYMBOL(_atomic_or); | 147 | EXPORT_SYMBOL(_atomic_or); |
149 | 148 | ||
150 | unsigned long _atomic_andn(volatile unsigned long *p, unsigned long mask) | 149 | unsigned long _atomic_andn(volatile unsigned long *p, unsigned long mask) |
151 | { | 150 | { |
152 | return __atomic_andn((int *)p, __atomic_setup(p), mask).val; | 151 | return __atomic_andn((int *)p, __atomic_setup(p), mask).val; |
153 | } | 152 | } |
154 | EXPORT_SYMBOL(_atomic_andn); | 153 | EXPORT_SYMBOL(_atomic_andn); |
155 | 154 | ||
156 | unsigned long _atomic_xor(volatile unsigned long *p, unsigned long mask) | 155 | unsigned long _atomic_xor(volatile unsigned long *p, unsigned long mask) |
157 | { | 156 | { |
158 | return __atomic_xor((int *)p, __atomic_setup(p), mask).val; | 157 | return __atomic_xor((int *)p, __atomic_setup(p), mask).val; |
159 | } | 158 | } |
160 | EXPORT_SYMBOL(_atomic_xor); | 159 | EXPORT_SYMBOL(_atomic_xor); |
161 | 160 | ||
162 | 161 | ||
163 | u64 _atomic64_xchg(atomic64_t *v, u64 n) | 162 | u64 _atomic64_xchg(atomic64_t *v, u64 n) |
164 | { | 163 | { |
165 | return __atomic64_xchg(&v->counter, __atomic_setup(v), n); | 164 | return __atomic64_xchg(&v->counter, __atomic_setup(v), n); |
166 | } | 165 | } |
167 | EXPORT_SYMBOL(_atomic64_xchg); | 166 | EXPORT_SYMBOL(_atomic64_xchg); |
168 | 167 | ||
169 | u64 _atomic64_xchg_add(atomic64_t *v, u64 i) | 168 | u64 _atomic64_xchg_add(atomic64_t *v, u64 i) |
170 | { | 169 | { |
171 | return __atomic64_xchg_add(&v->counter, __atomic_setup(v), i); | 170 | return __atomic64_xchg_add(&v->counter, __atomic_setup(v), i); |
172 | } | 171 | } |
173 | EXPORT_SYMBOL(_atomic64_xchg_add); | 172 | EXPORT_SYMBOL(_atomic64_xchg_add); |
174 | 173 | ||
175 | u64 _atomic64_xchg_add_unless(atomic64_t *v, u64 a, u64 u) | 174 | u64 _atomic64_xchg_add_unless(atomic64_t *v, u64 a, u64 u) |
176 | { | 175 | { |
177 | /* | 176 | /* |
178 | * Note: argument order is switched here since it is easier | 177 | * Note: argument order is switched here since it is easier |
179 | * to use the first argument consistently as the "old value" | 178 | * to use the first argument consistently as the "old value" |
180 | * in the assembly, as is done for _atomic_cmpxchg(). | 179 | * in the assembly, as is done for _atomic_cmpxchg(). |
181 | */ | 180 | */ |
182 | return __atomic64_xchg_add_unless(&v->counter, __atomic_setup(v), | 181 | return __atomic64_xchg_add_unless(&v->counter, __atomic_setup(v), |
183 | u, a); | 182 | u, a); |
184 | } | 183 | } |
185 | EXPORT_SYMBOL(_atomic64_xchg_add_unless); | 184 | EXPORT_SYMBOL(_atomic64_xchg_add_unless); |
186 | 185 | ||
187 | u64 _atomic64_cmpxchg(atomic64_t *v, u64 o, u64 n) | 186 | u64 _atomic64_cmpxchg(atomic64_t *v, u64 o, u64 n) |
188 | { | 187 | { |
189 | return __atomic64_cmpxchg(&v->counter, __atomic_setup(v), o, n); | 188 | return __atomic64_cmpxchg(&v->counter, __atomic_setup(v), o, n); |
190 | } | 189 | } |
191 | EXPORT_SYMBOL(_atomic64_cmpxchg); | 190 | EXPORT_SYMBOL(_atomic64_cmpxchg); |
192 | 191 | ||
193 | 192 | ||
194 | static inline int *__futex_setup(int __user *v) | ||
195 | { | ||
196 | /* | ||
197 | * Issue a prefetch to the counter to bring it into cache. | ||
198 | * As for __atomic_setup, but we can't do a read into the L1 | ||
199 | * since it might fault; instead we do a prefetch into the L2. | ||
200 | */ | ||
201 | __insn_prefetch(v); | ||
202 | return __atomic_hashed_lock((int __force *)v); | ||
203 | } | ||
204 | |||
205 | struct __get_user futex_set(u32 __user *v, int i) | ||
206 | { | ||
207 | return __atomic_xchg((int __force *)v, __futex_setup(v), i); | ||
208 | } | ||
209 | |||
210 | struct __get_user futex_add(u32 __user *v, int n) | ||
211 | { | ||
212 | return __atomic_xchg_add((int __force *)v, __futex_setup(v), n); | ||
213 | } | ||
214 | |||
215 | struct __get_user futex_or(u32 __user *v, int n) | ||
216 | { | ||
217 | return __atomic_or((int __force *)v, __futex_setup(v), n); | ||
218 | } | ||
219 | |||
220 | struct __get_user futex_andn(u32 __user *v, int n) | ||
221 | { | ||
222 | return __atomic_andn((int __force *)v, __futex_setup(v), n); | ||
223 | } | ||
224 | |||
225 | struct __get_user futex_xor(u32 __user *v, int n) | ||
226 | { | ||
227 | return __atomic_xor((int __force *)v, __futex_setup(v), n); | ||
228 | } | ||
229 | |||
230 | struct __get_user futex_cmpxchg(u32 __user *v, int o, int n) | ||
231 | { | ||
232 | return __atomic_cmpxchg((int __force *)v, __futex_setup(v), o, n); | ||
233 | } | ||
234 | |||
235 | /* | 193 | /* |
236 | * If any of the atomic or futex routines hit a bad address (not in | 194 | * If any of the atomic or futex routines hit a bad address (not in |
237 | * the page tables at kernel PL) this routine is called. The futex | 195 | * the page tables at kernel PL) this routine is called. The futex |
238 | * routines are never used on kernel space, and the normal atomics and | 196 | * routines are never used on kernel space, and the normal atomics and |
239 | * bitops are never used on user space. So a fault on kernel space | 197 | * bitops are never used on user space. So a fault on kernel space |
240 | * must be fatal, but a fault on userspace is a futex fault and we | 198 | * must be fatal, but a fault on userspace is a futex fault and we |
241 | * need to return -EFAULT. Note that the context this routine is | 199 | * need to return -EFAULT. Note that the context this routine is |
242 | * invoked in is the context of the "_atomic_xxx()" routines called | 200 | * invoked in is the context of the "_atomic_xxx()" routines called |
243 | * by the functions in this file. | 201 | * by the functions in this file. |
244 | */ | 202 | */ |
245 | struct __get_user __atomic_bad_address(int __user *addr) | 203 | struct __get_user __atomic_bad_address(int __user *addr) |
246 | { | 204 | { |
247 | if (unlikely(!access_ok(VERIFY_WRITE, addr, sizeof(int)))) | 205 | if (unlikely(!access_ok(VERIFY_WRITE, addr, sizeof(int)))) |
248 | panic("Bad address used for kernel atomic op: %p\n", addr); | 206 | panic("Bad address used for kernel atomic op: %p\n", addr); |
249 | return (struct __get_user) { .err = -EFAULT }; | 207 | return (struct __get_user) { .err = -EFAULT }; |
250 | } | 208 | } |
251 | 209 | ||
252 | 210 | ||
253 | #if CHIP_HAS_CBOX_HOME_MAP() | 211 | #if CHIP_HAS_CBOX_HOME_MAP() |
254 | static int __init noatomichash(char *str) | 212 | static int __init noatomichash(char *str) |
255 | { | 213 | { |
256 | pr_warning("noatomichash is deprecated.\n"); | 214 | pr_warning("noatomichash is deprecated.\n"); |
257 | return 1; | 215 | return 1; |
258 | } | 216 | } |
259 | __setup("noatomichash", noatomichash); | 217 | __setup("noatomichash", noatomichash); |
260 | #endif | 218 | #endif |
261 | 219 | ||
262 | void __init __init_atomic_per_cpu(void) | 220 | void __init __init_atomic_per_cpu(void) |
263 | { | 221 | { |
264 | #if ATOMIC_LOCKS_FOUND_VIA_TABLE() | 222 | #if ATOMIC_LOCKS_FOUND_VIA_TABLE() |
265 | 223 | ||
266 | unsigned int i; | 224 | unsigned int i; |
267 | int actual_cpu; | 225 | int actual_cpu; |
268 | 226 | ||
269 | /* | 227 | /* |
270 | * Before this is called from setup, we just have one lock for | 228 | * Before this is called from setup, we just have one lock for |
271 | * all atomic objects/operations. Here we replace the | 229 | * all atomic objects/operations. Here we replace the |
272 | * elements of atomic_lock_ptr so that they point at per_cpu | 230 | * elements of atomic_lock_ptr so that they point at per_cpu |
273 | * integers. This seemingly over-complex approach stems from | 231 | * integers. This seemingly over-complex approach stems from |
274 | * the fact that DEFINE_PER_CPU defines an entry for each cpu | 232 | * the fact that DEFINE_PER_CPU defines an entry for each cpu |
275 | * in the grid, not each cpu from 0..ATOMIC_HASH_SIZE-1. But | 233 | * in the grid, not each cpu from 0..ATOMIC_HASH_SIZE-1. But |
276 | * for efficient hashing of atomics to their locks we want a | 234 | * for efficient hashing of atomics to their locks we want a |
277 | * compile time constant power of 2 for the size of this | 235 | * compile time constant power of 2 for the size of this |
278 | * table, so we use ATOMIC_HASH_SIZE. | 236 | * table, so we use ATOMIC_HASH_SIZE. |
279 | * | 237 | * |
280 | * Here we populate atomic_lock_ptr from the per cpu | 238 | * Here we populate atomic_lock_ptr from the per cpu |
281 | * atomic_lock_pool, interspersing by actual cpu so that | 239 | * atomic_lock_pool, interspersing by actual cpu so that |
282 | * subsequent elements are homed on consecutive cpus. | 240 | * subsequent elements are homed on consecutive cpus. |
283 | */ | 241 | */ |
284 | 242 | ||
285 | actual_cpu = cpumask_first(cpu_possible_mask); | 243 | actual_cpu = cpumask_first(cpu_possible_mask); |
286 | 244 | ||
287 | for (i = 0; i < ATOMIC_HASH_L1_SIZE; ++i) { | 245 | for (i = 0; i < ATOMIC_HASH_L1_SIZE; ++i) { |
288 | /* | 246 | /* |
289 | * Preincrement to slightly bias against using cpu 0, | 247 | * Preincrement to slightly bias against using cpu 0, |
290 | * which has plenty of stuff homed on it already. | 248 | * which has plenty of stuff homed on it already. |
291 | */ | 249 | */ |
292 | actual_cpu = cpumask_next(actual_cpu, cpu_possible_mask); | 250 | actual_cpu = cpumask_next(actual_cpu, cpu_possible_mask); |
293 | if (actual_cpu >= nr_cpu_ids) | 251 | if (actual_cpu >= nr_cpu_ids) |
294 | actual_cpu = cpumask_first(cpu_possible_mask); | 252 | actual_cpu = cpumask_first(cpu_possible_mask); |
295 | 253 | ||
296 | atomic_lock_ptr[i] = &per_cpu(atomic_lock_pool, actual_cpu); | 254 | atomic_lock_ptr[i] = &per_cpu(atomic_lock_pool, actual_cpu); |
297 | } | 255 | } |
298 | 256 | ||
299 | #else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ | 257 | #else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ |
300 | 258 | ||
301 | /* Validate power-of-two and "bigger than cpus" assumption */ | 259 | /* Validate power-of-two and "bigger than cpus" assumption */ |
302 | BUILD_BUG_ON(ATOMIC_HASH_SIZE & (ATOMIC_HASH_SIZE-1)); | 260 | BUILD_BUG_ON(ATOMIC_HASH_SIZE & (ATOMIC_HASH_SIZE-1)); |
303 | BUG_ON(ATOMIC_HASH_SIZE < nr_cpu_ids); | 261 | BUG_ON(ATOMIC_HASH_SIZE < nr_cpu_ids); |
304 | 262 | ||
305 | /* | 263 | /* |
306 | * On TILEPro we prefer to use a single hash-for-home | 264 | * On TILEPro we prefer to use a single hash-for-home |
307 | * page, since this means atomic operations are less | 265 | * page, since this means atomic operations are less |
308 | * likely to encounter a TLB fault and thus should | 266 | * likely to encounter a TLB fault and thus should |
309 | * in general perform faster. You may wish to disable | 267 | * in general perform faster. You may wish to disable |
310 | * this in situations where few hash-for-home tiles | 268 | * this in situations where few hash-for-home tiles |
311 | * are configured. | 269 | * are configured. |
312 | */ | 270 | */ |
313 | BUG_ON((unsigned long)atomic_locks % PAGE_SIZE != 0); | 271 | BUG_ON((unsigned long)atomic_locks % PAGE_SIZE != 0); |
314 | 272 | ||
315 | /* The locks must all fit on one page. */ | 273 | /* The locks must all fit on one page. */ |
316 | BUILD_BUG_ON(ATOMIC_HASH_SIZE * sizeof(int) > PAGE_SIZE); | 274 | BUILD_BUG_ON(ATOMIC_HASH_SIZE * sizeof(int) > PAGE_SIZE); |
317 | 275 | ||
318 | /* | 276 | /* |
319 | * We use the page offset of the atomic value's address as | 277 | * We use the page offset of the atomic value's address as |
320 | * an index into atomic_locks, excluding the low 3 bits. | 278 | * an index into atomic_locks, excluding the low 3 bits. |
321 | * That should not produce more indices than ATOMIC_HASH_SIZE. | 279 | * That should not produce more indices than ATOMIC_HASH_SIZE. |
322 | */ | 280 | */ |
323 | BUILD_BUG_ON((PAGE_SIZE >> 3) > ATOMIC_HASH_SIZE); | 281 | BUILD_BUG_ON((PAGE_SIZE >> 3) > ATOMIC_HASH_SIZE); |
324 | 282 | ||
325 | #endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ | 283 | #endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ |
326 | |||
327 | /* The futex code makes this assumption, so we validate it here. */ | ||
328 | BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int)); | ||
329 | } | 284 | } |
330 | 285 |
arch/tile/lib/exports.c
1 | /* | 1 | /* |
2 | * Copyright 2010 Tilera Corporation. All Rights Reserved. | 2 | * Copyright 2010 Tilera Corporation. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU General Public License | 5 | * modify it under the terms of the GNU General Public License |
6 | * as published by the Free Software Foundation, version 2. | 6 | * as published by the Free Software Foundation, version 2. |
7 | * | 7 | * |
8 | * This program is distributed in the hope that it will be useful, but | 8 | * This program is distributed in the hope that it will be useful, but |
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 9 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | 10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or |
11 | * NON INFRINGEMENT. See the GNU General Public License for | 11 | * NON INFRINGEMENT. See the GNU General Public License for |
12 | * more details. | 12 | * more details. |
13 | * | 13 | * |
14 | * Exports from assembler code and from libtile-cc. | 14 | * Exports from assembler code and from libtile-cc. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | 18 | ||
19 | /* arch/tile/lib/usercopy.S */ | 19 | /* arch/tile/lib/usercopy.S */ |
20 | #include <linux/uaccess.h> | 20 | #include <linux/uaccess.h> |
21 | EXPORT_SYMBOL(__get_user_1); | ||
22 | EXPORT_SYMBOL(__get_user_2); | ||
23 | EXPORT_SYMBOL(__get_user_4); | ||
24 | EXPORT_SYMBOL(__get_user_8); | ||
25 | EXPORT_SYMBOL(__put_user_1); | ||
26 | EXPORT_SYMBOL(__put_user_2); | ||
27 | EXPORT_SYMBOL(__put_user_4); | ||
28 | EXPORT_SYMBOL(__put_user_8); | ||
29 | EXPORT_SYMBOL(strnlen_user_asm); | 21 | EXPORT_SYMBOL(strnlen_user_asm); |
30 | EXPORT_SYMBOL(strncpy_from_user_asm); | 22 | EXPORT_SYMBOL(strncpy_from_user_asm); |
31 | EXPORT_SYMBOL(clear_user_asm); | 23 | EXPORT_SYMBOL(clear_user_asm); |
32 | EXPORT_SYMBOL(flush_user_asm); | 24 | EXPORT_SYMBOL(flush_user_asm); |
33 | EXPORT_SYMBOL(inv_user_asm); | 25 | EXPORT_SYMBOL(inv_user_asm); |
34 | EXPORT_SYMBOL(finv_user_asm); | 26 | EXPORT_SYMBOL(finv_user_asm); |
35 | 27 | ||
36 | /* arch/tile/kernel/entry.S */ | 28 | /* arch/tile/kernel/entry.S */ |
37 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
38 | #include <asm/processor.h> | 30 | #include <asm/processor.h> |
39 | EXPORT_SYMBOL(current_text_addr); | 31 | EXPORT_SYMBOL(current_text_addr); |
40 | EXPORT_SYMBOL(dump_stack); | 32 | EXPORT_SYMBOL(dump_stack); |
41 | 33 | ||
42 | /* arch/tile/kernel/head.S */ | 34 | /* arch/tile/kernel/head.S */ |
43 | EXPORT_SYMBOL(empty_zero_page); | 35 | EXPORT_SYMBOL(empty_zero_page); |
44 | 36 | ||
45 | /* arch/tile/lib/, various memcpy files */ | 37 | /* arch/tile/lib/, various memcpy files */ |
46 | EXPORT_SYMBOL(memcpy); | 38 | EXPORT_SYMBOL(memcpy); |
47 | EXPORT_SYMBOL(__copy_to_user_inatomic); | 39 | EXPORT_SYMBOL(__copy_to_user_inatomic); |
48 | EXPORT_SYMBOL(__copy_from_user_inatomic); | 40 | EXPORT_SYMBOL(__copy_from_user_inatomic); |
49 | EXPORT_SYMBOL(__copy_from_user_zeroing); | 41 | EXPORT_SYMBOL(__copy_from_user_zeroing); |
50 | #ifdef __tilegx__ | 42 | #ifdef __tilegx__ |
51 | EXPORT_SYMBOL(__copy_in_user_inatomic); | 43 | EXPORT_SYMBOL(__copy_in_user_inatomic); |
52 | #endif | 44 | #endif |
53 | 45 | ||
54 | /* hypervisor glue */ | 46 | /* hypervisor glue */ |
55 | #include <hv/hypervisor.h> | 47 | #include <hv/hypervisor.h> |
56 | EXPORT_SYMBOL(hv_dev_open); | 48 | EXPORT_SYMBOL(hv_dev_open); |
57 | EXPORT_SYMBOL(hv_dev_pread); | 49 | EXPORT_SYMBOL(hv_dev_pread); |
58 | EXPORT_SYMBOL(hv_dev_pwrite); | 50 | EXPORT_SYMBOL(hv_dev_pwrite); |
59 | EXPORT_SYMBOL(hv_dev_preada); | 51 | EXPORT_SYMBOL(hv_dev_preada); |
60 | EXPORT_SYMBOL(hv_dev_pwritea); | 52 | EXPORT_SYMBOL(hv_dev_pwritea); |
61 | EXPORT_SYMBOL(hv_dev_poll); | 53 | EXPORT_SYMBOL(hv_dev_poll); |
62 | EXPORT_SYMBOL(hv_dev_poll_cancel); | 54 | EXPORT_SYMBOL(hv_dev_poll_cancel); |
63 | EXPORT_SYMBOL(hv_dev_close); | 55 | EXPORT_SYMBOL(hv_dev_close); |
64 | EXPORT_SYMBOL(hv_sysconf); | 56 | EXPORT_SYMBOL(hv_sysconf); |
65 | EXPORT_SYMBOL(hv_confstr); | 57 | EXPORT_SYMBOL(hv_confstr); |
66 | 58 | ||
67 | /* libgcc.a */ | 59 | /* libgcc.a */ |
68 | uint32_t __udivsi3(uint32_t dividend, uint32_t divisor); | 60 | uint32_t __udivsi3(uint32_t dividend, uint32_t divisor); |
69 | EXPORT_SYMBOL(__udivsi3); | 61 | EXPORT_SYMBOL(__udivsi3); |
70 | int32_t __divsi3(int32_t dividend, int32_t divisor); | 62 | int32_t __divsi3(int32_t dividend, int32_t divisor); |
71 | EXPORT_SYMBOL(__divsi3); | 63 | EXPORT_SYMBOL(__divsi3); |
72 | uint64_t __udivdi3(uint64_t dividend, uint64_t divisor); | 64 | uint64_t __udivdi3(uint64_t dividend, uint64_t divisor); |
73 | EXPORT_SYMBOL(__udivdi3); | 65 | EXPORT_SYMBOL(__udivdi3); |
74 | int64_t __divdi3(int64_t dividend, int64_t divisor); | 66 | int64_t __divdi3(int64_t dividend, int64_t divisor); |
75 | EXPORT_SYMBOL(__divdi3); | 67 | EXPORT_SYMBOL(__divdi3); |
76 | uint32_t __umodsi3(uint32_t dividend, uint32_t divisor); | 68 | uint32_t __umodsi3(uint32_t dividend, uint32_t divisor); |
77 | EXPORT_SYMBOL(__umodsi3); | 69 | EXPORT_SYMBOL(__umodsi3); |
78 | int32_t __modsi3(int32_t dividend, int32_t divisor); | 70 | int32_t __modsi3(int32_t dividend, int32_t divisor); |
79 | EXPORT_SYMBOL(__modsi3); | 71 | EXPORT_SYMBOL(__modsi3); |
80 | uint64_t __umoddi3(uint64_t dividend, uint64_t divisor); | 72 | uint64_t __umoddi3(uint64_t dividend, uint64_t divisor); |
81 | EXPORT_SYMBOL(__umoddi3); | 73 | EXPORT_SYMBOL(__umoddi3); |
82 | int64_t __moddi3(int64_t dividend, int64_t divisor); | 74 | int64_t __moddi3(int64_t dividend, int64_t divisor); |
83 | EXPORT_SYMBOL(__moddi3); | 75 | EXPORT_SYMBOL(__moddi3); |
84 | #ifndef __tilegx__ | 76 | #ifndef __tilegx__ |
85 | int64_t __muldi3(int64_t, int64_t); | 77 | int64_t __muldi3(int64_t, int64_t); |
86 | EXPORT_SYMBOL(__muldi3); | 78 | EXPORT_SYMBOL(__muldi3); |
87 | uint64_t __lshrdi3(uint64_t, unsigned int); | 79 | uint64_t __lshrdi3(uint64_t, unsigned int); |
88 | EXPORT_SYMBOL(__lshrdi3); | 80 | EXPORT_SYMBOL(__lshrdi3); |
89 | uint64_t __ashrdi3(uint64_t, unsigned int); | 81 | uint64_t __ashrdi3(uint64_t, unsigned int); |
90 | EXPORT_SYMBOL(__ashrdi3); | 82 | EXPORT_SYMBOL(__ashrdi3); |
91 | uint64_t __ashldi3(uint64_t, unsigned int); | 83 | uint64_t __ashldi3(uint64_t, unsigned int); |
92 | EXPORT_SYMBOL(__ashldi3); | 84 | EXPORT_SYMBOL(__ashldi3); |
93 | #endif | 85 | #endif |
94 | 86 |
arch/tile/lib/usercopy_32.S
1 | /* | 1 | /* |
2 | * Copyright 2010 Tilera Corporation. All Rights Reserved. | 2 | * Copyright 2010 Tilera Corporation. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU General Public License | 5 | * modify it under the terms of the GNU General Public License |
6 | * as published by the Free Software Foundation, version 2. | 6 | * as published by the Free Software Foundation, version 2. |
7 | * | 7 | * |
8 | * This program is distributed in the hope that it will be useful, but | 8 | * This program is distributed in the hope that it will be useful, but |
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 9 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | 10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or |
11 | * NON INFRINGEMENT. See the GNU General Public License for | 11 | * NON INFRINGEMENT. See the GNU General Public License for |
12 | * more details. | 12 | * more details. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/linkage.h> | 15 | #include <linux/linkage.h> |
16 | #include <asm/errno.h> | 16 | #include <asm/errno.h> |
17 | #include <asm/cache.h> | 17 | #include <asm/cache.h> |
18 | #include <arch/chip.h> | 18 | #include <arch/chip.h> |
19 | 19 | ||
20 | /* Access user memory, but use MMU to avoid propagating kernel exceptions. */ | 20 | /* Access user memory, but use MMU to avoid propagating kernel exceptions. */ |
21 | 21 | ||
22 | .pushsection .fixup,"ax" | ||
23 | |||
24 | get_user_fault: | ||
25 | { move r0, zero; move r1, zero } | ||
26 | { movei r2, -EFAULT; jrp lr } | ||
27 | ENDPROC(get_user_fault) | ||
28 | |||
29 | put_user_fault: | ||
30 | { movei r0, -EFAULT; jrp lr } | ||
31 | ENDPROC(put_user_fault) | ||
32 | |||
33 | .popsection | ||
34 | |||
35 | /* | ||
36 | * __get_user_N functions take a pointer in r0, and return 0 in r2 | ||
37 | * on success, with the value in r0; or else -EFAULT in r2. | ||
38 | */ | ||
39 | #define __get_user_N(bytes, LOAD) \ | ||
40 | STD_ENTRY(__get_user_##bytes); \ | ||
41 | 1: { LOAD r0, r0; move r1, zero; move r2, zero }; \ | ||
42 | jrp lr; \ | ||
43 | STD_ENDPROC(__get_user_##bytes); \ | ||
44 | .pushsection __ex_table,"a"; \ | ||
45 | .word 1b, get_user_fault; \ | ||
46 | .popsection | ||
47 | |||
48 | __get_user_N(1, lb_u) | ||
49 | __get_user_N(2, lh_u) | ||
50 | __get_user_N(4, lw) | ||
51 | |||
52 | /* | ||
53 | * __get_user_8 takes a pointer in r0, and returns 0 in r2 | ||
54 | * on success, with the value in r0/r1; or else -EFAULT in r2. | ||
55 | */ | ||
56 | STD_ENTRY(__get_user_8); | ||
57 | 1: { lw r0, r0; addi r1, r0, 4 }; | ||
58 | 2: { lw r1, r1; move r2, zero }; | ||
59 | jrp lr; | ||
60 | STD_ENDPROC(__get_user_8); | ||
61 | .pushsection __ex_table,"a"; | ||
62 | .word 1b, get_user_fault; | ||
63 | .word 2b, get_user_fault; | ||
64 | .popsection | ||
65 | |||
66 | /* | ||
67 | * __put_user_N functions take a value in r0 and a pointer in r1, | ||
68 | * and return 0 in r0 on success or -EFAULT on failure. | ||
69 | */ | ||
70 | #define __put_user_N(bytes, STORE) \ | ||
71 | STD_ENTRY(__put_user_##bytes); \ | ||
72 | 1: { STORE r1, r0; move r0, zero }; \ | ||
73 | jrp lr; \ | ||
74 | STD_ENDPROC(__put_user_##bytes); \ | ||
75 | .pushsection __ex_table,"a"; \ | ||
76 | .word 1b, put_user_fault; \ | ||
77 | .popsection | ||
78 | |||
79 | __put_user_N(1, sb) | ||
80 | __put_user_N(2, sh) | ||
81 | __put_user_N(4, sw) | ||
82 | |||
83 | /* | ||
84 | * __put_user_8 takes a value in r0/r1 and a pointer in r2, | ||
85 | * and returns 0 in r0 on success or -EFAULT on failure. | ||
86 | */ | ||
87 | STD_ENTRY(__put_user_8) | ||
88 | 1: { sw r2, r0; addi r2, r2, 4 } | ||
89 | 2: { sw r2, r1; move r0, zero } | ||
90 | jrp lr | ||
91 | STD_ENDPROC(__put_user_8) | ||
92 | .pushsection __ex_table,"a" | ||
93 | .word 1b, put_user_fault | ||
94 | .word 2b, put_user_fault | ||
95 | .popsection | ||
96 | |||
97 | |||
98 | /* | 22 | /* |
99 | * strnlen_user_asm takes the pointer in r0, and the length bound in r1. | 23 | * strnlen_user_asm takes the pointer in r0, and the length bound in r1. |
100 | * It returns the length, including the terminating NUL, or zero on exception. | 24 | * It returns the length, including the terminating NUL, or zero on exception. |
101 | * If length is greater than the bound, returns one plus the bound. | 25 | * If length is greater than the bound, returns one plus the bound. |
102 | */ | 26 | */ |
103 | STD_ENTRY(strnlen_user_asm) | 27 | STD_ENTRY(strnlen_user_asm) |
104 | { bz r1, 2f; addi r3, r0, -1 } /* bias down to include NUL */ | 28 | { bz r1, 2f; addi r3, r0, -1 } /* bias down to include NUL */ |
105 | 1: { lb_u r4, r0; addi r1, r1, -1 } | 29 | 1: { lb_u r4, r0; addi r1, r1, -1 } |
106 | bz r4, 2f | 30 | bz r4, 2f |
107 | { bnzt r1, 1b; addi r0, r0, 1 } | 31 | { bnzt r1, 1b; addi r0, r0, 1 } |
108 | 2: { sub r0, r0, r3; jrp lr } | 32 | 2: { sub r0, r0, r3; jrp lr } |
109 | STD_ENDPROC(strnlen_user_asm) | 33 | STD_ENDPROC(strnlen_user_asm) |
110 | .pushsection .fixup,"ax" | 34 | .pushsection .fixup,"ax" |
111 | strnlen_user_fault: | 35 | strnlen_user_fault: |
112 | { move r0, zero; jrp lr } | 36 | { move r0, zero; jrp lr } |
113 | ENDPROC(strnlen_user_fault) | 37 | ENDPROC(strnlen_user_fault) |
114 | .section __ex_table,"a" | 38 | .section __ex_table,"a" |
115 | .word 1b, strnlen_user_fault | 39 | .word 1b, strnlen_user_fault |
116 | .popsection | 40 | .popsection |
117 | 41 | ||
118 | /* | 42 | /* |
119 | * strncpy_from_user_asm takes the kernel target pointer in r0, | 43 | * strncpy_from_user_asm takes the kernel target pointer in r0, |
120 | * the userspace source pointer in r1, and the length bound (including | 44 | * the userspace source pointer in r1, and the length bound (including |
121 | * the trailing NUL) in r2. On success, it returns the string length | 45 | * the trailing NUL) in r2. On success, it returns the string length |
122 | * (not including the trailing NUL), or -EFAULT on failure. | 46 | * (not including the trailing NUL), or -EFAULT on failure. |
123 | */ | 47 | */ |
124 | STD_ENTRY(strncpy_from_user_asm) | 48 | STD_ENTRY(strncpy_from_user_asm) |
125 | { bz r2, 2f; move r3, r0 } | 49 | { bz r2, 2f; move r3, r0 } |
126 | 1: { lb_u r4, r1; addi r1, r1, 1; addi r2, r2, -1 } | 50 | 1: { lb_u r4, r1; addi r1, r1, 1; addi r2, r2, -1 } |
127 | { sb r0, r4; addi r0, r0, 1 } | 51 | { sb r0, r4; addi r0, r0, 1 } |
128 | bz r2, 2f | 52 | bz r2, 2f |
129 | bnzt r4, 1b | 53 | bnzt r4, 1b |
130 | addi r0, r0, -1 /* don't count the trailing NUL */ | 54 | addi r0, r0, -1 /* don't count the trailing NUL */ |
131 | 2: { sub r0, r0, r3; jrp lr } | 55 | 2: { sub r0, r0, r3; jrp lr } |
132 | STD_ENDPROC(strncpy_from_user_asm) | 56 | STD_ENDPROC(strncpy_from_user_asm) |
133 | .pushsection .fixup,"ax" | 57 | .pushsection .fixup,"ax" |
134 | strncpy_from_user_fault: | 58 | strncpy_from_user_fault: |
135 | { movei r0, -EFAULT; jrp lr } | 59 | { movei r0, -EFAULT; jrp lr } |
136 | ENDPROC(strncpy_from_user_fault) | 60 | ENDPROC(strncpy_from_user_fault) |
137 | .section __ex_table,"a" | 61 | .section __ex_table,"a" |
138 | .word 1b, strncpy_from_user_fault | 62 | .word 1b, strncpy_from_user_fault |
139 | .popsection | 63 | .popsection |
140 | 64 | ||
141 | /* | 65 | /* |
142 | * clear_user_asm takes the user target address in r0 and the | 66 | * clear_user_asm takes the user target address in r0 and the |
143 | * number of bytes to zero in r1. | 67 | * number of bytes to zero in r1. |
144 | * It returns the number of uncopiable bytes (hopefully zero) in r0. | 68 | * It returns the number of uncopiable bytes (hopefully zero) in r0. |
145 | * Note that we don't use a separate .fixup section here since we fall | 69 | * Note that we don't use a separate .fixup section here since we fall |
146 | * through into the "fixup" code as the last straight-line bundle anyway. | 70 | * through into the "fixup" code as the last straight-line bundle anyway. |
147 | */ | 71 | */ |
148 | STD_ENTRY(clear_user_asm) | 72 | STD_ENTRY(clear_user_asm) |
149 | { bz r1, 2f; or r2, r0, r1 } | 73 | { bz r1, 2f; or r2, r0, r1 } |
150 | andi r2, r2, 3 | 74 | andi r2, r2, 3 |
151 | bzt r2, .Lclear_aligned_user_asm | 75 | bzt r2, .Lclear_aligned_user_asm |
152 | 1: { sb r0, zero; addi r0, r0, 1; addi r1, r1, -1 } | 76 | 1: { sb r0, zero; addi r0, r0, 1; addi r1, r1, -1 } |
153 | bnzt r1, 1b | 77 | bnzt r1, 1b |
154 | 2: { move r0, r1; jrp lr } | 78 | 2: { move r0, r1; jrp lr } |
155 | .pushsection __ex_table,"a" | 79 | .pushsection __ex_table,"a" |
156 | .word 1b, 2b | 80 | .word 1b, 2b |
157 | .popsection | 81 | .popsection |
158 | 82 | ||
159 | .Lclear_aligned_user_asm: | 83 | .Lclear_aligned_user_asm: |
160 | 1: { sw r0, zero; addi r0, r0, 4; addi r1, r1, -4 } | 84 | 1: { sw r0, zero; addi r0, r0, 4; addi r1, r1, -4 } |
161 | bnzt r1, 1b | 85 | bnzt r1, 1b |
162 | 2: { move r0, r1; jrp lr } | 86 | 2: { move r0, r1; jrp lr } |
163 | STD_ENDPROC(clear_user_asm) | 87 | STD_ENDPROC(clear_user_asm) |
164 | .pushsection __ex_table,"a" | 88 | .pushsection __ex_table,"a" |
165 | .word 1b, 2b | 89 | .word 1b, 2b |
166 | .popsection | 90 | .popsection |
167 | 91 | ||
168 | /* | 92 | /* |
169 | * flush_user_asm takes the user target address in r0 and the | 93 | * flush_user_asm takes the user target address in r0 and the |
170 | * number of bytes to flush in r1. | 94 | * number of bytes to flush in r1. |
171 | * It returns the number of unflushable bytes (hopefully zero) in r0. | 95 | * It returns the number of unflushable bytes (hopefully zero) in r0. |
172 | */ | 96 | */ |
173 | STD_ENTRY(flush_user_asm) | 97 | STD_ENTRY(flush_user_asm) |
174 | bz r1, 2f | 98 | bz r1, 2f |
175 | { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } | 99 | { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } |
176 | { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } | 100 | { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } |
177 | { and r0, r0, r2; and r1, r1, r2 } | 101 | { and r0, r0, r2; and r1, r1, r2 } |
178 | { sub r1, r1, r0 } | 102 | { sub r1, r1, r0 } |
179 | 1: { flush r0; addi r1, r1, -CHIP_FLUSH_STRIDE() } | 103 | 1: { flush r0; addi r1, r1, -CHIP_FLUSH_STRIDE() } |
180 | { addi r0, r0, CHIP_FLUSH_STRIDE(); bnzt r1, 1b } | 104 | { addi r0, r0, CHIP_FLUSH_STRIDE(); bnzt r1, 1b } |
181 | 2: { move r0, r1; jrp lr } | 105 | 2: { move r0, r1; jrp lr } |
182 | STD_ENDPROC(flush_user_asm) | 106 | STD_ENDPROC(flush_user_asm) |
183 | .pushsection __ex_table,"a" | 107 | .pushsection __ex_table,"a" |
184 | .word 1b, 2b | 108 | .word 1b, 2b |
185 | .popsection | 109 | .popsection |
186 | 110 | ||
187 | /* | 111 | /* |
188 | * inv_user_asm takes the user target address in r0 and the | 112 | * inv_user_asm takes the user target address in r0 and the |
189 | * number of bytes to invalidate in r1. | 113 | * number of bytes to invalidate in r1. |
190 | * It returns the number of not inv'able bytes (hopefully zero) in r0. | 114 | * It returns the number of not inv'able bytes (hopefully zero) in r0. |
191 | */ | 115 | */ |
192 | STD_ENTRY(inv_user_asm) | 116 | STD_ENTRY(inv_user_asm) |
193 | bz r1, 2f | 117 | bz r1, 2f |
194 | { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } | 118 | { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } |
195 | { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } | 119 | { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } |
196 | { and r0, r0, r2; and r1, r1, r2 } | 120 | { and r0, r0, r2; and r1, r1, r2 } |
197 | { sub r1, r1, r0 } | 121 | { sub r1, r1, r0 } |
198 | 1: { inv r0; addi r1, r1, -CHIP_INV_STRIDE() } | 122 | 1: { inv r0; addi r1, r1, -CHIP_INV_STRIDE() } |
199 | { addi r0, r0, CHIP_INV_STRIDE(); bnzt r1, 1b } | 123 | { addi r0, r0, CHIP_INV_STRIDE(); bnzt r1, 1b } |
200 | 2: { move r0, r1; jrp lr } | 124 | 2: { move r0, r1; jrp lr } |
201 | STD_ENDPROC(inv_user_asm) | 125 | STD_ENDPROC(inv_user_asm) |
202 | .pushsection __ex_table,"a" | 126 | .pushsection __ex_table,"a" |
203 | .word 1b, 2b | 127 | .word 1b, 2b |
204 | .popsection | 128 | .popsection |
205 | 129 | ||
206 | /* | 130 | /* |
207 | * finv_user_asm takes the user target address in r0 and the | 131 | * finv_user_asm takes the user target address in r0 and the |
208 | * number of bytes to flush-invalidate in r1. | 132 | * number of bytes to flush-invalidate in r1. |
209 | * It returns the number of not finv'able bytes (hopefully zero) in r0. | 133 | * It returns the number of not finv'able bytes (hopefully zero) in r0. |
210 | */ | 134 | */ |
211 | STD_ENTRY(finv_user_asm) | 135 | STD_ENTRY(finv_user_asm) |
212 | bz r1, 2f | 136 | bz r1, 2f |
213 | { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } | 137 | { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } |
214 | { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } | 138 | { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } |
215 | { and r0, r0, r2; and r1, r1, r2 } | 139 | { and r0, r0, r2; and r1, r1, r2 } |
216 | { sub r1, r1, r0 } | 140 | { sub r1, r1, r0 } |
217 | 1: { finv r0; addi r1, r1, -CHIP_FINV_STRIDE() } | 141 | 1: { finv r0; addi r1, r1, -CHIP_FINV_STRIDE() } |
218 | { addi r0, r0, CHIP_FINV_STRIDE(); bnzt r1, 1b } | 142 | { addi r0, r0, CHIP_FINV_STRIDE(); bnzt r1, 1b } |
219 | 2: { move r0, r1; jrp lr } | 143 | 2: { move r0, r1; jrp lr } |
220 | STD_ENDPROC(finv_user_asm) | 144 | STD_ENDPROC(finv_user_asm) |
221 | .pushsection __ex_table,"a" | 145 | .pushsection __ex_table,"a" |
222 | .word 1b, 2b | 146 | .word 1b, 2b |
223 | .popsection | 147 | .popsection |
224 | 148 |
arch/tile/lib/usercopy_64.S
1 | /* | 1 | /* |
2 | * Copyright 2011 Tilera Corporation. All Rights Reserved. | 2 | * Copyright 2011 Tilera Corporation. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU General Public License | 5 | * modify it under the terms of the GNU General Public License |
6 | * as published by the Free Software Foundation, version 2. | 6 | * as published by the Free Software Foundation, version 2. |
7 | * | 7 | * |
8 | * This program is distributed in the hope that it will be useful, but | 8 | * This program is distributed in the hope that it will be useful, but |
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 9 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | 10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or |
11 | * NON INFRINGEMENT. See the GNU General Public License for | 11 | * NON INFRINGEMENT. See the GNU General Public License for |
12 | * more details. | 12 | * more details. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/linkage.h> | 15 | #include <linux/linkage.h> |
16 | #include <asm/errno.h> | 16 | #include <asm/errno.h> |
17 | #include <asm/cache.h> | 17 | #include <asm/cache.h> |
18 | #include <arch/chip.h> | 18 | #include <arch/chip.h> |
19 | 19 | ||
20 | /* Access user memory, but use MMU to avoid propagating kernel exceptions. */ | 20 | /* Access user memory, but use MMU to avoid propagating kernel exceptions. */ |
21 | 21 | ||
22 | .pushsection .fixup,"ax" | ||
23 | |||
24 | get_user_fault: | ||
25 | { movei r1, -EFAULT; move r0, zero } | ||
26 | jrp lr | ||
27 | ENDPROC(get_user_fault) | ||
28 | |||
29 | put_user_fault: | ||
30 | { movei r0, -EFAULT; jrp lr } | ||
31 | ENDPROC(put_user_fault) | ||
32 | |||
33 | .popsection | ||
34 | |||
35 | /* | ||
36 | * __get_user_N functions take a pointer in r0, and return 0 in r1 | ||
37 | * on success, with the value in r0; or else -EFAULT in r1. | ||
38 | */ | ||
39 | #define __get_user_N(bytes, LOAD) \ | ||
40 | STD_ENTRY(__get_user_##bytes); \ | ||
41 | 1: { LOAD r0, r0; move r1, zero }; \ | ||
42 | jrp lr; \ | ||
43 | STD_ENDPROC(__get_user_##bytes); \ | ||
44 | .pushsection __ex_table,"a"; \ | ||
45 | .quad 1b, get_user_fault; \ | ||
46 | .popsection | ||
47 | |||
48 | __get_user_N(1, ld1u) | ||
49 | __get_user_N(2, ld2u) | ||
50 | __get_user_N(4, ld4u) | ||
51 | __get_user_N(8, ld) | ||
52 | |||
53 | /* | ||
54 | * __put_user_N functions take a value in r0 and a pointer in r1, | ||
55 | * and return 0 in r0 on success or -EFAULT on failure. | ||
56 | */ | ||
57 | #define __put_user_N(bytes, STORE) \ | ||
58 | STD_ENTRY(__put_user_##bytes); \ | ||
59 | 1: { STORE r1, r0; move r0, zero }; \ | ||
60 | jrp lr; \ | ||
61 | STD_ENDPROC(__put_user_##bytes); \ | ||
62 | .pushsection __ex_table,"a"; \ | ||
63 | .quad 1b, put_user_fault; \ | ||
64 | .popsection | ||
65 | |||
66 | __put_user_N(1, st1) | ||
67 | __put_user_N(2, st2) | ||
68 | __put_user_N(4, st4) | ||
69 | __put_user_N(8, st) | ||
70 | |||
71 | /* | 22 | /* |
72 | * strnlen_user_asm takes the pointer in r0, and the length bound in r1. | 23 | * strnlen_user_asm takes the pointer in r0, and the length bound in r1. |
73 | * It returns the length, including the terminating NUL, or zero on exception. | 24 | * It returns the length, including the terminating NUL, or zero on exception. |
74 | * If length is greater than the bound, returns one plus the bound. | 25 | * If length is greater than the bound, returns one plus the bound. |
75 | */ | 26 | */ |
76 | STD_ENTRY(strnlen_user_asm) | 27 | STD_ENTRY(strnlen_user_asm) |
77 | { beqz r1, 2f; addi r3, r0, -1 } /* bias down to include NUL */ | 28 | { beqz r1, 2f; addi r3, r0, -1 } /* bias down to include NUL */ |
78 | 1: { ld1u r4, r0; addi r1, r1, -1 } | 29 | 1: { ld1u r4, r0; addi r1, r1, -1 } |
79 | beqz r4, 2f | 30 | beqz r4, 2f |
80 | { bnezt r1, 1b; addi r0, r0, 1 } | 31 | { bnezt r1, 1b; addi r0, r0, 1 } |
81 | 2: { sub r0, r0, r3; jrp lr } | 32 | 2: { sub r0, r0, r3; jrp lr } |
82 | STD_ENDPROC(strnlen_user_asm) | 33 | STD_ENDPROC(strnlen_user_asm) |
83 | .pushsection .fixup,"ax" | 34 | .pushsection .fixup,"ax" |
84 | strnlen_user_fault: | 35 | strnlen_user_fault: |
85 | { move r0, zero; jrp lr } | 36 | { move r0, zero; jrp lr } |
86 | ENDPROC(strnlen_user_fault) | 37 | ENDPROC(strnlen_user_fault) |
87 | .section __ex_table,"a" | 38 | .section __ex_table,"a" |
88 | .quad 1b, strnlen_user_fault | 39 | .quad 1b, strnlen_user_fault |
89 | .popsection | 40 | .popsection |
90 | 41 | ||
91 | /* | 42 | /* |
92 | * strncpy_from_user_asm takes the kernel target pointer in r0, | 43 | * strncpy_from_user_asm takes the kernel target pointer in r0, |
93 | * the userspace source pointer in r1, and the length bound (including | 44 | * the userspace source pointer in r1, and the length bound (including |
94 | * the trailing NUL) in r2. On success, it returns the string length | 45 | * the trailing NUL) in r2. On success, it returns the string length |
95 | * (not including the trailing NUL), or -EFAULT on failure. | 46 | * (not including the trailing NUL), or -EFAULT on failure. |
96 | */ | 47 | */ |
97 | STD_ENTRY(strncpy_from_user_asm) | 48 | STD_ENTRY(strncpy_from_user_asm) |
98 | { beqz r2, 2f; move r3, r0 } | 49 | { beqz r2, 2f; move r3, r0 } |
99 | 1: { ld1u r4, r1; addi r1, r1, 1; addi r2, r2, -1 } | 50 | 1: { ld1u r4, r1; addi r1, r1, 1; addi r2, r2, -1 } |
100 | { st1 r0, r4; addi r0, r0, 1 } | 51 | { st1 r0, r4; addi r0, r0, 1 } |
101 | beqz r2, 2f | 52 | beqz r2, 2f |
102 | bnezt r4, 1b | 53 | bnezt r4, 1b |
103 | addi r0, r0, -1 /* don't count the trailing NUL */ | 54 | addi r0, r0, -1 /* don't count the trailing NUL */ |
104 | 2: { sub r0, r0, r3; jrp lr } | 55 | 2: { sub r0, r0, r3; jrp lr } |
105 | STD_ENDPROC(strncpy_from_user_asm) | 56 | STD_ENDPROC(strncpy_from_user_asm) |
106 | .pushsection .fixup,"ax" | 57 | .pushsection .fixup,"ax" |
107 | strncpy_from_user_fault: | 58 | strncpy_from_user_fault: |
108 | { movei r0, -EFAULT; jrp lr } | 59 | { movei r0, -EFAULT; jrp lr } |
109 | ENDPROC(strncpy_from_user_fault) | 60 | ENDPROC(strncpy_from_user_fault) |
110 | .section __ex_table,"a" | 61 | .section __ex_table,"a" |
111 | .quad 1b, strncpy_from_user_fault | 62 | .quad 1b, strncpy_from_user_fault |
112 | .popsection | 63 | .popsection |
113 | 64 | ||
114 | /* | 65 | /* |
115 | * clear_user_asm takes the user target address in r0 and the | 66 | * clear_user_asm takes the user target address in r0 and the |
116 | * number of bytes to zero in r1. | 67 | * number of bytes to zero in r1. |
117 | * It returns the number of uncopiable bytes (hopefully zero) in r0. | 68 | * It returns the number of uncopiable bytes (hopefully zero) in r0. |
118 | * Note that we don't use a separate .fixup section here since we fall | 69 | * Note that we don't use a separate .fixup section here since we fall |
119 | * through into the "fixup" code as the last straight-line bundle anyway. | 70 | * through into the "fixup" code as the last straight-line bundle anyway. |
120 | */ | 71 | */ |
121 | STD_ENTRY(clear_user_asm) | 72 | STD_ENTRY(clear_user_asm) |
122 | { beqz r1, 2f; or r2, r0, r1 } | 73 | { beqz r1, 2f; or r2, r0, r1 } |
123 | andi r2, r2, 7 | 74 | andi r2, r2, 7 |
124 | beqzt r2, .Lclear_aligned_user_asm | 75 | beqzt r2, .Lclear_aligned_user_asm |
125 | 1: { st1 r0, zero; addi r0, r0, 1; addi r1, r1, -1 } | 76 | 1: { st1 r0, zero; addi r0, r0, 1; addi r1, r1, -1 } |
126 | bnezt r1, 1b | 77 | bnezt r1, 1b |
127 | 2: { move r0, r1; jrp lr } | 78 | 2: { move r0, r1; jrp lr } |
128 | .pushsection __ex_table,"a" | 79 | .pushsection __ex_table,"a" |
129 | .quad 1b, 2b | 80 | .quad 1b, 2b |
130 | .popsection | 81 | .popsection |
131 | 82 | ||
132 | .Lclear_aligned_user_asm: | 83 | .Lclear_aligned_user_asm: |
133 | 1: { st r0, zero; addi r0, r0, 8; addi r1, r1, -8 } | 84 | 1: { st r0, zero; addi r0, r0, 8; addi r1, r1, -8 } |
134 | bnezt r1, 1b | 85 | bnezt r1, 1b |
135 | 2: { move r0, r1; jrp lr } | 86 | 2: { move r0, r1; jrp lr } |
136 | STD_ENDPROC(clear_user_asm) | 87 | STD_ENDPROC(clear_user_asm) |
137 | .pushsection __ex_table,"a" | 88 | .pushsection __ex_table,"a" |
138 | .quad 1b, 2b | 89 | .quad 1b, 2b |
139 | .popsection | 90 | .popsection |
140 | 91 | ||
141 | /* | 92 | /* |
142 | * flush_user_asm takes the user target address in r0 and the | 93 | * flush_user_asm takes the user target address in r0 and the |
143 | * number of bytes to flush in r1. | 94 | * number of bytes to flush in r1. |
144 | * It returns the number of unflushable bytes (hopefully zero) in r0. | 95 | * It returns the number of unflushable bytes (hopefully zero) in r0. |
145 | */ | 96 | */ |
146 | STD_ENTRY(flush_user_asm) | 97 | STD_ENTRY(flush_user_asm) |
147 | beqz r1, 2f | 98 | beqz r1, 2f |
148 | { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } | 99 | { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } |
149 | { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } | 100 | { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } |
150 | { and r0, r0, r2; and r1, r1, r2 } | 101 | { and r0, r0, r2; and r1, r1, r2 } |
151 | { sub r1, r1, r0 } | 102 | { sub r1, r1, r0 } |
152 | 1: { flush r0; addi r1, r1, -CHIP_FLUSH_STRIDE() } | 103 | 1: { flush r0; addi r1, r1, -CHIP_FLUSH_STRIDE() } |
153 | { addi r0, r0, CHIP_FLUSH_STRIDE(); bnezt r1, 1b } | 104 | { addi r0, r0, CHIP_FLUSH_STRIDE(); bnezt r1, 1b } |
154 | 2: { move r0, r1; jrp lr } | 105 | 2: { move r0, r1; jrp lr } |
155 | STD_ENDPROC(flush_user_asm) | 106 | STD_ENDPROC(flush_user_asm) |
156 | .pushsection __ex_table,"a" | 107 | .pushsection __ex_table,"a" |
157 | .quad 1b, 2b | 108 | .quad 1b, 2b |
158 | .popsection | 109 | .popsection |
159 | 110 | ||
160 | /* | 111 | /* |
161 | * inv_user_asm takes the user target address in r0 and the | 112 | * inv_user_asm takes the user target address in r0 and the |
162 | * number of bytes to invalidate in r1. | 113 | * number of bytes to invalidate in r1. |
163 | * It returns the number of not inv'able bytes (hopefully zero) in r0. | 114 | * It returns the number of not inv'able bytes (hopefully zero) in r0. |
164 | */ | 115 | */ |
165 | STD_ENTRY(inv_user_asm) | 116 | STD_ENTRY(inv_user_asm) |
166 | beqz r1, 2f | 117 | beqz r1, 2f |
167 | { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } | 118 | { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } |
168 | { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } | 119 | { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } |
169 | { and r0, r0, r2; and r1, r1, r2 } | 120 | { and r0, r0, r2; and r1, r1, r2 } |
170 | { sub r1, r1, r0 } | 121 | { sub r1, r1, r0 } |
171 | 1: { inv r0; addi r1, r1, -CHIP_INV_STRIDE() } | 122 | 1: { inv r0; addi r1, r1, -CHIP_INV_STRIDE() } |
172 | { addi r0, r0, CHIP_INV_STRIDE(); bnezt r1, 1b } | 123 | { addi r0, r0, CHIP_INV_STRIDE(); bnezt r1, 1b } |
173 | 2: { move r0, r1; jrp lr } | 124 | 2: { move r0, r1; jrp lr } |
174 | STD_ENDPROC(inv_user_asm) | 125 | STD_ENDPROC(inv_user_asm) |
175 | .pushsection __ex_table,"a" | 126 | .pushsection __ex_table,"a" |
176 | .quad 1b, 2b | 127 | .quad 1b, 2b |
177 | .popsection | 128 | .popsection |
178 | 129 | ||
179 | /* | 130 | /* |
180 | * finv_user_asm takes the user target address in r0 and the | 131 | * finv_user_asm takes the user target address in r0 and the |
181 | * number of bytes to flush-invalidate in r1. | 132 | * number of bytes to flush-invalidate in r1. |
182 | * It returns the number of not finv'able bytes (hopefully zero) in r0. | 133 | * It returns the number of not finv'able bytes (hopefully zero) in r0. |
183 | */ | 134 | */ |
184 | STD_ENTRY(finv_user_asm) | 135 | STD_ENTRY(finv_user_asm) |
185 | beqz r1, 2f | 136 | beqz r1, 2f |
186 | { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } | 137 | { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } |
187 | { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } | 138 | { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } |
188 | { and r0, r0, r2; and r1, r1, r2 } | 139 | { and r0, r0, r2; and r1, r1, r2 } |
189 | { sub r1, r1, r0 } | 140 | { sub r1, r1, r0 } |
190 | 1: { finv r0; addi r1, r1, -CHIP_FINV_STRIDE() } | 141 | 1: { finv r0; addi r1, r1, -CHIP_FINV_STRIDE() } |
191 | { addi r0, r0, CHIP_FINV_STRIDE(); bnezt r1, 1b } | 142 | { addi r0, r0, CHIP_FINV_STRIDE(); bnezt r1, 1b } |
192 | 2: { move r0, r1; jrp lr } | 143 | 2: { move r0, r1; jrp lr } |
193 | STD_ENDPROC(finv_user_asm) | 144 | STD_ENDPROC(finv_user_asm) |
194 | .pushsection __ex_table,"a" | 145 | .pushsection __ex_table,"a" |
195 | .quad 1b, 2b | 146 | .quad 1b, 2b |
196 | .popsection | 147 | .popsection |
197 | 148 |