[kgtp] r1548 committed - Fix build issue with old Linux kernel. Update patches.

  • From: kgtp@xxxxxxxxxxxxxx
  • To: kgtp@xxxxxxxxxxxxx
  • Date: Tue, 07 May 2013 02:06:59 +0000

Revision: 1548
Author:   teawater
Date:     Mon May  6 19:06:35 2013
Log:      Fix build issue with old Linux kernel.  Update patches.

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

Modified:
 /trunk/gtp.c
 /trunk/gtp_2.6.20_to_2.6.32.patch
 /trunk/gtp_2.6.33_to_2.6.38.patch
 /trunk/gtp_2.6.39.patch
 /trunk/gtp_3.0_to_3.6.patch
 /trunk/gtp_3.7_to_upstream.patch
 /trunk/gtp_older_to_2.6.19.patch

=======================================
--- /trunk/gtp.c        Mon May  6 07:43:38 2013
+++ /trunk/gtp.c        Mon May  6 19:06:35 2013
@@ -5084,7 +5084,11 @@
/*XXX if there a another one, maybe we need add end frame to let reader know that this while step stop. */
                __get_cpu_var(gtp_step).step = tpe->step;
                __get_cpu_var(gtp_step).tpe = tpe;
+               #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24))
                if (regs->flags & X86_EFLAGS_IF)
+               #else
+               if (regs->eflags & X86_EFLAGS_IF)
+               #endif
                        __get_cpu_var(gtp_step).irq_need_open = 1;
                else
                        __get_cpu_var(gtp_step).irq_need_open = 0;
=======================================
--- /trunk/gtp_2.6.20_to_2.6.32.patch   Sun Feb 17 20:54:51 2013
+++ /trunk/gtp_2.6.20_to_2.6.32.patch   Mon May  6 19:06:35 2013
@@ -3662,7 +3662,7 @@

 --- /dev/null
 +++ b/lib/gtp.c
-@@ -0,0 +1,12093 @@
+@@ -0,0 +1,12887 @@
 +/*
 + * Kernel GDB tracepoint module.
 + *
@@ -3680,12 +3680,12 @@
 + * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 + *
-+ * Copyright(C) KGTP team (https://code.google.com/p/kgtp/), 2010, 2011, 2012, 2013
++ * Copyright(C) KGTP team (https://code.google.com/p/kgtp/), 2010-2013
 + *
 + */
 +
 +/* If "* 10" means that this is not a release version.  */
-+#define GTP_VERSION                   (20130218)
++#define GTP_VERSION                   (20130218 * 10)
 +
 +#include <linux/version.h>
 +#ifndef RHEL_RELEASE_VERSION
@@ -3764,6 +3764,9 @@
 +#include <linux/slab.h>
 +#include <linux/ctype.h>
 +#include <asm/atomic.h>
++#ifdef CONFIG_X86
++#include <asm/debugreg.h>
++#endif
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
 +#include <linux/kdebug.h>
 +#else
@@ -3874,7 +3877,9 @@
 +                               + sizeof(struct gtp_frame_var))
 +#endif
 +#ifdef GTP_RB
-+#define GTP_FRAME_HEAD_SIZE   (FID_SIZE + sizeof(u64) + sizeof(ULONGEST))
++/* The frame head size: FID_HEAD + count id + frame number + pointer to prev frem */ ++#define GTP_FRAME_HEAD_SIZE (FID_SIZE + sizeof(u64) + sizeof(ULONGEST) + sizeof(void *))
++/* The frame head size: FID_PAGE_BEGIN + count id */
 +#define GTP_FRAME_PAGE_BEGIN_SIZE     (FID_SIZE + sizeof(u64))
 +#endif
 +#ifdef GTP_FTRACE_RING_BUFFER
@@ -3957,7 +3962,7 @@
 +/* This gtp entry is registered inside the system.  */
 +#define GTP_ENTRY_FLAGS_REG           2
 +/* See $no_self_trace.  */
-+#define GTP_ENTRY_FLAGS_NO_SELF_TRACE 4
++#define GTP_ENTRY_FLAGS_SELF_TRACE    4
 +/* This gtp entry has passcount.  */
 +#define GTP_ENTRY_FLAGS_HAVE_PASS     8
 +/* See $printk_level.  */
@@ -4128,14 +4133,32 @@
 +
 +static pid_t                  gtp_current_pid;
 +
++#ifdef CONFIG_X86
++/* Following part is for while-stepping.  */
++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);
++#endif
++
 +#ifdef CONFIG_X86
++static int    gtp_have_watch_tracepoint;
++static int    gtp_have_step;
++#endif
++
++#ifdef CONFIG_X86
++/* Following part is for watch tracepoint.  */
 +/* This part is X86 special.  */
 +#define HWB_NUM                       4
 +
 +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 {
@@ -4213,16 +4236,16 @@
 +{
 +      switch(reg) {
 +      case 0:
-+              set_debugreg(val, 0);
++              gtp_set_debugreg(val, 0);
 +              break;
 +      case 1:
-+              set_debugreg(val, 1);
++              gtp_set_debugreg(val, 1);
 +              break;
 +      case 2:
-+              set_debugreg(val, 2);
++              gtp_set_debugreg(val, 2);
 +              break;
 +      case 3:
-+              set_debugreg(val, 3);
++              gtp_set_debugreg(val, 3);
 +              break;
 +      }
 +}
@@ -4233,11 +4256,11 @@
 +{
 +      read_lock(&gtp_hwb_lock);
 +      __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      set_debugreg(0UL, 0);
-+      set_debugreg(0UL, 1);
-+      set_debugreg(0UL, 2);
-+      set_debugreg(0UL, 3);
-+      set_debugreg(GTP_HWB_DR7_DEF, 7);
++      gtp_set_debugreg(0UL, 0);
++      gtp_set_debugreg(0UL, 1);
++      gtp_set_debugreg(0UL, 2);
++      gtp_set_debugreg(0UL, 3);
++      gtp_set_debugreg(GTP_HWB_DR7_DEF, 7);
 +      read_unlock(&gtp_hwb_lock);
 +}
 +
@@ -4245,11 +4268,11 @@
 +gtp_hwb_sync_local(void)
 +{
 +      __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      set_debugreg(gtp_hwb_drx[0], 0);
-+      set_debugreg(gtp_hwb_drx[1], 1);
-+      set_debugreg(gtp_hwb_drx[2], 2);
-+      set_debugreg(gtp_hwb_drx[3], 3);
-+      set_debugreg(gtp_hwb_dr7, 7);
++      gtp_set_debugreg(gtp_hwb_drx[0], 0);
++      gtp_set_debugreg(gtp_hwb_drx[1], 1);
++      gtp_set_debugreg(gtp_hwb_drx[2], 2);
++      gtp_set_debugreg(gtp_hwb_drx[3], 3);
++      gtp_set_debugreg(gtp_hwb_dr7, 7);
 +}
 +
 +static void
@@ -4404,7 +4427,7 @@
 +      GTP_VAR_PRINTK_LEVEL_ID                 = 11,
 +      GTP_VAR_PRINTK_FORMAT_ID                = 12,
 +      GTP_VAR_DUMP_STACK_ID                   = 13,
-+      GTP_VAR_NO_SELF_TRACE_ID                = 14,
++      GTP_VAR_SELF_TRACE_ID                   = 14,
 +      GTP_VAR_CPU_NUMBER_ID                   = 15,
 +      GTP_VAR_PC_PE_EN_ID                     = 16,
 +      GTP_VAR_KRET_ID                         = 17,
@@ -4437,8 +4460,11 @@
 +      GTP_WATCH_VAL_ID                        = 42,
 +      GTP_WATCH_COUNT_ID                      = 43,
 +
++      GTP_STEP_COUNT_ID                       = 44,
++      GTP_STEP_ID_ID                          = 45,
++
 +      GTP_VAR_SPECIAL_MIN                     = GTP_VAR_VERSION_ID,
-+      GTP_VAR_SPECIAL_MAX                     = GTP_WATCH_COUNT_ID,
++      GTP_VAR_SPECIAL_MAX                     = GTP_STEP_ID_ID,
 +};
 +
 +enum pe_tv_id {
@@ -5447,6 +5473,44 @@
 +};
 +#endif
 +
++#ifdef GTP_RB
++static int
++gtp_step_count_hooks_get_val(struct gtp_trace_s *gts, struct gtp_var *gtv,
++                           int64_t *val)
++{
++      if (gts->step)
++              *val = gts->tpe->step - gts->step + 1;
++      else
++              *val = 0;
++
++      return 0;
++}
++
++static struct gtp_var_hooks   gtp_step_count_hooks = {
++      .agent_get_val = gtp_step_count_hooks_get_val,
++};
++
++static DEFINE_PER_CPU(int64_t, gtp_step_id);
++
++static int
++gtp_step_id_hooks_get_val(struct gtp_trace_s *gts, struct gtp_var *gtv,
++                        int64_t *val)
++{
++      if (!gts->step) {
++              if (++ __get_cpu_var(gtp_step_id) == 0)
++                      __get_cpu_var(gtp_step_id) = 1;
++      }
++
++      *val = __get_cpu_var(gtp_step_id);
++
++      return 0;
++}
++
++static struct gtp_var_hooks   gtp_step_id_hooks = {
++      .agent_get_val = gtp_step_id_hooks_get_val,
++};
++#endif
++
 +static int
 +gtp_var_special_add_all(void)
 +{
@@ -5539,8 +5603,8 @@
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +
-+      var = gtp_var_special_add(GTP_VAR_NO_SELF_TRACE_ID, 0, 0,
-+                                "no_self_trace", NULL);
++      var = gtp_var_special_add(GTP_VAR_SELF_TRACE_ID, 0, 0,
++                                "self_trace", NULL);
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +
@@ -5666,6 +5730,16 @@
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +#endif
++      var = gtp_var_special_add(GTP_STEP_COUNT_ID, 0, 0,
++                                "step_count", &gtp_step_count_hooks);
++      if (IS_ERR(var))
++              return PTR_ERR(var);
++#ifdef GTP_RB
++      var = gtp_var_special_add(GTP_STEP_ID_ID, 0, 0,
++                                "step_id", &gtp_step_id_hooks);
++      if (IS_ERR(var))
++              return PTR_ERR(var);
++#endif
 +
 +      return 0;
 +}
@@ -7238,6 +7312,11 @@
 +      } while (0)
 +#endif
 +
++static int    gtp_collect_var(struct gtp_trace_s *gts, int num);
++#ifdef GTP_RB
++static int    gtp_var_array_step_id_id = 0;
++#endif
++
 +static int
 +gtp_action_head(struct gtp_trace_s *gts)
 +{
@@ -7286,6 +7365,13 @@
 +
 +      trace_nump = (ULONGEST *)tmp;
 +      *trace_nump = gts->tpe->num;
++      tmp += sizeof(ULONGEST);
++
++#ifdef GTP_RB
++      *(void **)tmp = gtp_rb_prev_frame_get(gts->next);
++      gtp_rb_prev_frame_set(gts->next, (void *)(tmp + sizeof(void *)
++                                                - GTP_FRAME_HEAD_SIZE));
++#endif
 +
 +#ifdef GTP_FTRACE_RING_BUFFER
 +      ring_buffer_unlock_commit(gtp_frame, rbe);
@@ -7294,6 +7380,14 @@
 +
 +      atomic_inc(&gtp_frame_create);
 +
++#ifdef GTP_RB
++      /* Auto collect $step_id.  */
++      if (gts->tpe->step) {
++              if (gtp_collect_var(gts, gtp_var_array_step_id_id))
++                      return -1;
++      }
++#endif
++
 +      return 0;
 +}
 +
@@ -7736,6 +7830,8 @@
 +
 +      return ret;
 +}
++
++/* The number is not the ID of tvar, it is the ID of gtp_var_array. */
 +
 +static int
 +gtp_collect_var(struct gtp_trace_s *gts, int num)
@@ -8391,6 +8487,30 @@
 +}
 +#endif
 +
++#ifdef CONFIG_X86
++/* while-stepping stop.  */
++
++static void
++gtp_step_stop(struct pt_regs *regs)
++{
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24))
++      regs->flags &= ~(X86_EFLAGS_TF);
++#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;
++}
++#endif
++
 +static void
 +gtp_handler(struct gtp_trace_s *gts)
 +{
@@ -8400,6 +8520,10 @@
 +      printk(GTP_DEBUG_V "gtp_handler: tracepoint %d %p\n",
 +             (int)gts->tpe->num, (void *)(CORE_ADDR)gts->tpe->addr);
 +#endif
++#ifdef CONFIG_X86
++      if (gts->step == 0 && __get_cpu_var(gtp_step).step)
++              gtp_step_stop(gts->regs);
++#endif
 +
 +      gts->read_memory = (void *)probe_kernel_read;
 +      if (gts->tpe->flags & GTP_ENTRY_FLAGS_CURRENT_TASK) {
@@ -8416,7 +8540,7 @@
 +              return;
 +#endif
 +
-+      if ((gts->tpe->flags & GTP_ENTRY_FLAGS_NO_SELF_TRACE)
++      if ((gts->tpe->flags & GTP_ENTRY_FLAGS_SELF_TRACE) == 0
 +          && (get_current()->pid == gtp_gtp_pid
 +              || get_current()->pid == gtp_gtpframe_pid)) {
 +                      return;
@@ -8441,7 +8565,7 @@
 +      gts->run = NULL;
 +
 +      /* Pass.  */
-+      if (gts->tpe->flags & GTP_ENTRY_FLAGS_HAVE_PASS) {
++      if (gts->step == 0 && gts->tpe->flags & GTP_ENTRY_FLAGS_HAVE_PASS) {
 +              if (atomic_dec_return(&gts->tpe->current_pass) < 0)
 +                      goto tpe_stop;
 +      }
@@ -8601,18 +8725,47 @@
 +      struct kretprobe        *kpret;
 +      struct gtp_kp           *gkp;
 +      union gtp_entry_u       *u;
++      struct gtp_entry                *tpe;
 +      struct gtp_trace_s      gts;
 +
-+      memset(&gts, 0, sizeof(struct gtp_trace_s));
-+
 +      kpret = container_of(p, struct kretprobe, kp);
 +      gkp = container_of(kpret, struct gtp_kp, kpret);
 +      u = container_of(gkp, union gtp_entry_u, kp);
-+      gts.tpe = container_of(u, struct gtp_entry, u);
-+      gts.regs = regs;
-+      gts.step = 1;
++      tpe = container_of(u, struct gtp_entry, u);
++
++      if (tpe->step == 1) {
++              memset(&gts, 0, sizeof(struct gtp_trace_s));
++
++              gts.tpe = tpe;
++              gts.regs = regs;
++              gts.step = tpe->step;
++
++              gtp_handler(&gts);
++      }
 +
-+      gtp_handler(&gts);
++#ifdef CONFIG_X86
++      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. */
++              __get_cpu_var(gtp_step).step = tpe->step;
++              __get_cpu_var(gtp_step).tpe = tpe;
++              #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24))
++              if (regs->flags & X86_EFLAGS_IF)
++              #else
++              if (regs->eflags & X86_EFLAGS_IF)
++              #endif
++                      __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
 +}
 +
 +static inline void
@@ -8893,6 +9046,7 @@
 +              gtp_list = gtp_list->next;
 +              gtp_action_release(tpe->cond);
 +              gtp_action_release(tpe->action_list);
++              gtp_action_release(tpe->step_action_list);
 +              gtp_src_release(tpe->src);
 +              gtp_src_release(tpe->action_cmd);
 +              gtp_src_release(tpe->printk_str);
@@ -9133,6 +9287,238 @@
 +
 +      return 0;
 +}
++
++#ifdef CONFIG_X86
++#define ADDR_PREFIX_OPCODE 0x67
++#define DATA_PREFIX_OPCODE 0x66
++#define LOCK_PREFIX_OPCODE 0xf0
++#define CS_PREFIX_OPCODE 0x2e
++#define DS_PREFIX_OPCODE 0x3e
++#define ES_PREFIX_OPCODE 0x26
++#define FS_PREFIX_OPCODE 0x64
++#define GS_PREFIX_OPCODE 0x65
++#define SS_PREFIX_OPCODE 0x36
++#define REPNE_PREFIX_OPCODE 0xf2
++#define REPE_PREFIX_OPCODE  0xf3
++
++static int
++gtp_step_check_insn(struct pt_regs *regs)
++{
++      uint32_t        opcode;
++      uint8_t         opcode8;
++      unsigned long   pc = GTP_REGS_PC(regs);
++
++      /* prefixes */
++      while (1) {
++              if (probe_kernel_read(&opcode8, (void *)pc, 1))
++                      return -1;
++              pc++;
++              switch (opcode8) {
++              case REPE_PREFIX_OPCODE:
++              case REPNE_PREFIX_OPCODE:
++              case LOCK_PREFIX_OPCODE:
++              case CS_PREFIX_OPCODE:
++              case SS_PREFIX_OPCODE:
++              case DS_PREFIX_OPCODE:
++              case ES_PREFIX_OPCODE:
++              case FS_PREFIX_OPCODE:
++              case GS_PREFIX_OPCODE:
++              case DATA_PREFIX_OPCODE:
++              case ADDR_PREFIX_OPCODE:
++#ifndef CONFIG_X86_32
++              case 0x40 ... 0x4f:
++#endif
++                      break;
++              default:
++                      goto out_prefixes;
++              }
++      }
++out_prefixes:
++
++      opcode = (uint32_t)opcode8;
++reswitch:
++      switch (opcode) {
++      case 0x0f:
++              if (probe_kernel_read(&opcode8, (void *)pc, 1))
++                      return -1;
++              opcode = (uint32_t) opcode8 | 0x0f00;
++              goto reswitch;
++              break;
++      case 0xfb:
++              /* sti */
++              __get_cpu_var(gtp_step).irq_need_open = 1;
++              GTP_REGS_PC(regs) = pc;
++              break;
++      case 0xfa:
++              /* cli */
++              __get_cpu_var(gtp_step).irq_need_open = 0;
++              GTP_REGS_PC(regs) = pc;
++              break;
++      case 0x0f07:
++              /* sysret */
++              return 1;
++              break;
++      };
++
++      return 0;
++}
++
++static int
++gtp_notifier_call(struct notifier_block *self, unsigned long cmd,
++                 void *ptr)
++{
++      int             ret = NOTIFY_DONE;
++      unsigned long   flags;
++      struct die_args *args;
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      int             i;
++#endif
++      unsigned long   dr6;
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      unsigned long   *dr6_p;
++#endif
++
++      if (cmd != DIE_DEBUG)
++              return ret;
++
++      local_irq_save(flags);
++      args = ptr;
++
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      /* Get from X86 hw_breakpoint_handler.  */
++      dr6_p = (unsigned long *)ERR_PTR(args->err);
++      dr6 = *dr6_p;
++#else
++      dr6 = args->err;
++#endif
++      gtp_set_debugreg(GTP_HWB_DR7_DEF, 7);
++
++      /* Handle while-stepping.  */
++      spin_lock(&__get_cpu_var(gtp_step).lock);
++      if ((dr6 & 0x4000) != 0) {
++              /* Clear the bit that handle by KGTP.  */
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++              (*dr6_p) &= ~(0x4000);
++#else
++              dr6 &= ~(0x4000);
++#endif
++              if (!__get_cpu_var(gtp_step).tpe || user_mode(args->regs))
++                      gtp_step_stop(args->regs);
++              else {
++                      int need_stop = gtp_step_check_insn(args->regs);
++                      if (need_stop < 0)
++                              printk(KERN_WARNING "KGTP: check insn in %p got 
error.",
++                                     (void *)GTP_REGS_PC(args->regs));
++
++                      preempt_disable();
++                      {
++                              struct gtp_trace_s      gts;
++
++                              memset(&gts, 0, sizeof(struct gtp_trace_s));
++                              gts.tpe = __get_cpu_var(gtp_step).tpe;
++                              gts.regs = args->regs;
++                              gts.step = __get_cpu_var(gtp_step).step;
++                              gtp_handler(&gts);
++                      }
++                      preempt_enable_no_resched();
++
++                      if (__get_cpu_var(gtp_step).step > 1 && !need_stop) {
++                              /* 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.  */
++                              gtp_step_stop(args->regs);
++                      }
++              }
++      }
++      spin_unlock(&__get_cpu_var(gtp_step).lock);
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      /* Handle watch traceppoint.  */
++      if ((dr6 & 0xf) == 0)
++              goto out;
++      read_lock(&gtp_hwb_lock);
++
++      for (i = 0; i < HWB_NUM; i++) {
++              if ((dr6 & (0x1 << i)) == 0)
++                      continue;
++              /* Clear the bit that handle by KGTP.  */
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++              (*dr6_p) &= ~(0x1 << i);
++#else
++              dr6 &= ~(0x1 << i);
++#endif
++              if (gtp_hwb[i].watch == NULL)
++                      continue;
++              /* Check if gtp_hwb is updated in other CPU.  */
++              if (__get_cpu_var(gtp_hwb_sync_count_local) != 
gtp_hwb_sync_count) {
++                      unsigned long   addr;
++
++                      gtp_get_debugreg(addr, i);
++                      if (addr != gtp_hwb[i].addr)
++                              continue;
++              }
++              preempt_disable();
++              {
++                      struct gtp_trace_s      gts;
++
++                      memset(&gts, 0, sizeof(struct gtp_trace_s));
++                      gts.tpe = gtp_hwb[i].watch;
++                      gts.regs = args->regs;
++                      gts.hwb = &gtp_hwb[i];
++                      gtp_handler(&gts);
++              }
++              preempt_enable_no_resched();
++      }
++
++      /* If the HWB need update in this CPU, just update it.  */
++      if (__get_cpu_var(gtp_hwb_sync_count_local) != gtp_hwb_sync_count) {
++              gtp_set_debugreg(gtp_hwb_drx[0], 0);
++              gtp_set_debugreg(gtp_hwb_drx[1], 1);
++              gtp_set_debugreg(gtp_hwb_drx[2], 2);
++              gtp_set_debugreg(gtp_hwb_drx[3], 3);
++              __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
++      }
++
++      gtp_set_debugreg(gtp_hwb_dr7, 7);
++      read_unlock(&gtp_hwb_lock);
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++out:
++#endif
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
++      gtp_set_debugreg(dr6, 6);
++#endif
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      /* If have some other traps, let other handler handle it.  */
++      if (((*dr6_p) & GTP_HWB_DR6_MASK) == 0)
++              ret = NOTIFY_STOP;
++      current->thread.debugreg6 = *dr6_p;
++#else
++      if ((dr6 & GTP_HWB_DR6_MASK) == 0)
++              ret = NOTIFY_STOP;
++      current->thread.debugreg6 = dr6;
++#endif
++
++      local_irq_restore(flags);
++      return ret;
++}
++
++static struct notifier_block gtp_notifier = {
++      .notifier_call = gtp_notifier_call,
++      .priority = 0x7ffffffe /* we need to be notified after kprobe.  */
++};
++#endif
 +
 +#ifdef CONFIG_X86
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0))
@@ -9229,102 +9615,8 @@
 +      gtp_hw_breakpoint_handler(breakinfo[3].num, regs);
 +}
 +#endif
-+#else
-+static int
-+gtp_notifier_call(struct notifier_block *self, unsigned long cmd,
-+                 void *ptr)
-+{
-+      int             ret = NOTIFY_DONE;
-+      unsigned long   flags;
-+      struct die_args *args;
-+      int             i;
-+      unsigned long   dr6;
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      unsigned long   *dr6_p;
 +#endif
 +
-+      if (cmd != DIE_DEBUG)
-+              return ret;
-+
-+      local_irq_save(flags);
-+      args = ptr;
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      /* Get from X86 hw_breakpoint_handler.  */
-+      dr6_p = (unsigned long *)ERR_PTR(args->err);
-+      dr6 = *dr6_p;
-+#else
-+      dr6 = args->err;
-+#endif
-+      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)
-+                      continue;
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+              /* Because KGTP handle all the hw-breakpoints.
-+                 So Just clear it.  */
-+              (*dr6_p) &= ~(0x1 << i);
-+#endif
-+              if (gtp_hwb[i].watch == NULL)
-+                      continue;
-+              /* Check if gtp_hwb is updated in other CPU.  */
-+              if (__get_cpu_var(gtp_hwb_sync_count_local) != 
gtp_hwb_sync_count) {
-+                      unsigned long   addr;
-+
-+                      gtp_get_debugreg(addr, i);
-+                      if (addr != gtp_hwb[i].addr)
-+                              continue;
-+              }
-+              preempt_disable();
-+              {
-+                      struct gtp_trace_s      gts;
-+
-+                      memset(&gts, 0, sizeof(struct gtp_trace_s));
-+                      gts.tpe = gtp_hwb[i].watch;
-+                      gts.regs = args->regs;
-+                      gts.hwb = &gtp_hwb[i];
-+                      gtp_handler(&gts);
-+              }
-+              preempt_enable_no_resched();
-+      }
-+
-+      /* If the HWB need update in this CPU, just update it.  */
-+      if (__get_cpu_var(gtp_hwb_sync_count_local) != gtp_hwb_sync_count) {
-+              set_debugreg(gtp_hwb_drx[0], 0);
-+              set_debugreg(gtp_hwb_drx[1], 1);
-+              set_debugreg(gtp_hwb_drx[2], 2);
-+              set_debugreg(gtp_hwb_drx[3], 3);
-+              __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      }
-+
-+      set_debugreg(gtp_hwb_dr7, 7);
-+      read_unlock(&gtp_hwb_lock);
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      /* If have some other traps, let other handler handle it.  */
-+      if ((dr6 & (~0xf)) == 0)
-+              ret = NOTIFY_STOP;
-+#else
-+      set_debugreg(0UL, 6);
-+      ret = NOTIFY_STOP;
-+#endif
-+
-+out:
-+      local_irq_restore(flags);
-+      return ret;
-+}
-+
-+static struct notifier_block gtp_notifier = {
-+      .notifier_call = gtp_notifier_call,
-+      .priority = 0x7fffffff /* we need to be notified first */
-+};
-+#endif
-+
 +static unsigned int
 +gtp_hwb_size_to_arch(int size)
 +{
@@ -9403,7 +9695,7 @@
 +
 +              /* Set gtp_hwb_dr7 and gtp_hwb_drx[num] to hwb.  */
 +              gtp_set_debugreg(gtp_hwb_drx[num], num);
-+              set_debugreg(gtp_hwb_dr7, 7);
++              gtp_set_debugreg(gtp_hwb_dr7, 7);
 +
 +              gtp_hwb_sync_count++;
 +              hwb->count = gtp_hwb_sync_count;
@@ -9460,7 +9752,7 @@
 +                      gtp_hwb_sync_count++;
 +
 +                      /* Sync gtp_hwb_dr7 update to hwb.  */
-+                      set_debugreg(gtp_hwb_dr7, 7);
++                      gtp_set_debugreg(gtp_hwb_dr7, 7);
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
 +                      /* Send ipi to let other cpu update.  */
@@ -9523,54 +9815,74 @@
 +              tasklet_kill(&tpe->disable_tasklet);
 +              tasklet_kill(&tpe->enable_tasklet);
 +#endif
++      }
++
++#ifdef CONFIG_X86
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      if (gtp_have_step || gtp_have_watch_tracepoint)
++#else
++      if (gtp_have_step)
++#endif
++              unregister_die_notifier(&gtp_notifier);
++
++      {
++              /* Init data of while-stepping.  */
++              int     cpu;
++              for_each_online_cpu(cpu) {
++                      struct gtp_step_s       *step = &per_cpu(gtp_step, cpu);
++
++                      spin_lock(&step->lock);
++                      step->step = 0;
++                      step->tpe = NULL;
++                      spin_unlock(&step->lock);
++              }
 +      }
