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> 8*9b046d02SHelge 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 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 29*9b046d02SHelge Deller /* 30*9b046d02SHelge Deller * Set up new instructions. Second break instruction will 31*9b046d02SHelge Deller * trigger call of parisc_kprobe_ss_handler(). 32*9b046d02SHelge Deller */ 338858ac8eSSven Schnelle p->opcode = *p->addr; 34*9b046d02SHelge Deller p->ainsn.insn[0] = p->opcode; 35*9b046d02SHelge Deller p->ainsn.insn[1] = PARISC_KPROBES_BREAK_INSN2; 36*9b046d02SHelge Deller 378858ac8eSSven Schnelle flush_insn_slot(p); 388858ac8eSSven Schnelle return 0; 398858ac8eSSven Schnelle } 408858ac8eSSven Schnelle 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 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 558858ac8eSSven Schnelle void __kprobes arch_disarm_kprobe(struct kprobe *p) 568858ac8eSSven Schnelle { 578858ac8eSSven Schnelle patch_text(p->addr, p->opcode); 588858ac8eSSven Schnelle } 598858ac8eSSven Schnelle 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 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 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 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]; 82*9b046d02SHelge Deller instruction_pointer_set(regs, (unsigned long)p->ainsn.insn); 838858ac8eSSven Schnelle } 848858ac8eSSven Schnelle 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 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 1558858ac8eSSven Schnelle * modificationt 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]; 173*9b046d02SHelge 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 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 194e0b59b7bSSven Schnelle static int __kprobes trampoline_probe_handler(struct kprobe *p, 195e0b59b7bSSven Schnelle struct pt_regs *regs) 196e0b59b7bSSven Schnelle { 197*9b046d02SHelge Deller __kretprobe_trampoline_handler(regs, NULL); 19816ff6f7aSMasami Hiramatsu 199e0b59b7bSSven Schnelle return 1; 200e0b59b7bSSven Schnelle } 201e0b59b7bSSven Schnelle 202*9b046d02SHelge Deller void arch_kretprobe_fixup_return(struct pt_regs *regs, 203*9b046d02SHelge Deller kprobe_opcode_t *correct_ret_addr) 204*9b046d02SHelge Deller { 205*9b046d02SHelge Deller regs->gr[2] = (unsigned long)correct_ret_addr; 206*9b046d02SHelge Deller } 207*9b046d02SHelge Deller 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 218e0b59b7bSSven Schnelle int __kprobes arch_trampoline_kprobe(struct kprobe *p) 219e0b59b7bSSven Schnelle { 220e0b59b7bSSven Schnelle return p->addr == trampoline_p.addr; 221e0b59b7bSSven Schnelle } 2228858ac8eSSven Schnelle 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