Skip to content

Commit 48c7294

Browse files
committed
LoongArch: Adjust user accessors for 32BIT/64BIT
Adjust user accessors for both 32BIT and 64BIT, including: get_user(), put_user(), copy_user(), clear_user(), etc. Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
1 parent 14338e6 commit 48c7294

3 files changed

Lines changed: 91 additions & 22 deletions

File tree

arch/loongarch/include/asm/uaccess.h

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,16 @@
1919
#include <asm/asm-extable.h>
2020
#include <asm-generic/access_ok.h>
2121

22+
#define __LSW 0
23+
#define __MSW 1
24+
2225
extern u64 __ua_limit;
2326

24-
#define __UA_ADDR ".dword"
27+
#ifdef CONFIG_64BIT
2528
#define __UA_LIMIT __ua_limit
29+
#else
30+
#define __UA_LIMIT 0x80000000UL
31+
#endif
2632

2733
/*
2834
* get_user: - Get a simple variable from user space.
@@ -126,6 +132,7 @@ extern u64 __ua_limit;
126132
*
127133
* Returns zero on success, or -EFAULT on error.
128134
*/
135+
129136
#define __put_user(x, ptr) \
130137
({ \
131138
int __pu_err = 0; \
@@ -146,7 +153,7 @@ do { \
146153
case 1: __get_data_asm(val, "ld.b", ptr); break; \
147154
case 2: __get_data_asm(val, "ld.h", ptr); break; \
148155
case 4: __get_data_asm(val, "ld.w", ptr); break; \
149-
case 8: __get_data_asm(val, "ld.d", ptr); break; \
156+
case 8: __get_data_asm_8(val, ptr); break; \
150157
default: BUILD_BUG(); break; \
151158
} \
152159
} while (0)
@@ -167,13 +174,39 @@ do { \
167174
(val) = (__typeof__(*(ptr))) __gu_tmp; \
168175
}
169176

177+
#ifdef CONFIG_64BIT
178+
#define __get_data_asm_8(val, ptr) \
179+
__get_data_asm(val, "ld.d", ptr)
180+
#else /* !CONFIG_64BIT */
181+
#define __get_data_asm_8(val, ptr) \
182+
{ \
183+
u32 __lo, __hi; \
184+
u32 __user *__ptr = (u32 __user *)(ptr); \
185+
\
186+
__asm__ __volatile__ ( \
187+
"1:\n" \
188+
" ld.w %1, %3 \n" \
189+
"2:\n" \
190+
" ld.w %2, %4 \n" \
191+
"3:\n" \
192+
_ASM_EXTABLE_UACCESS_ERR_ZERO(1b, 3b, %0, %1) \
193+
_ASM_EXTABLE_UACCESS_ERR_ZERO(2b, 3b, %0, %1) \
194+
: "+r" (__gu_err), "=&r" (__lo), "=r" (__hi) \
195+
: "m" (__ptr[__LSW]), "m" (__ptr[__MSW])); \
196+
if (__gu_err) \
197+
__hi = 0; \
198+
(val) = (__typeof__(val))((__typeof__((val)-(val))) \
199+
((((u64)__hi << 32) | __lo))); \
200+
}
201+
#endif /* CONFIG_64BIT */
202+
170203
#define __put_user_common(ptr, size) \
171204
do { \
172205
switch (size) { \
173206
case 1: __put_data_asm("st.b", ptr); break; \
174207
case 2: __put_data_asm("st.h", ptr); break; \
175208
case 4: __put_data_asm("st.w", ptr); break; \
176-
case 8: __put_data_asm("st.d", ptr); break; \
209+
case 8: __put_data_asm_8(ptr); break; \
177210
default: BUILD_BUG(); break; \
178211
} \
179212
} while (0)
@@ -190,6 +223,30 @@ do { \
190223
: "Jr" (__pu_val)); \
191224
}
192225

