Skip to contentSkip to conversation

PATCH Kernel watchpoint interface-2.6.9-rc4-mm1

PATCH In review Prasanna S Panchamukhi 3 participants 7 messages Oct 18, 2004 – Oct 22, 2004 ptrace support

lore
Share & tools
lore
#0 lore raw

cover PATCH Kernel watchpoint interface-2.6.9-rc4-mm1

Hi,

Often kernel developer try to moniter global variables.
These patches provide a simple interface for monitering global variables. Please see the comments in the watchpoint patch for details. These patches can be applied over 2.6.9-rc4-mm1.

Please provide your comments.

Thanks
Prasanna

Signature · 5 lines
Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-25044636
<[email protected]>
#1 lore raw

This patch provides global debug register settings. Used by kernel watchpoint interface patch.
---

---

 linux-2.6.9-rc4-prasanna/arch/i386/Kconfig.debug     |    7 
 linux-2.6.9-rc4-prasanna/arch/i386/kernel/Makefile   |    1 
 linux-2.6.9-rc4-prasanna/arch/i386/kernel/debugreg.c |  178 +++++++++++++++++++
 linux-2.6.9-rc4-prasanna/arch/i386/kernel/process.c  |   28 ++
 linux-2.6.9-rc4-prasanna/arch/i386/kernel/ptrace.c   |    5 
 linux-2.6.9-rc4-prasanna/arch/i386/kernel/signal.c   |    3 
 linux-2.6.9-rc4-prasanna/arch/i386/kernel/traps.c    |    4 
 linux-2.6.9-rc4-prasanna/include/asm-i386/debugreg.h |  162 +++++++++++++++++
 8 files changed, 383 insertions(+), 5 deletions(-)
arch/i386/Kconfig.debug renamed from arch/i386/Kconfig.debug~kprobes-debug-regs-2.6.9-rc4-mm1 +7 -0
diff -puN arch/i386/Kconfig.debug~kprobes-debug-regs-2.6.9-rc4-mm1 arch/i386/Kconfig.debug
@@ -29,6 +29,13 @@ config KPROBES
 	  for kernel debugging, non-intrusive instrumentation and testing.
 	  If in doubt, say "N".
 
+config DEBUGREG
+	bool "Global Debug Registers"
+	depends on DEBUG_KERNEL
+	help
+	  Global debug register settings will be honoured if this is turned on.
+	  If in doubt, say "N".
+
 config DEBUG_STACK_USAGE
 	bool "Stack utilization instrumentation"
 	depends on DEBUG_KERNEL
arch/i386/kernel/debugreg.c new file +178 -0

178 lines not on this page · raw message

arch/i386/kernel/Makefile renamed from arch/i386/kernel/Makefile~kprobes-debug-regs-2.6.9-rc4-mm1 +1 -0
diff -puN arch/i386/kernel/Makefile~kprobes-debug-regs-2.6.9-rc4-mm1 arch/i386/kernel/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_ACPI_SRAT) 	+= srat.o
 obj-$(CONFIG_HPET_TIMER) 	+= time_hpet.o
 obj-$(CONFIG_EFI) 		+= efi.o efi_stub.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
+obj-$(CONFIG_DEBUGREG)		+= debugreg.o
 
 EXTRA_AFLAGS   := -traditional
 
arch/i386/kernel/process.c renamed from arch/i386/kernel/process.c~kprobes-debug-regs-2.6.9-rc4-mm1 +27 -1
diff -puN arch/i386/kernel/process.c~kprobes-debug-regs-2.6.9-rc4-mm1 arch/i386/kernel/process.c
@@ -50,6 +50,7 @@
 #ifdef CONFIG_MATH_EMULATION
 #include <asm/math_emu.h>
 #endif
+#include <asm/debugreg.h>
 
 #include <linux/irq.h>
 #include <linux/err.h>
@@ -317,6 +318,8 @@ void exit_thread(void)
 		tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
 		put_cpu();
 	}
+	if (tsk->thread.debugreg[7])
+		dr_dec_use_count(tsk->thread.debugreg[7]);
 	perfctr_exit_thread(&tsk->thread);
 }
 
