[kgtp] r1544 committed - Let while-stepping auto close irq

  • From: kgtp@xxxxxxxxxxxxxx
  • To: kgtp@xxxxxxxxxxxxx
  • Date: Mon, 06 May 2013 09:37:46 +0000

Revision: 1544
Author:   teawater
Date:     Mon May  6 02:37:26 2013
Log:      Let while-stepping auto close irq

http://code.google.com/p/kgtp/source/detail?r=1544

Modified:
 /trunk/gtp.c

=======================================
--- /trunk/gtp.c        Sat Apr 20 06:58:43 2013
+++ /trunk/gtp.c        Mon May  6 02:37:26 2013
@@ -470,6 +470,7 @@
 struct gtp_step_s {
        spinlock_t              lock;
        int                     step;
+       int                     irq_need_open;
        struct gtp_entry        *tpe;
 };
 static DEFINE_PER_CPU(struct gtp_step_s, gtp_step);
@@ -488,7 +489,8 @@
 static unsigned long           gtp_hwb_drx[HWB_NUM];
 static unsigned long           gtp_hwb_dr7;

-#define GTP_HWB_DR7_DEF                0x400UL
+#define GTP_HWB_DR7_DEF                (0x400UL)
+#define GTP_HWB_DR6_MASK       (0xe00fUL)

 /* This part is for all the arch.  */
 struct gtp_hwb_s {
@@ -4825,8 +4827,16 @@
 #else
        regs->eflags &= ~(X86_EFLAGS_TF);
 #endif
+       if (__get_cpu_var(gtp_step).irq_need_open) {
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24))
+               regs->flags |= X86_EFLAGS_IF;
+#else
+               regs->eflags |= X86_EFLAGS_IF;
+#endif
+       }
        __get_cpu_var(gtp_step).step = 0;
        __get_cpu_var(gtp_step).tpe = NULL;
+       __get_cpu_var(gtp_step).irq_need_open = 0;
 }

 static void
@@ -5063,13 +5073,19 @@
        if (tpe->step > 1) {
                /* Let while-stepping begin.  */
/*XXX if there a another one, maybe we need add end frame to let reader know that this while step stop. */
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24))
-               regs->flags |= X86_EFLAGS_TF;
-#else
-               regs->eflags |= X86_EFLAGS_TF;
-#endif
                __get_cpu_var(gtp_step).step = tpe->step;
                __get_cpu_var(gtp_step).tpe = tpe;
+               if (regs->flags & X86_EFLAGS_IF)
+                       __get_cpu_var(gtp_step).irq_need_open = 1;
+               else
+                       __get_cpu_var(gtp_step).irq_need_open = 0;
+               #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24))
+               regs->flags |= X86_EFLAGS_TF;
+               regs->flags &= ~(X86_EFLAGS_IF);
+               #else
+               regs->eflags |= X86_EFLAGS_TF;
+               regs->eflags &= ~(X86_EFLAGS_IF);
+               #endif
        }
 #endif
 }
@@ -5595,6 +5611,31 @@
 }

 #ifdef CONFIG_X86
+static int
+gtp_step_check_insn(struct pt_regs *regs)
+{
+       uint8_t         insn;
+       unsigned long   pc = GTP_REGS_PC(regs);
+
+       if (probe_kernel_read(&insn, (void *)pc, 1))
+               return -1;
+
+       switch (insn) {
+       case 0xfb:
+               /* sti */
+               __get_cpu_var(gtp_step).irq_need_open = 1;
+               GTP_REGS_PC(regs) += 1;
+               break;
+       case 0xfa:
+               /* cli */
+               __get_cpu_var(gtp_step).irq_need_open = 0;
+               GTP_REGS_PC(regs) += 1;
+               break;
+       };
+
+       return 0;
+}
+
 static int
 gtp_notifier_call(struct notifier_block *self, unsigned long cmd,
                   void *ptr)
@@ -5623,6 +5664,7 @@
 #else
        dr6 = args->err;
 #endif
+       set_debugreg(GTP_HWB_DR7_DEF, 7);

        /* Handle while-stepping.  */
        spin_lock(&__get_cpu_var(gtp_step).lock);
@@ -5633,9 +5675,13 @@
 #else
                dr6 &= ~(0x4000);
 #endif
-               if (!__get_cpu_var(gtp_step).tpe)
+               if (!__get_cpu_var(gtp_step).tpe || user_mode(args->regs))
                        gtp_step_stop(args->regs);
                else {
+                       if (gtp_step_check_insn(args->regs))
+                               printk(KERN_WARNING "KGTP: check insn in %p got 
error.",
+                                      (void *)GTP_REGS_PC(args->regs));
+
                        preempt_disable();
                        {
                                struct gtp_trace_s      gts;
@@ -5649,6 +5695,16 @@
                        preempt_enable_no_resched();

                        if (__get_cpu_var(gtp_step).step > 1) {
+                               /* XXX: not sure need set eflags each step.  */
+#if 0
+                               #if (LINUX_VERSION_CODE > 
KERNEL_VERSION(2,6,24))
+                               args->regs->flags |= X86_EFLAGS_TF;
+                               args->regs->flags &= ~(X86_EFLAGS_IF);
+                               #else
+                               args->regs->eflags |= X86_EFLAGS_TF;
+                               args->regs->eflags &= ~(X86_EFLAGS_IF);
+                               #endif
+#endif
                                __get_cpu_var(gtp_step).step--;
                        } else {
                                /*XXX: maybe need add a end frame.  */
@@ -5663,7 +5719,6 @@
        if ((dr6 & 0xf) == 0)
                goto out;
        read_lock(&gtp_hwb_lock);
-       set_debugreg(GTP_HWB_DR7_DEF, 7);

        for (i = 0; i < HWB_NUM; i++) {
                if ((dr6 & (0x1 << i)) == 0)
@@ -5718,11 +5773,13 @@
 #endif
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
        /* If have some other traps, let other handler handle it.  */
-       if ((*dr6_p) == 0)
+       if (((*dr6_p) & GTP_HWB_DR6_MASK) == 0)
                ret = NOTIFY_STOP;
+       current->thread.debugreg6 = *dr6_p;
 #else
-       if (dr6 == 0)
+       if ((dr6 & GTP_HWB_DR6_MASK) == 0)
                ret = NOTIFY_STOP;
+       current->thread.debugreg6 = dr6;
 #endif

        local_irq_restore(flags);
@@ -6036,7 +6093,7 @@
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
        if (gtp_have_step || gtp_have_watch_tracepoint)
 #else
-       if (gtp_have_watch_tracepoint)
+       if (gtp_have_step)
 #endif
                unregister_die_notifier(&gtp_notifier);


Other related posts:

  • » [kgtp] r1544 committed - Let while-stepping auto close irq - kgtp