[PATCH v2 09/12] ARM: kprobes: treat R7 as the frame pointer register in Thumb2 builds

Ard Biesheuvel ardb at kernel.org
Mon Jan 31 23:42:17 PST 2022


On Mon, 31 Jan 2022 at 19:31, Nick Desaulniers <ndesaulniers at google.com> wrote:
>
> On Mon, Jan 31, 2022 at 9:04 AM Ard Biesheuvel <ardb at kernel.org> wrote:
> >
> > 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 at kernel.org>
> > ---
> >  arch/arm/include/asm/opcodes.h           | 14 ++++++++
> >  arch/arm/probes/kprobes/actions-common.c |  6 ++--
> >  arch/arm/probes/kprobes/actions-thumb.c  | 38 ++++++++++++++++----
> >  3 files changed, 48 insertions(+), 10 deletions(-)
> >
> > diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
> > index 38e3eabff5c3..9a6362408ea0 100644
> > --- a/arch/arm/include/asm/opcodes.h
> > +++ b/arch/arm/include/asm/opcodes.h
> > @@ -230,4 +230,18 @@ extern __u32 __opcode_to_mem_thumb32(__u32);
> >         ".short " __stringify(first) ", " __stringify(second) "\n\t"
> >  #endif
> >
> > +/*
> > + * Which register to preserve and which register can be clobbered in inline asm
> > + * that needs to be compatible with code that emits frame pointers.
> > + */
> > +#ifdef CONFIG_THUMB2_KERNEL
> > +#define FPREG_PRESERVE "r7"
> > +#define FPREG_CLOBBER  "r11"
> > +#define FPREG_PRESERVE_R7
> > +#else
> > +#define FPREG_PRESERVE "fp"
> > +#define FPREG_CLOBBER  "r7"
> > +#define FPREG_PRESERVE_R11
>
> I think you might be able to get away without FPREG_PRESERVE_R11 and
> even without FPREG_PRESERVE_R7. FPREG_PRESERVE_R11 is currently unused
> and FPREG_PRESERVE_R7 is synonymous with CONFIG_THUMB2_KERNEL at the
> moment (It doesn't look like patches 11 or 12 change that either).
> Looking at arch/arm/probes/kprobes/Makefile,
> arch/arm/probes/kprobes/actions-thumb.c is only built when
> CONFIG_THUMB2_KERNEL is enabled, so I don't think the #ifdefs are
> required; those `mov`s could be unguarded by the preprocessor?
>

You're quite right. I'll get rid of the macro and the CPP conditionals.

> > +#endif
> > +
> >  #endif /* __ASM_ARM_OPCODES_H */
> > diff --git a/arch/arm/probes/kprobes/actions-common.c b/arch/arm/probes/kprobes/actions-common.c
> > index 836aebe596cd..f0efe16e2fdb 100644
> > --- a/arch/arm/probes/kprobes/actions-common.c
> > +++ b/arch/arm/probes/kprobes/actions-common.c
> > @@ -84,7 +84,7 @@ 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"
> > +               "stmdb  sp!, {%[regs], " FPREG_PRESERVE "}\n\t"
> >                 "ldmia  %[regs], {r0-r12}       \n\t"
> >  #if __LINUX_ARM_ARCH__ >= 6
> >                 "blx    %[fn]                   \n\t"
> > @@ -96,10 +96,10 @@ 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"
> > +               "ldr    " FPREG_PRESERVE ", [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", FPREG_CLOBBER,
> >                   "r8", "r9", "r10", "r12", "memory", "cc"
> >                 );
> >  }
> > diff --git a/arch/arm/probes/kprobes/actions-thumb.c b/arch/arm/probes/kprobes/actions-thumb.c
> > index 7884fcb81c26..873757326533 100644
> > --- a/arch/arm/probes/kprobes/actions-thumb.c
> > +++ b/arch/arm/probes/kprobes/actions-thumb.c
> > @@ -447,14 +447,20 @@ t16_emulate_loregs(probes_opcode_t insn,
> >
> >         __asm__ __volatile__ (
> >                 "msr    cpsr_fs, %[oldcpsr]     \n\t"
> > +#ifdef FPREG_PRESERVE_R7
> > +               "mov    fp, r7                  \n\t"
> > +#endif
> >                 "ldmia  %[regs], {r0-r7}        \n\t"
> >                 "blx    %[fn]                   \n\t"
> >                 "stmia  %[regs], {r0-r7}        \n\t"
> > +#ifdef FPREG_PRESERVE_R7
> > +               "mov    r7, fp                  \n\t"
> > +#endif
> >                 "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", FPREG_CLOBBER,
> >                   "lr", "memory", "cc"
> >                 );
> >
> > @@ -524,15 +530,21 @@ t16_emulate_push(probes_opcode_t insn,
> >                 struct arch_probes_insn *asi, struct pt_regs *regs)
> >  {
> >         __asm__ __volatile__ (
> > +#ifdef FPREG_PRESERVE_R7
> > +               "mov    fp, r7                  \n\t"
> > +#endif
> >                 "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"
> > +#ifdef FPREG_PRESERVE_R7
> > +               "mov    r7, fp                  \n\t"
> > +#endif
> >                 :
> >                 : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
> > -               : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
> > -                 "lr", "memory", "cc"
> > +               : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r9",
> > +                 FPREG_CLOBBER, "lr", "memory", "cc"
> >                 );
> >  }
> >
> > @@ -558,15 +570,21 @@ t16_emulate_pop_nopc(probes_opcode_t insn,
> >                 struct arch_probes_insn *asi, struct pt_regs *regs)
> >  {
> >         __asm__ __volatile__ (
> > +#ifdef FPREG_PRESERVE_R7
> > +               "mov    fp, r7                  \n\t"
> > +#endif
> >                 "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"
> > +#ifdef FPREG_PRESERVE_R7
> > +               "mov    r7, fp                  \n\t"
> > +#endif
> >                 :
> >                 : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
> > -               : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
> > -                 "lr", "memory", "cc"
> > +               : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r9",
> > +                 FPREG_CLOBBER, "lr", "memory", "cc"
> >                 );
> >  }
> >
> > @@ -577,15 +595,21 @@ t16_emulate_pop_pc(probes_opcode_t insn,
> >         register unsigned long pc asm("r8");
> >
> >         __asm__ __volatile__ (
> > +#ifdef FPREG_PRESERVE_R7
> > +               "mov    fp, r7                  \n\t"
> > +#endif
> >                 "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"
> > +#ifdef FPREG_PRESERVE_R7
> > +               "mov    r7, fp                  \n\t"
> > +#endif
> >                 : "=r" (pc)
> >                 : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
> > -               : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
> > -                 "lr", "memory", "cc"
> > +               : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r9",
> > +                 FPREG_CLOBBER, "lr", "memory", "cc"
> >                 );
> >
> >         bx_write_pc(pc, regs);
> > --
> > 2.30.2
> >
>
>
> --
> Thanks,
> ~Nick Desaulniers



More information about the linux-arm-kernel mailing list