@@ -324,6 +327,8 @@ void flush_thread(void)
 {
 	struct task_struct *tsk = current;
 
+	if (tsk->thread.debugreg[7])
+		dr_dec_use_count(tsk->thread.debugreg[7]);
 	memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
 	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));	
 	/*
@@ -416,6 +421,9 @@ int copy_thread(int nr, unsigned long cl
 		desc->b = LDT_entry_b(&info);
 	}
 
+	if (tsk->thread.debugreg[7])
+		dr_inc_use_count(tsk->thread.debugreg[7]);
+
 	err = 0;
  out:
 	if (err && p->thread.io_bitmap_ptr) {
@@ -593,6 +601,24 @@ struct task_struct fastcall * __switch_t
 	/*
 	 * Now maybe reload the debug registers
 	 */
+#ifdef CONFIG_DEBUGREG
+{
+	/*
+	 * Don't reload global debug registers. Don't touch the global debug
+	 * register settings in dr7.
+	 */
+	unsigned long next_dr7 = next->debugreg[7];
+	if (unlikely(next_dr7)) {
+		if (DR7_L0(next_dr7)) loaddebug(next, 0);
+		if (DR7_L1(next_dr7)) loaddebug(next, 1);
+		if (DR7_L2(next_dr7)) loaddebug(next, 2);
+		if (DR7_L3(next_dr7)) loaddebug(next, 3);
+		/* no 4 and 5 */
+		loaddebug(next, 6);
+		load_process_dr7(next_dr7);
+	}
+}
+#else
 	if (unlikely(next->debugreg[7])) {
 		loaddebug(next, 0);
 		loaddebug(next, 1);
@@ -602,7 +628,7 @@ struct task_struct fastcall * __switch_t
 		loaddebug(next, 6);
 		loaddebug(next, 7);
 	}
-
+#endif
 	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr))
 		handle_io_bitmap(next, tss);
 
arch/i386/kernel/ptrace.c renamed from arch/i386/kernel/ptrace.c~kprobes-debug-regs-2.6.9-rc4-mm1 +5 -0
diff -puN arch/i386/kernel/ptrace.c~kprobes-debug-regs-2.6.9-rc4-mm1 arch/i386/kernel/ptrace.c
@@ -353,6 +353,11 @@ asmlinkage int sys_ptrace(long request, 
 
 			  addr -= (long) &dummy->u_debugreg;
 			  addr = addr >> 2;
+
+			  if (addr == 7 && (enable_debugreg(child->thread.debugreg[addr], data)) < 0) {
+				  ret = -EBUSY;
+				  break;
+			  }
 			  child->thread.debugreg[addr] = data;
 			  ret = 0;
 		  }
arch/i386/kernel/signal.c renamed from arch/i386/kernel/signal.c~kprobes-debug-regs-2.6.9-rc4-mm1 +2 -1
diff -puN arch/i386/kernel/signal.c~kprobes-debug-regs-2.6.9-rc4-mm1 arch/i386/kernel/signal.c
@@ -25,6 +25,7 @@
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/i387.h>
+#include <asm/debugreg.h>
 #include "sigframe.h"
 
 #define DEBUG_SIG 0
