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

arm64: kprobes: Remove redundant kprobe_step_ctx

The kprobe_step_ctx (kcb->ss_ctx) has ss_pending and match_addr, but
those are redundant because those can be replaced by KPROBE_HIT_SS and
&cur_kprobe->ainsn.api.insn[1] respectively.
To simplify the code, remove the kprobe_step_ctx.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
Acked-by: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20201103134900.337243-2-jean-philippe@linaro.org
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

Masami Hiramatsu and committed by
Catalin Marinas
ba090f9c f8394f23

+12 -48
-7
arch/arm64/include/asm/kprobes.h
··· 28 28 unsigned int status; 29 29 }; 30 30 31 - /* Single step context for kprobe */ 32 - struct kprobe_step_ctx { 33 - unsigned long ss_pending; 34 - unsigned long match_addr; 35 - }; 36 - 37 31 /* per-cpu kprobe control block */ 38 32 struct kprobe_ctlblk { 39 33 unsigned int kprobe_status; 40 34 unsigned long saved_irqflag; 41 35 struct prev_kprobe prev_kprobe; 42 - struct kprobe_step_ctx ss_ctx; 43 36 }; 44 37 45 38 void arch_remove_kprobe(struct kprobe *);
+12 -41
arch/arm64/kernel/probes/kprobes.c
··· 34 34 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); 35 35 36 36 static void __kprobes 37 - post_kprobe_handler(struct kprobe_ctlblk *, struct pt_regs *); 37 + post_kprobe_handler(struct kprobe *, struct kprobe_ctlblk *, struct pt_regs *); 38 38 39 39 static void __kprobes arch_prepare_ss_slot(struct kprobe *p) 40 40 { ··· 68 68 p->ainsn.api.handler((u32)p->opcode, (long)p->addr, regs); 69 69 70 70 /* single step simulated, now go for post processing */ 71 - post_kprobe_handler(kcb, regs); 71 + post_kprobe_handler(p, kcb, regs); 72 72 } 73 73 74 74 int __kprobes arch_prepare_kprobe(struct kprobe *p) ··· 177 177 regs->pstate |= kcb->saved_irqflag; 178 178 } 179 179 180 - static void __kprobes 181 - set_ss_context(struct kprobe_ctlblk *kcb, unsigned long addr) 182 - { 183 - kcb->ss_ctx.ss_pending = true; 184 - kcb->ss_ctx.match_addr = addr + sizeof(kprobe_opcode_t); 185 - } 186 - 187 - static void __kprobes clear_ss_context(struct kprobe_ctlblk *kcb) 188 - { 189 - kcb->ss_ctx.ss_pending = false; 190 - kcb->ss_ctx.match_addr = 0; 191 - } 192 - 193 180 static void __kprobes setup_singlestep(struct kprobe *p, 194 181 struct pt_regs *regs, 195 182 struct kprobe_ctlblk *kcb, int reenter) ··· 196 209 /* prepare for single stepping */ 197 210 slot = (unsigned long)p->ainsn.api.insn; 198 211 199 - set_ss_context(kcb, slot); /* mark pending ss */ 200 212 kprobes_save_local_irqflag(kcb, regs); 201 213 instruction_pointer_set(regs, slot); 202 214 } else { ··· 229 243 } 230 244 231 245 static void __kprobes 232 - post_kprobe_handler(struct kprobe_ctlblk *kcb, struct pt_regs *regs) 246 + post_kprobe_handler(struct kprobe *cur, struct kprobe_ctlblk *kcb, struct pt_regs *regs) 233 247 { 234 - struct kprobe *cur = kprobe_running(); 235 - 236 - if (!cur) 237 - return; 238 - 239 248 /* return addr restore if non-branching insn */ 240 249 if (cur->ainsn.api.restore != 0) 241 250 instruction_pointer_set(regs, cur->ainsn.api.restore); ··· 346 365 } 347 366 348 367 static int __kprobes 349 - kprobe_ss_hit(struct kprobe_ctlblk *kcb, unsigned long addr) 350 - { 351 - if ((kcb->ss_ctx.ss_pending) 352 - && (kcb->ss_ctx.match_addr == addr)) { 353 - clear_ss_context(kcb); /* clear pending ss */ 354 - return DBG_HOOK_HANDLED; 355 - } 356 - /* not ours, kprobes should ignore it */ 357 - return DBG_HOOK_ERROR; 358 - } 359 - 360 - static int __kprobes 361 368 kprobe_breakpoint_ss_handler(struct pt_regs *regs, unsigned int esr) 362 369 { 363 370 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); 364 - int retval; 371 + unsigned long addr = instruction_pointer(regs); 372 + struct kprobe *cur = kprobe_running(); 365 373 366 - /* return error if this is not our step */ 367 - retval = kprobe_ss_hit(kcb, instruction_pointer(regs)); 368 - 369 - if (retval == DBG_HOOK_HANDLED) { 374 + if (cur && (kcb->kprobe_status == KPROBE_HIT_SS) 375 + && ((unsigned long)&cur->ainsn.api.insn[1] == addr)) { 370 376 kprobes_restore_local_irqflag(kcb, regs); 371 - post_kprobe_handler(kcb, regs); 377 + post_kprobe_handler(cur, kcb, regs); 378 + 379 + return DBG_HOOK_HANDLED; 372 380 } 373 381 374 - return retval; 382 + /* not ours, kprobes should ignore it */ 383 + return DBG_HOOK_ERROR; 375 384 } 376 385 377 386 static struct break_hook kprobes_break_ss_hook = {