++#endif
 +
 +#ifdef CONFIG_X86
 +      /* Stop hwb.  */
++      if (gtp_have_watch_tracepoint) {
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0))
-+      {
-+              int     i;
++              {
++                      int     i;
 +
-+              /* Register hw breakpoints.  */
-+              for (i = 0; i < HWB_NUM; i++) {
-+                      unregister_wide_hw_breakpoint(breakinfo[i].pev);
-+                      breakinfo[i].pev = NULL;
++                      /* Register hw breakpoints.  */
++                      for (i = 0; i < HWB_NUM; i++) {
++                              unregister_wide_hw_breakpoint(breakinfo[i].pev);
++                              breakinfo[i].pev = NULL;
++                      }
 +              }
-+      }
 +#endif
 +
-+      gtp_hwb_stop(NULL);
++              gtp_hwb_stop(NULL);
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
-+      smp_call_function(gtp_hwb_stop, NULL, 1);
++              smp_call_function(gtp_hwb_stop, NULL, 1);
 +#else
-+      smp_call_function(gtp_hwb_stop, NULL, 0, 1);
++              smp_call_function(gtp_hwb_stop, NULL, 0, 1);
 +#endif
 +
-+      for (tpe = gtp_list; tpe; tpe = tpe->next) {
-+              if (tpe->type == gtp_entry_kprobe
-+                  || (tpe->flags & GTP_ENTRY_FLAGS_REG) == 0
-+                  || tpe->disable)
-+                      continue;
++              for (tpe = gtp_list; tpe; tpe = tpe->next) {
++                      if (tpe->type == gtp_entry_kprobe
++                          || (tpe->flags & GTP_ENTRY_FLAGS_REG) == 0
++                          || tpe->disable)
++                              continue;
 +
-+              if (tpe->type == gtp_entry_watch_static)
-+                      gtp_unregister_hwb(tpe->addr, 0);
++                      if (tpe->type == gtp_entry_watch_static)
++                              gtp_unregister_hwb(tpe->addr, 0);
 +
-+              tpe->flags &= ~GTP_ENTRY_FLAGS_REG;
++                      tpe->flags &= ~GTP_ENTRY_FLAGS_REG;
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
-+              tasklet_kill(&tpe->disable_tasklet);
-+              tasklet_kill(&tpe->enable_tasklet);
++                      tasklet_kill(&tpe->disable_tasklet);
++                      tasklet_kill(&tpe->enable_tasklet);
 +#endif
-+      }
++              }
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
-+      unregister_kprobe(&gtp_ipi_kp);
++              unregister_kprobe(&gtp_ipi_kp);
 +#endif
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
-+      unregister_die_notifier(&gtp_notifier);
++      }
 +#endif
-+#endif
 +
 +#ifdef GTP_PERF_EVENTS
 +      list_for_each(cur, &gtp_var_list) {
@@ -9642,6 +9954,10 @@
 +              gtp_frame_reset();
 +
 +      gtpro_list_clear();
++#ifdef CONFIG_X86
++      gtp_have_watch_tracepoint = 0;
++      gtp_have_step = 0;
++#endif
 +
 +      gtp_var_release(0);
 +
@@ -9756,12 +10072,13 @@
 +}
 +
 +static int
-+gtp_add_backtrace_actions(struct gtp_entry *tpe)
++gtp_add_backtrace_actions(struct gtp_entry *tpe, int step)
 +{
 +      struct action   *ae, *new_ae;
 +      int             got_r = 0, got_m = 0;
 +
-+      for (ae = tpe->action_list; ae; ae = ae->next) {
++      for (ae = step ? tpe->step_action_list : tpe->action_list;
++           ae; ae = ae->next) {
 +              if (ae->type == 'R')
 +                      got_r = 1;
 +              else if (ae->type == 'M' && ae->u.m.regnum == GTP_SP_NUM
@@ -9769,7 +10086,9 @@
 +                      got_m = 1;
 +
 +              if (got_r && got_m)
-+                      break;
++                      return 1;
++
++              /* Let ae point to the last entry of action_list.  */
 +              if (!ae->next)
 +                      break;
 +      }
@@ -9780,8 +10099,14 @@
 +                      return -ENOMEM;
 +              if (ae)
 +                      ae->next = new_ae;
-+              else
-+                      tpe->action_list = ae;
++              else {
++                      if (step)
++                              tpe->step_action_list = ae;
++                      else
++                              tpe->action_list = ae;
++              }
++
++              /* Because new_ae is the new tail.  So set it to ae. */
 +              ae = new_ae;
 +      }
 +
@@ -9793,15 +10118,19 @@
 +              new_ae->u.m.size = gtp_bt_size;
 +              if (ae)
 +                      ae->next = new_ae;
-+              else
-+                      tpe->action_list = ae;
++              else {
++                      if (step)
++                              tpe->step_action_list = ae;
++                      else
++                              tpe->action_list = ae;
++              }
 +      }
 +
 +      return 1;
 +}
 +
 +static int
-+gtp_check_getv(struct gtp_entry *tpe, struct action *ae,
++gtp_check_getv(struct gtp_entry *tpe, struct action *ae, int step,
 +             uint8_t *ebuf, unsigned int pc,
 +             struct gtp_x_var **list)
 +{
@@ -9823,12 +10152,12 @@
 +
 +      switch (var->type) {
 +      case gtp_var_special:
-+              if (arg == GTP_VAR_NO_SELF_TRACE_ID) {
-+                      tpe->flags |= GTP_ENTRY_FLAGS_NO_SELF_TRACE;
++              if (arg == GTP_VAR_SELF_TRACE_ID) {
++                      tpe->flags |= GTP_ENTRY_FLAGS_SELF_TRACE;
 +                      ret = 1;
 +                      goto out;
 +              } else if (arg == GTP_VAR_BT_ID) {
-+                      ret = gtp_add_backtrace_actions (tpe);
++                      ret = gtp_add_backtrace_actions (tpe, step);
 +                      goto out;
 +              } else if (arg == GTP_VAR_CURRENT_ID) {
 +                      tpe->flags |= GTP_ENTRY_FLAGS_CURRENT_TASK;
@@ -9897,7 +10226,7 @@
 +}
 +
 +static int
-+gtp_check_setv(struct gtp_entry *tpe, struct action *ae,
++gtp_check_setv(struct gtp_entry *tpe, struct action *ae, int step,
 +             uint8_t *ebuf, unsigned int pc,
 +             struct gtp_x_var **list, int loop,
 +             ULONGEST *stack, ULONGEST top)
@@ -9921,8 +10250,8 @@
 +      switch (var->type) {
 +      case gtp_var_special:
 +              switch (arg) {
-+              case GTP_VAR_NO_SELF_TRACE_ID:
-+                      tpe->flags |= GTP_ENTRY_FLAGS_NO_SELF_TRACE;
++              case GTP_VAR_SELF_TRACE_ID:
++                      tpe->flags |= GTP_ENTRY_FLAGS_SELF_TRACE;
 +                      ret = 1;
 +                      goto out;
 +                      break;
@@ -9933,7 +10262,7 @@
 +                      goto out;
 +                      break;
 +              case GTP_VAR_BT_ID:
-+                      ret = gtp_add_backtrace_actions (tpe);
++                      ret = gtp_add_backtrace_actions (tpe, step);
 +                      goto out;
 +                      break;
 +              case GTP_VAR_CURRENT_ID:
@@ -9942,11 +10271,10 @@
 +                      goto out;
 +                      break;
 +              case GTP_VAR_PRINTK_LEVEL_ID:
-+                      if (loop) {
***The diff for this file has been truncated for email.***
=======================================
--- /trunk/gtp_2.6.33_to_2.6.38.patch   Sun Feb 17 20:54:51 2013
+++ /trunk/gtp_2.6.33_to_2.6.38.patch   Mon May  6 19:06:35 2013
@@ -3726,7 +3726,7 @@

 --- /dev/null
 +++ b/lib/gtp.c
-@@ -0,0 +1,12093 @@
+@@ -0,0 +1,12887 @@
 +/*
 + * Kernel GDB tracepoint module.
 + *
@@ -3744,12 +3744,12 @@
 + * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 + *
-+ * Copyright(C) KGTP team (https://code.google.com/p/kgtp/), 2010, 2011, 2012, 2013
++ * Copyright(C) KGTP team (https://code.google.com/p/kgtp/), 2010-2013
 + *
 + */
 +
 +/* If "* 10" means that this is not a release version.  */
-+#define GTP_VERSION                   (20130218)
++#define GTP_VERSION                   (20130218 * 10)
 +
 +#include <linux/version.h>
 +#ifndef RHEL_RELEASE_VERSION
@@ -3828,6 +3828,9 @@
 +#include <linux/slab.h>
 +#include <linux/ctype.h>
 +#include <asm/atomic.h>
++#ifdef CONFIG_X86
++#include <asm/debugreg.h>
++#endif
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
 +#include <linux/kdebug.h>
 +#else
@@ -3938,7 +3941,9 @@
 +                               + sizeof(struct gtp_frame_var))
 +#endif
 +#ifdef GTP_RB
-+#define GTP_FRAME_HEAD_SIZE   (FID_SIZE + sizeof(u64) + sizeof(ULONGEST))
++/* The frame head size: FID_HEAD + count id + frame number + pointer to prev frem */ ++#define GTP_FRAME_HEAD_SIZE (FID_SIZE + sizeof(u64) + sizeof(ULONGEST) + sizeof(void *))
++/* The frame head size: FID_PAGE_BEGIN + count id */
 +#define GTP_FRAME_PAGE_BEGIN_SIZE     (FID_SIZE + sizeof(u64))
 +#endif
 +#ifdef GTP_FTRACE_RING_BUFFER
@@ -4021,7 +4026,7 @@
 +/* This gtp entry is registered inside the system.  */
 +#define GTP_ENTRY_FLAGS_REG           2
 +/* See $no_self_trace.  */
-+#define GTP_ENTRY_FLAGS_NO_SELF_TRACE 4
++#define GTP_ENTRY_FLAGS_SELF_TRACE    4
 +/* This gtp entry has passcount.  */
 +#define GTP_ENTRY_FLAGS_HAVE_PASS     8
 +/* See $printk_level.  */
@@ -4192,14 +4197,32 @@
 +
 +static pid_t                  gtp_current_pid;
 +
++#ifdef CONFIG_X86
++/* Following part is for while-stepping.  */
++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);
++#endif
++
 +#ifdef CONFIG_X86
++static int    gtp_have_watch_tracepoint;
++static int    gtp_have_step;
++#endif
++
++#ifdef CONFIG_X86
++/* Following part is for watch tracepoint.  */
 +/* This part is X86 special.  */
 +#define HWB_NUM                       4
 +
 +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 {
@@ -4277,16 +4300,16 @@
 +{
 +      switch(reg) {
 +      case 0:
-+              set_debugreg(val, 0);
++              gtp_set_debugreg(val, 0);
 +              break;
 +      case 1:
-+              set_debugreg(val, 1);
++              gtp_set_debugreg(val, 1);
 +              break;
 +      case 2:
-+              set_debugreg(val, 2);
++              gtp_set_debugreg(val, 2);
 +              break;
 +      case 3:
-+              set_debugreg(val, 3);
++              gtp_set_debugreg(val, 3);
 +              break;
 +      }
 +}
@@ -4297,11 +4320,11 @@
 +{
 +      read_lock(&gtp_hwb_lock);
 +      __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      set_debugreg(0UL, 0);
-+      set_debugreg(0UL, 1);
-+      set_debugreg(0UL, 2);
-+      set_debugreg(0UL, 3);
-+      set_debugreg(GTP_HWB_DR7_DEF, 7);
++      gtp_set_debugreg(0UL, 0);
++      gtp_set_debugreg(0UL, 1);
++      gtp_set_debugreg(0UL, 2);
++      gtp_set_debugreg(0UL, 3);
++      gtp_set_debugreg(GTP_HWB_DR7_DEF, 7);
 +      read_unlock(&gtp_hwb_lock);
 +}
 +
@@ -4309,11 +4332,11 @@
 +gtp_hwb_sync_local(void)
 +{
 +      __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      set_debugreg(gtp_hwb_drx[0], 0);
-+      set_debugreg(gtp_hwb_drx[1], 1);
-+      set_debugreg(gtp_hwb_drx[2], 2);
-+      set_debugreg(gtp_hwb_drx[3], 3);
-+      set_debugreg(gtp_hwb_dr7, 7);
++      gtp_set_debugreg(gtp_hwb_drx[0], 0);
++      gtp_set_debugreg(gtp_hwb_drx[1], 1);
++      gtp_set_debugreg(gtp_hwb_drx[2], 2);
++      gtp_set_debugreg(gtp_hwb_drx[3], 3);
++      gtp_set_debugreg(gtp_hwb_dr7, 7);
 +}
 +
 +static void
@@ -4468,7 +4491,7 @@
 +      GTP_VAR_PRINTK_LEVEL_ID                 = 11,
 +      GTP_VAR_PRINTK_FORMAT_ID                = 12,
 +      GTP_VAR_DUMP_STACK_ID                   = 13,
-+      GTP_VAR_NO_SELF_TRACE_ID                = 14,
++      GTP_VAR_SELF_TRACE_ID                   = 14,
 +      GTP_VAR_CPU_NUMBER_ID                   = 15,
 +      GTP_VAR_PC_PE_EN_ID                     = 16,
 +      GTP_VAR_KRET_ID                         = 17,
@@ -4501,8 +4524,11 @@
 +      GTP_WATCH_VAL_ID                        = 42,
 +      GTP_WATCH_COUNT_ID                      = 43,
 +
++      GTP_STEP_COUNT_ID                       = 44,
++      GTP_STEP_ID_ID                          = 45,
++
 +      GTP_VAR_SPECIAL_MIN                     = GTP_VAR_VERSION_ID,
-+      GTP_VAR_SPECIAL_MAX                     = GTP_WATCH_COUNT_ID,
++      GTP_VAR_SPECIAL_MAX                     = GTP_STEP_ID_ID,
 +};
 +
 +enum pe_tv_id {
@@ -5511,6 +5537,44 @@
 +};
 +#endif
 +
++#ifdef GTP_RB
++static int
++gtp_step_count_hooks_get_val(struct gtp_trace_s *gts, struct gtp_var *gtv,
++                           int64_t *val)
++{
++      if (gts->step)
++              *val = gts->tpe->step - gts->step + 1;
++      else
++              *val = 0;
++
++      return 0;
++}
++
++static struct gtp_var_hooks   gtp_step_count_hooks = {
++      .agent_get_val = gtp_step_count_hooks_get_val,
++};
++
++static DEFINE_PER_CPU(int64_t, gtp_step_id);
++
++static int
++gtp_step_id_hooks_get_val(struct gtp_trace_s *gts, struct gtp_var *gtv,
++                        int64_t *val)
++{
++      if (!gts->step) {
++              if (++ __get_cpu_var(gtp_step_id) == 0)
++                      __get_cpu_var(gtp_step_id) = 1;
++      }
++
++      *val = __get_cpu_var(gtp_step_id);
++
++      return 0;
++}
++
++static struct gtp_var_hooks   gtp_step_id_hooks = {
++      .agent_get_val = gtp_step_id_hooks_get_val,
++};
++#endif
++
 +static int
 +gtp_var_special_add_all(void)
 +{
@@ -5603,8 +5667,8 @@
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +
-+      var = gtp_var_special_add(GTP_VAR_NO_SELF_TRACE_ID, 0, 0,
-+                                "no_self_trace", NULL);
++      var = gtp_var_special_add(GTP_VAR_SELF_TRACE_ID, 0, 0,
++                                "self_trace", NULL);
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +
@@ -5730,6 +5794,16 @@
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +#endif
++      var = gtp_var_special_add(GTP_STEP_COUNT_ID, 0, 0,
++                                "step_count", &gtp_step_count_hooks);
++      if (IS_ERR(var))
++              return PTR_ERR(var);
++#ifdef GTP_RB
++      var = gtp_var_special_add(GTP_STEP_ID_ID, 0, 0,
++                                "step_id", &gtp_step_id_hooks);
++      if (IS_ERR(var))
++              return PTR_ERR(var);
++#endif
 +
 +      return 0;
 +}
@@ -7302,6 +7376,11 @@
 +      } while (0)
 +#endif
 +
++static int    gtp_collect_var(struct gtp_trace_s *gts, int num);
++#ifdef GTP_RB
++static int    gtp_var_array_step_id_id = 0;
++#endif
++
 +static int
 +gtp_action_head(struct gtp_trace_s *gts)
 +{
@@ -7350,6 +7429,13 @@
 +
 +      trace_nump = (ULONGEST *)tmp;
 +      *trace_nump = gts->tpe->num;
++      tmp += sizeof(ULONGEST);
++
++#ifdef GTP_RB
++      *(void **)tmp = gtp_rb_prev_frame_get(gts->next);
++      gtp_rb_prev_frame_set(gts->next, (void *)(tmp + sizeof(void *)
++                                                - GTP_FRAME_HEAD_SIZE));
++#endif
 +
 +#ifdef GTP_FTRACE_RING_BUFFER
 +      ring_buffer_unlock_commit(gtp_frame, rbe);
@@ -7358,6 +7444,14 @@
 +
 +      atomic_inc(&gtp_frame_create);
 +
++#ifdef GTP_RB
++      /* Auto collect $step_id.  */
++      if (gts->tpe->step) {
++              if (gtp_collect_var(gts, gtp_var_array_step_id_id))
++                      return -1;
++      }
++#endif
++
 +      return 0;
 +}
 +
@@ -7800,6 +7894,8 @@
 +
 +      return ret;
 +}
++
++/* The number is not the ID of tvar, it is the ID of gtp_var_array. */
 +
 +static int
 +gtp_collect_var(struct gtp_trace_s *gts, int num)
@@ -8455,6 +8551,30 @@
 +}
 +#endif
 +
++#ifdef CONFIG_X86
++/* while-stepping stop.  */
++
++static void
++gtp_step_stop(struct pt_regs *regs)
++{
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24))
++      regs->flags &= ~(X86_EFLAGS_TF);
++#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;
++}
++#endif
++
 +static void
 +gtp_handler(struct gtp_trace_s *gts)
 +{
@@ -8464,6 +8584,10 @@
 +      printk(GTP_DEBUG_V "gtp_handler: tracepoint %d %p\n",
 +             (int)gts->tpe->num, (void *)(CORE_ADDR)gts->tpe->addr);
 +#endif
++#ifdef CONFIG_X86
++      if (gts->step == 0 && __get_cpu_var(gtp_step).step)
++              gtp_step_stop(gts->regs);
++#endif
 +
 +      gts->read_memory = (void *)probe_kernel_read;
 +      if (gts->tpe->flags & GTP_ENTRY_FLAGS_CURRENT_TASK) {
@@ -8480,7 +8604,7 @@
 +              return;
 +#endif
 +
-+      if ((gts->tpe->flags & GTP_ENTRY_FLAGS_NO_SELF_TRACE)
++      if ((gts->tpe->flags & GTP_ENTRY_FLAGS_SELF_TRACE) == 0
 +          && (get_current()->pid == gtp_gtp_pid
 +              || get_current()->pid == gtp_gtpframe_pid)) {
 +                      return;
@@ -8505,7 +8629,7 @@
 +      gts->run = NULL;
 +
 +      /* Pass.  */
-+      if (gts->tpe->flags & GTP_ENTRY_FLAGS_HAVE_PASS) {
++      if (gts->step == 0 && gts->tpe->flags & GTP_ENTRY_FLAGS_HAVE_PASS) {
 +              if (atomic_dec_return(&gts->tpe->current_pass) < 0)
 +                      goto tpe_stop;
 +      }
@@ -8665,18 +8789,47 @@
 +      struct kretprobe        *kpret;
 +      struct gtp_kp           *gkp;
 +      union gtp_entry_u       *u;
++      struct gtp_entry                *tpe;
 +      struct gtp_trace_s      gts;
 +
-+      memset(&gts, 0, sizeof(struct gtp_trace_s));
-+
 +      kpret = container_of(p, struct kretprobe, kp);
 +      gkp = container_of(kpret, struct gtp_kp, kpret);
 +      u = container_of(gkp, union gtp_entry_u, kp);
-+      gts.tpe = container_of(u, struct gtp_entry, u);
-+      gts.regs = regs;
-+      gts.step = 1;
++      tpe = container_of(u, struct gtp_entry, u);
++
++      if (tpe->step == 1) {
++              memset(&gts, 0, sizeof(struct gtp_trace_s));
++
++              gts.tpe = tpe;
++              gts.regs = regs;
++              gts.step = tpe->step;
++
++              gtp_handler(&gts);
++      }
 +
-+      gtp_handler(&gts);
++#ifdef CONFIG_X86
++      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. */
++              __get_cpu_var(gtp_step).step = tpe->step;
++              __get_cpu_var(gtp_step).tpe = tpe;
++              #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24))
++              if (regs->flags & X86_EFLAGS_IF)
++              #else
++              if (regs->eflags & X86_EFLAGS_IF)
++              #endif
++                      __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
 +}
 +
 +static inline void
@@ -8957,6 +9110,7 @@
 +              gtp_list = gtp_list->next;
 +              gtp_action_release(tpe->cond);
 +              gtp_action_release(tpe->action_list);
++              gtp_action_release(tpe->step_action_list);
 +              gtp_src_release(tpe->src);
 +              gtp_src_release(tpe->action_cmd);
 +              gtp_src_release(tpe->printk_str);
@@ -9197,6 +9351,238 @@
 +
 +      return 0;
 +}
++
++#ifdef CONFIG_X86
++#define ADDR_PREFIX_OPCODE 0x67
++#define DATA_PREFIX_OPCODE 0x66
++#define LOCK_PREFIX_OPCODE 0xf0
++#define CS_PREFIX_OPCODE 0x2e
++#define DS_PREFIX_OPCODE 0x3e
++#define ES_PREFIX_OPCODE 0x26
++#define FS_PREFIX_OPCODE 0x64
++#define GS_PREFIX_OPCODE 0x65
++#define SS_PREFIX_OPCODE 0x36
++#define REPNE_PREFIX_OPCODE 0xf2
++#define REPE_PREFIX_OPCODE  0xf3
++
++static int
++gtp_step_check_insn(struct pt_regs *regs)
++{
++      uint32_t        opcode;
++      uint8_t         opcode8;
++      unsigned long   pc = GTP_REGS_PC(regs);
++
++      /* prefixes */
++      while (1) {
++              if (probe_kernel_read(&opcode8, (void *)pc, 1))
++                      return -1;
++              pc++;
++              switch (opcode8) {
++              case REPE_PREFIX_OPCODE:
++              case REPNE_PREFIX_OPCODE:
++              case LOCK_PREFIX_OPCODE:
++              case CS_PREFIX_OPCODE:
++              case SS_PREFIX_OPCODE:
++              case DS_PREFIX_OPCODE:
++              case ES_PREFIX_OPCODE:
++              case FS_PREFIX_OPCODE:
++              case GS_PREFIX_OPCODE:
++              case DATA_PREFIX_OPCODE:
++              case ADDR_PREFIX_OPCODE:
++#ifndef CONFIG_X86_32
++              case 0x40 ... 0x4f:
++#endif
++                      break;
++              default:
++                      goto out_prefixes;
++              }
++      }
++out_prefixes:
++
++      opcode = (uint32_t)opcode8;
++reswitch:
++      switch (opcode) {
++      case 0x0f:
++              if (probe_kernel_read(&opcode8, (void *)pc, 1))
++                      return -1;
++              opcode = (uint32_t) opcode8 | 0x0f00;
++              goto reswitch;
++              break;
++      case 0xfb:
++              /* sti */
++              __get_cpu_var(gtp_step).irq_need_open = 1;
++              GTP_REGS_PC(regs) = pc;
++              break;
++      case 0xfa:
++              /* cli */
++              __get_cpu_var(gtp_step).irq_need_open = 0;
++              GTP_REGS_PC(regs) = pc;
++              break;
++      case 0x0f07:
++              /* sysret */
++              return 1;
++              break;
++      };
++
++      return 0;
++}
++
++static int
++gtp_notifier_call(struct notifier_block *self, unsigned long cmd,
++                 void *ptr)
++{
++      int             ret = NOTIFY_DONE;
++      unsigned long   flags;
++      struct die_args *args;
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      int             i;
++#endif
++      unsigned long   dr6;
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      unsigned long   *dr6_p;
++#endif
++
++      if (cmd != DIE_DEBUG)
++              return ret;
++
++      local_irq_save(flags);
++      args = ptr;
++
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      /* Get from X86 hw_breakpoint_handler.  */
++      dr6_p = (unsigned long *)ERR_PTR(args->err);
++      dr6 = *dr6_p;
++#else
++      dr6 = args->err;
++#endif
++      gtp_set_debugreg(GTP_HWB_DR7_DEF, 7);
++
++      /* Handle while-stepping.  */
++      spin_lock(&__get_cpu_var(gtp_step).lock);
++      if ((dr6 & 0x4000) != 0) {
++              /* Clear the bit that handle by KGTP.  */
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++              (*dr6_p) &= ~(0x4000);
++#else
++              dr6 &= ~(0x4000);
++#endif
++              if (!__get_cpu_var(gtp_step).tpe || user_mode(args->regs))
++                      gtp_step_stop(args->regs);
++              else {
++                      int need_stop = gtp_step_check_insn(args->regs);
++                      if (need_stop < 0)
++                              printk(KERN_WARNING "KGTP: check insn in %p got 
error.",
++                                     (void *)GTP_REGS_PC(args->regs));
++
++                      preempt_disable();
++                      {
++                              struct gtp_trace_s      gts;
++
++                              memset(&gts, 0, sizeof(struct gtp_trace_s));
++                              gts.tpe = __get_cpu_var(gtp_step).tpe;
++                              gts.regs = args->regs;
++                              gts.step = __get_cpu_var(gtp_step).step;
++                              gtp_handler(&gts);
++                      }
++                      preempt_enable_no_resched();
++
++                      if (__get_cpu_var(gtp_step).step > 1 && !need_stop) {
++                              /* 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.  */
++                              gtp_step_stop(args->regs);
++                      }
++              }
++      }
++      spin_unlock(&__get_cpu_var(gtp_step).lock);
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      /* Handle watch traceppoint.  */
++      if ((dr6 & 0xf) == 0)
++              goto out;
++      read_lock(&gtp_hwb_lock);
++
++      for (i = 0; i < HWB_NUM; i++) {
++              if ((dr6 & (0x1 << i)) == 0)
++                      continue;
++              /* Clear the bit that handle by KGTP.  */
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++              (*dr6_p) &= ~(0x1 << i);
++#else
++              dr6 &= ~(0x1 << i);
++#endif
++              if (gtp_hwb[i].watch == NULL)
++                      continue;
++              /* Check if gtp_hwb is updated in other CPU.  */
++              if (__get_cpu_var(gtp_hwb_sync_count_local) != 
gtp_hwb_sync_count) {
++                      unsigned long   addr;
++
++                      gtp_get_debugreg(addr, i);
++                      if (addr != gtp_hwb[i].addr)
++                              continue;
++              }
++              preempt_disable();
++              {
++                      struct gtp_trace_s      gts;
++
++                      memset(&gts, 0, sizeof(struct gtp_trace_s));
++                      gts.tpe = gtp_hwb[i].watch;
++                      gts.regs = args->regs;
++                      gts.hwb = &gtp_hwb[i];
++                      gtp_handler(&gts);
++              }
++              preempt_enable_no_resched();
++      }
++
++      /* If the HWB need update in this CPU, just update it.  */
++      if (__get_cpu_var(gtp_hwb_sync_count_local) != gtp_hwb_sync_count) {
++              gtp_set_debugreg(gtp_hwb_drx[0], 0);
++              gtp_set_debugreg(gtp_hwb_drx[1], 1);
++              gtp_set_debugreg(gtp_hwb_drx[2], 2);
++              gtp_set_debugreg(gtp_hwb_drx[3], 3);
++              __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
++      }
++
++      gtp_set_debugreg(gtp_hwb_dr7, 7);
++      read_unlock(&gtp_hwb_lock);
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++out:
++#endif
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
++      gtp_set_debugreg(dr6, 6);
++#endif
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      /* If have some other traps, let other handler handle it.  */
++      if (((*dr6_p) & GTP_HWB_DR6_MASK) == 0)
++              ret = NOTIFY_STOP;
++      current->thread.debugreg6 = *dr6_p;
++#else
++      if ((dr6 & GTP_HWB_DR6_MASK) == 0)
++              ret = NOTIFY_STOP;
++      current->thread.debugreg6 = dr6;
++#endif
++
++      local_irq_restore(flags);
++      return ret;
++}
++
++static struct notifier_block gtp_notifier = {
++      .notifier_call = gtp_notifier_call,
++      .priority = 0x7ffffffe /* we need to be notified after kprobe.  */
++};
++#endif
 +
 +#ifdef CONFIG_X86
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0))
@@ -9293,102 +9679,8 @@
 +      gtp_hw_breakpoint_handler(breakinfo[3].num, regs);
 +}
 +#endif
-+#else
-+static int
-+gtp_notifier_call(struct notifier_block *self, unsigned long cmd,
-+                 void *ptr)
-+{
-+      int             ret = NOTIFY_DONE;
-+      unsigned long   flags;
-+      struct die_args *args;
-+      int             i;
-+      unsigned long   dr6;
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      unsigned long   *dr6_p;
 +#endif
 +
-+      if (cmd != DIE_DEBUG)
-+              return ret;
-+
-+      local_irq_save(flags);
-+      args = ptr;
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      /* Get from X86 hw_breakpoint_handler.  */
-+      dr6_p = (unsigned long *)ERR_PTR(args->err);
-+      dr6 = *dr6_p;
-+#else
-+      dr6 = args->err;
-+#endif
-+      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)
-+                      continue;
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+              /* Because KGTP handle all the hw-breakpoints.
-+                 So Just clear it.  */
-+              (*dr6_p) &= ~(0x1 << i);
-+#endif
-+              if (gtp_hwb[i].watch == NULL)
-+                      continue;
-+              /* Check if gtp_hwb is updated in other CPU.  */
-+              if (__get_cpu_var(gtp_hwb_sync_count_local) != 
gtp_hwb_sync_count) {
-+                      unsigned long   addr;
-+
-+                      gtp_get_debugreg(addr, i);
-+                      if (addr != gtp_hwb[i].addr)
-+                              continue;
-+              }
-+              preempt_disable();
-+              {
-+                      struct gtp_trace_s      gts;
-+
-+                      memset(&gts, 0, sizeof(struct gtp_trace_s));
-+                      gts.tpe = gtp_hwb[i].watch;
-+                      gts.regs = args->regs;
-+                      gts.hwb = &gtp_hwb[i];
-+                      gtp_handler(&gts);
-+              }
-+              preempt_enable_no_resched();
-+      }
-+
-+      /* If the HWB need update in this CPU, just update it.  */
-+      if (__get_cpu_var(gtp_hwb_sync_count_local) != gtp_hwb_sync_count) {
-+              set_debugreg(gtp_hwb_drx[0], 0);
-+              set_debugreg(gtp_hwb_drx[1], 1);
-+              set_debugreg(gtp_hwb_drx[2], 2);
-+              set_debugreg(gtp_hwb_drx[3], 3);
-+              __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      }
-+
-+      set_debugreg(gtp_hwb_dr7, 7);
-+      read_unlock(&gtp_hwb_lock);
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      /* If have some other traps, let other handler handle it.  */
-+      if ((dr6 & (~0xf)) == 0)
-+              ret = NOTIFY_STOP;
-+#else
-+      set_debugreg(0UL, 6);
-+      ret = NOTIFY_STOP;
-+#endif
-+
-+out:
-+      local_irq_restore(flags);
-+      return ret;
-+}
-+
-+static struct notifier_block gtp_notifier = {
-+      .notifier_call = gtp_notifier_call,
-+      .priority = 0x7fffffff /* we need to be notified first */
-+};
-+#endif
-+
 +static unsigned int
 +gtp_hwb_size_to_arch(int size)
 +{
@@ -9467,7 +9759,7 @@
 +
 +              /* Set gtp_hwb_dr7 and gtp_hwb_drx[num] to hwb.  */
 +              gtp_set_debugreg(gtp_hwb_drx[num], num);
-+              set_debugreg(gtp_hwb_dr7, 7);
++              gtp_set_debugreg(gtp_hwb_dr7, 7);
 +
 +              gtp_hwb_sync_count++;
 +              hwb->count = gtp_hwb_sync_count;
@@ -9524,7 +9816,7 @@
 +                      gtp_hwb_sync_count++;
 +
 +                      /* Sync gtp_hwb_dr7 update to hwb.  */
-+                      set_debugreg(gtp_hwb_dr7, 7);
++                      gtp_set_debugreg(gtp_hwb_dr7, 7);
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
 +                      /* Send ipi to let other cpu update.  */
@@ -9587,54 +9879,74 @@
 +              tasklet_kill(&tpe->disable_tasklet);
 +              tasklet_kill(&tpe->enable_tasklet);
 +#endif
++      }
++
++#ifdef CONFIG_X86
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      if (gtp_have_step || gtp_have_watch_tracepoint)
++#else
++      if (gtp_have_step)
++#endif
++              unregister_die_notifier(&gtp_notifier);
++
++      {
++              /* Init data of while-stepping.  */
++              int     cpu;
++              for_each_online_cpu(cpu) {
++                      struct gtp_step_s       *step = &per_cpu(gtp_step, cpu);
++
++                      spin_lock(&step->lock);
++                      step->step = 0;
++                      step->tpe = NULL;
++                      spin_unlock(&step->lock);
++              }
 +      }