@@ -600,7 +601,7 @@ int fastcall do_signal(struct pt_regs *r
 		 * have been cleared if the watchpoint triggered
 		 * inside the kernel.
 		 */
-		__asm__("movl %0,%%db7"	: : "r" (current->thread.debugreg[7]));
+		load_process_dr7(current->thread.debugreg[7]);
 
 		/* Whee!  Actually deliver the signal.  */
 		handle_signal(signr, &info, &ka, oldset, regs);
arch/i386/kernel/traps.c renamed from arch/i386/kernel/traps.c~kprobes-debug-regs-2.6.9-rc4-mm1 +1 -3
diff -puN arch/i386/kernel/traps.c~kprobes-debug-regs-2.6.9-rc4-mm1 arch/i386/kernel/traps.c
@@ -812,9 +812,7 @@ asmlinkage void do_debug(struct pt_regs 
 	 * the signal is delivered.
 	 */
 clear_dr7:
-	__asm__("movl %0,%%db7"
-		: /* no output */
-		: "r" (0));
+	load_process_dr7(0);
 	CHK_REMOTE_DEBUG(1,SIGTRAP,error_code,regs,)
 	return;
 
include/asm-i386/debugreg.h renamed from include/asm-i386/debugreg.h~kprobes-debug-regs-2.6.9-rc4-mm1 +162 -0

166 lines not on this page · raw message

_
Thanks
Prasanna

Signature · 5 lines
Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-25044636
<[email protected]>
#2 lore raw

This patch provides a simple interface for kernel-space watchpoints
using processor's debug registers. Using Kwatch interface users can moniter kernel global variables and dump the debugging information such as kernel stack, global variables, processor registers.

int register_kwatch(unsigned long addr, u8 length, u8 type,
kwatch_handler_t handler)

-length of the breakpoint can be 1,2 or 4 bytes long. -type can be read, write, execute.
0 Break on instruction execution only.
1 Break on data writes only.
3 Break on data reads or writes but not instruction fetches.

-return value is the debug register number allocated/used for setting up this watch point.

Sample code:

	This sample code sets a watchpoint on the instruction
	excution at do_fork.

	struct kwatch kp;
	void kwatch_handler(struct kwatch *p, struct pt_regs *regs)
	{
		.......<do-any-thing>........
	}

       debug_regs_num = register_kwatch(do_fork, 1, 0, kwatch_handler);

---

---

 linux-2.6.9-rc4-prasanna/arch/i386/Kconfig.debug   |    7 
 linux-2.6.9-rc4-prasanna/arch/i386/kernel/Makefile |    1 
 linux-2.6.9-rc4-prasanna/arch/i386/kernel/kwatch.c |  171 +++++++++++++++++++++
 linux-2.6.9-rc4-prasanna/arch/i386/kernel/traps.c  |    1 
 linux-2.6.9-rc4-prasanna/include/asm-i386/kwatch.h |   31 +++
 5 files changed, 211 insertions(+)
arch/i386/Kconfig.debug renamed from arch/i386/Kconfig.debug~kprobes-kernel-watchpoint-2.6.9-rc4-mm1 +7 -0
diff -puN arch/i386/Kconfig.debug~kprobes-kernel-watchpoint-2.6.9-rc4-mm1 arch/i386/Kconfig.debug
@@ -36,6 +36,13 @@ config DEBUGREG
 	  Global debug register settings will be honoured if this is turned on.
 	  If in doubt, say "N".
 
+config KWATCH
+	bool "Kwatch points"
+	depends on DEBUG_KERNEL && DEBUGREG
+	help
+	  This enables kernel-space watchpoints using processor's debug
+	  registers. If in doubt, say "N".
+
 config DEBUG_STACK_USAGE
 	bool "Stack utilization instrumentation"
 	depends on DEBUG_KERNEL
arch/i386/kernel/kwatch.c new file +171 -0

171 lines not on this page · raw message

arch/i386/kernel/Makefile renamed from arch/i386/kernel/Makefile~kprobes-kernel-watchpoint-2.6.9-rc4-mm1 +1 -0
diff -puN arch/i386/kernel/Makefile~kprobes-kernel-watchpoint-2.6.9-rc4-mm1 arch/i386/kernel/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_HPET_TIMER) 	+= time_hpet.o
 obj-$(CONFIG_EFI) 		+= efi.o efi_stub.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_DEBUGREG)		+= debugreg.o
+obj-$(CONFIG_KWATCH)		+= kwatch.o
 
 EXTRA_AFLAGS   := -traditional
 
arch/i386/kernel/traps.c renamed from arch/i386/kernel/traps.c~kprobes-kernel-watchpoint-2.6.9-rc4-mm1 +1 -0
diff -puN arch/i386/kernel/traps.c~kprobes-kernel-watchpoint-2.6.9-rc4-mm1 arch/i386/kernel/traps.c
@@ -43,6 +43,7 @@
 #include <asm/io.h>
 #include <asm/atomic.h>
 #include <asm/debugreg.h>
