aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2017-03-31 10:40:52 -0400
committerJames Hogan <james.hogan@imgtec.com>2017-04-05 10:27:32 -0400
commitd3ba2e922d4d1d61806fcb6e09512d2bee734d06 (patch)
tree5ef9ef8b411faacfd92cedbc89990ad7ee7f6710
parentfc1b759ae4e0f636c56ca8410207a8a36630a96e (diff)
metag/usercopy: Add 64-bit get_user support
Metag already supports 64-bit put_user, so add support for 64-bit get_user too so that the test_user_copy module can test both. Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: linux-metag@vger.kernel.org
-rw-r--r--arch/metag/include/asm/uaccess.h9
-rw-r--r--arch/metag/lib/usercopy.c24
2 files changed, 31 insertions, 2 deletions
diff --git a/arch/metag/include/asm/uaccess.h b/arch/metag/include/asm/uaccess.h
index 07238b39638c..469a2f1393d3 100644
--- a/arch/metag/include/asm/uaccess.h
+++ b/arch/metag/include/asm/uaccess.h
@@ -138,7 +138,8 @@ extern long __get_user_bad(void);
138 138
139#define __get_user_nocheck(x, ptr, size) \ 139#define __get_user_nocheck(x, ptr, size) \
140({ \ 140({ \
141 long __gu_err, __gu_val; \ 141 long __gu_err; \
142 long long __gu_val; \
142 __get_user_size(__gu_val, (ptr), (size), __gu_err); \ 143 __get_user_size(__gu_val, (ptr), (size), __gu_err); \
143 (x) = (__force __typeof__(*(ptr)))__gu_val; \ 144 (x) = (__force __typeof__(*(ptr)))__gu_val; \
144 __gu_err; \ 145 __gu_err; \
@@ -146,7 +147,8 @@ extern long __get_user_bad(void);
146 147
147#define __get_user_check(x, ptr, size) \ 148#define __get_user_check(x, ptr, size) \
148({ \ 149({ \
149 long __gu_err = -EFAULT, __gu_val = 0; \ 150 long __gu_err = -EFAULT; \
151 long long __gu_val = 0; \
150 const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ 152 const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
151 if (access_ok(VERIFY_READ, __gu_addr, size)) \ 153 if (access_ok(VERIFY_READ, __gu_addr, size)) \
152 __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ 154 __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
@@ -157,6 +159,7 @@ extern long __get_user_bad(void);
157extern unsigned char __get_user_asm_b(const void __user *addr, long *err); 159extern unsigned char __get_user_asm_b(const void __user *addr, long *err);
158extern unsigned short __get_user_asm_w(const void __user *addr, long *err); 160extern unsigned short __get_user_asm_w(const void __user *addr, long *err);
159extern unsigned int __get_user_asm_d(const void __user *addr, long *err); 161extern unsigned int __get_user_asm_d(const void __user *addr, long *err);
162extern unsigned long long __get_user_asm_l(const void __user *addr, long *err);
160 163
161#define __get_user_size(x, ptr, size, retval) \ 164#define __get_user_size(x, ptr, size, retval) \
162do { \ 165do { \
@@ -168,6 +171,8 @@ do { \
168 x = __get_user_asm_w(ptr, &retval); break; \ 171 x = __get_user_asm_w(ptr, &retval); break; \
169 case 4: \ 172 case 4: \
170 x = __get_user_asm_d(ptr, &retval); break; \ 173 x = __get_user_asm_d(ptr, &retval); break; \
174 case 8: \
175 x = __get_user_asm_l(ptr, &retval); break; \
171 default: \ 176 default: \
172 (x) = __get_user_bad(); \ 177 (x) = __get_user_bad(); \
173 } \ 178 } \
diff --git a/arch/metag/lib/usercopy.c b/arch/metag/lib/usercopy.c
index ceb4590fbca5..45e7b79eca19 100644
--- a/arch/metag/lib/usercopy.c
+++ b/arch/metag/lib/usercopy.c
@@ -1044,6 +1044,30 @@ unsigned int __get_user_asm_d(const void __user *addr, long *err)
1044} 1044}
1045EXPORT_SYMBOL(__get_user_asm_d); 1045EXPORT_SYMBOL(__get_user_asm_d);
1046 1046
1047unsigned long long __get_user_asm_l(const void __user *addr, long *err)
1048{
1049 register unsigned long long x asm ("D0Re0") = 0;
1050 asm volatile (
1051 " GETL %0,%t0,[%2]\n"
1052 "1:\n"
1053 " GETL %0,%t0,[%2]\n"
1054 "2:\n"
1055 " .section .fixup,\"ax\"\n"
1056 "3: MOV D0FrT,%3\n"
1057 " SETD [%1],D0FrT\n"
1058 " MOVT D0FrT,#HI(2b)\n"
1059 " JUMP D0FrT,#LO(2b)\n"
1060 " .previous\n"
1061 " .section __ex_table,\"a\"\n"
1062 " .long 1b,3b\n"
1063 " .previous\n"
1064 : "=r" (x)
1065 : "r" (err), "r" (addr), "P" (-EFAULT)
1066 : "D0FrT");
1067 return x;
1068}
1069EXPORT_SYMBOL(__get_user_asm_l);
1070
1047long __put_user_asm_b(unsigned int x, void __user *addr) 1071long __put_user_asm_b(unsigned int x, void __user *addr)
1048{ 1072{
1049 register unsigned int err asm ("D0Re0") = 0; 1073 register unsigned int err asm ("D0Re0") = 0;