Skip to content

Commit d877322

Browse files
committed
openrisc: Fix issue with get_user for 64-bit values
A build failure was raised by kbuild with the following error. drivers/android/binder.c: Assembler messages: drivers/android/binder.c:3861: Error: unrecognized keyword/register name `l.lwz ?ap,4(r24)' drivers/android/binder.c:3866: Error: unrecognized keyword/register name `l.addi ?ap,r0,0' The issue is with 64-bit get_user() calls on openrisc. I traced this to a problem where in the internally in the get_user macros there is a cast to long __gu_val this causes GCC to think the get_user call is 32-bit. This binder code is really long and GCC allocates register r30, which triggers the issue. The 64-bit get_user asm tries to get the 64-bit pair register, which for r30 overflows the general register names and returns the dummy register ?ap. The fix here is to move the temporary variables into the asm macros. We use a 32-bit __gu_tmp for 32-bit and smaller macro and a 64-bit tmp in the 64-bit macro. The cast in the 64-bit macro has a trick of casting through __typeof__((x)-(x)) which avoids the below warning. This was barrowed from riscv. arch/openrisc/include/asm/uaccess.h:240:8: warning: cast to pointer from integer of different size I tested this in a small unit test to check reading between 64-bit and 32-bit pointers to 64-bit and 32-bit values in all combinations. Also I ran make C=1 to confirm no new sparse warnings came up. It all looks clean to me. Link: https://lore.kernel.org/lkml/202008200453.ohnhqkjQ%25lkp@intel.com/ Signed-off-by: Stafford Horne <shorne@gmail.com> Reviewed-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
1 parent 3ae90d7 commit d877322

File tree

1 file changed

+21
-12
lines changed

1 file changed

+21
-12
lines changed

arch/openrisc/include/asm/uaccess.h

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -165,19 +165,19 @@ struct __large_struct {
165165

166166
#define __get_user_nocheck(x, ptr, size) \
167167
({ \
168-
long __gu_err, __gu_val; \
169-
__get_user_size(__gu_val, (ptr), (size), __gu_err); \
170-
(x) = (__force __typeof__(*(ptr)))__gu_val; \
168+
long __gu_err; \
169+
__get_user_size((x), (ptr), (size), __gu_err); \
171170
__gu_err; \
172171
})
173172

174173
#define __get_user_check(x, ptr, size) \
175174
({ \
176-
long __gu_err = -EFAULT, __gu_val = 0; \
175+
long __gu_err = -EFAULT; \
177176
const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
178-
if (access_ok(__gu_addr, size)) \
179-
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
180-
(x) = (__force __typeof__(*(ptr)))__gu_val; \
177+
if (access_ok(__gu_addr, size)) \
178+
__get_user_size((x), __gu_addr, (size), __gu_err); \
179+
else \
180+
(x) = (__typeof__(*(ptr))) 0; \
181181
__gu_err; \
182182
})
183183

@@ -191,11 +191,13 @@ do { \
191191
case 2: __get_user_asm(x, ptr, retval, "l.lhz"); break; \
192192
case 4: __get_user_asm(x, ptr, retval, "l.lwz"); break; \
193193
case 8: __get_user_asm2(x, ptr, retval); break; \
194-
default: (x) = __get_user_bad(); \
194+
default: (x) = (__typeof__(*(ptr)))__get_user_bad(); \
195195
} \
196196
} while (0)
197197

198198
#define __get_user_asm(x, addr, err, op) \
199+
{ \
200+
unsigned long __gu_tmp; \
199201
__asm__ __volatile__( \
200202
"1: "op" %1,0(%2)\n" \
201203
"2:\n" \
@@ -209,10 +211,14 @@ do { \
209211
" .align 2\n" \
210212
" .long 1b,3b\n" \
211213
".previous" \
212-
: "=r"(err), "=r"(x) \
213-
: "r"(addr), "i"(-EFAULT), "0"(err))
214+
: "=r"(err), "=r"(__gu_tmp) \
215+
: "r"(addr), "i"(-EFAULT), "0"(err)); \
216+
(x) = (__typeof__(*(addr)))__gu_tmp; \
217+
}
214218

215219
#define __get_user_asm2(x, addr, err) \
220+
{ \
221+
unsigned long long __gu_tmp; \
216222
__asm__ __volatile__( \
217223
"1: l.lwz %1,0(%2)\n" \
218224
"2: l.lwz %H1,4(%2)\n" \
@@ -229,8 +235,11 @@ do { \
229235
" .long 1b,4b\n" \
230236
" .long 2b,4b\n" \
231237
".previous" \
232-
: "=r"(err), "=&r"(x) \
233-
: "r"(addr), "i"(-EFAULT), "0"(err))
238+
: "=r"(err), "=&r"(__gu_tmp) \
239+
: "r"(addr), "i"(-EFAULT), "0"(err)); \
240+
(x) = (__typeof__(*(addr)))( \
241+
(__typeof__((x)-(x)))__gu_tmp); \
242+
}
234243

235244
/* more complex routines */
236245

0 commit comments

Comments
 (0)