++#endif
 +
 +#ifdef CONFIG_X86
 +      /* Stop hwb.  */
++      if (gtp_have_watch_tracepoint) {
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0))
-+      {
-+              int     i;
++              {
++                      int     i;
 +
-+              /* Register hw breakpoints.  */
-+              for (i = 0; i < HWB_NUM; i++) {
-+                      unregister_wide_hw_breakpoint(breakinfo[i].pev);
-+                      breakinfo[i].pev = NULL;
++                      /* Register hw breakpoints.  */
++                      for (i = 0; i < HWB_NUM; i++) {
++                              unregister_wide_hw_breakpoint(breakinfo[i].pev);
++                              breakinfo[i].pev = NULL;
++                      }
 +              }
-+      }
 +#endif
 +
-+      gtp_hwb_stop(NULL);
++              gtp_hwb_stop(NULL);
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
-+      smp_call_function(gtp_hwb_stop, NULL, 1);
++              smp_call_function(gtp_hwb_stop, NULL, 1);
 +#else
-+      smp_call_function(gtp_hwb_stop, NULL, 0, 1);
++              smp_call_function(gtp_hwb_stop, NULL, 0, 1);
 +#endif
 +
-+      for (tpe = gtp_list; tpe; tpe = tpe->next) {
-+              if (tpe->type == gtp_entry_kprobe
-+                  || (tpe->flags & GTP_ENTRY_FLAGS_REG) == 0
-+                  || tpe->disable)
-+                      continue;
++              for (tpe = gtp_list; tpe; tpe = tpe->next) {
++                      if (tpe->type == gtp_entry_kprobe
++                          || (tpe->flags & GTP_ENTRY_FLAGS_REG) == 0
++                          || tpe->disable)
++                              continue;
 +
-+              if (tpe->type == gtp_entry_watch_static)
-+                      gtp_unregister_hwb(tpe->addr, 0);
++                      if (tpe->type == gtp_entry_watch_static)
++                              gtp_unregister_hwb(tpe->addr, 0);
 +
-+              tpe->flags &= ~GTP_ENTRY_FLAGS_REG;
++                      tpe->flags &= ~GTP_ENTRY_FLAGS_REG;
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
-+              tasklet_kill(&tpe->disable_tasklet);
-+              tasklet_kill(&tpe->enable_tasklet);
++                      tasklet_kill(&tpe->disable_tasklet);
++                      tasklet_kill(&tpe->enable_tasklet);
 +#endif
-+      }
++              }
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
-+      unregister_kprobe(&gtp_ipi_kp);
++              unregister_kprobe(&gtp_ipi_kp);
 +#endif
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
-+      unregister_die_notifier(&gtp_notifier);
++      }
 +#endif
-+#endif
 +
 +#ifdef GTP_PERF_EVENTS
 +      list_for_each(cur, &gtp_var_list) {
@@ -9706,6 +10018,10 @@
 +              gtp_frame_reset();
 +
 +      gtpro_list_clear();
++#ifdef CONFIG_X86
++      gtp_have_watch_tracepoint = 0;
++      gtp_have_step = 0;
++#endif
 +
 +      gtp_var_release(0);
 +
@@ -9820,12 +10136,13 @@
 +}
 +
 +static int
-+gtp_add_backtrace_actions(struct gtp_entry *tpe)
++gtp_add_backtrace_actions(struct gtp_entry *tpe, int step)
 +{
 +      struct action   *ae, *new_ae;
 +      int             got_r = 0, got_m = 0;
 +
-+      for (ae = tpe->action_list; ae; ae = ae->next) {
++      for (ae = step ? tpe->step_action_list : tpe->action_list;
++           ae; ae = ae->next) {
 +              if (ae->type == 'R')
 +                      got_r = 1;
 +              else if (ae->type == 'M' && ae->u.m.regnum == GTP_SP_NUM
@@ -9833,7 +10150,9 @@
 +                      got_m = 1;
 +
 +              if (got_r && got_m)
-+                      break;
++                      return 1;
++
++              /* Let ae point to the last entry of action_list.  */
 +              if (!ae->next)
 +                      break;
 +      }
@@ -9844,8 +10163,14 @@
 +                      return -ENOMEM;
 +              if (ae)
 +                      ae->next = new_ae;
-+              else
-+                      tpe->action_list = ae;
++              else {
++                      if (step)
++                              tpe->step_action_list = ae;
++                      else
++                              tpe->action_list = ae;
++              }
++
++              /* Because new_ae is the new tail.  So set it to ae. */
 +              ae = new_ae;
 +      }
 +
@@ -9857,15 +10182,19 @@
 +              new_ae->u.m.size = gtp_bt_size;
 +              if (ae)
 +                      ae->next = new_ae;
-+              else
-+                      tpe->action_list = ae;
++              else {
++                      if (step)
++                              tpe->step_action_list = ae;
++                      else
++                              tpe->action_list = ae;
++              }
 +      }
 +
 +      return 1;
 +}
 +
 +static int