+#include <asm/kwatch.h>
 #include <asm/desc.h>
 #include <asm/i387.h>
 #include <asm/nmi.h>
include/asm-i386/kwatch.h new file +31 -0
diff -puN /dev/null include/asm-i386/kwatch.h
@@ -0,0 +1,31 @@
+#ifndef _ASM_KWATCH_H
+#define _ASM_KWATCH_H
+/*
+ * Dynamic Probes (kwatch points) support
+ *  	Vamsi Krishna S <[email protected]>, Oct, 2002
+ */
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+struct kwatch;
+typedef void (*kwatch_handler_t)(struct kwatch *, struct pt_regs *);
+
+struct kwatch {
+	unsigned long addr;	/* location of watchpoint */
+	u8 length;	/* range of address */
+	u8 type;	/* type of watchpoint */
+	kwatch_handler_t handler;
+};
+
+#define RF_MASK	0x00010000
+
+#ifdef CONFIG_KWATCH
+extern int register_kwatch(unsigned long addr, u8 length, u8 type, kwatch_handler_t handler);
+extern void unregister_kwatch(int debugreg);
+extern int kwatch_handler(unsigned long condition, struct pt_regs *regs);
+#else
+static inline int register_kwatch(unsigned long addr, u8 length, u8 type, kwatch_handler_t handler) { return -ENOSYS; }
+static inline void unregister_kwatch(int debugreg) { }
+static inline int kwatch_handler(unsigned long condition, struct pt_regs *regs) { return 0; }
+#endif
+#endif /* _ASM_KWATCH_H */

_
Thanks
Prasanna

Signature · 5 lines
Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-25044636
<[email protected]>
#3 lore raw

Hi All,

Please find the updated kernel watchpoint patch below. This patch can be applied over 2.6.9-final and helpful to setting hardware breakpoints.

Thanks
Prasanna

This patch provides a simple interface for kernel-space watchpoints
using processor's debug registers. Using Kwatch interface users can monitor kernel global variables and dump the debugging information such as kernel stack, global variables, processor registers.

int register_kwatch(unsigned long addr, u8 length, u8 type,
kwatch_handler_t handler)

-length of the breakpoint can be 1,2 or 4 bytes long. -type can be read, write, execute.
0 Break on instruction execution only.
1 Break on data writes only.
3 Break on data reads or writes but not instruction fetches.

-return value is the debug register number allocated/used for setting up this watch point.

Sample code:

	This sample code sets a watchpoint on the instruction
	excution at do_fork.

	struct kwatch kp;
	void kwatch_handler(struct kwatch *p, struct pt_regs *regs)
	{
		.......<do-any-thing>........
	}

       debug_regs_num = register_kwatch(do_fork, 1, 0, kwatch_handler);

---

---

 linux-2.6.9-final-prasanna/arch/i386/Kconfig.debug   |    8 
 linux-2.6.9-final-prasanna/arch/i386/kernel/Makefile |    1 
 linux-2.6.9-final-prasanna/arch/i386/kernel/kwatch.c |  190 +++++++++++++++++++
 linux-2.6.9-final-prasanna/include/asm-i386/kwatch.h |   50 +++++
 4 files changed, 249 insertions(+)
arch/i386/Kconfig.debug renamed from arch/i386/Kconfig.debug~kprobes-kernel-watchpoint-2.6.9-final +8 -0
diff -puN arch/i386/Kconfig.debug~kprobes-kernel-watchpoint-2.6.9-final arch/i386/Kconfig.debug
@@ -29,6 +29,14 @@ config KPROBES
 	  for kernel debugging, non-intrusive instrumentation and testing.
 	  If in doubt, say "N".
 
+config KWATCH
+	bool "Kwatch points"
+	depends on DEBUG_KERNEL
+	select DEBUGREG
+	help
+	  This enables kernel-space watchpoints using processor's debug
+	  registers. If in doubt, say "N".
+
 config DEBUGREG
 	bool "Global Debug Registers"
 	depends on DEBUG_KERNEL
