diff options
Diffstat (limited to 'arch/ia64/kernel/kprobes.c')
-rw-r--r-- | arch/ia64/kernel/kprobes.c | 124 |
1 files changed, 97 insertions, 27 deletions
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 884f5cd27d8a..471086b808a4 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c | |||
@@ -87,12 +87,25 @@ static enum instruction_type bundle_encoding[32][3] = { | |||
87 | * is IP relative instruction and update the kprobe | 87 | * is IP relative instruction and update the kprobe |
88 | * inst flag accordingly | 88 | * inst flag accordingly |
89 | */ | 89 | */ |
90 | static void update_kprobe_inst_flag(uint template, uint slot, uint major_opcode, | 90 | static void __kprobes update_kprobe_inst_flag(uint template, uint slot, |
91 | unsigned long kprobe_inst, struct kprobe *p) | 91 | uint major_opcode, |
92 | unsigned long kprobe_inst, | ||
93 | struct kprobe *p) | ||
92 | { | 94 | { |
93 | p->ainsn.inst_flag = 0; | 95 | p->ainsn.inst_flag = 0; |
94 | p->ainsn.target_br_reg = 0; | 96 | p->ainsn.target_br_reg = 0; |
95 | 97 | ||
98 | /* Check for Break instruction | ||
99 | * Bits 37:40 Major opcode to be zero | ||
100 | * Bits 27:32 X6 to be zero | ||
101 | * Bits 32:35 X3 to be zero | ||
102 | */ | ||
103 | if ((!major_opcode) && (!((kprobe_inst >> 27) & 0x1FF)) ) { | ||
104 | /* is a break instruction */ | ||
105 | p->ainsn.inst_flag |= INST_FLAG_BREAK_INST; | ||
106 | return; | ||
107 | } | ||
108 | |||
96 | if (bundle_encoding[template][slot] == B) { | 109 | if (bundle_encoding[template][slot] == B) { |
97 | switch (major_opcode) { | 110 | switch (major_opcode) { |
98 | case INDIRECT_CALL_OPCODE: | 111 | case INDIRECT_CALL_OPCODE: |
@@ -126,8 +139,10 @@ static void update_kprobe_inst_flag(uint template, uint slot, uint major_opcode | |||
126 | * Returns 0 if supported | 139 | * Returns 0 if supported |
127 | * Returns -EINVAL if unsupported | 140 | * Returns -EINVAL if unsupported |
128 | */ | 141 | */ |
129 | static int unsupported_inst(uint template, uint slot, uint major_opcode, | 142 | static int __kprobes unsupported_inst(uint template, uint slot, |
130 | unsigned long kprobe_inst, struct kprobe *p) | 143 | uint major_opcode, |
144 | unsigned long kprobe_inst, | ||
145 | struct kprobe *p) | ||
131 | { | 146 | { |
132 | unsigned long addr = (unsigned long)p->addr; | 147 | unsigned long addr = (unsigned long)p->addr; |
133 | 148 | ||
@@ -168,8 +183,9 @@ static int unsupported_inst(uint template, uint slot, uint major_opcode, | |||
168 | * on which we are inserting kprobe is cmp instruction | 183 | * on which we are inserting kprobe is cmp instruction |
169 | * with ctype as unc. | 184 | * with ctype as unc. |
170 | */ | 185 | */ |
171 | static uint is_cmp_ctype_unc_inst(uint template, uint slot, uint major_opcode, | 186 | static uint __kprobes is_cmp_ctype_unc_inst(uint template, uint slot, |
172 | unsigned long kprobe_inst) | 187 | uint major_opcode, |
188 | unsigned long kprobe_inst) | ||
173 | { | 189 | { |
174 | cmp_inst_t cmp_inst; | 190 | cmp_inst_t cmp_inst; |
175 | uint ctype_unc = 0; | 191 | uint ctype_unc = 0; |
@@ -201,8 +217,10 @@ out: | |||
201 | * In this function we override the bundle with | 217 | * In this function we override the bundle with |
202 | * the break instruction at the given slot. | 218 | * the break instruction at the given slot. |
203 | */ | 219 | */ |
204 | static void prepare_break_inst(uint template, uint slot, uint major_opcode, | 220 | static void __kprobes prepare_break_inst(uint template, uint slot, |
205 | unsigned long kprobe_inst, struct kprobe *p) | 221 | uint major_opcode, |
222 | unsigned long kprobe_inst, | ||
223 | struct kprobe *p) | ||
206 | { | 224 | { |
207 | unsigned long break_inst = BREAK_INST; | 225 | unsigned long break_inst = BREAK_INST; |
208 | bundle_t *bundle = &p->ainsn.insn.bundle; | 226 | bundle_t *bundle = &p->ainsn.insn.bundle; |
@@ -271,7 +289,8 @@ static inline int in_ivt_functions(unsigned long addr) | |||
271 | && addr < (unsigned long)__end_ivt_text); | 289 | && addr < (unsigned long)__end_ivt_text); |
272 | } | 290 | } |
273 | 291 | ||
274 | static int valid_kprobe_addr(int template, int slot, unsigned long addr) | 292 | static int __kprobes valid_kprobe_addr(int template, int slot, |
293 | unsigned long addr) | ||
275 | { | 294 | { |
276 | if ((slot > 2) || ((bundle_encoding[template][1] == L) && slot > 1)) { | 295 | if ((slot > 2) || ((bundle_encoding[template][1] == L) && slot > 1)) { |
277 | printk(KERN_WARNING "Attempting to insert unaligned kprobe " | 296 | printk(KERN_WARNING "Attempting to insert unaligned kprobe " |
@@ -323,7 +342,7 @@ static void kretprobe_trampoline(void) | |||
323 | * - cleanup by marking the instance as unused | 342 | * - cleanup by marking the instance as unused |
324 | * - long jump back to the original return address | 343 | * - long jump back to the original return address |
325 | */ | 344 | */ |
326 | int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | 345 | int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) |
327 | { | 346 | { |
328 | struct kretprobe_instance *ri = NULL; | 347 | struct kretprobe_instance *ri = NULL; |
329 | struct hlist_head *head; | 348 | struct hlist_head *head; |
@@ -381,7 +400,8 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
381 | return 1; | 400 | return 1; |
382 | } | 401 | } |
383 | 402 | ||
384 | void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) | 403 | void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, |
404 | struct pt_regs *regs) | ||
385 | { | 405 | { |
386 | struct kretprobe_instance *ri; | 406 | struct kretprobe_instance *ri; |
387 | 407 | ||
@@ -399,7 +419,7 @@ void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) | |||
399 | } | 419 | } |
400 | } | 420 | } |
401 | 421 | ||
402 | int arch_prepare_kprobe(struct kprobe *p) | 422 | int __kprobes arch_prepare_kprobe(struct kprobe *p) |
403 | { | 423 | { |
404 | unsigned long addr = (unsigned long) p->addr; | 424 | unsigned long addr = (unsigned long) p->addr; |
405 | unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL); | 425 | unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL); |
@@ -430,7 +450,7 @@ int arch_prepare_kprobe(struct kprobe *p) | |||
430 | return 0; | 450 | return 0; |
431 | } | 451 | } |
432 | 452 | ||
433 | void arch_arm_kprobe(struct kprobe *p) | 453 | void __kprobes arch_arm_kprobe(struct kprobe *p) |
434 | { | 454 | { |
435 | unsigned long addr = (unsigned long)p->addr; | 455 | unsigned long addr = (unsigned long)p->addr; |
436 | unsigned long arm_addr = addr & ~0xFULL; | 456 | unsigned long arm_addr = addr & ~0xFULL; |
@@ -439,7 +459,7 @@ void arch_arm_kprobe(struct kprobe *p) | |||
439 | flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t)); | 459 | flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t)); |
440 | } | 460 | } |
441 | 461 | ||
442 | void arch_disarm_kprobe(struct kprobe *p) | 462 | void __kprobes arch_disarm_kprobe(struct kprobe *p) |
443 | { | 463 | { |
444 | unsigned long addr = (unsigned long)p->addr; | 464 | unsigned long addr = (unsigned long)p->addr; |
445 | unsigned long arm_addr = addr & ~0xFULL; | 465 | unsigned long arm_addr = addr & ~0xFULL; |
@@ -449,7 +469,7 @@ void arch_disarm_kprobe(struct kprobe *p) | |||
449 | flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t)); | 469 | flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t)); |
450 | } | 470 | } |
451 | 471 | ||
452 | void arch_remove_kprobe(struct kprobe *p) | 472 | void __kprobes arch_remove_kprobe(struct kprobe *p) |
453 | { | 473 | { |
454 | } | 474 | } |
455 | 475 | ||
@@ -461,7 +481,7 @@ void arch_remove_kprobe(struct kprobe *p) | |||
461 | * to original stack address, handle the case where we need to fixup the | 481 | * to original stack address, handle the case where we need to fixup the |
462 | * relative IP address and/or fixup branch register. | 482 | * relative IP address and/or fixup branch register. |
463 | */ | 483 | */ |
464 | static void resume_execution(struct kprobe *p, struct pt_regs *regs) | 484 | static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) |
465 | { | 485 | { |
466 | unsigned long bundle_addr = ((unsigned long) (&p->opcode.bundle)) & ~0xFULL; | 486 | unsigned long bundle_addr = ((unsigned long) (&p->opcode.bundle)) & ~0xFULL; |
467 | unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL; | 487 | unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL; |
@@ -528,13 +548,16 @@ turn_ss_off: | |||
528 | ia64_psr(regs)->ss = 0; | 548 | ia64_psr(regs)->ss = 0; |
529 | } | 549 | } |
530 | 550 | ||
531 | static void prepare_ss(struct kprobe *p, struct pt_regs *regs) | 551 | static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs) |
532 | { | 552 | { |
533 | unsigned long bundle_addr = (unsigned long) &p->opcode.bundle; | 553 | unsigned long bundle_addr = (unsigned long) &p->opcode.bundle; |
534 | unsigned long slot = (unsigned long)p->addr & 0xf; | 554 | unsigned long slot = (unsigned long)p->addr & 0xf; |
535 | 555 | ||
536 | /* Update instruction pointer (IIP) and slot number (IPSR.ri) */ | 556 | /* single step inline if break instruction */ |
537 | regs->cr_iip = bundle_addr & ~0xFULL; | 557 | if (p->ainsn.inst_flag == INST_FLAG_BREAK_INST) |
558 | regs->cr_iip = (unsigned long)p->addr & ~0xFULL; | ||
559 | else | ||
560 | regs->cr_iip = bundle_addr & ~0xFULL; | ||
538 | 561 | ||
539 | if (slot > 2) | 562 | if (slot > 2) |
540 | slot = 0; | 563 | slot = 0; |
@@ -545,7 +568,39 @@ static void prepare_ss(struct kprobe *p, struct pt_regs *regs) | |||
545 | ia64_psr(regs)->ss = 1; | 568 | ia64_psr(regs)->ss = 1; |
546 | } | 569 | } |
547 | 570 | ||
548 | static int pre_kprobes_handler(struct die_args *args) | 571 | static int __kprobes is_ia64_break_inst(struct pt_regs *regs) |
572 | { | ||
573 | unsigned int slot = ia64_psr(regs)->ri; | ||
574 | unsigned int template, major_opcode; | ||
575 | unsigned long kprobe_inst; | ||
576 | unsigned long *kprobe_addr = (unsigned long *)regs->cr_iip; | ||
577 | bundle_t bundle; | ||
578 | |||
579 | memcpy(&bundle, kprobe_addr, sizeof(bundle_t)); | ||
580 | template = bundle.quad0.template; | ||
581 | |||
582 | /* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */ | ||
583 | if (slot == 1 && bundle_encoding[template][1] == L) | ||
584 | slot++; | ||
585 | |||
586 | /* Get Kprobe probe instruction at given slot*/ | ||
587 | get_kprobe_inst(&bundle, slot, &kprobe_inst, &major_opcode); | ||
588 | |||
589 | /* For break instruction, | ||
590 | * Bits 37:40 Major opcode to be zero | ||
591 | * Bits 27:32 X6 to be zero | ||
592 | * Bits 32:35 X3 to be zero | ||
593 | */ | ||
594 | if (major_opcode || ((kprobe_inst >> 27) & 0x1FF) ) { | ||
595 | /* Not a break instruction */ | ||
596 | return 0; | ||
597 | } | ||
598 | |||
599 | /* Is a break instruction */ | ||
600 | return 1; | ||
601 | } | ||
602 | |||
603 | static int __kprobes pre_kprobes_handler(struct die_args *args) | ||
549 | { | 604 | { |
550 | struct kprobe *p; | 605 | struct kprobe *p; |
551 | int ret = 0; | 606 | int ret = 0; |
@@ -558,7 +613,9 @@ static int pre_kprobes_handler(struct die_args *args) | |||
558 | if (kprobe_running()) { | 613 | if (kprobe_running()) { |
559 | p = get_kprobe(addr); | 614 | p = get_kprobe(addr); |
560 | if (p) { | 615 | if (p) { |
561 | if (kprobe_status == KPROBE_HIT_SS) { | 616 | if ( (kprobe_status == KPROBE_HIT_SS) && |
617 | (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)) { | ||
618 | ia64_psr(regs)->ss = 0; | ||
562 | unlock_kprobes(); | 619 | unlock_kprobes(); |
563 | goto no_kprobe; | 620 | goto no_kprobe; |
564 | } | 621 | } |
@@ -592,6 +649,19 @@ static int pre_kprobes_handler(struct die_args *args) | |||
592 | p = get_kprobe(addr); | 649 | p = get_kprobe(addr); |
593 | if (!p) { | 650 | if (!p) { |
594 | unlock_kprobes(); | 651 | unlock_kprobes(); |
652 | if (!is_ia64_break_inst(regs)) { | ||
653 | /* | ||
654 | * The breakpoint instruction was removed right | ||
655 | * after we hit it. Another cpu has removed | ||
656 | * either a probepoint or a debugger breakpoint | ||
657 | * at this address. In either case, no further | ||
658 | * handling of this interrupt is appropriate. | ||
659 | */ | ||
660 | ret = 1; | ||
661 | |||
662 | } | ||
663 | |||
664 | /* Not one of our break, let kernel handle it */ | ||
595 | goto no_kprobe; | 665 | goto no_kprobe; |
596 | } | 666 | } |
597 | 667 | ||
@@ -616,7 +686,7 @@ no_kprobe: | |||
616 | return ret; | 686 | return ret; |
617 | } | 687 | } |
618 | 688 | ||
619 | static int post_kprobes_handler(struct pt_regs *regs) | 689 | static int __kprobes post_kprobes_handler(struct pt_regs *regs) |
620 | { | 690 | { |
621 | if (!kprobe_running()) | 691 | if (!kprobe_running()) |
622 | return 0; | 692 | return 0; |
@@ -641,7 +711,7 @@ out: | |||
641 | return 1; | 711 | return 1; |
642 | } | 712 | } |
643 | 713 | ||
644 | static int kprobes_fault_handler(struct pt_regs *regs, int trapnr) | 714 | static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr) |
645 | { | 715 | { |
646 | if (!kprobe_running()) | 716 | if (!kprobe_running()) |
647 | return 0; | 717 | return 0; |
@@ -659,8 +729,8 @@ static int kprobes_fault_handler(struct pt_regs *regs, int trapnr) | |||
659 | return 0; | 729 | return 0; |
660 | } | 730 | } |
661 | 731 | ||
662 | int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, | 732 | int __kprobes kprobe_exceptions_notify(struct notifier_block *self, |
663 | void *data) | 733 | unsigned long val, void *data) |
664 | { | 734 | { |
665 | struct die_args *args = (struct die_args *)data; | 735 | struct die_args *args = (struct die_args *)data; |
666 | switch(val) { | 736 | switch(val) { |
@@ -681,7 +751,7 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, | |||
681 | return NOTIFY_DONE; | 751 | return NOTIFY_DONE; |
682 | } | 752 | } |
683 | 753 | ||
684 | int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | 754 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) |
685 | { | 755 | { |
686 | struct jprobe *jp = container_of(p, struct jprobe, kp); | 756 | struct jprobe *jp = container_of(p, struct jprobe, kp); |
687 | unsigned long addr = ((struct fnptr *)(jp->entry))->ip; | 757 | unsigned long addr = ((struct fnptr *)(jp->entry))->ip; |
@@ -703,7 +773,7 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
703 | return 1; | 773 | return 1; |
704 | } | 774 | } |
705 | 775 | ||
706 | int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | 776 | int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) |
707 | { | 777 | { |
708 | *regs = jprobe_saved_regs; | 778 | *regs = jprobe_saved_regs; |
709 | return 1; | 779 | return 1; |