-+gtp_check_getv(struct gtp_entry *tpe, struct action *ae,
++gtp_check_getv(struct gtp_entry *tpe, struct action *ae, int step,
 +             uint8_t *ebuf, unsigned int pc,
 +             struct gtp_x_var **list)
 +{
@@ -9887,12 +10216,12 @@
 +
 +      switch (var->type) {
 +      case gtp_var_special:
-+              if (arg == GTP_VAR_NO_SELF_TRACE_ID) {
-+                      tpe->flags |= GTP_ENTRY_FLAGS_NO_SELF_TRACE;
++              if (arg == GTP_VAR_SELF_TRACE_ID) {
++                      tpe->flags |= GTP_ENTRY_FLAGS_SELF_TRACE;
 +                      ret = 1;
 +                      goto out;
 +              } else if (arg == GTP_VAR_BT_ID) {
-+                      ret = gtp_add_backtrace_actions (tpe);
++                      ret = gtp_add_backtrace_actions (tpe, step);
 +                      goto out;
 +              } else if (arg == GTP_VAR_CURRENT_ID) {
 +                      tpe->flags |= GTP_ENTRY_FLAGS_CURRENT_TASK;
@@ -9961,7 +10290,7 @@
 +}
 +
 +static int
-+gtp_check_setv(struct gtp_entry *tpe, struct action *ae,
++gtp_check_setv(struct gtp_entry *tpe, struct action *ae, int step,
 +             uint8_t *ebuf, unsigned int pc,
 +             struct gtp_x_var **list, int loop,
 +             ULONGEST *stack, ULONGEST top)
@@ -9985,8 +10314,8 @@
 +      switch (var->type) {
 +      case gtp_var_special:
 +              switch (arg) {
-+              case GTP_VAR_NO_SELF_TRACE_ID:
-+                      tpe->flags |= GTP_ENTRY_FLAGS_NO_SELF_TRACE;
++              case GTP_VAR_SELF_TRACE_ID:
++                      tpe->flags |= GTP_ENTRY_FLAGS_SELF_TRACE;
 +                      ret = 1;
 +                      goto out;
 +                      break;
@@ -9997,7 +10326,7 @@
 +                      goto out;
 +                      break;
 +              case GTP_VAR_BT_ID:
-+                      ret = gtp_add_backtrace_actions (tpe);
++                      ret = gtp_add_backtrace_actions (tpe, step);
 +                      goto out;
 +                      break;
 +              case GTP_VAR_CURRENT_ID:
@@ -10006,11 +10335,10 @@
 +                      goto out;
 +                      break;
 +              case GTP_VAR_PRINTK_LEVEL_ID:
-+                      if (loop) {
***The diff for this file has been truncated for email.***
=======================================
--- /trunk/gtp_2.6.39.patch     Sun Feb 17 20:54:51 2013
+++ /trunk/gtp_2.6.39.patch     Mon May  6 19:06:35 2013
@@ -3716,7 +3716,7 @@

 --- /dev/null
 +++ b/lib/gtp.c
-@@ -0,0 +1,12093 @@
+@@ -0,0 +1,12887 @@
 +/*
 + * Kernel GDB tracepoint module.
 + *
@@ -3734,12 +3734,12 @@
 + * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 + *
-+ * Copyright(C) KGTP team (https://code.google.com/p/kgtp/), 2010, 2011, 2012, 2013
++ * Copyright(C) KGTP team (https://code.google.com/p/kgtp/), 2010-2013
 + *
 + */
 +
 +/* If "* 10" means that this is not a release version.  */
-+#define GTP_VERSION                   (20130218)
++#define GTP_VERSION                   (20130218 * 10)
 +
 +#include <linux/version.h>
 +#ifndef RHEL_RELEASE_VERSION
@@ -3818,6 +3818,9 @@
 +#include <linux/slab.h>
 +#include <linux/ctype.h>
 +#include <asm/atomic.h>
++#ifdef CONFIG_X86
++#include <asm/debugreg.h>
++#endif
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
 +#include <linux/kdebug.h>
 +#else
@@ -3928,7 +3931,9 @@
 +                               + sizeof(struct gtp_frame_var))
 +#endif
 +#ifdef GTP_RB
-+#define GTP_FRAME_HEAD_SIZE   (FID_SIZE + sizeof(u64) + sizeof(ULONGEST))
++/* The frame head size: FID_HEAD + count id + frame number + pointer to prev frem */ ++#define GTP_FRAME_HEAD_SIZE (FID_SIZE + sizeof(u64) + sizeof(ULONGEST) + sizeof(void *))
++/* The frame head size: FID_PAGE_BEGIN + count id */
 +#define GTP_FRAME_PAGE_BEGIN_SIZE     (FID_SIZE + sizeof(u64))
 +#endif
 +#ifdef GTP_FTRACE_RING_BUFFER
@@ -4011,7 +4016,7 @@
 +/* This gtp entry is registered inside the system.  */
 +#define GTP_ENTRY_FLAGS_REG           2
 +/* See $no_self_trace.  */
-+#define GTP_ENTRY_FLAGS_NO_SELF_TRACE 4
++#define GTP_ENTRY_FLAGS_SELF_TRACE    4
 +/* This gtp entry has passcount.  */
 +#define GTP_ENTRY_FLAGS_HAVE_PASS     8
 +/* See $printk_level.  */
@@ -4182,14 +4187,32 @@
 +
 +static pid_t                  gtp_current_pid;
 +
++#ifdef CONFIG_X86
++/* Following part is for while-stepping.  */
++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);
++#endif
++
 +#ifdef CONFIG_X86
++static int    gtp_have_watch_tracepoint;
++static int    gtp_have_step;
++#endif
++
++#ifdef CONFIG_X86
++/* Following part is for watch tracepoint.  */
 +/* This part is X86 special.  */
 +#define HWB_NUM                       4
 +
 +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 {
@@ -4267,16 +4290,16 @@
 +{
 +      switch(reg) {
 +      case 0:
-+              set_debugreg(val, 0);
++              gtp_set_debugreg(val, 0);
 +              break;
 +      case 1:
-+              set_debugreg(val, 1);
++              gtp_set_debugreg(val, 1);
 +              break;
 +      case 2:
-+              set_debugreg(val, 2);
++              gtp_set_debugreg(val, 2);
 +              break;
 +      case 3:
-+              set_debugreg(val, 3);
++              gtp_set_debugreg(val, 3);
 +              break;
 +      }
 +}
@@ -4287,11 +4310,11 @@
 +{
 +      read_lock(&gtp_hwb_lock);
 +      __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      set_debugreg(0UL, 0);
-+      set_debugreg(0UL, 1);
-+      set_debugreg(0UL, 2);
-+      set_debugreg(0UL, 3);
-+      set_debugreg(GTP_HWB_DR7_DEF, 7);
++      gtp_set_debugreg(0UL, 0);
++      gtp_set_debugreg(0UL, 1);
++      gtp_set_debugreg(0UL, 2);
++      gtp_set_debugreg(0UL, 3);
++      gtp_set_debugreg(GTP_HWB_DR7_DEF, 7);
 +      read_unlock(&gtp_hwb_lock);
 +}
 +
@@ -4299,11 +4322,11 @@
 +gtp_hwb_sync_local(void)
 +{
 +      __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      set_debugreg(gtp_hwb_drx[0], 0);
-+      set_debugreg(gtp_hwb_drx[1], 1);
-+      set_debugreg(gtp_hwb_drx[2], 2);
-+      set_debugreg(gtp_hwb_drx[3], 3);
-+      set_debugreg(gtp_hwb_dr7, 7);
++      gtp_set_debugreg(gtp_hwb_drx[0], 0);
++      gtp_set_debugreg(gtp_hwb_drx[1], 1);
++      gtp_set_debugreg(gtp_hwb_drx[2], 2);
++      gtp_set_debugreg(gtp_hwb_drx[3], 3);
++      gtp_set_debugreg(gtp_hwb_dr7, 7);
 +}
 +
 +static void
@@ -4458,7 +4481,7 @@
 +      GTP_VAR_PRINTK_LEVEL_ID                 = 11,
 +      GTP_VAR_PRINTK_FORMAT_ID                = 12,
 +      GTP_VAR_DUMP_STACK_ID                   = 13,
-+      GTP_VAR_NO_SELF_TRACE_ID                = 14,
++      GTP_VAR_SELF_TRACE_ID                   = 14,
 +      GTP_VAR_CPU_NUMBER_ID                   = 15,
 +      GTP_VAR_PC_PE_EN_ID                     = 16,
 +      GTP_VAR_KRET_ID                         = 17,
@@ -4491,8 +4514,11 @@
 +      GTP_WATCH_VAL_ID                        = 42,
 +      GTP_WATCH_COUNT_ID                      = 43,
 +
++      GTP_STEP_COUNT_ID                       = 44,
++      GTP_STEP_ID_ID                          = 45,
++
 +      GTP_VAR_SPECIAL_MIN                     = GTP_VAR_VERSION_ID,
-+      GTP_VAR_SPECIAL_MAX                     = GTP_WATCH_COUNT_ID,
++      GTP_VAR_SPECIAL_MAX                     = GTP_STEP_ID_ID,
 +};
 +
 +enum pe_tv_id {
@@ -5501,6 +5527,44 @@
 +};
 +#endif
 +
++#ifdef GTP_RB
++static int
++gtp_step_count_hooks_get_val(struct gtp_trace_s *gts, struct gtp_var *gtv,
++                           int64_t *val)
++{
++      if (gts->step)
++              *val = gts->tpe->step - gts->step + 1;
++      else
++              *val = 0;
++
++      return 0;
++}
++
++static struct gtp_var_hooks   gtp_step_count_hooks = {
++      .agent_get_val = gtp_step_count_hooks_get_val,
++};
++
++static DEFINE_PER_CPU(int64_t, gtp_step_id);
++
++static int
++gtp_step_id_hooks_get_val(struct gtp_trace_s *gts, struct gtp_var *gtv,
++                        int64_t *val)
++{
++      if (!gts->step) {
++              if (++ __get_cpu_var(gtp_step_id) == 0)
++                      __get_cpu_var(gtp_step_id) = 1;
++      }
++
++      *val = __get_cpu_var(gtp_step_id);
++
++      return 0;
++}
++
++static struct gtp_var_hooks   gtp_step_id_hooks = {
++      .agent_get_val = gtp_step_id_hooks_get_val,
++};
++#endif
++
 +static int
 +gtp_var_special_add_all(void)
 +{
@@ -5593,8 +5657,8 @@
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +
-+      var = gtp_var_special_add(GTP_VAR_NO_SELF_TRACE_ID, 0, 0,
-+                                "no_self_trace", NULL);
++      var = gtp_var_special_add(GTP_VAR_SELF_TRACE_ID, 0, 0,
++                                "self_trace", NULL);
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +
@@ -5720,6 +5784,16 @@
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +#endif
++      var = gtp_var_special_add(GTP_STEP_COUNT_ID, 0, 0,
++                                "step_count", &gtp_step_count_hooks);
++      if (IS_ERR(var))
++              return PTR_ERR(var);
++#ifdef GTP_RB
++      var = gtp_var_special_add(GTP_STEP_ID_ID, 0, 0,
++                                "step_id", &gtp_step_id_hooks);
++      if (IS_ERR(var))
++              return PTR_ERR(var);
++#endif
 +
 +      return 0;
 +}
@@ -7292,6 +7366,11 @@
 +      } while (0)
 +#endif
 +
++static int    gtp_collect_var(struct gtp_trace_s *gts, int num);
++#ifdef GTP_RB
++static int    gtp_var_array_step_id_id = 0;
++#endif
++
 +static int
 +gtp_action_head(struct gtp_trace_s *gts)
 +{
@@ -7340,6 +7419,13 @@
 +
 +      trace_nump = (ULONGEST *)tmp;
 +      *trace_nump = gts->tpe->num;
++      tmp += sizeof(ULONGEST);
++
++#ifdef GTP_RB
++      *(void **)tmp = gtp_rb_prev_frame_get(gts->next);
++      gtp_rb_prev_frame_set(gts->next, (void *)(tmp + sizeof(void *)
++                                                - GTP_FRAME_HEAD_SIZE));
++#endif
 +
 +#ifdef GTP_FTRACE_RING_BUFFER
 +      ring_buffer_unlock_commit(gtp_frame, rbe);
@@ -7348,6 +7434,14 @@
 +
 +      atomic_inc(&gtp_frame_create);
 +
++#ifdef GTP_RB
++      /* Auto collect $step_id.  */
++      if (gts->tpe->step) {
++              if (gtp_collect_var(gts, gtp_var_array_step_id_id))
++                      return -1;
++      }
++#endif
++
 +      return 0;
 +}
 +
@@ -7790,6 +7884,8 @@
 +
 +      return ret;
 +}
++
++/* The number is not the ID of tvar, it is the ID of gtp_var_array. */
 +
 +static int
 +gtp_collect_var(struct gtp_trace_s *gts, int num)
@@ -8445,6 +8541,30 @@
 +}
 +#endif
 +
++#ifdef CONFIG_X86
++/* while-stepping stop.  */
++
++static void
++gtp_step_stop(struct pt_regs *regs)
++{
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24))
++      regs->flags &= ~(X86_EFLAGS_TF);
++#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;
++}
++#endif
++
 +static void
 +gtp_handler(struct gtp_trace_s *gts)
 +{
@@ -8454,6 +8574,10 @@
 +      printk(GTP_DEBUG_V "gtp_handler: tracepoint %d %p\n",
 +             (int)gts->tpe->num, (void *)(CORE_ADDR)gts->tpe->addr);
 +#endif
++#ifdef CONFIG_X86
++      if (gts->step == 0 && __get_cpu_var(gtp_step).step)
++              gtp_step_stop(gts->regs);
++#endif
 +
 +      gts->read_memory = (void *)probe_kernel_read;
 +      if (gts->tpe->flags & GTP_ENTRY_FLAGS_CURRENT_TASK) {
@@ -8470,7 +8594,7 @@
 +              return;
 +#endif
 +
-+      if ((gts->tpe->flags & GTP_ENTRY_FLAGS_NO_SELF_TRACE)
++      if ((gts->tpe->flags & GTP_ENTRY_FLAGS_SELF_TRACE) == 0
 +          && (get_current()->pid == gtp_gtp_pid
 +              || get_current()->pid == gtp_gtpframe_pid)) {
 +                      return;
@@ -8495,7 +8619,7 @@
 +      gts->run = NULL;
 +
 +      /* Pass.  */
-+      if (gts->tpe->flags & GTP_ENTRY_FLAGS_HAVE_PASS) {
++      if (gts->step == 0 && gts->tpe->flags & GTP_ENTRY_FLAGS_HAVE_PASS) {
 +              if (atomic_dec_return(&gts->tpe->current_pass) < 0)
 +                      goto tpe_stop;
 +      }
@@ -8655,18 +8779,47 @@
 +      struct kretprobe        *kpret;
 +      struct gtp_kp           *gkp;
 +      union gtp_entry_u       *u;
++      struct gtp_entry                *tpe;
 +      struct gtp_trace_s      gts;
 +
-+      memset(&gts, 0, sizeof(struct gtp_trace_s));
-+
 +      kpret = container_of(p, struct kretprobe, kp);
 +      gkp = container_of(kpret, struct gtp_kp, kpret);
 +      u = container_of(gkp, union gtp_entry_u, kp);
-+      gts.tpe = container_of(u, struct gtp_entry, u);
-+      gts.regs = regs;
-+      gts.step = 1;
++      tpe = container_of(u, struct gtp_entry, u);
++
++      if (tpe->step == 1) {
++              memset(&gts, 0, sizeof(struct gtp_trace_s));
++
++              gts.tpe = tpe;
++              gts.regs = regs;
++              gts.step = tpe->step;
++
++              gtp_handler(&gts);
++      }
 +
-+      gtp_handler(&gts);
++#ifdef CONFIG_X86
++      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. */
++              __get_cpu_var(gtp_step).step = tpe->step;
++              __get_cpu_var(gtp_step).tpe = tpe;
++              #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24))
++              if (regs->flags & X86_EFLAGS_IF)
++              #else
++              if (regs->eflags & X86_EFLAGS_IF)
++              #endif
++                      __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
 +}
 +
 +static inline void
@@ -8947,6 +9100,7 @@
 +              gtp_list = gtp_list->next;
 +              gtp_action_release(tpe->cond);
 +              gtp_action_release(tpe->action_list);
++              gtp_action_release(tpe->step_action_list);
 +              gtp_src_release(tpe->src);
 +              gtp_src_release(tpe->action_cmd);
 +              gtp_src_release(tpe->printk_str);
@@ -9187,6 +9341,238 @@
 +
 +      return 0;
 +}
++
++#ifdef CONFIG_X86
++#define ADDR_PREFIX_OPCODE 0x67
++#define DATA_PREFIX_OPCODE 0x66
++#define LOCK_PREFIX_OPCODE 0xf0
++#define CS_PREFIX_OPCODE 0x2e
++#define DS_PREFIX_OPCODE 0x3e
++#define ES_PREFIX_OPCODE 0x26
++#define FS_PREFIX_OPCODE 0x64
++#define GS_PREFIX_OPCODE 0x65
++#define SS_PREFIX_OPCODE 0x36
++#define REPNE_PREFIX_OPCODE 0xf2
++#define REPE_PREFIX_OPCODE  0xf3
++
++static int
++gtp_step_check_insn(struct pt_regs *regs)
++{
++      uint32_t        opcode;
++      uint8_t         opcode8;
++      unsigned long   pc = GTP_REGS_PC(regs);
++
++      /* prefixes */
++      while (1) {
++              if (probe_kernel_read(&opcode8, (void *)pc, 1))
++                      return -1;
++              pc++;
++              switch (opcode8) {
++              case REPE_PREFIX_OPCODE:
++              case REPNE_PREFIX_OPCODE:
++              case LOCK_PREFIX_OPCODE:
++              case CS_PREFIX_OPCODE:
++              case SS_PREFIX_OPCODE:
++              case DS_PREFIX_OPCODE:
++              case ES_PREFIX_OPCODE:
++              case FS_PREFIX_OPCODE:
++              case GS_PREFIX_OPCODE:
++              case DATA_PREFIX_OPCODE:
++              case ADDR_PREFIX_OPCODE:
++#ifndef CONFIG_X86_32
++              case 0x40 ... 0x4f:
++#endif
++                      break;
++              default:
++                      goto out_prefixes;
++              }
++      }
++out_prefixes:
++
++      opcode = (uint32_t)opcode8;
++reswitch:
++      switch (opcode) {
++      case 0x0f:
++              if (probe_kernel_read(&opcode8, (void *)pc, 1))
++                      return -1;
++              opcode = (uint32_t) opcode8 | 0x0f00;
++              goto reswitch;
++              break;
++      case 0xfb:
++              /* sti */
++              __get_cpu_var(gtp_step).irq_need_open = 1;
++              GTP_REGS_PC(regs) = pc;
++              break;
++      case 0xfa:
++              /* cli */
++              __get_cpu_var(gtp_step).irq_need_open = 0;
++              GTP_REGS_PC(regs) = pc;
++              break;
++      case 0x0f07:
++              /* sysret */
++              return 1;
++              break;
++      };
++
++      return 0;
++}
++
++static int
++gtp_notifier_call(struct notifier_block *self, unsigned long cmd,
++                 void *ptr)
++{
++      int             ret = NOTIFY_DONE;
++      unsigned long   flags;
++      struct die_args *args;
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      int             i;
++#endif
++      unsigned long   dr6;
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      unsigned long   *dr6_p;
++#endif
++
++      if (cmd != DIE_DEBUG)
++              return ret;
++
++      local_irq_save(flags);
++      args = ptr;
++
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      /* Get from X86 hw_breakpoint_handler.  */
++      dr6_p = (unsigned long *)ERR_PTR(args->err);
++      dr6 = *dr6_p;
++#else
++      dr6 = args->err;
++#endif
++      gtp_set_debugreg(GTP_HWB_DR7_DEF, 7);
++
++      /* Handle while-stepping.  */
++      spin_lock(&__get_cpu_var(gtp_step).lock);
++      if ((dr6 & 0x4000) != 0) {
++              /* Clear the bit that handle by KGTP.  */
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++              (*dr6_p) &= ~(0x4000);
++#else
++              dr6 &= ~(0x4000);
++#endif
++              if (!__get_cpu_var(gtp_step).tpe || user_mode(args->regs))
++                      gtp_step_stop(args->regs);
++              else {
++                      int need_stop = gtp_step_check_insn(args->regs);
++                      if (need_stop < 0)
++                              printk(KERN_WARNING "KGTP: check insn in %p got 
error.",
++                                     (void *)GTP_REGS_PC(args->regs));
++
++                      preempt_disable();
++                      {
++                              struct gtp_trace_s      gts;
++
++                              memset(&gts, 0, sizeof(struct gtp_trace_s));
++                              gts.tpe = __get_cpu_var(gtp_step).tpe;
++                              gts.regs = args->regs;
++                              gts.step = __get_cpu_var(gtp_step).step;
++                              gtp_handler(&gts);
++                      }
++                      preempt_enable_no_resched();
++
++                      if (__get_cpu_var(gtp_step).step > 1 && !need_stop) {
++                              /* 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.  */
++                              gtp_step_stop(args->regs);
++                      }
++              }
++      }
++      spin_unlock(&__get_cpu_var(gtp_step).lock);
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      /* Handle watch traceppoint.  */
++      if ((dr6 & 0xf) == 0)
++              goto out;
++      read_lock(&gtp_hwb_lock);
++
++      for (i = 0; i < HWB_NUM; i++) {
++              if ((dr6 & (0x1 << i)) == 0)
++                      continue;
++              /* Clear the bit that handle by KGTP.  */
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++              (*dr6_p) &= ~(0x1 << i);
++#else
++              dr6 &= ~(0x1 << i);
++#endif
++              if (gtp_hwb[i].watch == NULL)
++                      continue;
++              /* Check if gtp_hwb is updated in other CPU.  */
++              if (__get_cpu_var(gtp_hwb_sync_count_local) != 
gtp_hwb_sync_count) {
++                      unsigned long   addr;
++
++                      gtp_get_debugreg(addr, i);
++                      if (addr != gtp_hwb[i].addr)
++                              continue;
++              }
++              preempt_disable();
++              {
++                      struct gtp_trace_s      gts;
++
++                      memset(&gts, 0, sizeof(struct gtp_trace_s));
++                      gts.tpe = gtp_hwb[i].watch;
++                      gts.regs = args->regs;
++                      gts.hwb = &gtp_hwb[i];
++                      gtp_handler(&gts);
++              }
++              preempt_enable_no_resched();
++      }
++
++      /* If the HWB need update in this CPU, just update it.  */
++      if (__get_cpu_var(gtp_hwb_sync_count_local) != gtp_hwb_sync_count) {
++              gtp_set_debugreg(gtp_hwb_drx[0], 0);
++              gtp_set_debugreg(gtp_hwb_drx[1], 1);
++              gtp_set_debugreg(gtp_hwb_drx[2], 2);
++              gtp_set_debugreg(gtp_hwb_drx[3], 3);
++              __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
++      }
++
++      gtp_set_debugreg(gtp_hwb_dr7, 7);
++      read_unlock(&gtp_hwb_lock);
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++out:
++#endif
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
++      gtp_set_debugreg(dr6, 6);
++#endif
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      /* If have some other traps, let other handler handle it.  */
++      if (((*dr6_p) & GTP_HWB_DR6_MASK) == 0)
++              ret = NOTIFY_STOP;
++      current->thread.debugreg6 = *dr6_p;
++#else
++      if ((dr6 & GTP_HWB_DR6_MASK) == 0)
++              ret = NOTIFY_STOP;
++      current->thread.debugreg6 = dr6;
++#endif
++
++      local_irq_restore(flags);
++      return ret;
++}
++
++static struct notifier_block gtp_notifier = {
++      .notifier_call = gtp_notifier_call,
++      .priority = 0x7ffffffe /* we need to be notified after kprobe.  */
++};
++#endif
 +
 +#ifdef CONFIG_X86
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0))
@@ -9283,102 +9669,8 @@
 +      gtp_hw_breakpoint_handler(breakinfo[3].num, regs);
 +}
 +#endif
-+#else
-+static int
-+gtp_notifier_call(struct notifier_block *self, unsigned long cmd,
-+                 void *ptr)
-+{
-+      int             ret = NOTIFY_DONE;
-+      unsigned long   flags;
-+      struct die_args *args;
-+      int             i;
-+      unsigned long   dr6;
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      unsigned long   *dr6_p;
 +#endif
 +
-+      if (cmd != DIE_DEBUG)
-+              return ret;
-+
-+      local_irq_save(flags);
-+      args = ptr;
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      /* Get from X86 hw_breakpoint_handler.  */
-+      dr6_p = (unsigned long *)ERR_PTR(args->err);
-+      dr6 = *dr6_p;
-+#else
-+      dr6 = args->err;
-+#endif
-+      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)
-+                      continue;
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+              /* Because KGTP handle all the hw-breakpoints.
-+                 So Just clear it.  */
-+              (*dr6_p) &= ~(0x1 << i);
-+#endif
-+              if (gtp_hwb[i].watch == NULL)
-+                      continue;
-+              /* Check if gtp_hwb is updated in other CPU.  */
-+              if (__get_cpu_var(gtp_hwb_sync_count_local) != 
gtp_hwb_sync_count) {
-+                      unsigned long   addr;
-+
-+                      gtp_get_debugreg(addr, i);
-+                      if (addr != gtp_hwb[i].addr)
-+                              continue;
-+              }
-+              preempt_disable();
-+              {
-+                      struct gtp_trace_s      gts;
-+
-+                      memset(&gts, 0, sizeof(struct gtp_trace_s));
-+                      gts.tpe = gtp_hwb[i].watch;
-+                      gts.regs = args->regs;
-+                      gts.hwb = &gtp_hwb[i];
-+                      gtp_handler(&gts);
-+              }
-+              preempt_enable_no_resched();
-+      }
-+
-+      /* If the HWB need update in this CPU, just update it.  */
-+      if (__get_cpu_var(gtp_hwb_sync_count_local) != gtp_hwb_sync_count) {
-+              set_debugreg(gtp_hwb_drx[0], 0);
-+              set_debugreg(gtp_hwb_drx[1], 1);
-+              set_debugreg(gtp_hwb_drx[2], 2);
-+              set_debugreg(gtp_hwb_drx[3], 3);
-+              __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      }
-+
-+      set_debugreg(gtp_hwb_dr7, 7);
-+      read_unlock(&gtp_hwb_lock);
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      /* If have some other traps, let other handler handle it.  */
-+      if ((dr6 & (~0xf)) == 0)
-+              ret = NOTIFY_STOP;
-+#else
-+      set_debugreg(0UL, 6);
-+      ret = NOTIFY_STOP;
-+#endif
-+
-+out:
-+      local_irq_restore(flags);
-+      return ret;
-+}
-+
-+static struct notifier_block gtp_notifier = {
-+      .notifier_call = gtp_notifier_call,
-+      .priority = 0x7fffffff /* we need to be notified first */
-+};
-+#endif
-+
 +static unsigned int
 +gtp_hwb_size_to_arch(int size)
 +{
@@ -9457,7 +9749,7 @@
 +
 +              /* Set gtp_hwb_dr7 and gtp_hwb_drx[num] to hwb.  */
 +              gtp_set_debugreg(gtp_hwb_drx[num], num);
-+              set_debugreg(gtp_hwb_dr7, 7);
++              gtp_set_debugreg(gtp_hwb_dr7, 7);
 +
 +              gtp_hwb_sync_count++;
 +              hwb->count = gtp_hwb_sync_count;
@@ -9514,7 +9806,7 @@
 +                      gtp_hwb_sync_count++;
 +
 +                      /* Sync gtp_hwb_dr7 update to hwb.  */
-+                      set_debugreg(gtp_hwb_dr7, 7);
++                      gtp_set_debugreg(gtp_hwb_dr7, 7);
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
 +                      /* Send ipi to let other cpu update.  */
@@ -9577,54 +9869,74 @@
 +              tasklet_kill(&tpe->disable_tasklet);
 +              tasklet_kill(&tpe->enable_tasklet);
 +#endif
++      }
++
++#ifdef CONFIG_X86
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      if (gtp_have_step || gtp_have_watch_tracepoint)
++#else
++      if (gtp_have_step)
++#endif
++              unregister_die_notifier(&gtp_notifier);
++
++      {
++              /* Init data of while-stepping.  */
++              int     cpu;
++              for_each_online_cpu(cpu) {
++                      struct gtp_step_s       *step = &per_cpu(gtp_step, cpu);
++
++                      spin_lock(&step->lock);
++                      step->step = 0;
++                      step->tpe = NULL;
++                      spin_unlock(&step->lock);
++              }
 +      }
++#endif
 +
 +#ifdef CONFIG_X86
 +      /* Stop hwb.  */
++      if (gtp_have_watch_tracepoint) {
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0))
-+      {
-+              int     i;
++              {
++                      int     i;
 +
-+              /* Register hw breakpoints.  */
-+              for (i = 0; i < HWB_NUM; i++) {
-+                      unregister_wide_hw_breakpoint(breakinfo[i].pev);
-+                      breakinfo[i].pev = NULL;
++                      /* Register hw breakpoints.  */
++                      for (i = 0; i < HWB_NUM; i++) {
++                              unregister_wide_hw_breakpoint(breakinfo[i].pev);
++                              breakinfo[i].pev = NULL;
++                      }
 +              }
-+      }
 +#endif
 +
-+      gtp_hwb_stop(NULL);
++              gtp_hwb_stop(NULL);
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
-+      smp_call_function(gtp_hwb_stop, NULL, 1);
++              smp_call_function(gtp_hwb_stop, NULL, 1);
 +#else
-+      smp_call_function(gtp_hwb_stop, NULL, 0, 1);
++              smp_call_function(gtp_hwb_stop, NULL, 0, 1);
 +#endif
 +
-+      for (tpe = gtp_list; tpe; tpe = tpe->next) {
-+              if (tpe->type == gtp_entry_kprobe
-+                  || (tpe->flags & GTP_ENTRY_FLAGS_REG) == 0
-+                  || tpe->disable)
-+                      continue;
++              for (tpe = gtp_list; tpe; tpe = tpe->next) {
++                      if (tpe->type == gtp_entry_kprobe
++                          || (tpe->flags & GTP_ENTRY_FLAGS_REG) == 0
++                          || tpe->disable)
++                              continue;
 +
-+              if (tpe->type == gtp_entry_watch_static)
-+                      gtp_unregister_hwb(tpe->addr, 0);
++                      if (tpe->type == gtp_entry_watch_static)
++                              gtp_unregister_hwb(tpe->addr, 0);
 +
-+              tpe->flags &= ~GTP_ENTRY_FLAGS_REG;
++                      tpe->flags &= ~GTP_ENTRY_FLAGS_REG;
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
-+              tasklet_kill(&tpe->disable_tasklet);
-+              tasklet_kill(&tpe->enable_tasklet);
++                      tasklet_kill(&tpe->disable_tasklet);
++                      tasklet_kill(&tpe->enable_tasklet);
 +#endif
-+      }
++              }
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
-+      unregister_kprobe(&gtp_ipi_kp);
++              unregister_kprobe(&gtp_ipi_kp);
 +#endif
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
-+      unregister_die_notifier(&gtp_notifier);
++      }
 +#endif
-+#endif
 +
 +#ifdef GTP_PERF_EVENTS
 +      list_for_each(cur, &gtp_var_list) {
@@ -9696,6 +10008,10 @@
 +              gtp_frame_reset();
 +
 +      gtpro_list_clear();
++#ifdef CONFIG_X86
++      gtp_have_watch_tracepoint = 0;
++      gtp_have_step = 0;
++#endif
 +
 +      gtp_var_release(0);
 +
@@ -9810,12 +10126,13 @@
 +}
 +
 +static int
-+gtp_add_backtrace_actions(struct gtp_entry *tpe)
++gtp_add_backtrace_actions(struct gtp_entry *tpe, int step)
 +{
 +      struct action   *ae, *new_ae;
 +      int             got_r = 0, got_m = 0;
 +
-+      for (ae = tpe->action_list; ae; ae = ae->next) {
++      for (ae = step ? tpe->step_action_list : tpe->action_list;
++           ae; ae = ae->next) {
 +              if (ae->type == 'R')
 +                      got_r = 1;
 +              else if (ae->type == 'M' && ae->u.m.regnum == GTP_SP_NUM
@@ -9823,7 +10140,9 @@
 +                      got_m = 1;
 +
 +              if (got_r && got_m)
-+                      break;
++                      return 1;
++
++              /* Let ae point to the last entry of action_list.  */
 +              if (!ae->next)
 +                      break;
 +      }
@@ -9834,8 +10153,14 @@
 +                      return -ENOMEM;
 +              if (ae)
 +                      ae->next = new_ae;
-+              else
-+                      tpe->action_list = ae;
++              else {
++                      if (step)
++                              tpe->step_action_list = ae;
++                      else
++                              tpe->action_list = ae;
++              }
++
++              /* Because new_ae is the new tail.  So set it to ae. */
 +              ae = new_ae;
 +      }
 +
@@ -9847,15 +10172,19 @@
 +              new_ae->u.m.size = gtp_bt_size;
 +              if (ae)
 +                      ae->next = new_ae;
-+              else
-+                      tpe->action_list = ae;
++              else {
++                      if (step)
++                              tpe->step_action_list = ae;
++                      else
++                              tpe->action_list = ae;
++              }
 +      }
 +
 +      return 1;
 +}
 +
 +static int
