diff options
Diffstat (limited to 'arch/ppc64/kernel/kprobes.c')
-rw-r--r-- | arch/ppc64/kernel/kprobes.c | 40 |
1 files changed, 21 insertions, 19 deletions
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c index a3d519518fb8..7e80d49c589a 100644 --- a/arch/ppc64/kernel/kprobes.c +++ b/arch/ppc64/kernel/kprobes.c | |||
@@ -44,7 +44,7 @@ static struct kprobe *kprobe_prev; | |||
44 | static unsigned long kprobe_status_prev, kprobe_saved_msr_prev; | 44 | static unsigned long kprobe_status_prev, kprobe_saved_msr_prev; |
45 | static struct pt_regs jprobe_saved_regs; | 45 | static struct pt_regs jprobe_saved_regs; |
46 | 46 | ||
47 | int arch_prepare_kprobe(struct kprobe *p) | 47 | int __kprobes arch_prepare_kprobe(struct kprobe *p) |
48 | { | 48 | { |
49 | int ret = 0; | 49 | int ret = 0; |
50 | kprobe_opcode_t insn = *p->addr; | 50 | kprobe_opcode_t insn = *p->addr; |
@@ -68,27 +68,27 @@ int arch_prepare_kprobe(struct kprobe *p) | |||
68 | return ret; | 68 | return ret; |
69 | } | 69 | } |
70 | 70 | ||
71 | void arch_copy_kprobe(struct kprobe *p) | 71 | void __kprobes arch_copy_kprobe(struct kprobe *p) |
72 | { | 72 | { |
73 | memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); | 73 | memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); |
74 | p->opcode = *p->addr; | 74 | p->opcode = *p->addr; |
75 | } | 75 | } |
76 | 76 | ||
77 | void arch_arm_kprobe(struct kprobe *p) | 77 | void __kprobes arch_arm_kprobe(struct kprobe *p) |
78 | { | 78 | { |
79 | *p->addr = BREAKPOINT_INSTRUCTION; | 79 | *p->addr = BREAKPOINT_INSTRUCTION; |
80 | flush_icache_range((unsigned long) p->addr, | 80 | flush_icache_range((unsigned long) p->addr, |
81 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); | 81 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); |
82 | } | 82 | } |
83 | 83 | ||
84 | void arch_disarm_kprobe(struct kprobe *p) | 84 | void __kprobes arch_disarm_kprobe(struct kprobe *p) |
85 | { | 85 | { |
86 | *p->addr = p->opcode; | 86 | *p->addr = p->opcode; |
87 | flush_icache_range((unsigned long) p->addr, | 87 | flush_icache_range((unsigned long) p->addr, |
88 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); | 88 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); |
89 | } | 89 | } |
90 | 90 | ||
91 | void arch_remove_kprobe(struct kprobe *p) | 91 | void __kprobes arch_remove_kprobe(struct kprobe *p) |
92 | { | 92 | { |
93 | up(&kprobe_mutex); | 93 | up(&kprobe_mutex); |
94 | free_insn_slot(p->ainsn.insn); | 94 | free_insn_slot(p->ainsn.insn); |
@@ -102,7 +102,7 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | |||
102 | regs->msr |= MSR_SE; | 102 | regs->msr |= MSR_SE; |
103 | 103 | ||
104 | /* single step inline if it is a trap variant */ | 104 | /* single step inline if it is a trap variant */ |
105 | if (IS_TW(insn) || IS_TD(insn) || IS_TWI(insn) || IS_TDI(insn)) | 105 | if (is_trap(insn)) |
106 | regs->nip = (unsigned long)p->addr; | 106 | regs->nip = (unsigned long)p->addr; |
107 | else | 107 | else |
108 | regs->nip = (unsigned long)p->ainsn.insn; | 108 | regs->nip = (unsigned long)p->ainsn.insn; |
@@ -122,7 +122,8 @@ static inline void restore_previous_kprobe(void) | |||
122 | kprobe_saved_msr = kprobe_saved_msr_prev; | 122 | kprobe_saved_msr = kprobe_saved_msr_prev; |
123 | } | 123 | } |
124 | 124 | ||
125 | void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) | 125 | void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, |
126 | struct pt_regs *regs) | ||
126 | { | 127 | { |
127 | struct kretprobe_instance *ri; | 128 | struct kretprobe_instance *ri; |
128 | 129 | ||
@@ -151,7 +152,9 @@ static inline int kprobe_handler(struct pt_regs *regs) | |||
151 | Disarm the probe we just hit, and ignore it. */ | 152 | Disarm the probe we just hit, and ignore it. */ |
152 | p = get_kprobe(addr); | 153 | p = get_kprobe(addr); |
153 | if (p) { | 154 | if (p) { |
154 | if (kprobe_status == KPROBE_HIT_SS) { | 155 | kprobe_opcode_t insn = *p->ainsn.insn; |
156 | if (kprobe_status == KPROBE_HIT_SS && | ||
157 | is_trap(insn)) { | ||
155 | regs->msr &= ~MSR_SE; | 158 | regs->msr &= ~MSR_SE; |
156 | regs->msr |= kprobe_saved_msr; | 159 | regs->msr |= kprobe_saved_msr; |
157 | unlock_kprobes(); | 160 | unlock_kprobes(); |
@@ -191,8 +194,7 @@ static inline int kprobe_handler(struct pt_regs *regs) | |||
191 | * trap variant, it could belong to someone else | 194 | * trap variant, it could belong to someone else |
192 | */ | 195 | */ |
193 | kprobe_opcode_t cur_insn = *addr; | 196 | kprobe_opcode_t cur_insn = *addr; |
194 | if (IS_TW(cur_insn) || IS_TD(cur_insn) || | 197 | if (is_trap(cur_insn)) |
195 | IS_TWI(cur_insn) || IS_TDI(cur_insn)) | ||
196 | goto no_kprobe; | 198 | goto no_kprobe; |
197 | /* | 199 | /* |
198 | * The breakpoint instruction was removed right | 200 | * The breakpoint instruction was removed right |
@@ -244,7 +246,7 @@ void kretprobe_trampoline_holder(void) | |||
244 | /* | 246 | /* |
245 | * Called when the probe at kretprobe trampoline is hit | 247 | * Called when the probe at kretprobe trampoline is hit |
246 | */ | 248 | */ |
247 | int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | 249 | int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) |
248 | { | 250 | { |
249 | struct kretprobe_instance *ri = NULL; | 251 | struct kretprobe_instance *ri = NULL; |
250 | struct hlist_head *head; | 252 | struct hlist_head *head; |
@@ -308,7 +310,7 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
308 | * single-stepped a copy of the instruction. The address of this | 310 | * single-stepped a copy of the instruction. The address of this |
309 | * copy is p->ainsn.insn. | 311 | * copy is p->ainsn.insn. |
310 | */ | 312 | */ |
311 | static void resume_execution(struct kprobe *p, struct pt_regs *regs) | 313 | static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) |
312 | { | 314 | { |
313 | int ret; | 315 | int ret; |
314 | unsigned int insn = *p->ainsn.insn; | 316 | unsigned int insn = *p->ainsn.insn; |
@@ -373,8 +375,8 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) | |||
373 | /* | 375 | /* |
374 | * Wrapper routine to for handling exceptions. | 376 | * Wrapper routine to for handling exceptions. |
375 | */ | 377 | */ |
376 | int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, | 378 | int __kprobes kprobe_exceptions_notify(struct notifier_block *self, |
377 | void *data) | 379 | unsigned long val, void *data) |
378 | { | 380 | { |
379 | struct die_args *args = (struct die_args *)data; | 381 | struct die_args *args = (struct die_args *)data; |
380 | int ret = NOTIFY_DONE; | 382 | int ret = NOTIFY_DONE; |
@@ -402,11 +404,11 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, | |||
402 | default: | 404 | default: |
403 | break; | 405 | break; |
404 | } | 406 | } |
405 | preempt_enable(); | 407 | preempt_enable_no_resched(); |
406 | return ret; | 408 | return ret; |
407 | } | 409 | } |
408 | 410 | ||
409 | int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | 411 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) |
410 | { | 412 | { |
411 | struct jprobe *jp = container_of(p, struct jprobe, kp); | 413 | struct jprobe *jp = container_of(p, struct jprobe, kp); |
412 | 414 | ||
@@ -419,16 +421,16 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
419 | return 1; | 421 | return 1; |
420 | } | 422 | } |
421 | 423 | ||
422 | void jprobe_return(void) | 424 | void __kprobes jprobe_return(void) |
423 | { | 425 | { |
424 | asm volatile("trap" ::: "memory"); | 426 | asm volatile("trap" ::: "memory"); |
425 | } | 427 | } |
426 | 428 | ||
427 | void jprobe_return_end(void) | 429 | void __kprobes jprobe_return_end(void) |
428 | { | 430 | { |
429 | }; | 431 | }; |
430 | 432 | ||
431 | int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | 433 | int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) |
432 | { | 434 | { |
433 | /* | 435 | /* |
434 | * FIXME - we should ideally be validating that we got here 'cos | 436 | * FIXME - we should ideally be validating that we got here 'cos |