linux/arch/csky/kernel/probes/ftrace.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2
   3#include <linux/kprobes.h>
   4
   5int arch_check_ftrace_location(struct kprobe *p)
   6{
   7        if (ftrace_location((unsigned long)p->addr))
   8                p->flags |= KPROBE_FLAG_FTRACE;
   9        return 0;
  10}
  11
  12/* Ftrace callback handler for kprobes -- called under preepmt disabled */
  13void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
  14                           struct ftrace_ops *ops, struct ftrace_regs *fregs)
  15{
  16        int bit;
  17        bool lr_saver = false;
  18        struct kprobe *p;
  19        struct kprobe_ctlblk *kcb;
  20        struct pt_regs *regs;
  21
  22        bit = ftrace_test_recursion_trylock(ip, parent_ip);
  23        if (bit < 0)
  24                return;
  25
  26        regs = ftrace_get_regs(fregs);
  27        preempt_disable_notrace();
  28        p = get_kprobe((kprobe_opcode_t *)ip);
  29        if (!p) {
  30                p = get_kprobe((kprobe_opcode_t *)(ip - MCOUNT_INSN_SIZE));
  31                if (unlikely(!p) || kprobe_disabled(p))
  32                        goto out;
  33                lr_saver = true;
  34        }
  35
  36        kcb = get_kprobe_ctlblk();
  37        if (kprobe_running()) {
  38                kprobes_inc_nmissed_count(p);
  39        } else {
  40                unsigned long orig_ip = instruction_pointer(regs);
  41
  42                if (lr_saver)
  43                        ip -= MCOUNT_INSN_SIZE;
  44                instruction_pointer_set(regs, ip);
  45                __this_cpu_write(current_kprobe, p);
  46                kcb->kprobe_status = KPROBE_HIT_ACTIVE;
  47                if (!p->pre_handler || !p->pre_handler(p, regs)) {
  48                        /*
  49                         * Emulate singlestep (and also recover regs->pc)
  50                         * as if there is a nop
  51                         */
  52                        instruction_pointer_set(regs,
  53                                (unsigned long)p->addr + MCOUNT_INSN_SIZE);
  54                        if (unlikely(p->post_handler)) {
  55                                kcb->kprobe_status = KPROBE_HIT_SSDONE;
  56                                p->post_handler(p, regs, 0);
  57                        }
  58                        instruction_pointer_set(regs, orig_ip);
  59                }
  60                /*
  61                 * If pre_handler returns !0, it changes regs->pc. We have to
  62                 * skip emulating post_handler.
  63                 */
  64                __this_cpu_write(current_kprobe, NULL);
  65        }
  66out:
  67        preempt_enable_notrace();
  68        ftrace_test_recursion_unlock(bit);
  69}
  70NOKPROBE_SYMBOL(kprobe_ftrace_handler);
  71
  72int arch_prepare_kprobe_ftrace(struct kprobe *p)
  73{
  74        p->ainsn.api.insn = NULL;
  75        return 0;
  76}
  77