diff options
| -rw-r--r-- | arch/x86/include/asm/kprobes.h | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/kprobes.c | 48 | ||||
| -rw-r--r-- | include/linux/kprobes.h | 2 | ||||
| -rw-r--r-- | kernel/kprobes.c | 2 |
4 files changed, 51 insertions, 2 deletions
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h index 547882539157..d3ddd17405d0 100644 --- a/arch/x86/include/asm/kprobes.h +++ b/arch/x86/include/asm/kprobes.h | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <asm/insn.h> | 27 | #include <asm/insn.h> |
| 28 | 28 | ||
| 29 | #define __ARCH_WANT_KPROBES_INSN_SLOT | 29 | #define __ARCH_WANT_KPROBES_INSN_SLOT |
| 30 | #define ARCH_SUPPORTS_KPROBES_ON_FTRACE | ||
| 30 | 31 | ||
| 31 | struct pt_regs; | 32 | struct pt_regs; |
| 32 | struct kprobe; | 33 | struct kprobe; |
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index e2f751efb7b1..47ae1023a93c 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c | |||
| @@ -1052,6 +1052,54 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 1052 | return 0; | 1052 | return 0; |
| 1053 | } | 1053 | } |
| 1054 | 1054 | ||
| 1055 | #ifdef KPROBES_CAN_USE_FTRACE | ||
| 1056 | /* Ftrace callback handler for kprobes */ | ||
| 1057 | void __kprobes kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, | ||
| 1058 | struct ftrace_ops *ops, struct pt_regs *regs) | ||
| 1059 | { | ||
| 1060 | struct kprobe *p; | ||
| 1061 | struct kprobe_ctlblk *kcb; | ||
| 1062 | unsigned long flags; | ||
| 1063 | |||
| 1064 | /* Disable irq for emulating a breakpoint and avoiding preempt */ | ||
| 1065 | local_irq_save(flags); | ||
| 1066 | |||
| 1067 | p = get_kprobe((kprobe_opcode_t *)ip); | ||
| 1068 | if (unlikely(!p) || kprobe_disabled(p)) | ||
| 1069 | goto end; | ||
| 1070 | |||
| 1071 | kcb = get_kprobe_ctlblk(); | ||
| 1072 | if (kprobe_running()) { | ||
| 1073 | kprobes_inc_nmissed_count(p); | ||
| 1074 | } else { | ||
| 1075 | regs->ip += sizeof(kprobe_opcode_t); | ||
| 1076 | |||
| 1077 | __this_cpu_write(current_kprobe, p); | ||
| 1078 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; | ||
| 1079 | if (p->pre_handler) | ||
| 1080 | p->pre_handler(p, regs); | ||
| 1081 | |||
| 1082 | if (unlikely(p->post_handler)) { | ||
| 1083 | /* Emulate singlestep as if there is a 5byte nop */ | ||
| 1084 | regs->ip = ip + MCOUNT_INSN_SIZE; | ||
| 1085 | kcb->kprobe_status = KPROBE_HIT_SSDONE; | ||
| 1086 | p->post_handler(p, regs, 0); | ||
| 1087 | } | ||
| 1088 | __this_cpu_write(current_kprobe, NULL); | ||
| 1089 | regs->ip = ip; /* Recover for next callback */ | ||
| 1090 | } | ||
| 1091 | end: | ||
| 1092 | local_irq_restore(flags); | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | int __kprobes arch_prepare_kprobe_ftrace(struct kprobe *p) | ||
| 1096 | { | ||
| 1097 | p->ainsn.insn = NULL; | ||
| 1098 | p->ainsn.boostable = -1; | ||
| 1099 | return 0; | ||
| 1100 | } | ||
| 1101 | #endif | ||
| 1102 | |||
| 1055 | int __init arch_init_kprobes(void) | 1103 | int __init arch_init_kprobes(void) |
| 1056 | { | 1104 | { |
| 1057 | return arch_init_optprobes(); | 1105 | return arch_init_optprobes(); |
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index aa0d05e852e3..23755ba42abc 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h | |||
| @@ -318,7 +318,7 @@ extern int proc_kprobes_optimization_handler(struct ctl_table *table, | |||
| 318 | #endif /* CONFIG_OPTPROBES */ | 318 | #endif /* CONFIG_OPTPROBES */ |
| 319 | #ifdef KPROBES_CAN_USE_FTRACE | 319 | #ifdef KPROBES_CAN_USE_FTRACE |
| 320 | extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, | 320 | extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, |
| 321 | struct pt_regs *regs); | 321 | struct ftrace_ops *ops, struct pt_regs *regs); |
| 322 | extern int arch_prepare_kprobe_ftrace(struct kprobe *p); | 322 | extern int arch_prepare_kprobe_ftrace(struct kprobe *p); |
| 323 | #endif | 323 | #endif |
| 324 | 324 | ||
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 69c16efc315b..35b4315d84f5 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
| @@ -921,7 +921,7 @@ static __kprobes struct kprobe *alloc_aggr_kprobe(struct kprobe *p) | |||
| 921 | 921 | ||
| 922 | #ifdef KPROBES_CAN_USE_FTRACE | 922 | #ifdef KPROBES_CAN_USE_FTRACE |
| 923 | static struct ftrace_ops kprobe_ftrace_ops __read_mostly = { | 923 | static struct ftrace_ops kprobe_ftrace_ops __read_mostly = { |
| 924 | .regs_func = kprobe_ftrace_handler, | 924 | .func = kprobe_ftrace_handler, |
| 925 | .flags = FTRACE_OPS_FL_SAVE_REGS, | 925 | .flags = FTRACE_OPS_FL_SAVE_REGS, |
| 926 | }; | 926 | }; |
| 927 | static int kprobe_ftrace_enabled; | 927 | static int kprobe_ftrace_enabled; |
