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>
This commit is contained in:
Ard Biesheuvel 2022-01-26 11:27:21 +01:00
parent 41918ec82e
commit dd12e97f3c
2 changed files with 17 additions and 7 deletions

View File

@ -84,7 +84,8 @@ emulate_generic_r0_12_noflags(probes_opcode_t insn,
register void *rfn asm("lr") = asi->insn_fn;
__asm__ __volatile__ (
"stmdb sp!, {%[regs], r11} \n\t"
ARM( "stmdb sp!, {%[regs], r11} \n\t" )
THUMB( "stmdb sp!, {%[regs], r7} \n\t" )
"ldmia %[regs], {r0-r12} \n\t"
#if __LINUX_ARM_ARCH__ >= 6
"blx %[fn] \n\t"
@ -96,10 +97,11 @@ emulate_generic_r0_12_noflags(probes_opcode_t insn,
#endif
"ldr lr, [sp], #4 \n\t" /* lr = regs */
"stmia lr, {r0-r12} \n\t"
"ldr r11, [sp], #4 \n\t"
ARM( "ldr r11, [sp], #4 \n\t" )
THUMB( "ldr r7, [sp], #4 \n\t" )
: [regs] "=r" (rregs), [fn] "=r" (rfn)
: "0" (rregs), "1" (rfn)
: "r0", "r2", "r3", "r4", "r5", "r6", "r7",
: "r0", "r2", "r3", "r4", "r5", "r6", ARM("r7") THUMB("r11"),
"r8", "r9", "r10", "r12", "memory", "cc"
);
}

View File

@ -447,14 +447,16 @@ t16_emulate_loregs(probes_opcode_t insn,
__asm__ __volatile__ (
"msr cpsr_fs, %[oldcpsr] \n\t"
"mov r11, r7 \n\t"
"ldmia %[regs], {r0-r7} \n\t"
"blx %[fn] \n\t"
"stmia %[regs], {r0-r7} \n\t"
"mov r7, r11 \n\t"
"mrs %[newcpsr], cpsr \n\t"
: [newcpsr] "=r" (newcpsr)
: [oldcpsr] "r" (oldcpsr), [regs] "r" (regs),
[fn] "r" (asi->insn_fn)
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r11",
"lr", "memory", "cc"
);
@ -524,14 +526,16 @@ t16_emulate_push(probes_opcode_t insn,
struct arch_probes_insn *asi, struct pt_regs *regs)
{
__asm__ __volatile__ (
"mov r11, r7 \n\t"
"ldr r9, [%[regs], #13*4] \n\t"
"ldr r8, [%[regs], #14*4] \n\t"
"ldmia %[regs], {r0-r7} \n\t"
"blx %[fn] \n\t"
"str r9, [%[regs], #13*4] \n\t"
"mov r7, r11 \n\t"
:
: [regs] "r" (regs), [fn] "r" (asi->insn_fn)
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r11",
"lr", "memory", "cc"
);
}
@ -558,14 +562,16 @@ t16_emulate_pop_nopc(probes_opcode_t insn,
struct arch_probes_insn *asi, struct pt_regs *regs)
{
__asm__ __volatile__ (
"mov r11, r7 \n\t"
"ldr r9, [%[regs], #13*4] \n\t"
"ldmia %[regs], {r0-r7} \n\t"
"blx %[fn] \n\t"
"stmia %[regs], {r0-r7} \n\t"
"str r9, [%[regs], #13*4] \n\t"
"mov r7, r11 \n\t"
:
: [regs] "r" (regs), [fn] "r" (asi->insn_fn)
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r9", "r11",
"lr", "memory", "cc"
);
}
@ -577,14 +583,16 @@ t16_emulate_pop_pc(probes_opcode_t insn,
register unsigned long pc asm("r8");
__asm__ __volatile__ (
"mov r11, r7 \n\t"
"ldr r9, [%[regs], #13*4] \n\t"
"ldmia %[regs], {r0-r7} \n\t"
"blx %[fn] \n\t"
"stmia %[regs], {r0-r7} \n\t"
"str r9, [%[regs], #13*4] \n\t"
"mov r7, r11 \n\t"
: "=r" (pc)
: [regs] "r" (regs), [fn] "r" (asi->insn_fn)
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r9", "r11",
"lr", "memory", "cc"
);