-+gtp_check_getv(struct gtp_entry *tpe, struct action *ae,
++gtp_check_getv(struct gtp_entry *tpe, struct action *ae, int step,
 +             uint8_t *ebuf, unsigned int pc,
 +             struct gtp_x_var **list)
 +{
@@ -9877,12 +10206,12 @@
 +
 +      switch (var->type) {
 +      case gtp_var_special:
-+              if (arg == GTP_VAR_NO_SELF_TRACE_ID) {
-+                      tpe->flags |= GTP_ENTRY_FLAGS_NO_SELF_TRACE;
++              if (arg == GTP_VAR_SELF_TRACE_ID) {
++                      tpe->flags |= GTP_ENTRY_FLAGS_SELF_TRACE;
 +                      ret = 1;
 +                      goto out;
 +              } else if (arg == GTP_VAR_BT_ID) {
-+                      ret = gtp_add_backtrace_actions (tpe);
++                      ret = gtp_add_backtrace_actions (tpe, step);
 +                      goto out;
 +              } else if (arg == GTP_VAR_CURRENT_ID) {
 +                      tpe->flags |= GTP_ENTRY_FLAGS_CURRENT_TASK;
@@ -9951,7 +10280,7 @@
 +}
 +
 +static int
-+gtp_check_setv(struct gtp_entry *tpe, struct action *ae,
++gtp_check_setv(struct gtp_entry *tpe, struct action *ae, int step,
 +             uint8_t *ebuf, unsigned int pc,
 +             struct gtp_x_var **list, int loop,
 +             ULONGEST *stack, ULONGEST top)
@@ -9975,8 +10304,8 @@
 +      switch (var->type) {
 +      case gtp_var_special:
 +              switch (arg) {
-+              case GTP_VAR_NO_SELF_TRACE_ID:
-+                      tpe->flags |= GTP_ENTRY_FLAGS_NO_SELF_TRACE;
++              case GTP_VAR_SELF_TRACE_ID:
++                      tpe->flags |= GTP_ENTRY_FLAGS_SELF_TRACE;
 +                      ret = 1;
 +                      goto out;
 +                      break;
@@ -9987,7 +10316,7 @@
 +                      goto out;
 +                      break;
 +              case GTP_VAR_BT_ID:
-+                      ret = gtp_add_backtrace_actions (tpe);
++                      ret = gtp_add_backtrace_actions (tpe, step);
 +                      goto out;
 +                      break;
 +              case GTP_VAR_CURRENT_ID:
@@ -9996,11 +10325,10 @@
 +                      goto out;
 +                      break;
 +              case GTP_VAR_PRINTK_LEVEL_ID:
-+                      if (loop) {
***The diff for this file has been truncated for email.***
=======================================
--- /trunk/gtp_3.0_to_3.6.patch Sun Feb 17 20:54:51 2013
+++ /trunk/gtp_3.0_to_3.6.patch Mon May  6 19:06:35 2013
@@ -3734,7 +3734,7 @@

 --- /dev/null
 +++ b/lib/gtp.c
-@@ -0,0 +1,12093 @@
+@@ -0,0 +1,12887 @@
 +/*
 + * Kernel GDB tracepoint module.
 + *
@@ -3752,12 +3752,12 @@
 + * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 + *
-+ * Copyright(C) KGTP team (https://code.google.com/p/kgtp/), 2010, 2011, 2012, 2013
++ * Copyright(C) KGTP team (https://code.google.com/p/kgtp/), 2010-2013
 + *
 + */
 +
 +/* If "* 10" means that this is not a release version.  */
-+#define GTP_VERSION                   (20130218)
++#define GTP_VERSION                   (20130218 * 10)
 +
 +#include <linux/version.h>
 +#ifndef RHEL_RELEASE_VERSION
@@ -3836,6 +3836,9 @@
 +#include <linux/slab.h>
 +#include <linux/ctype.h>
 +#include <asm/atomic.h>
++#ifdef CONFIG_X86
++#include <asm/debugreg.h>
++#endif
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
 +#include <linux/kdebug.h>
 +#else
@@ -3946,7 +3949,9 @@
 +                               + sizeof(struct gtp_frame_var))
 +#endif
 +#ifdef GTP_RB
-+#define GTP_FRAME_HEAD_SIZE   (FID_SIZE + sizeof(u64) + sizeof(ULONGEST))
++/* The frame head size: FID_HEAD + count id + frame number + pointer to prev frem */ ++#define GTP_FRAME_HEAD_SIZE (FID_SIZE + sizeof(u64) + sizeof(ULONGEST) + sizeof(void *))
++/* The frame head size: FID_PAGE_BEGIN + count id */
 +#define GTP_FRAME_PAGE_BEGIN_SIZE     (FID_SIZE + sizeof(u64))
 +#endif
 +#ifdef GTP_FTRACE_RING_BUFFER
@@ -4029,7 +4034,7 @@
 +/* This gtp entry is registered inside the system.  */
 +#define GTP_ENTRY_FLAGS_REG           2
 +/* See $no_self_trace.  */
-+#define GTP_ENTRY_FLAGS_NO_SELF_TRACE 4
++#define GTP_ENTRY_FLAGS_SELF_TRACE    4
 +/* This gtp entry has passcount.  */
 +#define GTP_ENTRY_FLAGS_HAVE_PASS     8
 +/* See $printk_level.  */
@@ -4200,14 +4205,32 @@
 +
 +static pid_t                  gtp_current_pid;
 +
++#ifdef CONFIG_X86
++/* Following part is for while-stepping.  */
++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);
++#endif
++
 +#ifdef CONFIG_X86
++static int    gtp_have_watch_tracepoint;
++static int    gtp_have_step;
++#endif
++
++#ifdef CONFIG_X86
++/* Following part is for watch tracepoint.  */
 +/* This part is X86 special.  */
 +#define HWB_NUM                       4
 +
 +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 {
@@ -4285,16 +4308,16 @@
 +{
 +      switch(reg) {
 +      case 0:
-+              set_debugreg(val, 0);
++              gtp_set_debugreg(val, 0);
 +              break;
 +      case 1:
-+              set_debugreg(val, 1);
++              gtp_set_debugreg(val, 1);
 +              break;
 +      case 2:
-+              set_debugreg(val, 2);
++              gtp_set_debugreg(val, 2);
 +              break;
 +      case 3:
-+              set_debugreg(val, 3);
++              gtp_set_debugreg(val, 3);
 +              break;
 +      }
 +}
@@ -4305,11 +4328,11 @@
 +{
 +      read_lock(&gtp_hwb_lock);
 +      __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      set_debugreg(0UL, 0);
-+      set_debugreg(0UL, 1);
-+      set_debugreg(0UL, 2);
-+      set_debugreg(0UL, 3);
-+      set_debugreg(GTP_HWB_DR7_DEF, 7);
++      gtp_set_debugreg(0UL, 0);
++      gtp_set_debugreg(0UL, 1);
++      gtp_set_debugreg(0UL, 2);
++      gtp_set_debugreg(0UL, 3);
++      gtp_set_debugreg(GTP_HWB_DR7_DEF, 7);
 +      read_unlock(&gtp_hwb_lock);
 +}
 +
@@ -4317,11 +4340,11 @@
 +gtp_hwb_sync_local(void)
 +{
 +      __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      set_debugreg(gtp_hwb_drx[0], 0);
-+      set_debugreg(gtp_hwb_drx[1], 1);
-+      set_debugreg(gtp_hwb_drx[2], 2);
-+      set_debugreg(gtp_hwb_drx[3], 3);
-+      set_debugreg(gtp_hwb_dr7, 7);
++      gtp_set_debugreg(gtp_hwb_drx[0], 0);
++      gtp_set_debugreg(gtp_hwb_drx[1], 1);
++      gtp_set_debugreg(gtp_hwb_drx[2], 2);
++      gtp_set_debugreg(gtp_hwb_drx[3], 3);
++      gtp_set_debugreg(gtp_hwb_dr7, 7);
 +}
 +
 +static void
@@ -4476,7 +4499,7 @@
 +      GTP_VAR_PRINTK_LEVEL_ID                 = 11,
 +      GTP_VAR_PRINTK_FORMAT_ID                = 12,
 +      GTP_VAR_DUMP_STACK_ID                   = 13,
-+      GTP_VAR_NO_SELF_TRACE_ID                = 14,
++      GTP_VAR_SELF_TRACE_ID                   = 14,
 +      GTP_VAR_CPU_NUMBER_ID                   = 15,
 +      GTP_VAR_PC_PE_EN_ID                     = 16,
 +      GTP_VAR_KRET_ID                         = 17,
@@ -4509,8 +4532,11 @@
 +      GTP_WATCH_VAL_ID                        = 42,
 +      GTP_WATCH_COUNT_ID                      = 43,
 +
++      GTP_STEP_COUNT_ID                       = 44,
++      GTP_STEP_ID_ID                          = 45,
++
 +      GTP_VAR_SPECIAL_MIN                     = GTP_VAR_VERSION_ID,
-+      GTP_VAR_SPECIAL_MAX                     = GTP_WATCH_COUNT_ID,
++      GTP_VAR_SPECIAL_MAX                     = GTP_STEP_ID_ID,
 +};
 +
 +enum pe_tv_id {
@@ -5519,6 +5545,44 @@
 +};
 +#endif
 +
++#ifdef GTP_RB
++static int
++gtp_step_count_hooks_get_val(struct gtp_trace_s *gts, struct gtp_var *gtv,
++                           int64_t *val)
++{
++      if (gts->step)
++              *val = gts->tpe->step - gts->step + 1;
++      else
++              *val = 0;
++
++      return 0;
++}
++
++static struct gtp_var_hooks   gtp_step_count_hooks = {
++      .agent_get_val = gtp_step_count_hooks_get_val,
++};
++
++static DEFINE_PER_CPU(int64_t, gtp_step_id);
++
++static int
++gtp_step_id_hooks_get_val(struct gtp_trace_s *gts, struct gtp_var *gtv,
++                        int64_t *val)
++{
++      if (!gts->step) {
++              if (++ __get_cpu_var(gtp_step_id) == 0)
++                      __get_cpu_var(gtp_step_id) = 1;
++      }
++
++      *val = __get_cpu_var(gtp_step_id);
++
++      return 0;
++}
++
++static struct gtp_var_hooks   gtp_step_id_hooks = {
++      .agent_get_val = gtp_step_id_hooks_get_val,
++};
++#endif
++
 +static int
 +gtp_var_special_add_all(void)
 +{
@@ -5611,8 +5675,8 @@
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +
-+      var = gtp_var_special_add(GTP_VAR_NO_SELF_TRACE_ID, 0, 0,
-+                                "no_self_trace", NULL);
++      var = gtp_var_special_add(GTP_VAR_SELF_TRACE_ID, 0, 0,
++                                "self_trace", NULL);
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +
@@ -5738,6 +5802,16 @@
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +#endif
++      var = gtp_var_special_add(GTP_STEP_COUNT_ID, 0, 0,
++                                "step_count", &gtp_step_count_hooks);
++      if (IS_ERR(var))
++              return PTR_ERR(var);
++#ifdef GTP_RB
++      var = gtp_var_special_add(GTP_STEP_ID_ID, 0, 0,
++                                "step_id", &gtp_step_id_hooks);
++      if (IS_ERR(var))
++              return PTR_ERR(var);
++#endif
 +
 +      return 0;
 +}
@@ -7310,6 +7384,11 @@
 +      } while (0)
 +#endif
 +
++static int    gtp_collect_var(struct gtp_trace_s *gts, int num);
++#ifdef GTP_RB
++static int    gtp_var_array_step_id_id = 0;
++#endif
++
 +static int
 +gtp_action_head(struct gtp_trace_s *gts)
 +{
@@ -7358,6 +7437,13 @@
 +
 +      trace_nump = (ULONGEST *)tmp;
 +      *trace_nump = gts->tpe->num;
++      tmp += sizeof(ULONGEST);
++
++#ifdef GTP_RB
++      *(void **)tmp = gtp_rb_prev_frame_get(gts->next);
++      gtp_rb_prev_frame_set(gts->next, (void *)(tmp + sizeof(void *)
++                                                - GTP_FRAME_HEAD_SIZE));
++#endif
 +
 +#ifdef GTP_FTRACE_RING_BUFFER
 +      ring_buffer_unlock_commit(gtp_frame, rbe);
@@ -7366,6 +7452,14 @@
 +
 +      atomic_inc(&gtp_frame_create);
 +
++#ifdef GTP_RB
++      /* Auto collect $step_id.  */
++      if (gts->tpe->step) {
++              if (gtp_collect_var(gts, gtp_var_array_step_id_id))
++                      return -1;
++      }
++#endif
++
 +      return 0;
 +}
 +
@@ -7808,6 +7902,8 @@
 +
 +      return ret;
 +}
++
++/* The number is not the ID of tvar, it is the ID of gtp_var_array. */
 +
 +static int
 +gtp_collect_var(struct gtp_trace_s *gts, int num)
@@ -8463,6 +8559,30 @@
 +}
 +#endif
 +
++#ifdef CONFIG_X86
++/* while-stepping stop.  */
++
++static void
++gtp_step_stop(struct pt_regs *regs)
++{
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24))
++      regs->flags &= ~(X86_EFLAGS_TF);
++#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;
++}
++#endif
++
 +static void
 +gtp_handler(struct gtp_trace_s *gts)
 +{
@@ -8472,6 +8592,10 @@
 +      printk(GTP_DEBUG_V "gtp_handler: tracepoint %d %p\n",
 +             (int)gts->tpe->num, (void *)(CORE_ADDR)gts->tpe->addr);
 +#endif
++#ifdef CONFIG_X86
++      if (gts->step == 0 && __get_cpu_var(gtp_step).step)
++              gtp_step_stop(gts->regs);
++#endif
 +
 +      gts->read_memory = (void *)probe_kernel_read;
 +      if (gts->tpe->flags & GTP_ENTRY_FLAGS_CURRENT_TASK) {
@@ -8488,7 +8612,7 @@
 +              return;
 +#endif
 +
-+      if ((gts->tpe->flags & GTP_ENTRY_FLAGS_NO_SELF_TRACE)
++      if ((gts->tpe->flags & GTP_ENTRY_FLAGS_SELF_TRACE) == 0
 +          && (get_current()->pid == gtp_gtp_pid
 +              || get_current()->pid == gtp_gtpframe_pid)) {
 +                      return;
@@ -8513,7 +8637,7 @@
 +      gts->run = NULL;
 +
 +      /* Pass.  */
-+      if (gts->tpe->flags & GTP_ENTRY_FLAGS_HAVE_PASS) {
++      if (gts->step == 0 && gts->tpe->flags & GTP_ENTRY_FLAGS_HAVE_PASS) {
 +              if (atomic_dec_return(&gts->tpe->current_pass) < 0)
 +                      goto tpe_stop;
 +      }
@@ -8673,18 +8797,47 @@
 +      struct kretprobe        *kpret;
 +      struct gtp_kp           *gkp;
 +      union gtp_entry_u       *u;
++      struct gtp_entry                *tpe;
 +      struct gtp_trace_s      gts;
 +
-+      memset(&gts, 0, sizeof(struct gtp_trace_s));
-+
 +      kpret = container_of(p, struct kretprobe, kp);
 +      gkp = container_of(kpret, struct gtp_kp, kpret);
 +      u = container_of(gkp, union gtp_entry_u, kp);
-+      gts.tpe = container_of(u, struct gtp_entry, u);
-+      gts.regs = regs;
-+      gts.step = 1;
++      tpe = container_of(u, struct gtp_entry, u);
++
++      if (tpe->step == 1) {
++              memset(&gts, 0, sizeof(struct gtp_trace_s));
++
++              gts.tpe = tpe;
++              gts.regs = regs;
++              gts.step = tpe->step;
++
++              gtp_handler(&gts);
++      }
 +
-+      gtp_handler(&gts);
++#ifdef CONFIG_X86
++      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. */
++              __get_cpu_var(gtp_step).step = tpe->step;
++              __get_cpu_var(gtp_step).tpe = tpe;
++              #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24))
++              if (regs->flags & X86_EFLAGS_IF)
++              #else
++              if (regs->eflags & X86_EFLAGS_IF)
++              #endif
++                      __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
 +}
 +
 +static inline void
@@ -8965,6 +9118,7 @@
 +              gtp_list = gtp_list->next;
 +              gtp_action_release(tpe->cond);
 +              gtp_action_release(tpe->action_list);
++              gtp_action_release(tpe->step_action_list);
 +              gtp_src_release(tpe->src);
 +              gtp_src_release(tpe->action_cmd);
 +              gtp_src_release(tpe->printk_str);
@@ -9205,6 +9359,238 @@
 +
 +      return 0;
 +}
++
++#ifdef CONFIG_X86
++#define ADDR_PREFIX_OPCODE 0x67
++#define DATA_PREFIX_OPCODE 0x66
++#define LOCK_PREFIX_OPCODE 0xf0
++#define CS_PREFIX_OPCODE 0x2e
++#define DS_PREFIX_OPCODE 0x3e
++#define ES_PREFIX_OPCODE 0x26
++#define FS_PREFIX_OPCODE 0x64
++#define GS_PREFIX_OPCODE 0x65
++#define SS_PREFIX_OPCODE 0x36
++#define REPNE_PREFIX_OPCODE 0xf2
++#define REPE_PREFIX_OPCODE  0xf3
++
++static int
++gtp_step_check_insn(struct pt_regs *regs)
++{
++      uint32_t        opcode;
++      uint8_t         opcode8;
++      unsigned long   pc = GTP_REGS_PC(regs);
++
++      /* prefixes */
++      while (1) {
++              if (probe_kernel_read(&opcode8, (void *)pc, 1))
++                      return -1;
++              pc++;
++              switch (opcode8) {
++              case REPE_PREFIX_OPCODE:
++              case REPNE_PREFIX_OPCODE:
++              case LOCK_PREFIX_OPCODE:
++              case CS_PREFIX_OPCODE:
++              case SS_PREFIX_OPCODE:
++              case DS_PREFIX_OPCODE:
++              case ES_PREFIX_OPCODE:
++              case FS_PREFIX_OPCODE:
++              case GS_PREFIX_OPCODE:
++              case DATA_PREFIX_OPCODE:
++              case ADDR_PREFIX_OPCODE:
++#ifndef CONFIG_X86_32
++              case 0x40 ... 0x4f:
++#endif
++                      break;
++              default:
++                      goto out_prefixes;
++              }
++      }
++out_prefixes:
++
++      opcode = (uint32_t)opcode8;
++reswitch:
++      switch (opcode) {
++      case 0x0f:
++              if (probe_kernel_read(&opcode8, (void *)pc, 1))
++                      return -1;
++              opcode = (uint32_t) opcode8 | 0x0f00;
++              goto reswitch;
++              break;
++      case 0xfb:
++              /* sti */
++              __get_cpu_var(gtp_step).irq_need_open = 1;
++              GTP_REGS_PC(regs) = pc;
++              break;
++      case 0xfa:
++              /* cli */
++              __get_cpu_var(gtp_step).irq_need_open = 0;
++              GTP_REGS_PC(regs) = pc;
++              break;
++      case 0x0f07:
++              /* sysret */
++              return 1;
++              break;
++      };
++
++      return 0;
++}
++
++static int
++gtp_notifier_call(struct notifier_block *self, unsigned long cmd,
++                 void *ptr)
++{
++      int             ret = NOTIFY_DONE;
++      unsigned long   flags;
++      struct die_args *args;
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      int             i;
++#endif
++      unsigned long   dr6;
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      unsigned long   *dr6_p;
++#endif
++
++      if (cmd != DIE_DEBUG)
++              return ret;
++
++      local_irq_save(flags);
++      args = ptr;
++
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      /* Get from X86 hw_breakpoint_handler.  */
++      dr6_p = (unsigned long *)ERR_PTR(args->err);
++      dr6 = *dr6_p;
++#else
++      dr6 = args->err;
++#endif
++      gtp_set_debugreg(GTP_HWB_DR7_DEF, 7);
++
++      /* Handle while-stepping.  */
++      spin_lock(&__get_cpu_var(gtp_step).lock);
++      if ((dr6 & 0x4000) != 0) {
++              /* Clear the bit that handle by KGTP.  */
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++              (*dr6_p) &= ~(0x4000);
++#else
++              dr6 &= ~(0x4000);
++#endif
++              if (!__get_cpu_var(gtp_step).tpe || user_mode(args->regs))
++                      gtp_step_stop(args->regs);
++              else {
++                      int need_stop = gtp_step_check_insn(args->regs);
++                      if (need_stop < 0)
++                              printk(KERN_WARNING "KGTP: check insn in %p got 
error.",
++                                     (void *)GTP_REGS_PC(args->regs));
++
++                      preempt_disable();
++                      {
++                              struct gtp_trace_s      gts;
++
++                              memset(&gts, 0, sizeof(struct gtp_trace_s));
++                              gts.tpe = __get_cpu_var(gtp_step).tpe;
++                              gts.regs = args->regs;
++                              gts.step = __get_cpu_var(gtp_step).step;
++                              gtp_handler(&gts);
++                      }
++                      preempt_enable_no_resched();
++
++                      if (__get_cpu_var(gtp_step).step > 1 && !need_stop) {
++                              /* 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.  */
++                              gtp_step_stop(args->regs);
++                      }
++              }
++      }
++      spin_unlock(&__get_cpu_var(gtp_step).lock);
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      /* Handle watch traceppoint.  */
++      if ((dr6 & 0xf) == 0)
++              goto out;
++      read_lock(&gtp_hwb_lock);
++
++      for (i = 0; i < HWB_NUM; i++) {
++              if ((dr6 & (0x1 << i)) == 0)
++                      continue;
++              /* Clear the bit that handle by KGTP.  */
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++              (*dr6_p) &= ~(0x1 << i);
++#else
++              dr6 &= ~(0x1 << i);
++#endif
++              if (gtp_hwb[i].watch == NULL)
++                      continue;
++              /* Check if gtp_hwb is updated in other CPU.  */
++              if (__get_cpu_var(gtp_hwb_sync_count_local) != 
gtp_hwb_sync_count) {
++                      unsigned long   addr;
++
++                      gtp_get_debugreg(addr, i);
++                      if (addr != gtp_hwb[i].addr)
++                              continue;
++              }
++              preempt_disable();
++              {
++                      struct gtp_trace_s      gts;
++
++                      memset(&gts, 0, sizeof(struct gtp_trace_s));
++                      gts.tpe = gtp_hwb[i].watch;
++                      gts.regs = args->regs;
++                      gts.hwb = &gtp_hwb[i];
++                      gtp_handler(&gts);
++              }
++              preempt_enable_no_resched();
++      }
++
++      /* If the HWB need update in this CPU, just update it.  */
++      if (__get_cpu_var(gtp_hwb_sync_count_local) != gtp_hwb_sync_count) {
++              gtp_set_debugreg(gtp_hwb_drx[0], 0);
++              gtp_set_debugreg(gtp_hwb_drx[1], 1);
++              gtp_set_debugreg(gtp_hwb_drx[2], 2);
++              gtp_set_debugreg(gtp_hwb_drx[3], 3);
++              __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
++      }
++
++      gtp_set_debugreg(gtp_hwb_dr7, 7);
++      read_unlock(&gtp_hwb_lock);
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++out:
++#endif
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
++      gtp_set_debugreg(dr6, 6);
++#endif
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      /* If have some other traps, let other handler handle it.  */
++      if (((*dr6_p) & GTP_HWB_DR6_MASK) == 0)
++              ret = NOTIFY_STOP;
++      current->thread.debugreg6 = *dr6_p;
++#else
++      if ((dr6 & GTP_HWB_DR6_MASK) == 0)
++              ret = NOTIFY_STOP;
++      current->thread.debugreg6 = dr6;
++#endif
++
++      local_irq_restore(flags);
++      return ret;
++}
++
++static struct notifier_block gtp_notifier = {
++      .notifier_call = gtp_notifier_call,
++      .priority = 0x7ffffffe /* we need to be notified after kprobe.  */
++};
++#endif
 +
 +#ifdef CONFIG_X86
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0))
@@ -9301,102 +9687,8 @@
 +      gtp_hw_breakpoint_handler(breakinfo[3].num, regs);
 +}
 +#endif
-+#else
-+static int
-+gtp_notifier_call(struct notifier_block *self, unsigned long cmd,
-+                 void *ptr)
-+{
-+      int             ret = NOTIFY_DONE;
-+      unsigned long   flags;
-+      struct die_args *args;
-+      int             i;
-+      unsigned long   dr6;
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      unsigned long   *dr6_p;
 +#endif
 +
-+      if (cmd != DIE_DEBUG)
-+              return ret;
-+
-+      local_irq_save(flags);
-+      args = ptr;
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      /* Get from X86 hw_breakpoint_handler.  */
-+      dr6_p = (unsigned long *)ERR_PTR(args->err);
-+      dr6 = *dr6_p;
-+#else
-+      dr6 = args->err;
-+#endif
-+      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)
-+                      continue;
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+              /* Because KGTP handle all the hw-breakpoints.
-+                 So Just clear it.  */
-+              (*dr6_p) &= ~(0x1 << i);
-+#endif
-+              if (gtp_hwb[i].watch == NULL)
-+                      continue;
-+              /* Check if gtp_hwb is updated in other CPU.  */
-+              if (__get_cpu_var(gtp_hwb_sync_count_local) != 
gtp_hwb_sync_count) {
-+                      unsigned long   addr;
-+
-+                      gtp_get_debugreg(addr, i);
-+                      if (addr != gtp_hwb[i].addr)
-+                              continue;
-+              }
-+              preempt_disable();
-+              {
-+                      struct gtp_trace_s      gts;
-+
-+                      memset(&gts, 0, sizeof(struct gtp_trace_s));
-+                      gts.tpe = gtp_hwb[i].watch;
-+                      gts.regs = args->regs;
-+                      gts.hwb = &gtp_hwb[i];
-+                      gtp_handler(&gts);
-+              }
-+              preempt_enable_no_resched();
-+      }
-+
-+      /* If the HWB need update in this CPU, just update it.  */
-+      if (__get_cpu_var(gtp_hwb_sync_count_local) != gtp_hwb_sync_count) {
-+              set_debugreg(gtp_hwb_drx[0], 0);
-+              set_debugreg(gtp_hwb_drx[1], 1);
-+              set_debugreg(gtp_hwb_drx[2], 2);
-+              set_debugreg(gtp_hwb_drx[3], 3);
-+              __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      }
-+
-+      set_debugreg(gtp_hwb_dr7, 7);
-+      read_unlock(&gtp_hwb_lock);
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      /* If have some other traps, let other handler handle it.  */
-+      if ((dr6 & (~0xf)) == 0)
-+              ret = NOTIFY_STOP;
-+#else
-+      set_debugreg(0UL, 6);
-+      ret = NOTIFY_STOP;
-+#endif
-+
-+out:
-+      local_irq_restore(flags);
-+      return ret;
-+}
-+
-+static struct notifier_block gtp_notifier = {
-+      .notifier_call = gtp_notifier_call,
-+      .priority = 0x7fffffff /* we need to be notified first */
-+};
-+#endif
-+
 +static unsigned int
 +gtp_hwb_size_to_arch(int size)
 +{
@@ -9475,7 +9767,7 @@
 +
 +              /* Set gtp_hwb_dr7 and gtp_hwb_drx[num] to hwb.  */
 +              gtp_set_debugreg(gtp_hwb_drx[num], num);
-+              set_debugreg(gtp_hwb_dr7, 7);
++              gtp_set_debugreg(gtp_hwb_dr7, 7);
 +
 +              gtp_hwb_sync_count++;
 +              hwb->count = gtp_hwb_sync_count;
@@ -9532,7 +9824,7 @@
 +                      gtp_hwb_sync_count++;
 +
 +                      /* Sync gtp_hwb_dr7 update to hwb.  */
-+                      set_debugreg(gtp_hwb_dr7, 7);
++                      gtp_set_debugreg(gtp_hwb_dr7, 7);
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
 +                      /* Send ipi to let other cpu update.  */
@@ -9595,54 +9887,74 @@
 +              tasklet_kill(&tpe->disable_tasklet);
 +              tasklet_kill(&tpe->enable_tasklet);
 +#endif
++      }
++
++#ifdef CONFIG_X86
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      if (gtp_have_step || gtp_have_watch_tracepoint)
++#else
++      if (gtp_have_step)
++#endif
++              unregister_die_notifier(&gtp_notifier);
++
++      {
++              /* Init data of while-stepping.  */
++              int     cpu;
++              for_each_online_cpu(cpu) {
++                      struct gtp_step_s       *step = &per_cpu(gtp_step, cpu);
++
++                      spin_lock(&step->lock);
++                      step->step = 0;
++                      step->tpe = NULL;
++                      spin_unlock(&step->lock);
++              }
 +      }
