Commit dd12e97f authored by Ard Biesheuvel's avatar Ard Biesheuvel
Browse files

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: default avatarArd Biesheuvel <ardb@kernel.org>
Reviewed-by: default avatarMasami Hiramatsu <mhiramat@kernel.org>
parent 41918ec8
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -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"
		);
}
+12 −4
Original line number Diff line number Diff line
@@ -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"
		);