18858ac8eSSven Schnelle // SPDX-License-Identifier: GPL-2.0
28858ac8eSSven Schnelle /*
38858ac8eSSven Schnelle * arch/parisc/kernel/kprobes.c
48858ac8eSSven Schnelle *
58858ac8eSSven Schnelle * PA-RISC kprobes implementation
68858ac8eSSven Schnelle *
78858ac8eSSven Schnelle * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org>
89b046d02SHelge Deller * Copyright (c) 2022 Helge Deller <deller@gmx.de>
98858ac8eSSven Schnelle */
108858ac8eSSven Schnelle
118858ac8eSSven Schnelle #include <linux/types.h>
128858ac8eSSven Schnelle #include <linux/kprobes.h>
138858ac8eSSven Schnelle #include <linux/slab.h>
148858ac8eSSven Schnelle #include <asm/cacheflush.h>
158858ac8eSSven Schnelle #include <asm/patch.h>
168858ac8eSSven Schnelle
178858ac8eSSven Schnelle DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
188858ac8eSSven Schnelle DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
198858ac8eSSven Schnelle
arch_prepare_kprobe(struct kprobe * p)208858ac8eSSven Schnelle int __kprobes arch_prepare_kprobe(struct kprobe *p)
218858ac8eSSven Schnelle {
228858ac8eSSven Schnelle if ((unsigned long)p->addr & 3UL)
238858ac8eSSven Schnelle return -EINVAL;
248858ac8eSSven Schnelle
258858ac8eSSven Schnelle p->ainsn.insn = get_insn_slot();
268858ac8eSSven Schnelle if (!p->ainsn.insn)
278858ac8eSSven Schnelle return -ENOMEM;
288858ac8eSSven Schnelle
299b046d02SHelge Deller /*
309b046d02SHelge Deller * Set up new instructions. Second break instruction will
319b046d02SHelge Deller * trigger call of parisc_kprobe_ss_handler().
329b046d02SHelge Deller */
338858ac8eSSven Schnelle p->opcode = *p->addr;
349b046d02SHelge Deller p->ainsn.insn[0] = p->opcode;
359b046d02SHelge Deller p->ainsn.insn[1] = PARISC_KPROBES_BREAK_INSN2;
369b046d02SHelge Deller
378858ac8eSSven Schnelle flush_insn_slot(p);
388858ac8eSSven Schnelle return 0;
398858ac8eSSven Schnelle }
408858ac8eSSven Schnelle
arch_remove_kprobe(struct kprobe * p)418858ac8eSSven Schnelle void __kprobes arch_remove_kprobe(struct kprobe *p)
428858ac8eSSven Schnelle {
438858ac8eSSven Schnelle if (!p->ainsn.insn)
448858ac8eSSven Schnelle return;
458858ac8eSSven Schnelle
468858ac8eSSven Schnelle free_insn_slot(p->ainsn.insn, 0);
478858ac8eSSven Schnelle p->ainsn.insn = NULL;
488858ac8eSSven Schnelle }
498858ac8eSSven Schnelle
arch_arm_kprobe(struct kprobe * p)508858ac8eSSven Schnelle void __kprobes arch_arm_kprobe(struct kprobe *p)
518858ac8eSSven Schnelle {
528858ac8eSSven Schnelle patch_text(p->addr, PARISC_KPROBES_BREAK_INSN);
538858ac8eSSven Schnelle }
548858ac8eSSven Schnelle
arch_disarm_kprobe(struct kprobe * p)558858ac8eSSven Schnelle void __kprobes arch_disarm_kprobe(struct kprobe *p)
568858ac8eSSven Schnelle {
578858ac8eSSven Schnelle patch_text(p->addr, p->opcode);
588858ac8eSSven Schnelle }
598858ac8eSSven Schnelle
save_previous_kprobe(struct kprobe_ctlblk * kcb)608858ac8eSSven Schnelle static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
618858ac8eSSven Schnelle {
628858ac8eSSven Schnelle kcb->prev_kprobe.kp = kprobe_running();
638858ac8eSSven Schnelle kcb->prev_kprobe.status = kcb->kprobe_status;
648858ac8eSSven Schnelle }
658858ac8eSSven Schnelle
restore_previous_kprobe(struct kprobe_ctlblk * kcb)668858ac8eSSven Schnelle static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
678858ac8eSSven Schnelle {
688858ac8eSSven Schnelle __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
698858ac8eSSven Schnelle kcb->kprobe_status = kcb->prev_kprobe.status;
708858ac8eSSven Schnelle }
718858ac8eSSven Schnelle
set_current_kprobe(struct kprobe * p)728858ac8eSSven Schnelle static inline void __kprobes set_current_kprobe(struct kprobe *p)
738858ac8eSSven Schnelle {
748858ac8eSSven Schnelle __this_cpu_write(current_kprobe, p);
758858ac8eSSven Schnelle }
768858ac8eSSven Schnelle
setup_singlestep(struct kprobe * p,struct kprobe_ctlblk * kcb,struct pt_regs * regs)778858ac8eSSven Schnelle static void __kprobes setup_singlestep(struct kprobe *p,
788858ac8eSSven Schnelle struct kprobe_ctlblk *kcb, struct pt_regs *regs)
798858ac8eSSven Schnelle {
808858ac8eSSven Schnelle kcb->iaoq[0] = regs->iaoq[0];
818858ac8eSSven Schnelle kcb->iaoq[1] = regs->iaoq[1];
829b046d02SHelge Deller instruction_pointer_set(regs, (unsigned long)p->ainsn.insn);
838858ac8eSSven Schnelle }
848858ac8eSSven Schnelle
parisc_kprobe_break_handler(struct pt_regs * regs)858858ac8eSSven Schnelle int __kprobes parisc_kprobe_break_handler(struct pt_regs *regs)
868858ac8eSSven Schnelle {
878858ac8eSSven Schnelle struct kprobe *p;
888858ac8eSSven Schnelle struct kprobe_ctlblk *kcb;
898858ac8eSSven Schnelle
908858ac8eSSven Schnelle preempt_disable();
918858ac8eSSven Schnelle
928858ac8eSSven Schnelle kcb = get_kprobe_ctlblk();
938858ac8eSSven Schnelle p = get_kprobe((unsigned long *)regs->iaoq[0]);
948858ac8eSSven Schnelle
958858ac8eSSven Schnelle if (!p) {
968858ac8eSSven Schnelle preempt_enable_no_resched();
978858ac8eSSven Schnelle return 0;
988858ac8eSSven Schnelle }
998858ac8eSSven Schnelle
1008858ac8eSSven Schnelle if (kprobe_running()) {
1018858ac8eSSven Schnelle /*
1028858ac8eSSven Schnelle * We have reentered the kprobe_handler, since another kprobe
1038858ac8eSSven Schnelle * was hit while within the handler, we save the original
1048858ac8eSSven Schnelle * kprobes and single step on the instruction of the new probe
1058858ac8eSSven Schnelle * without calling any user handlers to avoid recursive
1068858ac8eSSven Schnelle * kprobes.
1078858ac8eSSven Schnelle */
1088858ac8eSSven Schnelle save_previous_kprobe(kcb);
1098858ac8eSSven Schnelle set_current_kprobe(p);
1108858ac8eSSven Schnelle kprobes_inc_nmissed_count(p);
1118858ac8eSSven Schnelle setup_singlestep(p, kcb, regs);
1128858ac8eSSven Schnelle kcb->kprobe_status = KPROBE_REENTER;
1138858ac8eSSven Schnelle return 1;
1148858ac8eSSven Schnelle }
1158858ac8eSSven Schnelle
1168858ac8eSSven Schnelle set_current_kprobe(p);
1178858ac8eSSven Schnelle kcb->kprobe_status = KPROBE_HIT_ACTIVE;
1188858ac8eSSven Schnelle
1198858ac8eSSven Schnelle /* If we have no pre-handler or it returned 0, we continue with
1208858ac8eSSven Schnelle * normal processing. If we have a pre-handler and it returned
1218858ac8eSSven Schnelle * non-zero - which means user handler setup registers to exit
1228858ac8eSSven Schnelle * to another instruction, we must skip the single stepping.
1238858ac8eSSven Schnelle */
1248858ac8eSSven Schnelle
1258858ac8eSSven Schnelle if (!p->pre_handler || !p->pre_handler(p, regs)) {
1268858ac8eSSven Schnelle setup_singlestep(p, kcb, regs);
1278858ac8eSSven Schnelle kcb->kprobe_status = KPROBE_HIT_SS;
1288858ac8eSSven Schnelle } else {
1298858ac8eSSven Schnelle reset_current_kprobe();
1308858ac8eSSven Schnelle preempt_enable_no_resched();
1318858ac8eSSven Schnelle }
1328858ac8eSSven Schnelle return 1;
1338858ac8eSSven Schnelle }
1348858ac8eSSven Schnelle
parisc_kprobe_ss_handler(struct pt_regs * regs)1358858ac8eSSven Schnelle int __kprobes parisc_kprobe_ss_handler(struct pt_regs *regs)
1368858ac8eSSven Schnelle {
1378858ac8eSSven Schnelle struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
1388858ac8eSSven Schnelle struct kprobe *p = kprobe_running();
1398858ac8eSSven Schnelle
14059a783dbSHelge Deller if (!p)
14159a783dbSHelge Deller return 0;
14259a783dbSHelge Deller
1438858ac8eSSven Schnelle if (regs->iaoq[0] != (unsigned long)p->ainsn.insn+4)
1448858ac8eSSven Schnelle return 0;
1458858ac8eSSven Schnelle
1468858ac8eSSven Schnelle /* restore back original saved kprobe variables and continue */
1478858ac8eSSven Schnelle if (kcb->kprobe_status == KPROBE_REENTER) {
1488858ac8eSSven Schnelle restore_previous_kprobe(kcb);
1498858ac8eSSven Schnelle return 1;
1508858ac8eSSven Schnelle }
1518858ac8eSSven Schnelle
1528858ac8eSSven Schnelle /* for absolute branch instructions we can copy iaoq_b. for relative
1538858ac8eSSven Schnelle * branch instructions we need to calculate the new address based on the
1548858ac8eSSven Schnelle * difference between iaoq_f and iaoq_b. We cannot use iaoq_b without
155*a65bcad5SJulia Lawall * modifications because it's based on our ainsn.insn address.
1568858ac8eSSven Schnelle */
1578858ac8eSSven Schnelle
1588858ac8eSSven Schnelle if (p->post_handler)
1598858ac8eSSven Schnelle p->post_handler(p, regs, 0);
1608858ac8eSSven Schnelle
1618858ac8eSSven Schnelle switch (regs->iir >> 26) {
1628858ac8eSSven Schnelle case 0x38: /* BE */
1638858ac8eSSven Schnelle case 0x39: /* BE,L */
1648858ac8eSSven Schnelle case 0x3a: /* BV */
1658858ac8eSSven Schnelle case 0x3b: /* BVE */
1668858ac8eSSven Schnelle /* for absolute branches, regs->iaoq[1] has already the right
1678858ac8eSSven Schnelle * address
1688858ac8eSSven Schnelle */
1698858ac8eSSven Schnelle regs->iaoq[0] = kcb->iaoq[1];
1708858ac8eSSven Schnelle break;
1718858ac8eSSven Schnelle default:
1728858ac8eSSven Schnelle regs->iaoq[0] = kcb->iaoq[1];
1739b046d02SHelge Deller regs->iaoq[1] = regs->iaoq[0] + 4;
1748858ac8eSSven Schnelle break;
1758858ac8eSSven Schnelle }
1768858ac8eSSven Schnelle kcb->kprobe_status = KPROBE_HIT_SSDONE;
1778858ac8eSSven Schnelle reset_current_kprobe();
1788858ac8eSSven Schnelle return 1;
1798858ac8eSSven Schnelle }
1808858ac8eSSven Schnelle
__kretprobe_trampoline(void)181adf8a61aSMasami Hiramatsu void __kretprobe_trampoline(void)
182e0b59b7bSSven Schnelle {
183e0b59b7bSSven Schnelle asm volatile("nop");
184e0b59b7bSSven Schnelle asm volatile("nop");
185e0b59b7bSSven Schnelle }
186e0b59b7bSSven Schnelle
187e0b59b7bSSven Schnelle static int __kprobes trampoline_probe_handler(struct kprobe *p,
188e0b59b7bSSven Schnelle struct pt_regs *regs);
189e0b59b7bSSven Schnelle
190e0b59b7bSSven Schnelle static struct kprobe trampoline_p = {
191e0b59b7bSSven Schnelle .pre_handler = trampoline_probe_handler
192e0b59b7bSSven Schnelle };
193e0b59b7bSSven Schnelle
trampoline_probe_handler(struct kprobe * p,struct pt_regs * regs)194e0b59b7bSSven Schnelle static int __kprobes trampoline_probe_handler(struct kprobe *p,
195e0b59b7bSSven Schnelle struct pt_regs *regs)
196e0b59b7bSSven Schnelle {
1979b046d02SHelge Deller __kretprobe_trampoline_handler(regs, NULL);
19816ff6f7aSMasami Hiramatsu
199e0b59b7bSSven Schnelle return 1;
200e0b59b7bSSven Schnelle }
201e0b59b7bSSven Schnelle
arch_kretprobe_fixup_return(struct pt_regs * regs,kprobe_opcode_t * correct_ret_addr)2029b046d02SHelge Deller void arch_kretprobe_fixup_return(struct pt_regs *regs,
2039b046d02SHelge Deller kprobe_opcode_t *correct_ret_addr)
2049b046d02SHelge Deller {
2059b046d02SHelge Deller regs->gr[2] = (unsigned long)correct_ret_addr;
2069b046d02SHelge Deller }
2079b046d02SHelge Deller
arch_prepare_kretprobe(struct kretprobe_instance * ri,struct pt_regs * regs)208e0b59b7bSSven Schnelle void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
209e0b59b7bSSven Schnelle struct pt_regs *regs)
210e0b59b7bSSven Schnelle {
211e0b59b7bSSven Schnelle ri->ret_addr = (kprobe_opcode_t *)regs->gr[2];
21216ff6f7aSMasami Hiramatsu ri->fp = NULL;
213e0b59b7bSSven Schnelle
214e0b59b7bSSven Schnelle /* Replace the return addr with trampoline addr. */
215e0b59b7bSSven Schnelle regs->gr[2] = (unsigned long)trampoline_p.addr;
216e0b59b7bSSven Schnelle }
217e0b59b7bSSven Schnelle
arch_trampoline_kprobe(struct kprobe * p)218e0b59b7bSSven Schnelle int __kprobes arch_trampoline_kprobe(struct kprobe *p)
219e0b59b7bSSven Schnelle {
220e0b59b7bSSven Schnelle return p->addr == trampoline_p.addr;
221e0b59b7bSSven Schnelle }
2228858ac8eSSven Schnelle
arch_init_kprobes(void)2238858ac8eSSven Schnelle int __init arch_init_kprobes(void)
2248858ac8eSSven Schnelle {
225e0b59b7bSSven Schnelle trampoline_p.addr = (kprobe_opcode_t *)
226adf8a61aSMasami Hiramatsu dereference_function_descriptor(__kretprobe_trampoline);
227e0b59b7bSSven Schnelle return register_kprobe(&trampoline_p);
2288858ac8eSSven Schnelle }
229