++#endif
 +
 +#ifdef CONFIG_X86
 +      /* Stop hwb.  */
++      if (gtp_have_watch_tracepoint) {
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0))
-+      {
-+              int     i;
++              {
++                      int     i;
 +
-+              /* Register hw breakpoints.  */
-+              for (i = 0; i < HWB_NUM; i++) {
-+                      unregister_wide_hw_breakpoint(breakinfo[i].pev);
-+                      breakinfo[i].pev = NULL;
++                      /* Register hw breakpoints.  */
++                      for (i = 0; i < HWB_NUM; i++) {
++                              unregister_wide_hw_breakpoint(breakinfo[i].pev);
++                              breakinfo[i].pev = NULL;
++                      }
 +              }
-+      }
 +#endif
 +
-+      gtp_hwb_stop(NULL);
++              gtp_hwb_stop(NULL);
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
-+      smp_call_function(gtp_hwb_stop, NULL, 1);
++              smp_call_function(gtp_hwb_stop, NULL, 1);
 +#else
-+      smp_call_function(gtp_hwb_stop, NULL, 0, 1);
++              smp_call_function(gtp_hwb_stop, NULL, 0, 1);
 +#endif
 +
-+      for (tpe = gtp_list; tpe; tpe = tpe->next) {
-+              if (tpe->type == gtp_entry_kprobe
-+                  || (tpe->flags & GTP_ENTRY_FLAGS_REG) == 0
-+                  || tpe->disable)
-+                      continue;
++              for (tpe = gtp_list; tpe; tpe = tpe->next) {
++                      if (tpe->type == gtp_entry_kprobe
++                          || (tpe->flags & GTP_ENTRY_FLAGS_REG) == 0
++                          || tpe->disable)
++                              continue;
 +
-+              if (tpe->type == gtp_entry_watch_static)
-+                      gtp_unregister_hwb(tpe->addr, 0);
++                      if (tpe->type == gtp_entry_watch_static)
++                              gtp_unregister_hwb(tpe->addr, 0);
 +
-+              tpe->flags &= ~GTP_ENTRY_FLAGS_REG;
++                      tpe->flags &= ~GTP_ENTRY_FLAGS_REG;
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
-+              tasklet_kill(&tpe->disable_tasklet);
-+              tasklet_kill(&tpe->enable_tasklet);
++                      tasklet_kill(&tpe->disable_tasklet);
++                      tasklet_kill(&tpe->enable_tasklet);
 +#endif
-+      }
++              }
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
-+      unregister_kprobe(&gtp_ipi_kp);
++              unregister_kprobe(&gtp_ipi_kp);
 +#endif
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
-+      unregister_die_notifier(&gtp_notifier);
++      }
 +#endif
-+#endif
 +
 +#ifdef GTP_PERF_EVENTS
 +      list_for_each(cur, &gtp_var_list) {
@@ -9714,6 +10026,10 @@
 +              gtp_frame_reset();
 +
 +      gtpro_list_clear();
++#ifdef CONFIG_X86
++      gtp_have_watch_tracepoint = 0;
++      gtp_have_step = 0;
++#endif
 +
 +      gtp_var_release(0);
 +
@@ -9828,12 +10144,13 @@
 +}
 +
 +static int
-+gtp_add_backtrace_actions(struct gtp_entry *tpe)
++gtp_add_backtrace_actions(struct gtp_entry *tpe, int step)
 +{
 +      struct action   *ae, *new_ae;
 +      int             got_r = 0, got_m = 0;
 +
-+      for (ae = tpe->action_list; ae; ae = ae->next) {
++      for (ae = step ? tpe->step_action_list : tpe->action_list;
++           ae; ae = ae->next) {
 +              if (ae->type == 'R')
 +                      got_r = 1;
 +              else if (ae->type == 'M' && ae->u.m.regnum == GTP_SP_NUM
@@ -9841,7 +10158,9 @@
 +                      got_m = 1;
 +
 +              if (got_r && got_m)
-+                      break;
++                      return 1;
++
++              /* Let ae point to the last entry of action_list.  */
 +              if (!ae->next)
 +                      break;
 +      }
@@ -9852,8 +10171,14 @@
 +                      return -ENOMEM;
 +              if (ae)
 +                      ae->next = new_ae;
-+              else
-+                      tpe->action_list = ae;
++              else {
++                      if (step)
++                              tpe->step_action_list = ae;
++                      else
++                              tpe->action_list = ae;
++              }
++
++              /* Because new_ae is the new tail.  So set it to ae. */
 +              ae = new_ae;
 +      }
 +
@@ -9865,15 +10190,19 @@
 +              new_ae->u.m.size = gtp_bt_size;
 +              if (ae)
 +                      ae->next = new_ae;
-+              else
-+                      tpe->action_list = ae;
++              else {
++                      if (step)
++                              tpe->step_action_list = ae;
++                      else
++                              tpe->action_list = ae;
++              }
 +      }
 +
 +      return 1;
 +}
 +
 +static int
