Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Dynamic Ftrace based Kprobes Optimization
0004  *
0005  * Copyright (C) Hitachi Ltd., 2012
0006  * Copyright 2016 Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
0007  *        IBM Corporation
0008  */
0009 #include <linux/kprobes.h>
0010 #include <linux/ptrace.h>
0011 #include <linux/hardirq.h>
0012 #include <linux/preempt.h>
0013 #include <linux/ftrace.h>
0014 
0015 /* Ftrace callback handler for kprobes */
0016 void kprobe_ftrace_handler(unsigned long nip, unsigned long parent_nip,
0017                struct ftrace_ops *ops, struct ftrace_regs *fregs)
0018 {
0019     struct kprobe *p;
0020     struct kprobe_ctlblk *kcb;
0021     struct pt_regs *regs;
0022     int bit;
0023 
0024     bit = ftrace_test_recursion_trylock(nip, parent_nip);
0025     if (bit < 0)
0026         return;
0027 
0028     regs = ftrace_get_regs(fregs);
0029     p = get_kprobe((kprobe_opcode_t *)nip);
0030     if (unlikely(!p) || kprobe_disabled(p))
0031         goto out;
0032 
0033     kcb = get_kprobe_ctlblk();
0034     if (kprobe_running()) {
0035         kprobes_inc_nmissed_count(p);
0036     } else {
0037         /*
0038          * On powerpc, NIP is *before* this instruction for the
0039          * pre handler
0040          */
0041         regs_add_return_ip(regs, -MCOUNT_INSN_SIZE);
0042 
0043         __this_cpu_write(current_kprobe, p);
0044         kcb->kprobe_status = KPROBE_HIT_ACTIVE;
0045         if (!p->pre_handler || !p->pre_handler(p, regs)) {
0046             /*
0047              * Emulate singlestep (and also recover regs->nip)
0048              * as if there is a nop
0049              */
0050             regs_add_return_ip(regs, MCOUNT_INSN_SIZE);
0051             if (unlikely(p->post_handler)) {
0052                 kcb->kprobe_status = KPROBE_HIT_SSDONE;
0053                 p->post_handler(p, regs, 0);
0054             }
0055         }
0056         /*
0057          * If pre_handler returns !0, it changes regs->nip. We have to
0058          * skip emulating post_handler.
0059          */
0060         __this_cpu_write(current_kprobe, NULL);
0061     }
0062 out:
0063     ftrace_test_recursion_unlock(bit);
0064 }
0065 NOKPROBE_SYMBOL(kprobe_ftrace_handler);
0066 
0067 int arch_prepare_kprobe_ftrace(struct kprobe *p)
0068 {
0069     p->ainsn.insn = NULL;
0070     p->ainsn.boostable = -1;
0071     return 0;
0072 }