arch/i386/kernel/kwatch.c new file +190 -0

190 lines not on this page · raw message

arch/i386/kernel/Makefile renamed from arch/i386/kernel/Makefile~kprobes-kernel-watchpoint-2.6.9-final +1 -0
diff -puN arch/i386/kernel/Makefile~kprobes-kernel-watchpoint-2.6.9-final arch/i386/kernel/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_HPET_TIMER) 	+= time_hpet.o
 obj-$(CONFIG_EFI) 		+= efi.o efi_stub.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_DEBUGREG)		+= debugreg.o
+obj-$(CONFIG_KWATCH)		+= kwatch.o
 
 EXTRA_AFLAGS   := -traditional
 
include/asm-i386/kwatch.h new file +50 -0

50 lines not on this page · raw message

_

Signature · 5 lines
Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-25044636
<[email protected]>
#4 lore raw
In reply to Prasanna S Panchamukhi

arch/i386/Kconfig.debug config KPROBES · line 38

Quoted 10 lines · Prasanna S Panchamukhi

This patch provides global debug register settings. Used by kernel watchpoint interface patch.

arch/i386/Kconfig.debug renamed from arch/i386/Kconfig.debug~kprobes-debug-regs-2.6.9-rc4-mm1 +7 -0
+config DEBUGREG
+	bool "Global Debug Registers"
+	depends on DEBUG_KERNEL
+	help
+	  Global debug register settings will be honoured if this is turned on.
+	  If in doubt, say "N".
+

I like most of the patch, but Kconfig is wrong. This option should not be exposed to end users, instead CONFIG_DEBUGREG should be selected by the debug code that calls debugreg. IOW, kgdb, kdb or kwatch select debugreg, not the other way around.

#5 lore raw
In reply to Prasanna S Panchamukhi

arch/i386/Kconfig.debug config KPROBES · line 33

Quoted 2 lines
arch/i386/Kconfig.debug renamed from arch/i386/Kconfig.debug~kprobes-debug-regs-2.6.9-rc4-mm1 +2 -0
+config DEBUGREG
+	bool "Global Debug Registers"

I agree with Keith that it shouldn't be user visible. I would always enable it in fact.

arch/i386/kernel/debugreg.c line 58

