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

arm64: probes: Break ret out from bl/blr

Prepare for GCS by breaking RET out into its own function, where
it makes more sense to encapsulate the new behavior independent
from the branch instructions.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Will Deacon <will@kernel.org>

authored by

Jeremy Linton and committed by
Will Deacon
47687aa4 8f5ae30d

+15 -5
+4 -3
arch/arm64/kernel/probes/decode-insn.c
··· 108 108 aarch64_insn_is_bl(insn)) { 109 109 api->handler = simulate_b_bl; 110 110 } else if (aarch64_insn_is_br(insn) || 111 - aarch64_insn_is_blr(insn) || 112 - aarch64_insn_is_ret(insn)) { 113 - api->handler = simulate_br_blr_ret; 111 + aarch64_insn_is_blr(insn)) { 112 + api->handler = simulate_br_blr; 113 + } else if (aarch64_insn_is_ret(insn)) { 114 + api->handler = simulate_ret; 114 115 } else { 115 116 /* 116 117 * Instruction cannot be stepped out-of-line and we don't
+9 -1
arch/arm64/kernel/probes/simulate-insn.c
··· 126 126 } 127 127 128 128 void __kprobes 129 - simulate_br_blr_ret(u32 opcode, long addr, struct pt_regs *regs) 129 + simulate_br_blr(u32 opcode, long addr, struct pt_regs *regs) 130 130 { 131 131 int xn = (opcode >> 5) & 0x1f; 132 132 ··· 136 136 /* Link register is x30 */ 137 137 if (((opcode >> 21) & 0x3) == 1) 138 138 set_x_reg(regs, 30, addr + 4); 139 + } 140 + 141 + void __kprobes 142 + simulate_ret(u32 opcode, long addr, struct pt_regs *regs) 143 + { 144 + int xn = (opcode >> 5) & 0x1f; 145 + 146 + instruction_pointer_set(regs, get_x_reg(regs, xn)); 139 147 } 140 148 141 149 void __kprobes
+2 -1
arch/arm64/kernel/probes/simulate-insn.h
··· 11 11 void simulate_adr_adrp(u32 opcode, long addr, struct pt_regs *regs); 12 12 void simulate_b_bl(u32 opcode, long addr, struct pt_regs *regs); 13 13 void simulate_b_cond(u32 opcode, long addr, struct pt_regs *regs); 14 - void simulate_br_blr_ret(u32 opcode, long addr, struct pt_regs *regs); 14 + void simulate_br_blr(u32 opcode, long addr, struct pt_regs *regs); 15 + void simulate_ret(u32 opcode, long addr, struct pt_regs *regs); 15 16 void simulate_cbz_cbnz(u32 opcode, long addr, struct pt_regs *regs); 16 17 void simulate_tbz_tbnz(u32 opcode, long addr, struct pt_regs *regs); 17 18 void simulate_ldr_literal(u32 opcode, long addr, struct pt_regs *regs);