aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/kernel/kprobes.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc64/kernel/kprobes.c')
-rw-r--r--arch/ppc64/kernel/kprobes.c40
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;
44static unsigned long kprobe_status_prev, kprobe_saved_msr_prev; 44static unsigned long kprobe_status_prev, kprobe_saved_msr_prev;
45static struct pt_regs jprobe_saved_regs; 45static struct pt_regs jprobe_saved_regs;
46 46
47int arch_prepare_kprobe(struct kprobe *p) 47int __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
71void arch_copy_kprobe(struct kprobe *p) 71void __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
77void arch_arm_kprobe(struct kprobe *p) 77void __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
84void arch_disarm_kprobe(struct kprobe *p) 84void __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
91void arch_remove_kprobe(struct kprobe *p) 91void __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
125void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) 125void __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 */
247int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) 249int __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 */
311static void resume_execution(struct kprobe *p, struct pt_regs *regs) 313static 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 */
376int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, 378int __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
409int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) 411int __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
422void jprobe_return(void) 424void __kprobes jprobe_return(void)
423{ 425{
424 asm volatile("trap" ::: "memory"); 426 asm volatile("trap" ::: "memory");
425} 427}
426 428
427void jprobe_return_end(void) 429void __kprobes jprobe_return_end(void)
428{ 430{
429}; 431};
430 432
431int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) 433int __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