aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/kprobes.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/kernel/kprobes.c')
-rw-r--r--arch/ia64/kernel/kprobes.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 82a41ac29386..4b1bd539ec47 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -554,6 +554,38 @@ static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs)
554 ia64_psr(regs)->ss = 1; 554 ia64_psr(regs)->ss = 1;
555} 555}
556 556
557static int __kprobes is_ia64_break_inst(struct pt_regs *regs)
558{
559 unsigned int slot = ia64_psr(regs)->ri;
560 unsigned int template, major_opcode;
561 unsigned long kprobe_inst;
562 unsigned long *kprobe_addr = (unsigned long *)regs->cr_iip;
563 bundle_t bundle;
564
565 memcpy(&bundle, kprobe_addr, sizeof(bundle_t));
566 template = bundle.quad0.template;
567
568 /* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */
569 if (slot == 1 && bundle_encoding[template][1] == L)
570 slot++;
571
572 /* Get Kprobe probe instruction at given slot*/
573 get_kprobe_inst(&bundle, slot, &kprobe_inst, &major_opcode);
574
575 /* For break instruction,
576 * Bits 37:40 Major opcode to be zero
577 * Bits 27:32 X6 to be zero
578 * Bits 32:35 X3 to be zero
579 */
580 if (major_opcode || ((kprobe_inst >> 27) & 0x1FF) ) {
581 /* Not a break instruction */
582 return 0;
583 }
584
585 /* Is a break instruction */
586 return 1;
587}
588
557static int __kprobes pre_kprobes_handler(struct die_args *args) 589static int __kprobes pre_kprobes_handler(struct die_args *args)
558{ 590{
559 struct kprobe *p; 591 struct kprobe *p;
@@ -601,6 +633,19 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
601 p = get_kprobe(addr); 633 p = get_kprobe(addr);
602 if (!p) { 634 if (!p) {
603 unlock_kprobes(); 635 unlock_kprobes();
636 if (!is_ia64_break_inst(regs)) {
637 /*
638 * The breakpoint instruction was removed right
639 * after we hit it. Another cpu has removed
640 * either a probepoint or a debugger breakpoint
641 * at this address. In either case, no further
642 * handling of this interrupt is appropriate.
643 */
644 ret = 1;
645
646 }
647
648 /* Not one of our break, let kernel handle it */
604 goto no_kprobe; 649 goto no_kprobe;
605 } 650 }
606 651