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

arm64: probes: Move kprobes-specific fields

We share struct arch_probe_insn between krpboes and uprobes, but most of
its fields aren't necessary for uprobes:

* The 'insn' field is only used by kprobes as a pointer to the XOL slot.

* The 'restore' field is only used by probes as the PC to restore after
stepping an instruction in the XOL slot.

* The 'pstate_cc' field isn't used by kprobes or uprobes, and seems to
only exist as a result of copy-pasting the 32-bit arm implementation
of kprobes.

As these fields live in struct arch_probe_insn they cannot use
definitions that only exist when CONFIG_KPROBES=y, such as the
kprobe_opcode_t typedef, which we'd like to use in subsequent patches.

Clean this up by removing the 'pstate_cc' field, and moving the
kprobes-specific fields into the kprobes-specific struct
arch_specific_insn. To make it clear that the fields are related to
stepping instructions in the XOL slot, 'insn' is renamed to 'xol_insn'
and 'restore' is renamed to 'xol_restore'

At the same time, remove the misleading and useless comment above struct
arch_probe_insn.

The should be no functional change as a result of this patch.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20241008155851.801546-5-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

Mark Rutland and committed by
Catalin Marinas
6105c5d4 13f8f1e0

+18 -20
+3 -5
arch/arm64/include/asm/probes.h
··· 12 12 typedef u32 probe_opcode_t; 13 13 typedef void (probes_handler_t) (u32 opcode, long addr, struct pt_regs *); 14 14 15 - /* architecture specific copy of original instruction */ 16 15 struct arch_probe_insn { 17 - probe_opcode_t *insn; 18 - pstate_check_t *pstate_cc; 19 16 probes_handler_t *handler; 20 - /* restore address after step xol */ 21 - unsigned long restore; 22 17 }; 23 18 #ifdef CONFIG_KPROBES 24 19 typedef u32 kprobe_opcode_t; 25 20 struct arch_specific_insn { 26 21 struct arch_probe_insn api; 22 + probe_opcode_t *xol_insn; 23 + /* restore address after step xol */ 24 + unsigned long xol_restore; 27 25 }; 28 26 #endif 29 27
+15 -15
arch/arm64/kernel/probes/kprobes.c
··· 43 43 44 44 static void __kprobes arch_prepare_ss_slot(struct kprobe *p) 45 45 { 46 - kprobe_opcode_t *addr = p->ainsn.api.insn; 46 + kprobe_opcode_t *addr = p->ainsn.xol_insn; 47 47 48 48 /* 49 49 * Prepare insn slot, Mark Rutland points out it depends on a coupe of ··· 70 70 /* 71 71 * Needs restoring of return address after stepping xol. 72 72 */ 73 - p->ainsn.api.restore = (unsigned long) p->addr + 73 + p->ainsn.xol_restore = (unsigned long) p->addr + 74 74 sizeof(kprobe_opcode_t); 75 75 } 76 76 77 77 static void __kprobes arch_prepare_simulate(struct kprobe *p) 78 78 { 79 79 /* This instructions is not executed xol. No need to adjust the PC */ 80 - p->ainsn.api.restore = 0; 80 + p->ainsn.xol_restore = 0; 81 81 } 82 82 83 83 static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs) ··· 110 110 return -EINVAL; 111 111 112 112 case INSN_GOOD_NO_SLOT: /* insn need simulation */ 113 - p->ainsn.api.insn = NULL; 113 + p->ainsn.xol_insn = NULL; 114 114 break; 115 115 116 116 case INSN_GOOD: /* instruction uses slot */ 117 - p->ainsn.api.insn = get_insn_slot(); 118 - if (!p->ainsn.api.insn) 117 + p->ainsn.xol_insn = get_insn_slot(); 118 + if (!p->ainsn.xol_insn) 119 119 return -ENOMEM; 120 120 break; 121 121 } 122 122 123 123 /* prepare the instruction */ 124 - if (p->ainsn.api.insn) 124 + if (p->ainsn.xol_insn) 125 125 arch_prepare_ss_slot(p); 126 126 else 127 127 arch_prepare_simulate(p); ··· 148 148 149 149 void __kprobes arch_remove_kprobe(struct kprobe *p) 150 150 { 151 - if (p->ainsn.api.insn) { 152 - free_insn_slot(p->ainsn.api.insn, 0); 153 - p->ainsn.api.insn = NULL; 151 + if (p->ainsn.xol_insn) { 152 + free_insn_slot(p->ainsn.xol_insn, 0); 153 + p->ainsn.xol_insn = NULL; 154 154 } 155 155 } 156 156 ··· 205 205 } 206 206 207 207 208 - if (p->ainsn.api.insn) { 208 + if (p->ainsn.xol_insn) { 209 209 /* prepare for single stepping */ 210 - slot = (unsigned long)p->ainsn.api.insn; 210 + slot = (unsigned long)p->ainsn.xol_insn; 211 211 212 212 kprobes_save_local_irqflag(kcb, regs); 213 213 instruction_pointer_set(regs, slot); ··· 245 245 post_kprobe_handler(struct kprobe *cur, struct kprobe_ctlblk *kcb, struct pt_regs *regs) 246 246 { 247 247 /* return addr restore if non-branching insn */ 248 - if (cur->ainsn.api.restore != 0) 249 - instruction_pointer_set(regs, cur->ainsn.api.restore); 248 + if (cur->ainsn.xol_restore != 0) 249 + instruction_pointer_set(regs, cur->ainsn.xol_restore); 250 250 251 251 /* restore back original saved kprobe variables and continue */ 252 252 if (kcb->kprobe_status == KPROBE_REENTER) { ··· 348 348 struct kprobe *cur = kprobe_running(); 349 349 350 350 if (cur && (kcb->kprobe_status & (KPROBE_HIT_SS | KPROBE_REENTER)) && 351 - ((unsigned long)&cur->ainsn.api.insn[1] == addr)) { 351 + ((unsigned long)&cur->ainsn.xol_insn[1] == addr)) { 352 352 kprobes_restore_local_irqflag(kcb, regs); 353 353 post_kprobe_handler(cur, kcb, regs); 354 354