Quoted 3 lines
arch/i386/kernel/debugreg.c new file +3 -0
+{
+	int i;
+	if (flag == DR_ALLOC_LOCAL) {

[...] This all would be simpler if you used lib/idr.c, no?

arch/i386/kernel/debugreg.c line 116

Quoted 6 lines
arch/i386/kernel/debugreg.c new file +6 -0
+int dr_free(int regnum)
+{
+	spin_lock(&dr_lock);
+	if (regnum >= DR_MAX || dr_list[regnum].flag == DR_UNUSED) {
+		spin_unlock(&dr_lock);
+		return -1;

This should printk

arch/i386/kernel/process.c struct task_struct fastcall * __switch_t · line 615

Quoted 12 lines
arch/i386/kernel/process.c renamed from arch/i386/kernel/process.c~kprobes-debug-regs-2.6.9-rc4-mm1 +12 -0
+#ifdef CONFIG_DEBUGREG
+{
+	/*
+	 * Don't reload global debug registers. Don't touch the global debug
+	 * register settings in dr7.
+	 */
+	unsigned long next_dr7 = next->debugreg[7];
+	if (unlikely(next_dr7)) {
+		if (DR7_L0(next_dr7)) loaddebug(next, 0);
+		if (DR7_L1(next_dr7)) loaddebug(next, 1);
+		if (DR7_L2(next_dr7)) loaddebug(next, 2);
+		if (DR7_L3(next_dr7)) loaddebug(next, 3);

I would do this differently - check instead if the registers are different between the tasks and only reload when different. This will make updating/freeing more expensive because you will need to change all tasks, but imho it's worth it.

And then no ifdefs please.

arch/i386/kernel/traps.c asmlinkage void do_debug(struct pt_regs · line 816

Quoted 7 lines
arch/i386/kernel/traps.c renamed from arch/i386/kernel/traps.c~kprobes-debug-regs-2.6.9-rc4-mm1 +1 -3
 	 */
 clear_dr7:
-	__asm__("movl %0,%%db7"
-		: /* no output */
-		: "r" (0));
+	load_process_dr7(0);
 	CHK_REMOTE_DEBUG(1,SIGTRAP,error_code,regs,)

That's mm (and should go away anyways because debug notifiers are better) I would do the patch against mainline so that it can be actually merged.

-Andi

#6 lore raw

Hi,

I have updated the patch with Andi Kleen's and Keith Owens suggestions. This patch can be applied over 2.6.9-final.
Kindly review and provide your feedback.

Thanks
Prasanna

This patch provides debug register allocation mechanism. Useful for debuggers like IOW, kgdb, kdb, kernel watchpoint.
---

---

---

 linux-2.6.9-final-prasanna/arch/i386/Kconfig.debug     |    8 
 linux-2.6.9-final-prasanna/arch/i386/kernel/Makefile   |    1 
 linux-2.6.9-final-prasanna/arch/i386/kernel/debugreg.c |  288 +++++++++++++++++
 linux-2.6.9-final-prasanna/arch/i386/kernel/process.c  |   25 +
 linux-2.6.9-final-prasanna/arch/i386/kernel/ptrace.c   |    5 
 linux-2.6.9-final-prasanna/arch/i386/kernel/signal.c   |    3 
 linux-2.6.9-final-prasanna/arch/i386/kernel/traps.c    |    4 
 linux-2.6.9-final-prasanna/include/asm-i386/debugreg.h |  162 +++++++++
 8 files changed, 486 insertions(+), 10 deletions(-)
arch/i386/Kconfig.debug renamed from arch/i386/Kconfig.debug~kprobes-debug-regs-2.6.9-final +8 -0
diff -puN arch/i386/Kconfig.debug~kprobes-debug-regs-2.6.9-final arch/i386/Kconfig.debug
@@ -29,6 +29,14 @@ config KPROBES
 	  for kernel debugging, non-intrusive instrumentation and testing.
 	  If in doubt, say "N".
 
+config DEBUGREG
+	bool "Global Debug Registers"
+	depends on DEBUG_KERNEL
+	default off
+	help
+	  Global debug register settings need to be enabled by the
+	  debuggers using it.
+
 config DEBUG_STACK_USAGE
 	bool "Stack utilization instrumentation"
 	depends on DEBUG_KERNEL
arch/i386/kernel/debugreg.c new file +288 -0

288 lines not on this page · raw message

arch/i386/kernel/Makefile renamed from arch/i386/kernel/Makefile~kprobes-debug-regs-2.6.9-final +1 -0
diff -puN arch/i386/kernel/Makefile~kprobes-debug-regs-2.6.9-final arch/i386/kernel/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_ACPI_SRAT) 	+= srat.o
 obj-$(CONFIG_HPET_TIMER) 	+= time_hpet.o
 obj-$(CONFIG_EFI) 		+= efi.o efi_stub.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
+obj-$(CONFIG_DEBUGREG)		+= debugreg.o
 
 EXTRA_AFLAGS   := -traditional
 
arch/i386/kernel/process.c renamed from arch/i386/kernel/process.c~kprobes-debug-regs-2.6.9-final +19 -6
diff -puN arch/i386/kernel/process.c~kprobes-debug-regs-2.6.9-final arch/i386/kernel/process.c
@@ -49,6 +49,7 @@
 #ifdef CONFIG_MATH_EMULATION
 #include <asm/math_emu.h>
 #endif
+#include <asm/debugreg.h>
 
 #include <linux/irq.h>
 #include <linux/err.h>
@@ -316,12 +317,16 @@ void exit_thread(void)
 		tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
 		put_cpu();
 	}
+	if (tsk->thread.debugreg[7])
+		dr_dec_use_count(tsk->thread.debugreg[7]);
 }
 
 void flush_thread(void)
 {
 	struct task_struct *tsk = current;
 
+	if (tsk->thread.debugreg[7])
+		dr_dec_use_count(tsk->thread.debugreg[7]);
 	memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
 	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));	
 	/*
@@ -413,6 +418,9 @@ int copy_thread(int nr, unsigned long cl
 		desc->b = LDT_entry_b(&info);
 	}
 
+	if (tsk->thread.debugreg[7])
+		dr_inc_use_count(tsk->thread.debugreg[7]);
+
 	err = 0;
  out:
 	if (err && p->thread.io_bitmap_ptr) {
@@ -588,14 +596,19 @@ struct task_struct fastcall * __switch_t
 	/*
 	 * Now maybe reload the debug registers
 	 */
-	if (unlikely(next->debugreg[7])) {
-		loaddebug(next, 0);
-		loaddebug(next, 1);
-		loaddebug(next, 2);
-		loaddebug(next, 3);
+	/*
+	 * Don't reload global debug registers. Don't touch the global debug
+	 * register settings in dr7.
+	 */
+	unsigned long next_dr7 = next->debugreg[7];
+	if (unlikely(next_dr7)) {
+		if (prev->debugreg[0] != next->debugreg[0]) loaddebug(next, 0);
+		if (prev->debugreg[1] != next->debugreg[1]) loaddebug(next, 1);
+		if (prev->debugreg[2] != next->debugreg[2]) loaddebug(next, 2);
+		if (prev->debugreg[3] != next->debugreg[3]) loaddebug(next, 3);
 		/* no 4 and 5 */
 		loaddebug(next, 6);
-		loaddebug(next, 7);
+		load_process_dr7(next_dr7);
 	}
 
 	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr))
arch/i386/kernel/ptrace.c renamed from arch/i386/kernel/ptrace.c~kprobes-debug-regs-2.6.9-final +5 -0
diff -puN arch/i386/kernel/ptrace.c~kprobes-debug-regs-2.6.9-final arch/i386/kernel/ptrace.c
@@ -353,6 +353,11 @@ asmlinkage int sys_ptrace(long request, 
 
 			  addr -= (long) &dummy->u_debugreg;
 			  addr = addr >> 2;
+
+			  if (addr == 7 && (enable_debugreg(child->thread.debugreg[addr], data)) < 0) {
+				  ret = -EBUSY;
+				  break;
+			  }
 			  child->thread.debugreg[addr] = data;
 			  ret = 0;
 		  }
arch/i386/kernel/signal.c renamed from arch/i386/kernel/signal.c~kprobes-debug-regs-2.6.9-final +2 -1
diff -puN arch/i386/kernel/signal.c~kprobes-debug-regs-2.6.9-final arch/i386/kernel/signal.c
@@ -25,6 +25,7 @@
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/i387.h>
+#include <asm/debugreg.h>
 #include "sigframe.h"
 
 #define DEBUG_SIG 0
@@ -600,7 +601,7 @@ int fastcall do_signal(struct pt_regs *r
 		 * have been cleared if the watchpoint triggered
 		 * inside the kernel.
 		 */
-		__asm__("movl %0,%%db7"	: : "r" (current->thread.debugreg[7]));
+		load_process_dr7(current->thread.debugreg[7]);
 
 		/* Whee!  Actually deliver the signal.  */
 		handle_signal(signr, &info, &ka, oldset, regs);
arch/i386/kernel/traps.c renamed from arch/i386/kernel/traps.c~kprobes-debug-regs-2.6.9-final +1 -3
diff -puN arch/i386/kernel/traps.c~kprobes-debug-regs-2.6.9-final arch/i386/kernel/traps.c
@@ -760,9 +760,7 @@ asmlinkage void do_debug(struct pt_regs 
 	 * the signal is delivered.
 	 */
 clear_dr7:
-	__asm__("movl %0,%%db7"
-		: /* no output */
-		: "r" (0));
+	load_process_dr7(0);
 	return;
 
 debug_vm86:
include/asm-i386/debugreg.h renamed from include/asm-i386/debugreg.h~kprobes-debug-regs-2.6.9-final +162 -0

166 lines not on this page · raw message

_

Signature · 5 lines
Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-25044636
<[email protected]>