diff options
Diffstat (limited to 'arch/tile/lib')
-rw-r--r-- | arch/tile/lib/atomic_32.c | 47 | ||||
-rw-r--r-- | arch/tile/lib/exports.c | 8 | ||||
-rw-r--r-- | arch/tile/lib/memchr_64.c | 8 | ||||
-rw-r--r-- | arch/tile/lib/memcpy_64.c | 23 | ||||
-rw-r--r-- | arch/tile/lib/memcpy_tile64.c | 8 | ||||
-rw-r--r-- | arch/tile/lib/strchr_64.c | 15 | ||||
-rw-r--r-- | arch/tile/lib/string-endian.h | 33 | ||||
-rw-r--r-- | arch/tile/lib/strlen_64.c | 11 | ||||
-rw-r--r-- | arch/tile/lib/usercopy_32.S | 76 | ||||
-rw-r--r-- | arch/tile/lib/usercopy_64.S | 49 |
10 files changed, 71 insertions, 207 deletions
diff --git a/arch/tile/lib/atomic_32.c b/arch/tile/lib/atomic_32.c index 771b251b409d..f5cada70c3c8 100644 --- a/arch/tile/lib/atomic_32.c +++ b/arch/tile/lib/atomic_32.c | |||
@@ -18,7 +18,6 @@ | |||
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> */ |
@@ -50,7 +49,7 @@ 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() |
@@ -191,47 +190,6 @@ u64 _atomic64_cmpxchg(atomic64_t *v, u64 o, u64 n) | |||
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 |
@@ -323,7 +281,4 @@ void __init __init_atomic_per_cpu(void) | |||
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 | } |
diff --git a/arch/tile/lib/exports.c b/arch/tile/lib/exports.c index 2a81d32de0da..dd5f0a33fdaf 100644 --- a/arch/tile/lib/exports.c +++ b/arch/tile/lib/exports.c | |||
@@ -18,14 +18,6 @@ | |||
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); |
diff --git a/arch/tile/lib/memchr_64.c b/arch/tile/lib/memchr_64.c index 84fdc8d8e735..6f867dbf7c56 100644 --- a/arch/tile/lib/memchr_64.c +++ b/arch/tile/lib/memchr_64.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include "string-endian.h" | ||
18 | 19 | ||
19 | void *memchr(const void *s, int c, size_t n) | 20 | void *memchr(const void *s, int c, size_t n) |
20 | { | 21 | { |
@@ -39,11 +40,8 @@ void *memchr(const void *s, int c, size_t n) | |||
39 | 40 | ||
40 | /* Read the first word, but munge it so that bytes before the array | 41 | /* Read the first word, but munge it so that bytes before the array |
41 | * will not match goal. | 42 | * will not match goal. |
42 | * | ||
43 | * Note that this shift count expression works because we know | ||
44 | * shift counts are taken mod 64. | ||
45 | */ | 43 | */ |
46 | before_mask = (1ULL << (s_int << 3)) - 1; | 44 | before_mask = MASK(s_int); |
47 | v = (*p | before_mask) ^ (goal & before_mask); | 45 | v = (*p | before_mask) ^ (goal & before_mask); |
48 | 46 | ||
49 | /* Compute the address of the last byte. */ | 47 | /* Compute the address of the last byte. */ |
@@ -65,7 +63,7 @@ void *memchr(const void *s, int c, size_t n) | |||
65 | /* We found a match, but it might be in a byte past the end | 63 | /* We found a match, but it might be in a byte past the end |
66 | * of the array. | 64 | * of the array. |
67 | */ | 65 | */ |
68 | ret = ((char *)p) + (__insn_ctz(bits) >> 3); | 66 | ret = ((char *)p) + (CFZ(bits) >> 3); |
69 | return (ret <= last_byte_ptr) ? ret : NULL; | 67 | return (ret <= last_byte_ptr) ? ret : NULL; |
70 | } | 68 | } |
71 | EXPORT_SYMBOL(memchr); | 69 | EXPORT_SYMBOL(memchr); |
diff --git a/arch/tile/lib/memcpy_64.c b/arch/tile/lib/memcpy_64.c index 3fab9a6a2bbe..c79b8e7c6828 100644 --- a/arch/tile/lib/memcpy_64.c +++ b/arch/tile/lib/memcpy_64.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #define __memcpy memcpy | ||
19 | /* EXPORT_SYMBOL() is in arch/tile/lib/exports.c since this should be asm. */ | 18 | /* EXPORT_SYMBOL() is in arch/tile/lib/exports.c since this should be asm. */ |
20 | 19 | ||
21 | /* Must be 8 bytes in size. */ | 20 | /* Must be 8 bytes in size. */ |
@@ -188,6 +187,7 @@ int USERCOPY_FUNC(void *__restrict dstv, const void *__restrict srcv, size_t n) | |||
188 | 187 | ||
189 | /* n != 0 if we get here. Write out any trailing bytes. */ | 188 | /* n != 0 if we get here. Write out any trailing bytes. */ |
190 | dst1 = (char *)dst8; | 189 | dst1 = (char *)dst8; |
190 | #ifndef __BIG_ENDIAN__ | ||
191 | if (n & 4) { | 191 | if (n & 4) { |
192 | ST4((uint32_t *)dst1, final); | 192 | ST4((uint32_t *)dst1, final); |
193 | dst1 += 4; | 193 | dst1 += 4; |
@@ -202,11 +202,30 @@ int USERCOPY_FUNC(void *__restrict dstv, const void *__restrict srcv, size_t n) | |||
202 | } | 202 | } |
203 | if (n) | 203 | if (n) |
204 | ST1((uint8_t *)dst1, final); | 204 | ST1((uint8_t *)dst1, final); |
205 | #else | ||
206 | if (n & 4) { | ||
207 | ST4((uint32_t *)dst1, final >> 32); | ||
208 | dst1 += 4; | ||
209 | } | ||
210 | else | ||
211 | { | ||
212 | final >>= 32; | ||
213 | } | ||
214 | if (n & 2) { | ||
215 | ST2((uint16_t *)dst1, final >> 16); | ||
216 | dst1 += 2; | ||
217 | } | ||
218 | else | ||
219 | { | ||
220 | final >>= 16; | ||
221 | } | ||
222 | if (n & 1) | ||
223 | ST1((uint8_t *)dst1, final >> 8); | ||
224 | #endif | ||
205 | 225 | ||
206 | return RETVAL; | 226 | return RETVAL; |
207 | } | 227 | } |
208 | 228 | ||
209 | |||
210 | #ifdef USERCOPY_FUNC | 229 | #ifdef USERCOPY_FUNC |
211 | #undef ST1 | 230 | #undef ST1 |
212 | #undef ST2 | 231 | #undef ST2 |
diff --git a/arch/tile/lib/memcpy_tile64.c b/arch/tile/lib/memcpy_tile64.c index b2fe15e01075..3bc4b4e40d93 100644 --- a/arch/tile/lib/memcpy_tile64.c +++ b/arch/tile/lib/memcpy_tile64.c | |||
@@ -160,7 +160,7 @@ retry_source: | |||
160 | break; | 160 | break; |
161 | if (get_remote_cache_cpu(src_pte) == smp_processor_id()) | 161 | if (get_remote_cache_cpu(src_pte) == smp_processor_id()) |
162 | break; | 162 | break; |
163 | src_page = pfn_to_page(hv_pte_get_pfn(src_pte)); | 163 | src_page = pfn_to_page(pte_pfn(src_pte)); |
164 | get_page(src_page); | 164 | get_page(src_page); |
165 | if (pte_val(src_pte) != pte_val(*src_ptep)) { | 165 | if (pte_val(src_pte) != pte_val(*src_ptep)) { |
166 | put_page(src_page); | 166 | put_page(src_page); |
@@ -168,7 +168,7 @@ retry_source: | |||
168 | } | 168 | } |
169 | if (pte_huge(src_pte)) { | 169 | if (pte_huge(src_pte)) { |
170 | /* Adjust the PTE to correspond to a small page */ | 170 | /* Adjust the PTE to correspond to a small page */ |
171 | int pfn = hv_pte_get_pfn(src_pte); | 171 | int pfn = pte_pfn(src_pte); |
172 | pfn += (((unsigned long)source & (HPAGE_SIZE-1)) | 172 | pfn += (((unsigned long)source & (HPAGE_SIZE-1)) |
173 | >> PAGE_SHIFT); | 173 | >> PAGE_SHIFT); |
174 | src_pte = pfn_pte(pfn, src_pte); | 174 | src_pte = pfn_pte(pfn, src_pte); |
@@ -188,7 +188,7 @@ retry_dest: | |||
188 | put_page(src_page); | 188 | put_page(src_page); |
189 | break; | 189 | break; |
190 | } | 190 | } |
191 | dst_page = pfn_to_page(hv_pte_get_pfn(dst_pte)); | 191 | dst_page = pfn_to_page(pte_pfn(dst_pte)); |
192 | if (dst_page == src_page) { | 192 | if (dst_page == src_page) { |
193 | /* | 193 | /* |
194 | * Source and dest are on the same page; this | 194 | * Source and dest are on the same page; this |
@@ -206,7 +206,7 @@ retry_dest: | |||
206 | } | 206 | } |
207 | if (pte_huge(dst_pte)) { | 207 | if (pte_huge(dst_pte)) { |
208 | /* Adjust the PTE to correspond to a small page */ | 208 | /* Adjust the PTE to correspond to a small page */ |
209 | int pfn = hv_pte_get_pfn(dst_pte); | 209 | int pfn = pte_pfn(dst_pte); |
210 | pfn += (((unsigned long)dest & (HPAGE_SIZE-1)) | 210 | pfn += (((unsigned long)dest & (HPAGE_SIZE-1)) |
211 | >> PAGE_SHIFT); | 211 | >> PAGE_SHIFT); |
212 | dst_pte = pfn_pte(pfn, dst_pte); | 212 | dst_pte = pfn_pte(pfn, dst_pte); |
diff --git a/arch/tile/lib/strchr_64.c b/arch/tile/lib/strchr_64.c index 617a9273aaa8..f39f9dc422b0 100644 --- a/arch/tile/lib/strchr_64.c +++ b/arch/tile/lib/strchr_64.c | |||
@@ -15,8 +15,7 @@ | |||
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | 18 | #include "string-endian.h" | |
19 | #undef strchr | ||
20 | 19 | ||
21 | char *strchr(const char *s, int c) | 20 | char *strchr(const char *s, int c) |
22 | { | 21 | { |
@@ -33,13 +32,9 @@ char *strchr(const char *s, int c) | |||
33 | * match neither zero nor goal (we make sure the high bit of each | 32 | * match neither zero nor goal (we make sure the high bit of each |
34 | * byte is 1, and the low 7 bits are all the opposite of the goal | 33 | * byte is 1, and the low 7 bits are all the opposite of the goal |
35 | * byte). | 34 | * byte). |
36 | * | ||
37 | * Note that this shift count expression works because we know shift | ||
38 | * counts are taken mod 64. | ||
39 | */ | 35 | */ |
40 | const uint64_t before_mask = (1ULL << (s_int << 3)) - 1; | 36 | const uint64_t before_mask = MASK(s_int); |
41 | uint64_t v = (*p | before_mask) ^ | 37 | uint64_t v = (*p | before_mask) ^ (goal & __insn_v1shrui(before_mask, 1)); |
42 | (goal & __insn_v1shrsi(before_mask, 1)); | ||
43 | 38 | ||
44 | uint64_t zero_matches, goal_matches; | 39 | uint64_t zero_matches, goal_matches; |
45 | while (1) { | 40 | while (1) { |
@@ -55,8 +50,8 @@ char *strchr(const char *s, int c) | |||
55 | v = *++p; | 50 | v = *++p; |
56 | } | 51 | } |
57 | 52 | ||
58 | z = __insn_ctz(zero_matches); | 53 | z = CFZ(zero_matches); |
59 | g = __insn_ctz(goal_matches); | 54 | g = CFZ(goal_matches); |
60 | 55 | ||
61 | /* If we found c before '\0' we got a match. Note that if c == '\0' | 56 | /* If we found c before '\0' we got a match. Note that if c == '\0' |
62 | * then g == z, and we correctly return the address of the '\0' | 57 | * then g == z, and we correctly return the address of the '\0' |
diff --git a/arch/tile/lib/string-endian.h b/arch/tile/lib/string-endian.h new file mode 100644 index 000000000000..c0eed7ce69c3 --- /dev/null +++ b/arch/tile/lib/string-endian.h | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | * Copyright 2011 Tilera Corporation. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation, version 2. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * Provide a mask based on the pointer alignment that | ||
15 | * sets up non-zero bytes before the beginning of the string. | ||
16 | * The MASK expression works because shift counts are taken mod 64. | ||
17 | * Also, specify how to count "first" and "last" bits | ||
18 | * when the bits have been read as a word. | ||
19 | */ | ||
20 | |||
21 | #include <asm/byteorder.h> | ||
22 | |||
23 | #ifdef __LITTLE_ENDIAN | ||
24 | #define MASK(x) (__insn_shl(1ULL, (x << 3)) - 1) | ||
25 | #define NULMASK(x) ((2ULL << x) - 1) | ||
26 | #define CFZ(x) __insn_ctz(x) | ||
27 | #define REVCZ(x) __insn_clz(x) | ||
28 | #else | ||
29 | #define MASK(x) (__insn_shl(-2LL, ((-x << 3) - 1))) | ||
30 | #define NULMASK(x) (-2LL << (63 - x)) | ||
31 | #define CFZ(x) __insn_clz(x) | ||
32 | #define REVCZ(x) __insn_ctz(x) | ||
33 | #endif | ||
diff --git a/arch/tile/lib/strlen_64.c b/arch/tile/lib/strlen_64.c index 1c92d46202a8..9583fc3361fa 100644 --- a/arch/tile/lib/strlen_64.c +++ b/arch/tile/lib/strlen_64.c | |||
@@ -15,8 +15,7 @@ | |||
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | 18 | #include "string-endian.h" | |
19 | #undef strlen | ||
20 | 19 | ||
21 | size_t strlen(const char *s) | 20 | size_t strlen(const char *s) |
22 | { | 21 | { |
@@ -24,15 +23,13 @@ size_t strlen(const char *s) | |||
24 | const uintptr_t s_int = (uintptr_t) s; | 23 | const uintptr_t s_int = (uintptr_t) s; |
25 | const uint64_t *p = (const uint64_t *)(s_int & -8); | 24 | const uint64_t *p = (const uint64_t *)(s_int & -8); |
26 | 25 | ||
27 | /* Read the first word, but force bytes before the string to be nonzero. | 26 | /* Read and MASK the first word. */ |
28 | * This expression works because we know shift counts are taken mod 64. | 27 | uint64_t v = *p | MASK(s_int); |
29 | */ | ||
30 | uint64_t v = *p | ((1ULL << (s_int << 3)) - 1); | ||
31 | 28 | ||
32 | uint64_t bits; | 29 | uint64_t bits; |
33 | while ((bits = __insn_v1cmpeqi(v, 0)) == 0) | 30 | while ((bits = __insn_v1cmpeqi(v, 0)) == 0) |
34 | v = *++p; | 31 | v = *++p; |
35 | 32 | ||
36 | return ((const char *)p) + (__insn_ctz(bits) >> 3) - s; | 33 | return ((const char *)p) + (CFZ(bits) >> 3) - s; |
37 | } | 34 | } |
38 | EXPORT_SYMBOL(strlen); | 35 | EXPORT_SYMBOL(strlen); |
diff --git a/arch/tile/lib/usercopy_32.S b/arch/tile/lib/usercopy_32.S index 979f76d83746..b62d002af009 100644 --- a/arch/tile/lib/usercopy_32.S +++ b/arch/tile/lib/usercopy_32.S | |||
@@ -19,82 +19,6 @@ | |||
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. |
diff --git a/arch/tile/lib/usercopy_64.S b/arch/tile/lib/usercopy_64.S index 2ff44f87b78e..adb2dbbc70cd 100644 --- a/arch/tile/lib/usercopy_64.S +++ b/arch/tile/lib/usercopy_64.S | |||
@@ -19,55 +19,6 @@ | |||
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. |