226+
#ifdef CONFIG_64BIT
227+
#define __put_data_asm_8(ptr) \
228+
__put_data_asm("st.d", ptr)
229+
#else /* !CONFIG_64BIT */
230+
#define __put_data_asm_8(ptr) \
231+
{ \
232+
u32 __user *__ptr = (u32 __user *)(ptr); \
233+
u64 __x = (__typeof__((__pu_val)-(__pu_val)))(__pu_val); \
234+
\
235+
__asm__ __volatile__ ( \
236+
"1:\n" \
237+
" st.w %z3, %1 \n" \
238+
"2:\n" \
239+
" st.w %z4, %2 \n" \
240+
"3:\n" \
241+
_ASM_EXTABLE_UACCESS_ERR(1b, 3b, %0) \
242+
_ASM_EXTABLE_UACCESS_ERR(2b, 3b, %0) \
243+
: "+r" (__pu_err), \
244+
"=m" (__ptr[__LSW]), \
245+
"=m" (__ptr[__MSW]) \
246+
: "rJ" (__x), "rJ" (__x >> 32)); \
247+
}
248+
#endif /* CONFIG_64BIT */
249+
193250
#define __get_kernel_nofault(dst, src, type, err_label) \
194251
do { \
195252
int __gu_err = 0; \

arch/loongarch/lib/clear_user.S

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,15 @@
1313
#include <asm/unwind_hints.h>
1414

1515
SYM_FUNC_START(__clear_user)
16+
#ifdef CONFIG_32BIT
17+
b __clear_user_generic
18+
#else
1619
/*
1720
* Some CPUs support hardware unaligned access
1821
*/
1922
ALTERNATIVE "b __clear_user_generic", \
2023
"b __clear_user_fast", CPU_FEATURE_UAL
24+
#endif
2125
SYM_FUNC_END(__clear_user)
2226

2327
EXPORT_SYMBOL(__clear_user)
@@ -29,19 +33,20 @@ EXPORT_SYMBOL(__clear_user)
2933
* a1: size
3034
*/
3135
SYM_FUNC_START(__clear_user_generic)
32-
beqz a1, 2f
36+
beqz a1, 2f
3337

34-
1: st.b zero, a0, 0
35-
addi.d a0, a0, 1
36-
addi.d a1, a1, -1
37-
bgtz a1, 1b
38+
1: st.b zero, a0, 0
39+
PTR_ADDI a0, a0, 1
40+
PTR_ADDI a1, a1, -1
41+
bgtz a1, 1b
3842

39-
2: move a0, a1
40-
jr ra
43+
2: move a0, a1
44+
jr ra
4145

42-
_asm_extable 1b, 2b
46+
_asm_extable 1b, 2b
4347
SYM_FUNC_END(__clear_user_generic)
4448

49+
#ifdef CONFIG_64BIT
4550
/*
4651
* unsigned long __clear_user_fast(void *addr, unsigned long size)
4752
*
@@ -207,3 +212,4 @@ SYM_FUNC_START(__clear_user_fast)
207212
SYM_FUNC_END(__clear_user_fast)
208213

209214
STACK_FRAME_NON_STANDARD __clear_user_fast
215+
#endif

arch/loongarch/lib/copy_user.S

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,15 @@
1313
#include <asm/unwind_hints.h>
1414

1515
SYM_FUNC_START(__copy_user)
16+
#ifdef CONFIG_32BIT
17+
b __copy_user_generic
18+
#else
1619
/*
1720
* Some CPUs support hardware unaligned access
1821
*/
1922
ALTERNATIVE "b __copy_user_generic", \
2023
"b __copy_user_fast", CPU_FEATURE_UAL
24+
#endif
2125
SYM_FUNC_END(__copy_user)
2226

2327
EXPORT_SYMBOL(__copy_user)
@@ -30,22 +34,23 @@ EXPORT_SYMBOL(__copy_user)
3034
* a2: n
3135
*/
3236
SYM_FUNC_START(__copy_user_generic)
33-
beqz a2, 3f
37+
beqz a2, 3f
3438

35-
1: ld.b t0, a1, 0
36-
2: st.b t0, a0, 0
37-
addi.d a0, a0, 1
38-
addi.d a1, a1, 1
39-
addi.d a2, a2, -1
40-
bgtz a2, 1b
39+
1: ld.b t0, a1, 0
40+
2: st.b t0, a0, 0
41+
PTR_ADDI a0, a0, 1
42+
PTR_ADDI a1, a1, 1
43+
PTR_ADDI a2, a2, -1
44+
bgtz a2, 1b
4145

42-
3: move a0, a2
43-
jr ra
46+
3: move a0, a2
47+
jr ra
4448

45-
_asm_extable 1b, 3b
46-
_asm_extable 2b, 3b
49+
_asm_extable 1b, 3b
50+
_asm_extable 2b, 3b
4751
SYM_FUNC_END(__copy_user_generic)
4852

53+
#ifdef CONFIG_64BIT
4954
/*
5055
* unsigned long __copy_user_fast(void *to, const void *from, unsigned long n)
5156
*
@@ -281,3 +286,4 @@ SYM_FUNC_START(__copy_user_fast)
281286
SYM_FUNC_END(__copy_user_fast)
282287

283288
STACK_FRAME_NON_STANDARD __copy_user_fast
289+
#endif

0 commit comments

Comments
 (0)