-+gtp_check_getv(struct gtp_entry *tpe, struct action *ae,
++gtp_check_getv(struct gtp_entry *tpe, struct action *ae, int step,
 +             uint8_t *ebuf, unsigned int pc,
 +             struct gtp_x_var **list)
 +{
@@ -9895,12 +10224,12 @@
 +
 +      switch (var->type) {
 +      case gtp_var_special:
-+              if (arg == GTP_VAR_NO_SELF_TRACE_ID) {
-+                      tpe->flags |= GTP_ENTRY_FLAGS_NO_SELF_TRACE;
++              if (arg == GTP_VAR_SELF_TRACE_ID) {
++                      tpe->flags |= GTP_ENTRY_FLAGS_SELF_TRACE;
 +                      ret = 1;
 +                      goto out;
 +              } else if (arg == GTP_VAR_BT_ID) {
-+                      ret = gtp_add_backtrace_actions (tpe);
++                      ret = gtp_add_backtrace_actions (tpe, step);
 +                      goto out;
 +              } else if (arg == GTP_VAR_CURRENT_ID) {
 +                      tpe->flags |= GTP_ENTRY_FLAGS_CURRENT_TASK;
@@ -9969,7 +10298,7 @@
 +}
 +
 +static int
-+gtp_check_setv(struct gtp_entry *tpe, struct action *ae,
++gtp_check_setv(struct gtp_entry *tpe, struct action *ae, int step,
 +             uint8_t *ebuf, unsigned int pc,
 +             struct gtp_x_var **list, int loop,
 +             ULONGEST *stack, ULONGEST top)
@@ -9993,8 +10322,8 @@
 +      switch (var->type) {
 +      case gtp_var_special:
 +              switch (arg) {
-+              case GTP_VAR_NO_SELF_TRACE_ID:
-+                      tpe->flags |= GTP_ENTRY_FLAGS_NO_SELF_TRACE;
++              case GTP_VAR_SELF_TRACE_ID:
++                      tpe->flags |= GTP_ENTRY_FLAGS_SELF_TRACE;
 +                      ret = 1;
 +                      goto out;
 +                      break;
@@ -10005,7 +10334,7 @@
 +                      goto out;
 +                      break;
 +              case GTP_VAR_BT_ID:
-+                      ret = gtp_add_backtrace_actions (tpe);
++                      ret = gtp_add_backtrace_actions (tpe, step);
 +                      goto out;
 +                      break;
 +              case GTP_VAR_CURRENT_ID:
@@ -10014,11 +10343,10 @@
 +                      goto out;
 +                      break;
 +              case GTP_VAR_PRINTK_LEVEL_ID:
-+                      if (loop) {
***The diff for this file has been truncated for email.***
=======================================
--- /trunk/gtp_3.7_to_upstream.patch    Sun Feb 17 20:54:51 2013
+++ /trunk/gtp_3.7_to_upstream.patch    Mon May  6 19:06:35 2013
@@ -3614,7 +3614,7 @@
 +Please go to HOWTO to get more message about howto use KGTP.
 --- a/arch/arm/mm/flush.c
 +++ b/arch/arm/mm/flush.c
-@@ -336,3 +336,5 @@ void __flush_anon_page(struct vm_area_st
+@@ -339,3 +339,5 @@ void __flush_anon_page(struct vm_area_st
         */
        __cpuc_flush_dcache_area(page_address(page), PAGE_SIZE);
  }
@@ -3622,7 +3622,7 @@
 +
 --- a/include/linux/perf_event.h
 +++ b/include/linux/perf_event.h
-@@ -829,4 +829,12 @@ _name##_show(struct device *dev,                          
        \
+@@ -847,4 +847,12 @@ _name##_show(struct device *dev,                          
        \
                                                                        \
  static struct device_attribute format_attr_##_name = __ATTR_RO(_name)

@@ -3637,7 +3637,7 @@
  #endif /* _LINUX_PERF_EVENT_H */
 --- a/kernel/events/core.c
 +++ b/kernel/events/core.c
-@@ -42,6 +42,12 @@
+@@ -44,6 +44,12 @@

  #include <asm/irq_regs.h>

@@ -3650,7 +3650,7 @@
  struct remote_function_call {
        struct task_struct      *p;
        int                     (*func)(void *info);
-@@ -1393,6 +1399,9 @@ static void perf_set_shadow_time(struct
+@@ -1434,6 +1440,9 @@ static void perf_set_shadow_time(struct
        else
                event->shadow_ctx_time = tstamp - ctx->timestamp;
  }
@@ -3660,7 +3660,7 @@

  #define MAX_INTERRUPTS (~0ULL)

-@@ -1890,6 +1899,9 @@ static void ctx_sched_out(struct perf_ev
+@@ -1931,6 +1940,9 @@ static void ctx_sched_out(struct perf_ev
        }
        perf_pmu_enable(ctx->pmu);
  }
@@ -3670,7 +3670,7 @@

  /*
   * Test whether two contexts are equivalent, i.e. whether they
-@@ -3175,6 +3187,14 @@ static void perf_event_reset(struct perf
+@@ -3226,6 +3238,14 @@ static void perf_event_reset(struct perf
        perf_event_update_userpage(event);
  }

@@ -3685,8 +3685,8 @@
  /*
   * Holding the top-level event's child_mutex means that any
   * descendant process that has inherited this event will block
-@@ -7521,3 +7541,15 @@ struct cgroup_subsys perf_subsys = {
-       .broken_hierarchy = true,
+@@ -7579,3 +7599,15 @@ struct cgroup_subsys perf_subsys = {
+       .attach         = perf_cgroup_attach,
  };
  #endif /* CONFIG_CGROUP_PERF */
 +
@@ -3703,7 +3703,7 @@
 +EXPORT_SYMBOL_GPL(local_perf_event_disable);
 --- a/lib/Kconfig.debug
 +++ b/lib/Kconfig.debug
-@@ -1453,6 +1453,16 @@ config ASYNC_RAID6_TEST
+@@ -1475,6 +1475,16 @@ config ASYNC_RAID6_TEST

          If unsure, say N.

@@ -3722,7 +3722,7 @@
  source "lib/Kconfig.kgdb"
 --- a/lib/Makefile
 +++ b/lib/Makefile
-@@ -148,6 +148,8 @@ interval_tree_test-objs := interval_tree
+@@ -151,6 +151,8 @@ interval_tree_test-objs := interval_tree

  obj-$(CONFIG_ASN1) += asn1_decoder.o

@@ -3733,7 +3733,7 @@

 --- /dev/null
 +++ b/lib/gtp.c
-@@ -0,0 +1,12093 @@
+@@ -0,0 +1,12887 @@
 +/*
 + * Kernel GDB tracepoint module.
 + *
@@ -3751,12 +3751,12 @@
 + * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 + *
-+ * Copyright(C) KGTP team (https://code.google.com/p/kgtp/), 2010, 2011, 2012, 2013
++ * Copyright(C) KGTP team (https://code.google.com/p/kgtp/), 2010-2013
 + *
 + */
 +
 +/* If "* 10" means that this is not a release version.  */
-+#define GTP_VERSION                   (20130218)
++#define GTP_VERSION                   (20130218 * 10)
 +
 +#include <linux/version.h>
 +#ifndef RHEL_RELEASE_VERSION
@@ -3835,6 +3835,9 @@
 +#include <linux/slab.h>
 +#include <linux/ctype.h>
 +#include <asm/atomic.h>
++#ifdef CONFIG_X86
++#include <asm/debugreg.h>
++#endif
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
 +#include <linux/kdebug.h>
 +#else
@@ -3945,7 +3948,9 @@
 +                               + sizeof(struct gtp_frame_var))
 +#endif
 +#ifdef GTP_RB
-+#define GTP_FRAME_HEAD_SIZE   (FID_SIZE + sizeof(u64) + sizeof(ULONGEST))
++/* The frame head size: FID_HEAD + count id + frame number + pointer to prev frem */ ++#define GTP_FRAME_HEAD_SIZE (FID_SIZE + sizeof(u64) + sizeof(ULONGEST) + sizeof(void *))
++/* The frame head size: FID_PAGE_BEGIN + count id */
 +#define GTP_FRAME_PAGE_BEGIN_SIZE     (FID_SIZE + sizeof(u64))
 +#endif
 +#ifdef GTP_FTRACE_RING_BUFFER
@@ -4028,7 +4033,7 @@
 +/* This gtp entry is registered inside the system.  */
 +#define GTP_ENTRY_FLAGS_REG           2
 +/* See $no_self_trace.  */
-+#define GTP_ENTRY_FLAGS_NO_SELF_TRACE 4
++#define GTP_ENTRY_FLAGS_SELF_TRACE    4
 +/* This gtp entry has passcount.  */
 +#define GTP_ENTRY_FLAGS_HAVE_PASS     8
 +/* See $printk_level.  */
@@ -4200,13 +4205,31 @@
 +static pid_t                  gtp_current_pid;
 +
 +#ifdef CONFIG_X86
++/* Following part is for while-stepping.  */
++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);
++#endif
++
++#ifdef CONFIG_X86
++static int    gtp_have_watch_tracepoint;
++static int    gtp_have_step;
++#endif
++
++#ifdef CONFIG_X86
++/* Following part is for watch tracepoint.  */
 +/* This part is X86 special.  */
 +#define HWB_NUM                       4
 +
 +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 {
@@ -4284,16 +4307,16 @@
 +{
 +      switch(reg) {
 +      case 0:
-+              set_debugreg(val, 0);
++              gtp_set_debugreg(val, 0);
 +              break;
 +      case 1:
-+              set_debugreg(val, 1);
++              gtp_set_debugreg(val, 1);
 +              break;
 +      case 2:
-+              set_debugreg(val, 2);
++              gtp_set_debugreg(val, 2);
 +              break;
 +      case 3:
-+              set_debugreg(val, 3);
++              gtp_set_debugreg(val, 3);
 +              break;
 +      }
 +}
@@ -4304,11 +4327,11 @@
 +{
 +      read_lock(&gtp_hwb_lock);
 +      __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      set_debugreg(0UL, 0);
-+      set_debugreg(0UL, 1);
-+      set_debugreg(0UL, 2);
-+      set_debugreg(0UL, 3);
-+      set_debugreg(GTP_HWB_DR7_DEF, 7);
++      gtp_set_debugreg(0UL, 0);
++      gtp_set_debugreg(0UL, 1);
++      gtp_set_debugreg(0UL, 2);
++      gtp_set_debugreg(0UL, 3);
++      gtp_set_debugreg(GTP_HWB_DR7_DEF, 7);
 +      read_unlock(&gtp_hwb_lock);
 +}
 +
@@ -4316,11 +4339,11 @@
 +gtp_hwb_sync_local(void)
 +{
 +      __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      set_debugreg(gtp_hwb_drx[0], 0);
-+      set_debugreg(gtp_hwb_drx[1], 1);
-+      set_debugreg(gtp_hwb_drx[2], 2);
-+      set_debugreg(gtp_hwb_drx[3], 3);
-+      set_debugreg(gtp_hwb_dr7, 7);
++      gtp_set_debugreg(gtp_hwb_drx[0], 0);
++      gtp_set_debugreg(gtp_hwb_drx[1], 1);
++      gtp_set_debugreg(gtp_hwb_drx[2], 2);
++      gtp_set_debugreg(gtp_hwb_drx[3], 3);
++      gtp_set_debugreg(gtp_hwb_dr7, 7);
 +}
 +
 +static void
@@ -4475,7 +4498,7 @@
 +      GTP_VAR_PRINTK_LEVEL_ID                 = 11,
 +      GTP_VAR_PRINTK_FORMAT_ID                = 12,
 +      GTP_VAR_DUMP_STACK_ID                   = 13,
-+      GTP_VAR_NO_SELF_TRACE_ID                = 14,
++      GTP_VAR_SELF_TRACE_ID                   = 14,
 +      GTP_VAR_CPU_NUMBER_ID                   = 15,
 +      GTP_VAR_PC_PE_EN_ID                     = 16,
 +      GTP_VAR_KRET_ID                         = 17,
@@ -4508,8 +4531,11 @@
 +      GTP_WATCH_VAL_ID                        = 42,
 +      GTP_WATCH_COUNT_ID                      = 43,
 +
++      GTP_STEP_COUNT_ID                       = 44,
++      GTP_STEP_ID_ID                          = 45,
++
 +      GTP_VAR_SPECIAL_MIN                     = GTP_VAR_VERSION_ID,
-+      GTP_VAR_SPECIAL_MAX                     = GTP_WATCH_COUNT_ID,
++      GTP_VAR_SPECIAL_MAX                     = GTP_STEP_ID_ID,
 +};
 +
 +enum pe_tv_id {
@@ -5518,6 +5544,44 @@
 +};
 +#endif
 +
++#ifdef GTP_RB
++static int
++gtp_step_count_hooks_get_val(struct gtp_trace_s *gts, struct gtp_var *gtv,
++                           int64_t *val)
++{
++      if (gts->step)
++              *val = gts->tpe->step - gts->step + 1;
++      else
++              *val = 0;
++
++      return 0;
++}
++
++static struct gtp_var_hooks   gtp_step_count_hooks = {
++      .agent_get_val = gtp_step_count_hooks_get_val,
++};
++
++static DEFINE_PER_CPU(int64_t, gtp_step_id);
++
++static int
++gtp_step_id_hooks_get_val(struct gtp_trace_s *gts, struct gtp_var *gtv,
++                        int64_t *val)
++{
++      if (!gts->step) {
++              if (++ __get_cpu_var(gtp_step_id) == 0)
++                      __get_cpu_var(gtp_step_id) = 1;
++      }
++
++      *val = __get_cpu_var(gtp_step_id);
++
++      return 0;
++}
++
++static struct gtp_var_hooks   gtp_step_id_hooks = {
++      .agent_get_val = gtp_step_id_hooks_get_val,
++};
++#endif
++
 +static int
 +gtp_var_special_add_all(void)
 +{
@@ -5610,8 +5674,8 @@
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +
-+      var = gtp_var_special_add(GTP_VAR_NO_SELF_TRACE_ID, 0, 0,
-+                                "no_self_trace", NULL);
++      var = gtp_var_special_add(GTP_VAR_SELF_TRACE_ID, 0, 0,
++                                "self_trace", NULL);
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +
@@ -5737,6 +5801,16 @@
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +#endif
++      var = gtp_var_special_add(GTP_STEP_COUNT_ID, 0, 0,
++                                "step_count", &gtp_step_count_hooks);
++      if (IS_ERR(var))
++              return PTR_ERR(var);
++#ifdef GTP_RB
++      var = gtp_var_special_add(GTP_STEP_ID_ID, 0, 0,
++                                "step_id", &gtp_step_id_hooks);
++      if (IS_ERR(var))
++              return PTR_ERR(var);
++#endif
 +
 +      return 0;
 +}
@@ -7309,6 +7383,11 @@
 +      } while (0)
 +#endif
 +
++static int    gtp_collect_var(struct gtp_trace_s *gts, int num);
++#ifdef GTP_RB
++static int    gtp_var_array_step_id_id = 0;
++#endif
++
 +static int
 +gtp_action_head(struct gtp_trace_s *gts)
 +{
@@ -7357,6 +7436,13 @@
 +
 +      trace_nump = (ULONGEST *)tmp;
 +      *trace_nump = gts->tpe->num;
++      tmp += sizeof(ULONGEST);
++
++#ifdef GTP_RB
++      *(void **)tmp = gtp_rb_prev_frame_get(gts->next);
++      gtp_rb_prev_frame_set(gts->next, (void *)(tmp + sizeof(void *)
++                                                - GTP_FRAME_HEAD_SIZE));
++#endif
 +
 +#ifdef GTP_FTRACE_RING_BUFFER
 +      ring_buffer_unlock_commit(gtp_frame, rbe);
@@ -7365,6 +7451,14 @@
 +
 +      atomic_inc(&gtp_frame_create);
 +
++#ifdef GTP_RB
++      /* Auto collect $step_id.  */
++      if (gts->tpe->step) {
++              if (gtp_collect_var(gts, gtp_var_array_step_id_id))
++                      return -1;
++      }
++#endif
++
 +      return 0;
 +}
 +
@@ -7807,6 +7901,8 @@
 +
 +      return ret;
 +}
++
++/* The number is not the ID of tvar, it is the ID of gtp_var_array. */
 +
 +static int
 +gtp_collect_var(struct gtp_trace_s *gts, int num)
@@ -8462,6 +8558,30 @@
 +}
 +#endif
 +
++#ifdef CONFIG_X86
++/* while-stepping stop.  */
++
++static void
++gtp_step_stop(struct pt_regs *regs)
++{
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24))
++      regs->flags &= ~(X86_EFLAGS_TF);
++#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;
++}
++#endif
++
 +static void
 +gtp_handler(struct gtp_trace_s *gts)
 +{
@@ -8471,6 +8591,10 @@
 +      printk(GTP_DEBUG_V "gtp_handler: tracepoint %d %p\n",
 +             (int)gts->tpe->num, (void *)(CORE_ADDR)gts->tpe->addr);
 +#endif
++#ifdef CONFIG_X86
++      if (gts->step == 0 && __get_cpu_var(gtp_step).step)
++              gtp_step_stop(gts->regs);
++#endif
 +
 +      gts->read_memory = (void *)probe_kernel_read;
 +      if (gts->tpe->flags & GTP_ENTRY_FLAGS_CURRENT_TASK) {
@@ -8487,7 +8611,7 @@
 +              return;
 +#endif
 +
-+      if ((gts->tpe->flags & GTP_ENTRY_FLAGS_NO_SELF_TRACE)
++      if ((gts->tpe->flags & GTP_ENTRY_FLAGS_SELF_TRACE) == 0
 +          && (get_current()->pid == gtp_gtp_pid
 +              || get_current()->pid == gtp_gtpframe_pid)) {
 +                      return;
@@ -8512,7 +8636,7 @@
 +      gts->run = NULL;
 +
 +      /* Pass.  */
-+      if (gts->tpe->flags & GTP_ENTRY_FLAGS_HAVE_PASS) {
++      if (gts->step == 0 && gts->tpe->flags & GTP_ENTRY_FLAGS_HAVE_PASS) {
 +              if (atomic_dec_return(&gts->tpe->current_pass) < 0)
 +                      goto tpe_stop;
 +      }
@@ -8672,18 +8796,47 @@
 +      struct kretprobe        *kpret;
 +      struct gtp_kp           *gkp;
 +      union gtp_entry_u       *u;
++      struct gtp_entry                *tpe;
 +      struct gtp_trace_s      gts;
 +
-+      memset(&gts, 0, sizeof(struct gtp_trace_s));
-+
 +      kpret = container_of(p, struct kretprobe, kp);
 +      gkp = container_of(kpret, struct gtp_kp, kpret);
 +      u = container_of(gkp, union gtp_entry_u, kp);
-+      gts.tpe = container_of(u, struct gtp_entry, u);
-+      gts.regs = regs;
-+      gts.step = 1;
++      tpe = container_of(u, struct gtp_entry, u);
++
++      if (tpe->step == 1) {
++              memset(&gts, 0, sizeof(struct gtp_trace_s));
++
++              gts.tpe = tpe;
++              gts.regs = regs;
++              gts.step = tpe->step;
 +
-+      gtp_handler(&gts);
++              gtp_handler(&gts);
++      }
++
++#ifdef CONFIG_X86
++      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. */
++              __get_cpu_var(gtp_step).step = tpe->step;
++              __get_cpu_var(gtp_step).tpe = tpe;
++              #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24))
++              if (regs->flags & X86_EFLAGS_IF)
++              #else
++              if (regs->eflags & X86_EFLAGS_IF)
++              #endif
++                      __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
 +}
 +
 +static inline void
@@ -8964,6 +9117,7 @@
 +              gtp_list = gtp_list->next;
 +              gtp_action_release(tpe->cond);
 +              gtp_action_release(tpe->action_list);
++              gtp_action_release(tpe->step_action_list);
 +              gtp_src_release(tpe->src);
 +              gtp_src_release(tpe->action_cmd);
 +              gtp_src_release(tpe->printk_str);
@@ -9204,6 +9358,238 @@
 +
 +      return 0;
 +}
++
++#ifdef CONFIG_X86
++#define ADDR_PREFIX_OPCODE 0x67
++#define DATA_PREFIX_OPCODE 0x66
++#define LOCK_PREFIX_OPCODE 0xf0
++#define CS_PREFIX_OPCODE 0x2e
++#define DS_PREFIX_OPCODE 0x3e
++#define ES_PREFIX_OPCODE 0x26
++#define FS_PREFIX_OPCODE 0x64
++#define GS_PREFIX_OPCODE 0x65
++#define SS_PREFIX_OPCODE 0x36
++#define REPNE_PREFIX_OPCODE 0xf2
++#define REPE_PREFIX_OPCODE  0xf3
++
++static int
++gtp_step_check_insn(struct pt_regs *regs)
++{
++      uint32_t        opcode;
++      uint8_t         opcode8;
++      unsigned long   pc = GTP_REGS_PC(regs);
++
++      /* prefixes */
++      while (1) {
++              if (probe_kernel_read(&opcode8, (void *)pc, 1))
++                      return -1;
++              pc++;
++              switch (opcode8) {
++              case REPE_PREFIX_OPCODE:
++              case REPNE_PREFIX_OPCODE:
++              case LOCK_PREFIX_OPCODE:
++              case CS_PREFIX_OPCODE:
++              case SS_PREFIX_OPCODE:
++              case DS_PREFIX_OPCODE:
++              case ES_PREFIX_OPCODE:
++              case FS_PREFIX_OPCODE:
++              case GS_PREFIX_OPCODE:
++              case DATA_PREFIX_OPCODE:
++              case ADDR_PREFIX_OPCODE:
++#ifndef CONFIG_X86_32
++              case 0x40 ... 0x4f:
++#endif
++                      break;
++              default:
++                      goto out_prefixes;
++              }
++      }
++out_prefixes:
++
++      opcode = (uint32_t)opcode8;
++reswitch:
++      switch (opcode) {
++      case 0x0f:
++              if (probe_kernel_read(&opcode8, (void *)pc, 1))
++                      return -1;
++              opcode = (uint32_t) opcode8 | 0x0f00;
++              goto reswitch;
++              break;
++      case 0xfb:
++              /* sti */
++              __get_cpu_var(gtp_step).irq_need_open = 1;
++              GTP_REGS_PC(regs) = pc;
++              break;
++      case 0xfa:
++              /* cli */
++              __get_cpu_var(gtp_step).irq_need_open = 0;
++              GTP_REGS_PC(regs) = pc;
++              break;
++      case 0x0f07:
++              /* sysret */
++              return 1;
++              break;
++      };
++
++      return 0;
++}
++
++static int
++gtp_notifier_call(struct notifier_block *self, unsigned long cmd,
++                 void *ptr)
++{
++      int             ret = NOTIFY_DONE;
++      unsigned long   flags;
++      struct die_args *args;
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      int             i;
++#endif
++      unsigned long   dr6;
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      unsigned long   *dr6_p;
++#endif
++
++      if (cmd != DIE_DEBUG)
++              return ret;
++
++      local_irq_save(flags);
++      args = ptr;
++
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      /* Get from X86 hw_breakpoint_handler.  */
++      dr6_p = (unsigned long *)ERR_PTR(args->err);
++      dr6 = *dr6_p;
++#else
++      dr6 = args->err;
++#endif
++      gtp_set_debugreg(GTP_HWB_DR7_DEF, 7);
++
++      /* Handle while-stepping.  */
++      spin_lock(&__get_cpu_var(gtp_step).lock);
++      if ((dr6 & 0x4000) != 0) {
++              /* Clear the bit that handle by KGTP.  */
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++              (*dr6_p) &= ~(0x4000);
++#else
++              dr6 &= ~(0x4000);
++#endif
++              if (!__get_cpu_var(gtp_step).tpe || user_mode(args->regs))
++                      gtp_step_stop(args->regs);
++              else {
++                      int need_stop = gtp_step_check_insn(args->regs);
++                      if (need_stop < 0)
++                              printk(KERN_WARNING "KGTP: check insn in %p got 
error.",
++                                     (void *)GTP_REGS_PC(args->regs));
++
++                      preempt_disable();
++                      {
++                              struct gtp_trace_s      gts;
++
++                              memset(&gts, 0, sizeof(struct gtp_trace_s));
++                              gts.tpe = __get_cpu_var(gtp_step).tpe;
++                              gts.regs = args->regs;
++                              gts.step = __get_cpu_var(gtp_step).step;
++                              gtp_handler(&gts);
++                      }
++                      preempt_enable_no_resched();
++
++                      if (__get_cpu_var(gtp_step).step > 1 && !need_stop) {
++                              /* 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.  */
++                              gtp_step_stop(args->regs);
++                      }
++              }
++      }
++      spin_unlock(&__get_cpu_var(gtp_step).lock);
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      /* Handle watch traceppoint.  */
++      if ((dr6 & 0xf) == 0)
++              goto out;
++      read_lock(&gtp_hwb_lock);
++
++      for (i = 0; i < HWB_NUM; i++) {
++              if ((dr6 & (0x1 << i)) == 0)
++                      continue;
++              /* Clear the bit that handle by KGTP.  */
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++              (*dr6_p) &= ~(0x1 << i);
++#else
++              dr6 &= ~(0x1 << i);
++#endif
++              if (gtp_hwb[i].watch == NULL)
++                      continue;
++              /* Check if gtp_hwb is updated in other CPU.  */
++              if (__get_cpu_var(gtp_hwb_sync_count_local) != 
gtp_hwb_sync_count) {
++                      unsigned long   addr;
++
++                      gtp_get_debugreg(addr, i);
++                      if (addr != gtp_hwb[i].addr)
++                              continue;
++              }
++              preempt_disable();
++              {
++                      struct gtp_trace_s      gts;
++
++                      memset(&gts, 0, sizeof(struct gtp_trace_s));
++                      gts.tpe = gtp_hwb[i].watch;
++                      gts.regs = args->regs;
++                      gts.hwb = &gtp_hwb[i];
++                      gtp_handler(&gts);
++              }
++              preempt_enable_no_resched();
++      }
++
++      /* If the HWB need update in this CPU, just update it.  */
++      if (__get_cpu_var(gtp_hwb_sync_count_local) != gtp_hwb_sync_count) {
++              gtp_set_debugreg(gtp_hwb_drx[0], 0);
++              gtp_set_debugreg(gtp_hwb_drx[1], 1);
++              gtp_set_debugreg(gtp_hwb_drx[2], 2);
++              gtp_set_debugreg(gtp_hwb_drx[3], 3);
++              __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
++      }
++
++      gtp_set_debugreg(gtp_hwb_dr7, 7);
++      read_unlock(&gtp_hwb_lock);
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++out:
++#endif
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
++      gtp_set_debugreg(dr6, 6);
++#endif
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      /* If have some other traps, let other handler handle it.  */
++      if (((*dr6_p) & GTP_HWB_DR6_MASK) == 0)
++              ret = NOTIFY_STOP;
++      current->thread.debugreg6 = *dr6_p;
++#else
++      if ((dr6 & GTP_HWB_DR6_MASK) == 0)
++              ret = NOTIFY_STOP;
++      current->thread.debugreg6 = dr6;
++#endif
++
++      local_irq_restore(flags);
++      return ret;
++}
++
++static struct notifier_block gtp_notifier = {
++      .notifier_call = gtp_notifier_call,
++      .priority = 0x7ffffffe /* we need to be notified after kprobe.  */
++};
++#endif
 +
 +#ifdef CONFIG_X86
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0))
@@ -9300,102 +9686,8 @@
 +      gtp_hw_breakpoint_handler(breakinfo[3].num, regs);
 +}
 +#endif
-+#else
-+static int
-+gtp_notifier_call(struct notifier_block *self, unsigned long cmd,
-+                 void *ptr)
-+{
-+      int             ret = NOTIFY_DONE;
-+      unsigned long   flags;
-+      struct die_args *args;
-+      int             i;
-+      unsigned long   dr6;
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      unsigned long   *dr6_p;
 +#endif
 +
-+      if (cmd != DIE_DEBUG)
-+              return ret;
-+
-+      local_irq_save(flags);
-+      args = ptr;
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      /* Get from X86 hw_breakpoint_handler.  */
-+      dr6_p = (unsigned long *)ERR_PTR(args->err);
-+      dr6 = *dr6_p;
-+#else
-+      dr6 = args->err;
-+#endif
-+      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)
-+                      continue;
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+              /* Because KGTP handle all the hw-breakpoints.
-+                 So Just clear it.  */
-+              (*dr6_p) &= ~(0x1 << i);
-+#endif
-+              if (gtp_hwb[i].watch == NULL)
-+                      continue;
-+              /* Check if gtp_hwb is updated in other CPU.  */
-+              if (__get_cpu_var(gtp_hwb_sync_count_local) != 
gtp_hwb_sync_count) {
-+                      unsigned long   addr;
-+
-+                      gtp_get_debugreg(addr, i);
-+                      if (addr != gtp_hwb[i].addr)
-+                              continue;
-+              }
-+              preempt_disable();
-+              {
-+                      struct gtp_trace_s      gts;
-+
-+                      memset(&gts, 0, sizeof(struct gtp_trace_s));
-+                      gts.tpe = gtp_hwb[i].watch;
-+                      gts.regs = args->regs;
-+                      gts.hwb = &gtp_hwb[i];
-+                      gtp_handler(&gts);
-+              }
-+              preempt_enable_no_resched();
-+      }
-+
-+      /* If the HWB need update in this CPU, just update it.  */
-+      if (__get_cpu_var(gtp_hwb_sync_count_local) != gtp_hwb_sync_count) {
-+              set_debugreg(gtp_hwb_drx[0], 0);
-+              set_debugreg(gtp_hwb_drx[1], 1);
-+              set_debugreg(gtp_hwb_drx[2], 2);
-+              set_debugreg(gtp_hwb_drx[3], 3);
-+              __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      }
-+
-+      set_debugreg(gtp_hwb_dr7, 7);
-+      read_unlock(&gtp_hwb_lock);
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      /* If have some other traps, let other handler handle it.  */
-+      if ((dr6 & (~0xf)) == 0)
-+              ret = NOTIFY_STOP;
-+#else
-+      set_debugreg(0UL, 6);
-+      ret = NOTIFY_STOP;
-+#endif
-+
-+out:
-+      local_irq_restore(flags);
-+      return ret;
-+}
-+
-+static struct notifier_block gtp_notifier = {
-+      .notifier_call = gtp_notifier_call,
-+      .priority = 0x7fffffff /* we need to be notified first */
-+};
-+#endif
-+
 +static unsigned int
 +gtp_hwb_size_to_arch(int size)
 +{
@@ -9474,7 +9766,7 @@
 +
 +              /* Set gtp_hwb_dr7 and gtp_hwb_drx[num] to hwb.  */
 +              gtp_set_debugreg(gtp_hwb_drx[num], num);
-+              set_debugreg(gtp_hwb_dr7, 7);
++              gtp_set_debugreg(gtp_hwb_dr7, 7);
 +
 +              gtp_hwb_sync_count++;
 +              hwb->count = gtp_hwb_sync_count;
@@ -9531,7 +9823,7 @@
 +                      gtp_hwb_sync_count++;
 +
 +                      /* Sync gtp_hwb_dr7 update to hwb.  */
-+                      set_debugreg(gtp_hwb_dr7, 7);
++                      gtp_set_debugreg(gtp_hwb_dr7, 7);
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
 +                      /* Send ipi to let other cpu update.  */
@@ -9594,54 +9886,74 @@
 +              tasklet_kill(&tpe->disable_tasklet);
 +              tasklet_kill(&tpe->enable_tasklet);
 +#endif
++      }
++
++#ifdef CONFIG_X86
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      if (gtp_have_step || gtp_have_watch_tracepoint)
++#else
++      if (gtp_have_step)
++#endif
++              unregister_die_notifier(&gtp_notifier);
++
++      {
++              /* Init data of while-stepping.  */
++              int     cpu;
++              for_each_online_cpu(cpu) {
++                      struct gtp_step_s       *step = &per_cpu(gtp_step, cpu);
++
++                      spin_lock(&step->lock);
++                      step->step = 0;
++                      step->tpe = NULL;
++                      spin_unlock(&step->lock);
++              }
 +      }
++#endif
 +
 +#ifdef CONFIG_X86
 +      /* Stop hwb.  */
++      if (gtp_have_watch_tracepoint) {
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0))
-+      {
-+              int     i;
++              {
++                      int     i;
 +
-+              /* Register hw breakpoints.  */
-+              for (i = 0; i < HWB_NUM; i++) {
-+                      unregister_wide_hw_breakpoint(breakinfo[i].pev);
-+                      breakinfo[i].pev = NULL;
++                      /* Register hw breakpoints.  */
++                      for (i = 0; i < HWB_NUM; i++) {
++                              unregister_wide_hw_breakpoint(breakinfo[i].pev);
++                              breakinfo[i].pev = NULL;
++                      }
 +              }
-+      }
 +#endif
 +
-+      gtp_hwb_stop(NULL);
++              gtp_hwb_stop(NULL);
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
-+      smp_call_function(gtp_hwb_stop, NULL, 1);
++              smp_call_function(gtp_hwb_stop, NULL, 1);
 +#else
-+      smp_call_function(gtp_hwb_stop, NULL, 0, 1);
++              smp_call_function(gtp_hwb_stop, NULL, 0, 1);
 +#endif
 +
-+      for (tpe = gtp_list; tpe; tpe = tpe->next) {
-+              if (tpe->type == gtp_entry_kprobe
-+                  || (tpe->flags & GTP_ENTRY_FLAGS_REG) == 0
-+                  || tpe->disable)
-+                      continue;
++              for (tpe = gtp_list; tpe; tpe = tpe->next) {
++                      if (tpe->type == gtp_entry_kprobe
++                          || (tpe->flags & GTP_ENTRY_FLAGS_REG) == 0
++                          || tpe->disable)
++                              continue;
 +
-+              if (tpe->type == gtp_entry_watch_static)
-+                      gtp_unregister_hwb(tpe->addr, 0);
++                      if (tpe->type == gtp_entry_watch_static)
++                              gtp_unregister_hwb(tpe->addr, 0);
 +
-+              tpe->flags &= ~GTP_ENTRY_FLAGS_REG;
++                      tpe->flags &= ~GTP_ENTRY_FLAGS_REG;
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
-+              tasklet_kill(&tpe->disable_tasklet);
-+              tasklet_kill(&tpe->enable_tasklet);
++                      tasklet_kill(&tpe->disable_tasklet);
++                      tasklet_kill(&tpe->enable_tasklet);
 +#endif
-+      }
++              }
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
-+      unregister_kprobe(&gtp_ipi_kp);
++              unregister_kprobe(&gtp_ipi_kp);
 +#endif
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
-+      unregister_die_notifier(&gtp_notifier);
++      }
 +#endif
-+#endif
 +
 +#ifdef GTP_PERF_EVENTS
 +      list_for_each(cur, &gtp_var_list) {
@@ -9713,6 +10025,10 @@
 +              gtp_frame_reset();
 +
 +      gtpro_list_clear();
++#ifdef CONFIG_X86
++      gtp_have_watch_tracepoint = 0;
++      gtp_have_step = 0;
++#endif
 +
 +      gtp_var_release(0);
 +
@@ -9827,12 +10143,13 @@
 +}
 +
 +static int
-+gtp_add_backtrace_actions(struct gtp_entry *tpe)
++gtp_add_backtrace_actions(struct gtp_entry *tpe, int step)
 +{
 +      struct action   *ae, *new_ae;
 +      int             got_r = 0, got_m = 0;
 +
-+      for (ae = tpe->action_list; ae; ae = ae->next) {
++      for (ae = step ? tpe->step_action_list : tpe->action_list;
++           ae; ae = ae->next) {
 +              if (ae->type == 'R')
 +                      got_r = 1;
 +              else if (ae->type == 'M' && ae->u.m.regnum == GTP_SP_NUM
@@ -9840,7 +10157,9 @@
 +                      got_m = 1;
 +
 +              if (got_r && got_m)
-+                      break;
++                      return 1;
++
++              /* Let ae point to the last entry of action_list.  */
 +              if (!ae->next)
 +                      break;
 +      }
@@ -9851,8 +10170,14 @@
 +                      return -ENOMEM;
 +              if (ae)
 +                      ae->next = new_ae;
-+              else
-+                      tpe->action_list = ae;
++              else {
++                      if (step)
***The diff for this file has been truncated for email.***
=======================================
--- /trunk/gtp_older_to_2.6.19.patch    Sun Feb 17 20:54:51 2013
+++ /trunk/gtp_older_to_2.6.19.patch    Mon May  6 19:06:35 2013
@@ -3655,7 +3655,7 @@

 --- /dev/null
 +++ b/lib/gtp.c
-@@ -0,0 +1,12093 @@
+@@ -0,0 +1,12887 @@
 +/*
 + * Kernel GDB tracepoint module.
 + *
@@ -3673,12 +3673,12 @@
 + * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 + *
-+ * Copyright(C) KGTP team (https://code.google.com/p/kgtp/), 2010, 2011, 2012, 2013
++ * Copyright(C) KGTP team (https://code.google.com/p/kgtp/), 2010-2013
 + *
 + */
 +
 +/* If "* 10" means that this is not a release version.  */
-+#define GTP_VERSION                   (20130218)
++#define GTP_VERSION                   (20130218 * 10)
 +
 +#include <linux/version.h>
 +#ifndef RHEL_RELEASE_VERSION
@@ -3757,6 +3757,9 @@
 +#include <linux/slab.h>
 +#include <linux/ctype.h>
 +#include <asm/atomic.h>
++#ifdef CONFIG_X86
++#include <asm/debugreg.h>
++#endif
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
 +#include <linux/kdebug.h>
 +#else
@@ -3867,7 +3870,9 @@
 +                               + sizeof(struct gtp_frame_var))
 +#endif
 +#ifdef GTP_RB
-+#define GTP_FRAME_HEAD_SIZE   (FID_SIZE + sizeof(u64) + sizeof(ULONGEST))
++/* The frame head size: FID_HEAD + count id + frame number + pointer to prev frem */ ++#define GTP_FRAME_HEAD_SIZE (FID_SIZE + sizeof(u64) + sizeof(ULONGEST) + sizeof(void *))
++/* The frame head size: FID_PAGE_BEGIN + count id */
 +#define GTP_FRAME_PAGE_BEGIN_SIZE     (FID_SIZE + sizeof(u64))
 +#endif
 +#ifdef GTP_FTRACE_RING_BUFFER
@@ -3950,7 +3955,7 @@
 +/* This gtp entry is registered inside the system.  */
 +#define GTP_ENTRY_FLAGS_REG           2
 +/* See $no_self_trace.  */
-+#define GTP_ENTRY_FLAGS_NO_SELF_TRACE 4
++#define GTP_ENTRY_FLAGS_SELF_TRACE    4
 +/* This gtp entry has passcount.  */
 +#define GTP_ENTRY_FLAGS_HAVE_PASS     8
 +/* See $printk_level.  */
@@ -4121,14 +4126,32 @@
 +
 +static pid_t                  gtp_current_pid;
 +
++#ifdef CONFIG_X86
++/* Following part is for while-stepping.  */
++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);
++#endif
++
 +#ifdef CONFIG_X86
++static int    gtp_have_watch_tracepoint;
++static int    gtp_have_step;
++#endif
++
++#ifdef CONFIG_X86
++/* Following part is for watch tracepoint.  */
 +/* This part is X86 special.  */
 +#define HWB_NUM                       4
 +
 +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 {
@@ -4206,16 +4229,16 @@
 +{
 +      switch(reg) {
 +      case 0:
-+              set_debugreg(val, 0);
++              gtp_set_debugreg(val, 0);
 +              break;
 +      case 1:
-+              set_debugreg(val, 1);
++              gtp_set_debugreg(val, 1);
 +              break;
 +      case 2:
-+              set_debugreg(val, 2);
++              gtp_set_debugreg(val, 2);
 +              break;
 +      case 3:
-+              set_debugreg(val, 3);
++              gtp_set_debugreg(val, 3);
 +              break;
 +      }
 +}
@@ -4226,11 +4249,11 @@
 +{
 +      read_lock(&gtp_hwb_lock);
 +      __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      set_debugreg(0UL, 0);
-+      set_debugreg(0UL, 1);
-+      set_debugreg(0UL, 2);
-+      set_debugreg(0UL, 3);
-+      set_debugreg(GTP_HWB_DR7_DEF, 7);
++      gtp_set_debugreg(0UL, 0);
++      gtp_set_debugreg(0UL, 1);
++      gtp_set_debugreg(0UL, 2);
++      gtp_set_debugreg(0UL, 3);
++      gtp_set_debugreg(GTP_HWB_DR7_DEF, 7);
 +      read_unlock(&gtp_hwb_lock);
 +}
 +
@@ -4238,11 +4261,11 @@
 +gtp_hwb_sync_local(void)
 +{
 +      __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      set_debugreg(gtp_hwb_drx[0], 0);
-+      set_debugreg(gtp_hwb_drx[1], 1);
-+      set_debugreg(gtp_hwb_drx[2], 2);
-+      set_debugreg(gtp_hwb_drx[3], 3);
-+      set_debugreg(gtp_hwb_dr7, 7);
++      gtp_set_debugreg(gtp_hwb_drx[0], 0);
++      gtp_set_debugreg(gtp_hwb_drx[1], 1);
++      gtp_set_debugreg(gtp_hwb_drx[2], 2);
++      gtp_set_debugreg(gtp_hwb_drx[3], 3);
++      gtp_set_debugreg(gtp_hwb_dr7, 7);
 +}
 +
 +static void
@@ -4397,7 +4420,7 @@
 +      GTP_VAR_PRINTK_LEVEL_ID                 = 11,
 +      GTP_VAR_PRINTK_FORMAT_ID                = 12,
 +      GTP_VAR_DUMP_STACK_ID                   = 13,
-+      GTP_VAR_NO_SELF_TRACE_ID                = 14,
++      GTP_VAR_SELF_TRACE_ID                   = 14,
 +      GTP_VAR_CPU_NUMBER_ID                   = 15,
 +      GTP_VAR_PC_PE_EN_ID                     = 16,
 +      GTP_VAR_KRET_ID                         = 17,
@@ -4430,8 +4453,11 @@
 +      GTP_WATCH_VAL_ID                        = 42,
 +      GTP_WATCH_COUNT_ID                      = 43,
 +
++      GTP_STEP_COUNT_ID                       = 44,
++      GTP_STEP_ID_ID                          = 45,
++
 +      GTP_VAR_SPECIAL_MIN                     = GTP_VAR_VERSION_ID,
-+      GTP_VAR_SPECIAL_MAX                     = GTP_WATCH_COUNT_ID,
++      GTP_VAR_SPECIAL_MAX                     = GTP_STEP_ID_ID,
 +};
 +
 +enum pe_tv_id {
@@ -5440,6 +5466,44 @@
 +};
 +#endif
 +
++#ifdef GTP_RB
++static int
++gtp_step_count_hooks_get_val(struct gtp_trace_s *gts, struct gtp_var *gtv,
++                           int64_t *val)
++{
++      if (gts->step)
++              *val = gts->tpe->step - gts->step + 1;
++      else
++              *val = 0;
++
++      return 0;
++}
++
++static struct gtp_var_hooks   gtp_step_count_hooks = {
++      .agent_get_val = gtp_step_count_hooks_get_val,
++};
++
++static DEFINE_PER_CPU(int64_t, gtp_step_id);
++
++static int
++gtp_step_id_hooks_get_val(struct gtp_trace_s *gts, struct gtp_var *gtv,
++                        int64_t *val)
++{
++      if (!gts->step) {
++              if (++ __get_cpu_var(gtp_step_id) == 0)
++                      __get_cpu_var(gtp_step_id) = 1;
++      }
++
++      *val = __get_cpu_var(gtp_step_id);
++
++      return 0;
++}
++
++static struct gtp_var_hooks   gtp_step_id_hooks = {
++      .agent_get_val = gtp_step_id_hooks_get_val,
++};
++#endif
++
 +static int
 +gtp_var_special_add_all(void)
 +{
@@ -5532,8 +5596,8 @@
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +
-+      var = gtp_var_special_add(GTP_VAR_NO_SELF_TRACE_ID, 0, 0,
-+                                "no_self_trace", NULL);
++      var = gtp_var_special_add(GTP_VAR_SELF_TRACE_ID, 0, 0,
++                                "self_trace", NULL);
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +
@@ -5659,6 +5723,16 @@
 +      if (IS_ERR(var))
 +              return PTR_ERR(var);
 +#endif
++      var = gtp_var_special_add(GTP_STEP_COUNT_ID, 0, 0,
++                                "step_count", &gtp_step_count_hooks);
++      if (IS_ERR(var))
++              return PTR_ERR(var);
++#ifdef GTP_RB
++      var = gtp_var_special_add(GTP_STEP_ID_ID, 0, 0,
++                                "step_id", &gtp_step_id_hooks);
++      if (IS_ERR(var))
++              return PTR_ERR(var);
++#endif
 +
 +      return 0;
 +}
@@ -7231,6 +7305,11 @@
 +      } while (0)
 +#endif
 +
++static int    gtp_collect_var(struct gtp_trace_s *gts, int num);
++#ifdef GTP_RB
++static int    gtp_var_array_step_id_id = 0;
++#endif
++
 +static int
 +gtp_action_head(struct gtp_trace_s *gts)
 +{
@@ -7279,6 +7358,13 @@
 +
 +      trace_nump = (ULONGEST *)tmp;
 +      *trace_nump = gts->tpe->num;
++      tmp += sizeof(ULONGEST);
++
++#ifdef GTP_RB
++      *(void **)tmp = gtp_rb_prev_frame_get(gts->next);
++      gtp_rb_prev_frame_set(gts->next, (void *)(tmp + sizeof(void *)
++                                                - GTP_FRAME_HEAD_SIZE));
++#endif
 +
 +#ifdef GTP_FTRACE_RING_BUFFER
 +      ring_buffer_unlock_commit(gtp_frame, rbe);
@@ -7287,6 +7373,14 @@
 +
 +      atomic_inc(&gtp_frame_create);
 +
++#ifdef GTP_RB
++      /* Auto collect $step_id.  */
++      if (gts->tpe->step) {
++              if (gtp_collect_var(gts, gtp_var_array_step_id_id))
++                      return -1;
++      }
++#endif
++
 +      return 0;
 +}
 +
@@ -7729,6 +7823,8 @@
 +
 +      return ret;
 +}
++
++/* The number is not the ID of tvar, it is the ID of gtp_var_array. */
 +
 +static int
 +gtp_collect_var(struct gtp_trace_s *gts, int num)
@@ -8384,6 +8480,30 @@
 +}
 +#endif
 +
