public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: David Daney <ddaney@avtrex.com>
To: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Subject: [Patch 6/6] Ptrace support for HARDWARE_WATCHPOINTS.
Date: Mon, 21 Apr 2008 17:40:11 -0700	[thread overview]
Message-ID: <480D33EB.30808@avtrex.com> (raw)
In-Reply-To: <480D2151.2020701@avtrex.com>

This is the final part of the patch.  Here we add ptrace support so that
gdb can read and set the watch register values.

We add two new ptrace requests PTRACE_GET_WATCH_REGS, and
PTRACE_SET_WATCH_REGS to access the watch registers.  Since MIPS has more
than one format for watch registers, the data structure is a union, the
first structure member is an enum that tells us which layout is in use.
For this first cut at the patch, I only support mips32 style registers.

Signed-off-by: David Daney <ddaney@avtrex.com>
---
 arch/mips/kernel/ptrace.c |   81 +++++++++++++++++++++++++++++++++++++++++++++
 include/asm-mips/ptrace.h |   23 +++++++++++++
 2 files changed, 104 insertions(+), 0 deletions(-)

diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 35234b9..d6dece8 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -46,7 +46,12 @@
  */
 void ptrace_disable(struct task_struct *child)
 {
+#ifdef CONFIG_HARDWARE_WATCHPOINTS
+	/* Don't load the watchpoint registers for the ex-child. */
+	clear_tsk_thread_flag(child, TIF_LOAD_WATCH);
+#else
 	/* Nothing to do.. */
+#endif
 }
 
 /*
@@ -167,6 +172,72 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
 	return 0;
 }
 
+#ifdef CONFIG_HARDWARE_WATCHPOINTS
+int ptrace_get_watch_regs(struct task_struct *child,
+			  struct pt_watch_regs __user *addr)
+{
+	int i;
+
+	if (!cpu_has_watch)
+		return -EIO;
+	if (!access_ok(VERIFY_WRITE, addr, sizeof(struct pt_watch_regs)))
+		return -EIO;
+
+	__put_user (pt_watch_style_mips32, &addr->style);
+	__put_user (current_cpu_data.watch_reg_count, &addr->mips32.num_valid);
+	__put_user (current_cpu_data.watch_reg_mask, &addr->mips32.reg_mask);
+	__put_user (current_cpu_data.watch_reg_irw, &addr->mips32.irw_mask);
+	for (i = 0; i < current_cpu_data.watch_reg_count; i++) {
+		__put_user (child->thread.watch.mips32.watchlo[i],
+			    &addr->mips32.watchlo[i]);
+		__put_user (child->thread.watch.mips32.watchhi[i] & 0xfff,
+			    &addr->mips32.watchhi[i]);
+	}
+
+	return 0;
+}
+
+int ptrace_set_watch_regs(struct task_struct *child,
+			  struct pt_watch_regs __user *addr)
+{
+	int i;
+	int watch_active = 0;
+	unsigned long lt[NUM_WATCH_REGS];
+	unsigned int ht[NUM_WATCH_REGS];
+
+	if (!cpu_has_watch)
+		return -EIO;
+	if (!access_ok(VERIFY_READ, addr, sizeof(struct pt_watch_regs)))
+		return -EIO;
+	/* Check the values. */
+	for (i = 0; i < NUM_WATCH_REGS; i++) {
+		__get_user(lt[i], &addr->mips32.watchlo[i]);
+		if (lt[i] & __UA_LIMIT)
+			return -EINVAL;
+
+		__get_user(ht[i], &addr->mips32.watchhi[i]);
+		if (ht[i] & ~0xff8)
+			return -EINVAL;
+	}
+	/* Install them. */
+	for (i = 0; i < NUM_WATCH_REGS; i++) {
+		if (lt[i] & 7)
+			watch_active = 1;
+		child->thread.watch.mips32.watchlo[i] = lt[i];
+		/* Set the G bit. */
+		child->thread.watch.mips32.watchhi[i] = ht[i] | 0x40000000;
+	}
+
+	if (watch_active)
+		set_tsk_thread_flag(child, TIF_LOAD_WATCH);
+	else
+		clear_tsk_thread_flag(child, TIF_LOAD_WATCH);
+
+	return 0;
+}
+
+#endif
+
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
 	int ret;
@@ -439,7 +510,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 		ret = put_user(task_thread_info(child)->tp_value,
 				(unsigned long __user *) data);
 		break;
+#ifdef CONFIG_HARDWARE_WATCHPOINTS
+	case PTRACE_GET_WATCH_REGS:
+		ret = ptrace_get_watch_regs(child,
+					(struct pt_watch_regs __user *) addr);
+		break;
 
+	case PTRACE_SET_WATCH_REGS:
+		ret = ptrace_set_watch_regs(child,
+					(struct pt_watch_regs __user *) addr);
+		break;
+#endif
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		break;
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
index 786f7e3..8fb1bcc 100644
--- a/include/asm-mips/ptrace.h
+++ b/include/asm-mips/ptrace.h
@@ -71,6 +71,29 @@ struct pt_regs {
 #define PTRACE_POKEDATA_3264	0xc3
 #define PTRACE_GET_THREAD_AREA_3264	0xc4
 
+/* Read and write watchpoint registers.  */
+enum pt_watch_style {
+	pt_watch_style_mips32,
+	pt_watch_style_mips64
+};
+struct mips32_watch_regs {
+	unsigned int num_valid;
+	unsigned int reg_mask;
+	unsigned int irw_mask;
+	unsigned long watchlo[8];
+	unsigned int watchhi[8];
+};
+
+struct pt_watch_regs {
+	enum pt_watch_style style;
+	union {
+		struct mips32_watch_regs mips32;
+	};
+};
+
+#define PTRACE_GET_WATCH_REGS	0xd0
+#define PTRACE_SET_WATCH_REGS	0xd1
+
 #ifdef __KERNEL__
 
 #include <linux/linkage.h>
-- 
1.5.5


  parent reply	other threads:[~2008-04-22  0:40 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-04-21 23:20 [Patch 0/6] MIPS Hardware watchpoint support for gdb David Daney
2008-04-22  0:01 ` [Patch 1/6] Add HARDWARE_WATCHPOINTS configure option David Daney
2008-04-22  0:10 ` [Patch 2/6] Add HARDWARE_WATCHPOINTS definitions and support code David Daney
2008-04-22  0:15 ` [Patch 3/6] Probe watch registers and report configuration David Daney
2008-04-22  0:21 ` [Patch 4/6] Watch trap handling for HARDWARE_WATCHPOINTS David Daney
2008-04-22  0:33 ` [Patch 5/6] Scheduler support " David Daney
2008-04-22  0:40 ` David Daney [this message]
2008-04-22 16:23   ` [Patch 6/6] Ptrace " Daniel Jacobowitz
2008-04-22 18:26     ` Maciej W. Rozycki
  -- strict thread matches above, loose matches on Subject: below --
2008-04-29  1:21 [Patch 0/6] MIPS Hardware watchpoint support for gdb (version 2) David Daney
2008-04-29  1:43 ` [PATCH 6/6] Ptrace support for HARDWARE_WATCHPOINTS David Daney

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=480D33EB.30808@avtrex.com \
    --to=ddaney@avtrex.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mips@linux-mips.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox