ARM: kprobes: treat R7 as the frame pointer register in Thumb2 builds
authorArd Biesheuvel <ardb@kernel.org>
Wed, 26 Jan 2022 10:27:21 +0000 (11:27 +0100)
committerArd Biesheuvel <ardb@kernel.org>
Wed, 9 Feb 2022 08:13:59 +0000 (09:13 +0100)
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>
arch/arm/probes/kprobes/actions-common.c
arch/arm/probes/kprobes/actions-thumb.c

index 836aebe..7917134 100644 (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"
                );
 }
index 7884fcb..51624fc 100644 (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"
                );