linux/arch/parisc/kernel/kprobes.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * arch/parisc/kernel/kprobes.c
   4 *
   5 * PA-RISC kprobes implementation
   6 *
   7 * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org>
   8 */
   9
  10#include <linux/types.h>
  11#include <linux/kprobes.h>
  12#include <linux/slab.h>
  13#include <asm/cacheflush.h>
  14#include <asm/patch.h>
  15
  16DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
  17DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
  18
  19int __kprobes arch_prepare_kprobe(struct kprobe *p)
  20{
  21        if ((unsigned long)p->addr & 3UL)
  22                return -EINVAL;
  23
  24        p->ainsn.insn = get_insn_slot();
  25        if (!p->ainsn.insn)
  26                return -ENOMEM;
  27
  28        memcpy(p->ainsn.insn, p->addr,
  29                MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
  30        p->opcode = *p->addr;
  31        flush_insn_slot(p);
  32        return 0;
  33}
  34
  35void __kprobes arch_remove_kprobe(struct kprobe *p)
  36{
  37        if (!p->ainsn.insn)
  38                return;
  39
  40        free_insn_slot(p->ainsn.insn, 0);
  41        p->ainsn.insn = NULL;
  42}
  43
  44void __kprobes arch_arm_kprobe(struct kprobe *p)
  45{
  46        patch_text(p->addr, PARISC_KPROBES_BREAK_INSN);
  47}
  48
  49void __kprobes arch_disarm_kprobe(struct kprobe *p)
  50{
  51        patch_text(p->addr, p->opcode);
  52}
  53
  54static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
  55{
  56        kcb->prev_kprobe.kp = kprobe_running();
  57        kcb->prev_kprobe.status = kcb->kprobe_status;
  58}
  59
  60static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
  61{
  62        __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
  63        kcb->kprobe_status = kcb->prev_kprobe.status;
  64}
  65
  66static inline void __kprobes set_current_kprobe(struct kprobe *p)
  67{
  68        __this_cpu_write(current_kprobe, p);
  69}
  70
  71static void __kprobes setup_singlestep(struct kprobe *p,
  72                struct kprobe_ctlblk *kcb, struct pt_regs *regs)
  73{
  74        kcb->iaoq[0] = regs->iaoq[0];
  75        kcb->iaoq[1] = regs->iaoq[1];
  76        regs->iaoq[0] = (unsigned long)p->ainsn.insn;
  77        mtctl(0, 0);
  78        regs->gr[0] |= PSW_R;
  79}
  80
  81int __kprobes parisc_kprobe_break_handler(struct pt_regs *regs)
  82{
  83        struct kprobe *p;
  84        struct kprobe_ctlblk *kcb;
  85
  86        preempt_disable();
  87
  88        kcb = get_kprobe_ctlblk();
  89        p = get_kprobe((unsigned long *)regs->iaoq[0]);
  90
  91        if (!p) {
  92                preempt_enable_no_resched();
  93                return 0;
  94        }
  95
  96        if (kprobe_running()) {
  97                /*
  98                 * We have reentered the kprobe_handler, since another kprobe
  99                 * was hit while within the handler, we save the original
 100                 * kprobes and single step on the instruction of the new probe
 101                 * without calling any user handlers to avoid recursive
 102                 * kprobes.
 103                 */
 104                save_previous_kprobe(kcb);
 105                set_current_kprobe(p);
 106                kprobes_inc_nmissed_count(p);
 107                setup_singlestep(p, kcb, regs);
 108                kcb->kprobe_status = KPROBE_REENTER;
 109                return 1;
 110        }
 111
 112        set_current_kprobe(p);
 113        kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 114
 115        /* If we have no pre-handler or it returned 0, we continue with
 116         * normal processing. If we have a pre-handler and it returned
 117         * non-zero - which means user handler setup registers to exit
 118         * to another instruction, we must skip the single stepping.
 119         */
 120
 121        if (!p->pre_handler || !p->pre_handler(p, regs)) {
 122                setup_singlestep(p, kcb, regs);
 123                kcb->kprobe_status = KPROBE_HIT_SS;
 124        } else {
 125                reset_current_kprobe();
 126                preempt_enable_no_resched();
 127        }
 128        return 1;
 129}
 130
 131int __kprobes parisc_kprobe_ss_handler(struct pt_regs *regs)
 132{
 133        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 134        struct kprobe *p = kprobe_running();
 135
 136        if (!p)
 137                return 0;
 138
 139        if (regs->iaoq[0] != (unsigned long)p->ainsn.insn+4)
 140                return 0;
 141
 142        /* restore back original saved kprobe variables and continue */
 143        if (kcb->kprobe_status == KPROBE_REENTER) {
 144                restore_previous_kprobe(kcb);
 145                return 1;
 146        }
 147
 148        /* for absolute branch instructions we can copy iaoq_b. for relative
 149         * branch instructions we need to calculate the new address based on the
 150         * difference between iaoq_f and iaoq_b. We cannot use iaoq_b without
 151         * modificationt because it's based on our ainsn.insn address.
 152         */
 153
 154        if (p->post_handler)
 155                p->post_handler(p, regs, 0);
 156
 157        switch (regs->iir >> 26) {
 158        case 0x38: /* BE */
 159        case 0x39: /* BE,L */
 160        case 0x3a: /* BV */
 161        case 0x3b: /* BVE */
 162                /* for absolute branches, regs->iaoq[1] has already the right
 163                 * address
 164                 */
 165                regs->iaoq[0] = kcb->iaoq[1];
 166                break;
 167        default:
 168                regs->iaoq[1] = kcb->iaoq[0];
 169                regs->iaoq[1] += (regs->iaoq[1] - regs->iaoq[0]) + 4;
 170                regs->iaoq[0] = kcb->iaoq[1];
 171                break;
 172        }
 173        kcb->kprobe_status = KPROBE_HIT_SSDONE;
 174        reset_current_kprobe();
 175        return 1;
 176}
 177
 178static inline void kretprobe_trampoline(void)
 179{
 180        asm volatile("nop");
 181        asm volatile("nop");
 182}
 183
 184static int __kprobes trampoline_probe_handler(struct kprobe *p,
 185                                              struct pt_regs *regs);
 186
 187static struct kprobe trampoline_p = {
 188        .pre_handler = trampoline_probe_handler
 189};
 190
 191static int __kprobes trampoline_probe_handler(struct kprobe *p,
 192                                              struct pt_regs *regs)
 193{
 194        unsigned long orig_ret_address;
 195
 196        orig_ret_address = __kretprobe_trampoline_handler(regs, trampoline_p.addr, NULL);
 197        instruction_pointer_set(regs, orig_ret_address);
 198
 199        return 1;
 200}
 201
 202void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 203                                      struct pt_regs *regs)
 204{
 205        ri->ret_addr = (kprobe_opcode_t *)regs->gr[2];
 206        ri->fp = NULL;
 207
 208        /* Replace the return addr with trampoline addr. */
 209        regs->gr[2] = (unsigned long)trampoline_p.addr;
 210}
 211
 212int __kprobes arch_trampoline_kprobe(struct kprobe *p)
 213{
 214        return p->addr == trampoline_p.addr;
 215}
 216
 217int __init arch_init_kprobes(void)
 218{
 219        trampoline_p.addr = (kprobe_opcode_t *)
 220                dereference_function_descriptor(kretprobe_trampoline);
 221        return register_kprobe(&trampoline_p);
 222}
 223