aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm64/kernel/armv8_deprecated.c36
1 files changed, 22 insertions, 14 deletions
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index 42ffdb54e162..b0988bb1bf64 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -280,35 +280,43 @@ static void __init register_insn_emulation_sysctl(struct ctl_table *table)
280/* 280/*
281 * Error-checking SWP macros implemented using ldxr{b}/stxr{b} 281 * Error-checking SWP macros implemented using ldxr{b}/stxr{b}
282 */ 282 */
283#define __user_swpX_asm(data, addr, res, temp, B) \ 283
284/* Arbitrary constant to ensure forward-progress of the LL/SC loop */
285#define __SWP_LL_SC_LOOPS 4
286
287#define __user_swpX_asm(data, addr, res, temp, temp2, B) \
284 __asm__ __volatile__( \ 288 __asm__ __volatile__( \
289 " mov %w3, %w7\n" \
285 ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \ 290 ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \
286 CONFIG_ARM64_PAN) \ 291 CONFIG_ARM64_PAN) \
287 "0: ldxr"B" %w2, [%3]\n" \ 292 "0: ldxr"B" %w2, [%4]\n" \
288 "1: stxr"B" %w0, %w1, [%3]\n" \ 293 "1: stxr"B" %w0, %w1, [%4]\n" \
289 " cbz %w0, 2f\n" \ 294 " cbz %w0, 2f\n" \
290 " mov %w0, %w4\n" \ 295 " sub %w3, %w3, #1\n" \
296 " cbnz %w3, 0b\n" \
297 " mov %w0, %w5\n" \
291 " b 3f\n" \ 298 " b 3f\n" \
292 "2:\n" \ 299 "2:\n" \
293 " mov %w1, %w2\n" \ 300 " mov %w1, %w2\n" \
294 "3:\n" \ 301 "3:\n" \
295 " .pushsection .fixup,\"ax\"\n" \ 302 " .pushsection .fixup,\"ax\"\n" \
296 " .align 2\n" \ 303 " .align 2\n" \
297 "4: mov %w0, %w5\n" \ 304 "4: mov %w0, %w6\n" \
298 " b 3b\n" \ 305 " b 3b\n" \
299 " .popsection" \ 306 " .popsection" \
300 _ASM_EXTABLE(0b, 4b) \ 307 _ASM_EXTABLE(0b, 4b) \
301 _ASM_EXTABLE(1b, 4b) \ 308 _ASM_EXTABLE(1b, 4b) \
302 ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \ 309 ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \
303 CONFIG_ARM64_PAN) \ 310 CONFIG_ARM64_PAN) \
304 : "=&r" (res), "+r" (data), "=&r" (temp) \ 311 : "=&r" (res), "+r" (data), "=&r" (temp), "=&r" (temp2) \
305 : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT) \ 312 : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT), \
313 "i" (__SWP_LL_SC_LOOPS) \
306 : "memory") 314 : "memory")
307 315
308#define __user_swp_asm(data, addr, res, temp) \ 316#define __user_swp_asm(data, addr, res, temp, temp2) \
309 __user_swpX_asm(data, addr, res, temp, "") 317 __user_swpX_asm(data, addr, res, temp, temp2, "")
310#define __user_swpb_asm(data, addr, res, temp) \ 318#define __user_swpb_asm(data, addr, res, temp, temp2) \
311 __user_swpX_asm(data, addr, res, temp, "b") 319 __user_swpX_asm(data, addr, res, temp, temp2, "b")
312 320
313/* 321/*
314 * Bit 22 of the instruction encoding distinguishes between 322 * Bit 22 of the instruction encoding distinguishes between
@@ -328,12 +336,12 @@ static int emulate_swpX(unsigned int address, unsigned int *data,
328 } 336 }
329 337
330 while (1) { 338 while (1) {
331 unsigned long temp; 339 unsigned long temp, temp2;
332 340
333 if (type == TYPE_SWPB) 341 if (type == TYPE_SWPB)
334 __user_swpb_asm(*data, address, res, temp); 342 __user_swpb_asm(*data, address, res, temp, temp2);
335 else 343 else
336 __user_swp_asm(*data, address, res, temp); 344 __user_swp_asm(*data, address, res, temp, temp2);
337 345
338 if (likely(res != -EAGAIN) || signal_pending(current)) 346 if (likely(res != -EAGAIN) || signal_pending(current))
339 break; 347 break;