Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: kprobes: treat R7 as the frame pointer register in Thumb2 builds

Thumb2 code uses R7 as the frame pointer rather than R11, because the
opcodes to access it are generally shorter.

This means that there are cases where we cannot simply add it to the
clobber list of an asm() block, but need to preserve/restore it
explicitly, or the compiler may complain in some cases (e.g., Clang
builds with ftrace enabled).

Since R11 is not special in that case, clobber it instead, and use it to
preserve/restore the value of R7.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>

+17 -7
+5 -3
arch/arm/probes/kprobes/actions-common.c
··· 84 84 register void *rfn asm("lr") = asi->insn_fn; 85 85 86 86 __asm__ __volatile__ ( 87 - "stmdb sp!, {%[regs], r11} \n\t" 87 + ARM( "stmdb sp!, {%[regs], r11} \n\t" ) 88 + THUMB( "stmdb sp!, {%[regs], r7} \n\t" ) 88 89 "ldmia %[regs], {r0-r12} \n\t" 89 90 #if __LINUX_ARM_ARCH__ >= 6 90 91 "blx %[fn] \n\t" ··· 97 96 #endif 98 97 "ldr lr, [sp], #4 \n\t" /* lr = regs */ 99 98 "stmia lr, {r0-r12} \n\t" 100 - "ldr r11, [sp], #4 \n\t" 99 + ARM( "ldr r11, [sp], #4 \n\t" ) 100 + THUMB( "ldr r7, [sp], #4 \n\t" ) 101 101 : [regs] "=r" (rregs), [fn] "=r" (rfn) 102 102 : "0" (rregs), "1" (rfn) 103 - : "r0", "r2", "r3", "r4", "r5", "r6", "r7", 103 + : "r0", "r2", "r3", "r4", "r5", "r6", ARM("r7") THUMB("r11"), 104 104 "r8", "r9", "r10", "r12", "memory", "cc" 105 105 ); 106 106 }
+12 -4
arch/arm/probes/kprobes/actions-thumb.c
··· 447 447 448 448 __asm__ __volatile__ ( 449 449 "msr cpsr_fs, %[oldcpsr] \n\t" 450 + "mov r11, r7 \n\t" 450 451 "ldmia %[regs], {r0-r7} \n\t" 451 452 "blx %[fn] \n\t" 452 453 "stmia %[regs], {r0-r7} \n\t" 454 + "mov r7, r11 \n\t" 453 455 "mrs %[newcpsr], cpsr \n\t" 454 456 : [newcpsr] "=r" (newcpsr) 455 457 : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs), 456 458 [fn] "r" (asi->insn_fn) 457 - : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 459 + : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r11", 458 460 "lr", "memory", "cc" 459 461 ); 460 462 ··· 526 524 struct arch_probes_insn *asi, struct pt_regs *regs) 527 525 { 528 526 __asm__ __volatile__ ( 527 + "mov r11, r7 \n\t" 529 528 "ldr r9, [%[regs], #13*4] \n\t" 530 529 "ldr r8, [%[regs], #14*4] \n\t" 531 530 "ldmia %[regs], {r0-r7} \n\t" 532 531 "blx %[fn] \n\t" 533 532 "str r9, [%[regs], #13*4] \n\t" 533 + "mov r7, r11 \n\t" 534 534 : 535 535 : [regs] "r" (regs), [fn] "r" (asi->insn_fn) 536 - : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", 536 + : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r11", 537 537 "lr", "memory", "cc" 538 538 ); 539 539 } ··· 562 558 struct arch_probes_insn *asi, struct pt_regs *regs) 563 559 { 564 560 __asm__ __volatile__ ( 561 + "mov r11, r7 \n\t" 565 562 "ldr r9, [%[regs], #13*4] \n\t" 566 563 "ldmia %[regs], {r0-r7} \n\t" 567 564 "blx %[fn] \n\t" 568 565 "stmia %[regs], {r0-r7} \n\t" 569 566 "str r9, [%[regs], #13*4] \n\t" 567 + "mov r7, r11 \n\t" 570 568 : 571 569 : [regs] "r" (regs), [fn] "r" (asi->insn_fn) 572 - : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", 570 + : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r9", "r11", 573 571 "lr", "memory", "cc" 574 572 ); 575 573 } ··· 583 577 register unsigned long pc asm("r8"); 584 578 585 579 __asm__ __volatile__ ( 580 + "mov r11, r7 \n\t" 586 581 "ldr r9, [%[regs], #13*4] \n\t" 587 582 "ldmia %[regs], {r0-r7} \n\t" 588 583 "blx %[fn] \n\t" 589 584 "stmia %[regs], {r0-r7} \n\t" 590 585 "str r9, [%[regs], #13*4] \n\t" 586 + "mov r7, r11 \n\t" 591 587 : "=r" (pc) 592 588 : [regs] "r" (regs), [fn] "r" (asi->insn_fn) 593 - : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", 589 + : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r9", "r11", 594 590 "lr", "memory", "cc" 595 591 ); 596 592