static inline unsigned long get_debugctlmsr(void)
 {
-    unsigned long debugctlmsr = 0;
+       unsigned long debugctlmsr = 0;
 
 #ifndef CONFIG_X86_DEBUGCTLMSR
        if (boot_cpu_data.x86 < 6)
 #endif
        rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr);
 
-    return debugctlmsr;
+       return debugctlmsr;
 }
 
 static inline void update_debugctlmsr(unsigned long debugctlmsr)
 
 #define TIF_IO_BITMAP          22      /* uses I/O bitmap */
 #define TIF_FREEZE             23      /* is freezing for suspend */
 #define TIF_FORCED_TF          24      /* true if TF in eflags artificially */
+#define TIF_BLOCKSTEP          25      /* set when we want DEBUGCTLMSR_BTF */
 #define TIF_LAZY_MMU_UPDATES   27      /* task is updating the mmu lazily */
 #define TIF_SYSCALL_TRACEPOINT 28      /* syscall tracepoint instrumentation */
 
 #define _TIF_IO_BITMAP         (1 << TIF_IO_BITMAP)
 #define _TIF_FREEZE            (1 << TIF_FREEZE)
 #define _TIF_FORCED_TF         (1 << TIF_FORCED_TF)
+#define _TIF_BLOCKSTEP         (1 << TIF_BLOCKSTEP)
 #define _TIF_LAZY_MMU_UPDATES  (1 << TIF_LAZY_MMU_UPDATES)
 #define _TIF_SYSCALL_TRACEPOINT        (1 << TIF_SYSCALL_TRACEPOINT)
 
 
 /* flags to check in __switch_to() */
 #define _TIF_WORK_CTXSW                                                        \
-       (_TIF_IO_BITMAP|_TIF_NOTSC)
+       (_TIF_IO_BITMAP|_TIF_NOTSC|_TIF_BLOCKSTEP)
 
 #define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY)
 #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW|_TIF_DEBUG)
 
 
 static void __kprobes clear_btf(void)
 {
-       /* XXX */
+       if (test_thread_flag(TIF_BLOCKSTEP)) {
+               unsigned long debugctl = get_debugctlmsr();
+
+               debugctl &= ~DEBUGCTLMSR_BTF;
+               update_debugctlmsr(debugctl);
+       }
 }
 
 static void __kprobes restore_btf(void)
 {
-       /* XXX */
+       if (test_thread_flag(TIF_BLOCKSTEP)) {
+               unsigned long debugctl = get_debugctlmsr();
+
+               debugctl |= DEBUGCTLMSR_BTF;
+               update_debugctlmsr(debugctl);
+       }
 }
 
 void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 
        prev = &prev_p->thread;
        next = &next_p->thread;
 
+       if (test_tsk_thread_flag(prev_p, TIF_BLOCKSTEP) ^
+           test_tsk_thread_flag(next_p, TIF_BLOCKSTEP)) {
+               unsigned long debugctl = get_debugctlmsr();
+
+               debugctl &= ~DEBUGCTLMSR_BTF;
+               if (test_tsk_thread_flag(next_p, TIF_BLOCKSTEP))
+                       debugctl |= DEBUGCTLMSR_BTF;
+
+               update_debugctlmsr(debugctl);
+       }
+
        if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
            test_tsk_thread_flag(next_p, TIF_NOTSC)) {
                /* prev and next are different */
 
         * So noone should try to use debugger block stepping in a program
         * that uses user-mode single stepping itself.
         */
-       if (!enable_single_step(child))
-               return;
-       /* XXX */
+       if (enable_single_step(child) && block) {
+               unsigned long debugctl = get_debugctlmsr();
+
+               debugctl |= DEBUGCTLMSR_BTF;
+               update_debugctlmsr(debugctl);
+               set_tsk_thread_flag(child, TIF_BLOCKSTEP);
+       } else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) {
+               unsigned long debugctl = get_debugctlmsr();
+
+               debugctl &= ~DEBUGCTLMSR_BTF;
+               update_debugctlmsr(debugctl);
+               clear_tsk_thread_flag(child, TIF_BLOCKSTEP);
+       }
 }
 
 void user_enable_single_step(struct task_struct *child)
        /*
         * Make sure block stepping (BTF) is disabled.
         */
-       /* XXX */
+       if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) {
+               unsigned long debugctl = get_debugctlmsr();
+
+               debugctl &= ~DEBUGCTLMSR_BTF;
+               update_debugctlmsr(debugctl);
+               clear_tsk_thread_flag(child, TIF_BLOCKSTEP);
+       }
 
        /* Always clear TIF_SINGLESTEP... */
        clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 
        /* DR6 may or may not be cleared by the CPU */
        set_debugreg(0, 6);
 
+       /*
+        * The processor cleared BTF, so don't mark that we need it set.
+        */
+       clear_tsk_thread_flag(tsk, TIF_BLOCKSTEP);
+
        /* Store the virtualized DR6 value */
        tsk->thread.debugreg6 = dr6;