++#ifdef CONFIG_X86
++/* while-stepping stop.  */
++
++static void
++gtp_step_stop(struct pt_regs *regs)
++{
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24))
++      regs->flags &= ~(X86_EFLAGS_TF);
++#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;
++}
++#endif
++
 +static void
 +gtp_handler(struct gtp_trace_s *gts)
 +{
@@ -8393,6 +8513,10 @@
 +      printk(GTP_DEBUG_V "gtp_handler: tracepoint %d %p\n",
 +             (int)gts->tpe->num, (void *)(CORE_ADDR)gts->tpe->addr);
 +#endif
++#ifdef CONFIG_X86
++      if (gts->step == 0 && __get_cpu_var(gtp_step).step)
++              gtp_step_stop(gts->regs);
++#endif
 +
 +      gts->read_memory = (void *)probe_kernel_read;
 +      if (gts->tpe->flags & GTP_ENTRY_FLAGS_CURRENT_TASK) {
@@ -8409,7 +8533,7 @@
 +              return;
 +#endif
 +
-+      if ((gts->tpe->flags & GTP_ENTRY_FLAGS_NO_SELF_TRACE)
++      if ((gts->tpe->flags & GTP_ENTRY_FLAGS_SELF_TRACE) == 0
 +          && (get_current()->pid == gtp_gtp_pid
 +              || get_current()->pid == gtp_gtpframe_pid)) {
 +                      return;
@@ -8434,7 +8558,7 @@
 +      gts->run = NULL;
 +
 +      /* Pass.  */
-+      if (gts->tpe->flags & GTP_ENTRY_FLAGS_HAVE_PASS) {
++      if (gts->step == 0 && gts->tpe->flags & GTP_ENTRY_FLAGS_HAVE_PASS) {
 +              if (atomic_dec_return(&gts->tpe->current_pass) < 0)
 +                      goto tpe_stop;
 +      }
@@ -8594,18 +8718,47 @@
 +      struct kretprobe        *kpret;
 +      struct gtp_kp           *gkp;
 +      union gtp_entry_u       *u;
++      struct gtp_entry                *tpe;
 +      struct gtp_trace_s      gts;
 +
-+      memset(&gts, 0, sizeof(struct gtp_trace_s));
-+
 +      kpret = container_of(p, struct kretprobe, kp);
 +      gkp = container_of(kpret, struct gtp_kp, kpret);
 +      u = container_of(gkp, union gtp_entry_u, kp);
-+      gts.tpe = container_of(u, struct gtp_entry, u);
-+      gts.regs = regs;
-+      gts.step = 1;
++      tpe = container_of(u, struct gtp_entry, u);
++
++      if (tpe->step == 1) {
++              memset(&gts, 0, sizeof(struct gtp_trace_s));
++
++              gts.tpe = tpe;
++              gts.regs = regs;
++              gts.step = tpe->step;
++
++              gtp_handler(&gts);
++      }
 +
-+      gtp_handler(&gts);
++#ifdef CONFIG_X86
++      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. */
++              __get_cpu_var(gtp_step).step = tpe->step;
++              __get_cpu_var(gtp_step).tpe = tpe;
++              #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24))
++              if (regs->flags & X86_EFLAGS_IF)
++              #else
++              if (regs->eflags & X86_EFLAGS_IF)
++              #endif
++                      __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
 +}
 +
 +static inline void
@@ -8886,6 +9039,7 @@
 +              gtp_list = gtp_list->next;
 +              gtp_action_release(tpe->cond);
 +              gtp_action_release(tpe->action_list);
++              gtp_action_release(tpe->step_action_list);
 +              gtp_src_release(tpe->src);
 +              gtp_src_release(tpe->action_cmd);
 +              gtp_src_release(tpe->printk_str);
@@ -9126,6 +9280,238 @@
 +
 +      return 0;
 +}
++
++#ifdef CONFIG_X86
++#define ADDR_PREFIX_OPCODE 0x67
++#define DATA_PREFIX_OPCODE 0x66
++#define LOCK_PREFIX_OPCODE 0xf0
++#define CS_PREFIX_OPCODE 0x2e
++#define DS_PREFIX_OPCODE 0x3e
++#define ES_PREFIX_OPCODE 0x26
++#define FS_PREFIX_OPCODE 0x64
++#define GS_PREFIX_OPCODE 0x65
++#define SS_PREFIX_OPCODE 0x36
++#define REPNE_PREFIX_OPCODE 0xf2
++#define REPE_PREFIX_OPCODE  0xf3
++
++static int
++gtp_step_check_insn(struct pt_regs *regs)
++{
++      uint32_t        opcode;
++      uint8_t         opcode8;
++      unsigned long   pc = GTP_REGS_PC(regs);
++
++      /* prefixes */
++      while (1) {
++              if (probe_kernel_read(&opcode8, (void *)pc, 1))
++                      return -1;
++              pc++;
++              switch (opcode8) {
++              case REPE_PREFIX_OPCODE:
++              case REPNE_PREFIX_OPCODE:
++              case LOCK_PREFIX_OPCODE:
++              case CS_PREFIX_OPCODE:
++              case SS_PREFIX_OPCODE:
++              case DS_PREFIX_OPCODE:
++              case ES_PREFIX_OPCODE:
++              case FS_PREFIX_OPCODE:
++              case GS_PREFIX_OPCODE:
++              case DATA_PREFIX_OPCODE:
++              case ADDR_PREFIX_OPCODE:
++#ifndef CONFIG_X86_32
++              case 0x40 ... 0x4f:
++#endif
++                      break;
++              default:
++                      goto out_prefixes;
++              }
++      }
++out_prefixes:
++
++      opcode = (uint32_t)opcode8;
++reswitch:
++      switch (opcode) {
++      case 0x0f:
++              if (probe_kernel_read(&opcode8, (void *)pc, 1))
++                      return -1;
++              opcode = (uint32_t) opcode8 | 0x0f00;
++              goto reswitch;
++              break;
++      case 0xfb:
++              /* sti */
++              __get_cpu_var(gtp_step).irq_need_open = 1;
++              GTP_REGS_PC(regs) = pc;
++              break;
++      case 0xfa:
++              /* cli */
++              __get_cpu_var(gtp_step).irq_need_open = 0;
++              GTP_REGS_PC(regs) = pc;
++              break;
++      case 0x0f07:
++              /* sysret */
++              return 1;
++              break;
++      };
++
++      return 0;
++}
++
++static int
++gtp_notifier_call(struct notifier_block *self, unsigned long cmd,
++                 void *ptr)
++{
++      int             ret = NOTIFY_DONE;
++      unsigned long   flags;
++      struct die_args *args;
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      int             i;
++#endif
++      unsigned long   dr6;
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      unsigned long   *dr6_p;
++#endif
++
++      if (cmd != DIE_DEBUG)
++              return ret;
++
++      local_irq_save(flags);
++      args = ptr;
++
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      /* Get from X86 hw_breakpoint_handler.  */
++      dr6_p = (unsigned long *)ERR_PTR(args->err);
++      dr6 = *dr6_p;
++#else
++      dr6 = args->err;
++#endif
++      gtp_set_debugreg(GTP_HWB_DR7_DEF, 7);
++
++      /* Handle while-stepping.  */
++      spin_lock(&__get_cpu_var(gtp_step).lock);
++      if ((dr6 & 0x4000) != 0) {
++              /* Clear the bit that handle by KGTP.  */
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++              (*dr6_p) &= ~(0x4000);
++#else
++              dr6 &= ~(0x4000);
++#endif
++              if (!__get_cpu_var(gtp_step).tpe || user_mode(args->regs))
++                      gtp_step_stop(args->regs);
++              else {
++                      int need_stop = gtp_step_check_insn(args->regs);
++                      if (need_stop < 0)
++                              printk(KERN_WARNING "KGTP: check insn in %p got 
error.",
++                                     (void *)GTP_REGS_PC(args->regs));
++
++                      preempt_disable();
++                      {
++                              struct gtp_trace_s      gts;
++
++                              memset(&gts, 0, sizeof(struct gtp_trace_s));
++                              gts.tpe = __get_cpu_var(gtp_step).tpe;
++                              gts.regs = args->regs;
++                              gts.step = __get_cpu_var(gtp_step).step;
++                              gtp_handler(&gts);
++                      }
++                      preempt_enable_no_resched();
++
++                      if (__get_cpu_var(gtp_step).step > 1 && !need_stop) {
++                              /* 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.  */
++                              gtp_step_stop(args->regs);
++                      }
++              }
++      }
++      spin_unlock(&__get_cpu_var(gtp_step).lock);
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      /* Handle watch traceppoint.  */
++      if ((dr6 & 0xf) == 0)
++              goto out;
++      read_lock(&gtp_hwb_lock);
++
++      for (i = 0; i < HWB_NUM; i++) {
++              if ((dr6 & (0x1 << i)) == 0)
++                      continue;
++              /* Clear the bit that handle by KGTP.  */
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++              (*dr6_p) &= ~(0x1 << i);
++#else
++              dr6 &= ~(0x1 << i);
++#endif
++              if (gtp_hwb[i].watch == NULL)
++                      continue;
++              /* Check if gtp_hwb is updated in other CPU.  */
++              if (__get_cpu_var(gtp_hwb_sync_count_local) != 
gtp_hwb_sync_count) {
++                      unsigned long   addr;
++
++                      gtp_get_debugreg(addr, i);
++                      if (addr != gtp_hwb[i].addr)
++                              continue;
++              }
++              preempt_disable();
++              {
++                      struct gtp_trace_s      gts;
++
++                      memset(&gts, 0, sizeof(struct gtp_trace_s));
++                      gts.tpe = gtp_hwb[i].watch;
++                      gts.regs = args->regs;
++                      gts.hwb = &gtp_hwb[i];
++                      gtp_handler(&gts);
++              }
++              preempt_enable_no_resched();
++      }
++
++      /* If the HWB need update in this CPU, just update it.  */
++      if (__get_cpu_var(gtp_hwb_sync_count_local) != gtp_hwb_sync_count) {
++              gtp_set_debugreg(gtp_hwb_drx[0], 0);
++              gtp_set_debugreg(gtp_hwb_drx[1], 1);
++              gtp_set_debugreg(gtp_hwb_drx[2], 2);
++              gtp_set_debugreg(gtp_hwb_drx[3], 3);
++              __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
++      }
++
++      gtp_set_debugreg(gtp_hwb_dr7, 7);
++      read_unlock(&gtp_hwb_lock);
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++out:
++#endif
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
++      gtp_set_debugreg(dr6, 6);
++#endif
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
++      /* If have some other traps, let other handler handle it.  */
++      if (((*dr6_p) & GTP_HWB_DR6_MASK) == 0)
++              ret = NOTIFY_STOP;
++      current->thread.debugreg6 = *dr6_p;
++#else
++      if ((dr6 & GTP_HWB_DR6_MASK) == 0)
++              ret = NOTIFY_STOP;
++      current->thread.debugreg6 = dr6;
++#endif
++
++      local_irq_restore(flags);
++      return ret;
++}
++
++static struct notifier_block gtp_notifier = {
++      .notifier_call = gtp_notifier_call,
++      .priority = 0x7ffffffe /* we need to be notified after kprobe.  */
++};
++#endif
 +
 +#ifdef CONFIG_X86
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0))
@@ -9222,102 +9608,8 @@
 +      gtp_hw_breakpoint_handler(breakinfo[3].num, regs);
 +}
 +#endif
-+#else
-+static int
-+gtp_notifier_call(struct notifier_block *self, unsigned long cmd,
-+                 void *ptr)
-+{
-+      int             ret = NOTIFY_DONE;
-+      unsigned long   flags;
-+      struct die_args *args;
-+      int             i;
-+      unsigned long   dr6;
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      unsigned long   *dr6_p;
 +#endif
 +
-+      if (cmd != DIE_DEBUG)
-+              return ret;
-+
-+      local_irq_save(flags);
-+      args = ptr;
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      /* Get from X86 hw_breakpoint_handler.  */
-+      dr6_p = (unsigned long *)ERR_PTR(args->err);
-+      dr6 = *dr6_p;
-+#else
-+      dr6 = args->err;
-+#endif
-+      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)
-+                      continue;
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+              /* Because KGTP handle all the hw-breakpoints.
-+                 So Just clear it.  */
-+              (*dr6_p) &= ~(0x1 << i);
-+#endif
-+              if (gtp_hwb[i].watch == NULL)
-+                      continue;
-+              /* Check if gtp_hwb is updated in other CPU.  */
-+              if (__get_cpu_var(gtp_hwb_sync_count_local) != 
gtp_hwb_sync_count) {
-+                      unsigned long   addr;
-+
-+                      gtp_get_debugreg(addr, i);
-+                      if (addr != gtp_hwb[i].addr)
-+                              continue;
-+              }
-+              preempt_disable();
-+              {
-+                      struct gtp_trace_s      gts;
-+
-+                      memset(&gts, 0, sizeof(struct gtp_trace_s));
-+                      gts.tpe = gtp_hwb[i].watch;
-+                      gts.regs = args->regs;
-+                      gts.hwb = &gtp_hwb[i];
-+                      gtp_handler(&gts);
-+              }
-+              preempt_enable_no_resched();
-+      }
-+
-+      /* If the HWB need update in this CPU, just update it.  */
-+      if (__get_cpu_var(gtp_hwb_sync_count_local) != gtp_hwb_sync_count) {
-+              set_debugreg(gtp_hwb_drx[0], 0);
-+              set_debugreg(gtp_hwb_drx[1], 1);
-+              set_debugreg(gtp_hwb_drx[2], 2);
-+              set_debugreg(gtp_hwb_drx[3], 3);
-+              __get_cpu_var(gtp_hwb_sync_count_local) = gtp_hwb_sync_count;
-+      }
-+
-+      set_debugreg(gtp_hwb_dr7, 7);
-+      read_unlock(&gtp_hwb_lock);
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-+      /* If have some other traps, let other handler handle it.  */
-+      if ((dr6 & (~0xf)) == 0)
-+              ret = NOTIFY_STOP;
-+#else
-+      set_debugreg(0UL, 6);
-+      ret = NOTIFY_STOP;
-+#endif
-+
-+out:
-+      local_irq_restore(flags);
-+      return ret;
-+}
-+
-+static struct notifier_block gtp_notifier = {
-+      .notifier_call = gtp_notifier_call,
-+      .priority = 0x7fffffff /* we need to be notified first */
-+};
-+#endif
-+
 +static unsigned int
 +gtp_hwb_size_to_arch(int size)
 +{
@@ -9396,7 +9688,7 @@
 +
 +              /* Set gtp_hwb_dr7 and gtp_hwb_drx[num] to hwb.  */
 +              gtp_set_debugreg(gtp_hwb_drx[num], num);
-+              set_debugreg(gtp_hwb_dr7, 7);
++              gtp_set_debugreg(gtp_hwb_dr7, 7);
 +
 +              gtp_hwb_sync_count++;
 +              hwb->count = gtp_hwb_sync_count;
@@ -9453,7 +9745,7 @@
 +                      gtp_hwb_sync_count++;
 +
 +                      /* Sync gtp_hwb_dr7 update to hwb.  */
-+                      set_debugreg(gtp_hwb_dr7, 7);
++                      gtp_set_debugreg(gtp_hwb_dr7, 7);
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
 +                      /* Send ipi to let other cpu update.  */
@@ -9516,54 +9808,74 @@
 +              tasklet_kill(&tpe->disable_tasklet);
 +              tasklet_kill(&tpe->enable_tasklet);
 +#endif
++      }
++
++#ifdef CONFIG_X86
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
++      if (gtp_have_step || gtp_have_watch_tracepoint)
++#else
++      if (gtp_have_step)
++#endif
++              unregister_die_notifier(&gtp_notifier);
++
++      {
++              /* Init data of while-stepping.  */
++              int     cpu;
++              for_each_online_cpu(cpu) {
++                      struct gtp_step_s       *step = &per_cpu(gtp_step, cpu);
++
++                      spin_lock(&step->lock);
++                      step->step = 0;
++                      step->tpe = NULL;
++                      spin_unlock(&step->lock);
++              }
 +      }
++#endif
 +
 +#ifdef CONFIG_X86
 +      /* Stop hwb.  */
++      if (gtp_have_watch_tracepoint) {
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0))
-+      {
-+              int     i;
++              {
++                      int     i;
 +
-+              /* Register hw breakpoints.  */
-+              for (i = 0; i < HWB_NUM; i++) {
-+                      unregister_wide_hw_breakpoint(breakinfo[i].pev);
-+                      breakinfo[i].pev = NULL;
++                      /* Register hw breakpoints.  */
++                      for (i = 0; i < HWB_NUM; i++) {
++                              unregister_wide_hw_breakpoint(breakinfo[i].pev);
++                              breakinfo[i].pev = NULL;
++                      }
 +              }
-+      }
 +#endif
 +
-+      gtp_hwb_stop(NULL);
++              gtp_hwb_stop(NULL);
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
-+      smp_call_function(gtp_hwb_stop, NULL, 1);
++              smp_call_function(gtp_hwb_stop, NULL, 1);
 +#else
-+      smp_call_function(gtp_hwb_stop, NULL, 0, 1);
++              smp_call_function(gtp_hwb_stop, NULL, 0, 1);
 +#endif
 +
-+      for (tpe = gtp_list; tpe; tpe = tpe->next) {
-+              if (tpe->type == gtp_entry_kprobe
-+                  || (tpe->flags & GTP_ENTRY_FLAGS_REG) == 0
-+                  || tpe->disable)
-+                      continue;
++              for (tpe = gtp_list; tpe; tpe = tpe->next) {
++                      if (tpe->type == gtp_entry_kprobe
++                          || (tpe->flags & GTP_ENTRY_FLAGS_REG) == 0
++                          || tpe->disable)
++                              continue;
 +
-+              if (tpe->type == gtp_entry_watch_static)
-+                      gtp_unregister_hwb(tpe->addr, 0);
++                      if (tpe->type == gtp_entry_watch_static)
++                              gtp_unregister_hwb(tpe->addr, 0);
 +
-+              tpe->flags &= ~GTP_ENTRY_FLAGS_REG;
++                      tpe->flags &= ~GTP_ENTRY_FLAGS_REG;
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
-+              tasklet_kill(&tpe->disable_tasklet);
-+              tasklet_kill(&tpe->enable_tasklet);
++                      tasklet_kill(&tpe->disable_tasklet);
++                      tasklet_kill(&tpe->enable_tasklet);
 +#endif
-+      }
++              }
 +
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
-+      unregister_kprobe(&gtp_ipi_kp);
++              unregister_kprobe(&gtp_ipi_kp);
 +#endif
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
-+      unregister_die_notifier(&gtp_notifier);
++      }
 +#endif
-+#endif
 +
 +#ifdef GTP_PERF_EVENTS
 +      list_for_each(cur, &gtp_var_list) {
@@ -9635,6 +9947,10 @@
 +              gtp_frame_reset();
 +
 +      gtpro_list_clear();
++#ifdef CONFIG_X86
++      gtp_have_watch_tracepoint = 0;
++      gtp_have_step = 0;
++#endif
 +
 +      gtp_var_release(0);
 +
@@ -9749,12 +10065,13 @@
 +}
 +
 +static int
-+gtp_add_backtrace_actions(struct gtp_entry *tpe)
++gtp_add_backtrace_actions(struct gtp_entry *tpe, int step)
 +{
 +      struct action   *ae, *new_ae;
 +      int             got_r = 0, got_m = 0;
 +
-+      for (ae = tpe->action_list; ae; ae = ae->next) {
++      for (ae = step ? tpe->step_action_list : tpe->action_list;
++           ae; ae = ae->next) {
 +              if (ae->type == 'R')
 +                      got_r = 1;
 +              else if (ae->type == 'M' && ae->u.m.regnum == GTP_SP_NUM
@@ -9762,7 +10079,9 @@
 +                      got_m = 1;
 +
 +              if (got_r && got_m)
-+                      break;
++                      return 1;
++
++              /* Let ae point to the last entry of action_list.  */
 +              if (!ae->next)
 +                      break;
 +      }
@@ -9773,8 +10092,14 @@
 +                      return -ENOMEM;
 +              if (ae)
 +                      ae->next = new_ae;
-+              else
-+                      tpe->action_list = ae;
++              else {
++                      if (step)
++                              tpe->step_action_list = ae;
++                      else
++                              tpe->action_list = ae;
++              }
++
++              /* Because new_ae is the new tail.  So set it to ae. */
 +              ae = new_ae;
 +      }
 +
@@ -9786,15 +10111,19 @@
 +              new_ae->u.m.size = gtp_bt_size;
 +              if (ae)
 +                      ae->next = new_ae;
-+              else
-+                      tpe->action_list = ae;
++              else {
++                      if (step)
++                              tpe->step_action_list = ae;
++                      else
++                              tpe->action_list = ae;
++              }
 +      }
 +
 +      return 1;
 +}
 +
 +static int
-+gtp_check_getv(struct gtp_entry *tpe, struct action *ae,
++gtp_check_getv(struct gtp_entry *tpe, struct action *ae, int step,
 +             uint8_t *ebuf, unsigned int pc,
 +             struct gtp_x_var **list)
 +{
@@ -9816,12 +10145,12 @@
 +
 +      switch (var->type) {
 +      case gtp_var_special:
-+              if (arg == GTP_VAR_NO_SELF_TRACE_ID) {
-+                      tpe->flags |= GTP_ENTRY_FLAGS_NO_SELF_TRACE;
++              if (arg == GTP_VAR_SELF_TRACE_ID) {
++                      tpe->flags |= GTP_ENTRY_FLAGS_SELF_TRACE;
 +                      ret = 1;
 +                      goto out;
 +              } else if (arg == GTP_VAR_BT_ID) {
-+                      ret = gtp_add_backtrace_actions (tpe);
++                      ret = gtp_add_backtrace_actions (tpe, step);
 +                      goto out;
 +              } else if (arg == GTP_VAR_CURRENT_ID) {
 +                      tpe->flags |= GTP_ENTRY_FLAGS_CURRENT_TASK;
@@ -9890,7 +10219,7 @@
 +}
 +
 +static int
-+gtp_check_setv(struct gtp_entry *tpe, struct action *ae,
++gtp_check_setv(struct gtp_entry *tpe, struct action *ae, int step,
 +             uint8_t *ebuf, unsigned int pc,
 +             struct gtp_x_var **list, int loop,
 +             ULONGEST *stack, ULONGEST top)
@@ -9914,8 +10243,8 @@
 +      switch (var->type) {
 +      case gtp_var_special:
 +              switch (arg) {
-+              case GTP_VAR_NO_SELF_TRACE_ID:
-+                      tpe->flags |= GTP_ENTRY_FLAGS_NO_SELF_TRACE;
++              case GTP_VAR_SELF_TRACE_ID:
++                      tpe->flags |= GTP_ENTRY_FLAGS_SELF_TRACE;
 +                      ret = 1;
 +                      goto out;
 +                      break;
@@ -9926,7 +10255,7 @@
 +                      goto out;
 +                      break;
 +              case GTP_VAR_BT_ID:
-+                      ret = gtp_add_backtrace_actions (tpe);
++                      ret = gtp_add_backtrace_actions (tpe, step);
 +                      goto out;
 +                      break;
 +              case GTP_VAR_CURRENT_ID:
@@ -9935,11 +10264,10 @@
 +                      goto out;
 +                      break;
 +              case GTP_VAR_PRINTK_LEVEL_ID:
-+                      if (loop) {
***The diff for this file has been truncated for email.***

Other related posts:

  • » [kgtp] r1548 committed - Fix build issue with old Linux kernel. Update patches. - kgtp