Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src Add support for hardware assisted watchpoints/breakpoints AP...
details: https://anonhg.NetBSD.org/src/rev/ad781831d207
branches: trunk
changeset: 349589:ad781831d207
user: kamil <kamil%NetBSD.org@localhost>
date: Thu Dec 15 12:04:17 2016 +0000
description:
Add support for hardware assisted watchpoints/breakpoints API in ptrace(2)
Add new ptrace(2) calls:
- PT_COUNT_WATCHPOINTS - count the number of available hardware watchpoints
- PT_READ_WATCHPOINT - read struct ptrace_watchpoint from the kernel state
- PT_WRITE_WATCHPOINT - write new struct ptrace_watchpoint state, this
includes enabling and disabling watchpoints
The ptrace_watchpoint structure contains MI and MD parts:
typedef struct ptrace_watchpoint {
int pw_index; /* HW Watchpoint ID (count from 0) */
lwpid_t pw_lwpid; /* LWP described */
struct mdpw pw_md; /* MD fields */
} ptrace_watchpoint_t;
For example amd64 defines MD as follows:
struct mdpw {
void *md_address;
int md_condition;
int md_length;
};
These calls are protected with the __HAVE_PTRACE_WATCHPOINTS guard.
Tested on amd64, initial support added for i386 and XEN.
Sponsored by <The NetBSD Foundation>
diffstat:
distrib/sets/lists/comp/md.amd64 | 3 +-
distrib/sets/lists/comp/md.i386 | 3 +-
sys/arch/amd64/amd64/machdep.c | 7 +-
sys/arch/amd64/amd64/netbsd32_machdep.c | 6 +-
sys/arch/amd64/amd64/process_machdep.c | 93 ++++++++++++-
sys/arch/amd64/amd64/trap.c | 17 ++-
sys/arch/amd64/conf/files.amd64 | 3 +-
sys/arch/amd64/include/proc.h | 9 +-
sys/arch/amd64/include/ptrace.h | 53 ++++++-
sys/arch/amd64/include/userret.h | 14 +-
sys/arch/i386/conf/files.i386 | 3 +-
sys/arch/i386/i386/machdep.c | 7 +-
sys/arch/i386/i386/process_machdep.c | 93 ++++++++++++-
sys/arch/i386/include/proc.h | 7 +-
sys/arch/i386/include/ptrace.h | 42 +++++-
sys/arch/i386/include/userret.h | 14 +-
sys/arch/x86/include/Makefile | 3 +-
sys/arch/x86/include/dbregs.h | 117 +++++++++++++++-
sys/arch/x86/x86/dbregs.c | 230 ++++++++++++++++++++++++++++++++
sys/arch/x86/x86/vm_machdep.c | 10 +-
sys/arch/xen/conf/files.xen | 3 +-
sys/compat/netbsd32/netbsd32_ptrace.c | 19 ++-
sys/kern/sys_ptrace.c | 5 +-
sys/kern/sys_ptrace_common.c | 105 ++++++++++++++-
sys/sys/ptrace.h | 55 +++++++-
25 files changed, 865 insertions(+), 56 deletions(-)
diffs (truncated from 1497 to 300 lines):
diff -r bac6f032bf7c -r ad781831d207 distrib/sets/lists/comp/md.amd64
--- a/distrib/sets/lists/comp/md.amd64 Thu Dec 15 11:32:03 2016 +0000
+++ b/distrib/sets/lists/comp/md.amd64 Thu Dec 15 12:04:17 2016 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: md.amd64,v 1.239 2016/12/14 12:59:51 kre Exp $
+# $NetBSD: md.amd64,v 1.240 2016/12/15 12:04:18 kamil Exp $
./usr/include/amd64 comp-c-include
./usr/include/amd64/ansi.h comp-c-include
@@ -496,6 +496,7 @@
./usr/include/x86/cpu_ucode.h comp-c-include
./usr/include/x86/cputypes.h comp-c-include
./usr/include/x86/cpuvar.h comp-c-include
+./usr/include/x86/dbregs.h comp-c-include
./usr/include/x86/float.h comp-c-include
./usr/include/x86/fpu.h comp-c-include
./usr/include/x86/ieee.h comp-c-include
diff -r bac6f032bf7c -r ad781831d207 distrib/sets/lists/comp/md.i386
--- a/distrib/sets/lists/comp/md.i386 Thu Dec 15 11:32:03 2016 +0000
+++ b/distrib/sets/lists/comp/md.i386 Thu Dec 15 12:04:17 2016 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: md.i386,v 1.159 2016/10/15 11:34:30 christos Exp $
+# $NetBSD: md.i386,v 1.160 2016/12/15 12:04:18 kamil Exp $
./usr/include/clang-3.4/__wmmintrin_aes.h comp-obsolete obsolete
./usr/include/clang-3.4/__wmmintrin_pclmul.h comp-obsolete obsolete
./usr/include/clang-3.4/ammintrin.h comp-obsolete obsolete
@@ -370,6 +370,7 @@
./usr/include/x86/cpu_ucode.h comp-c-include
./usr/include/x86/cputypes.h comp-c-include
./usr/include/x86/cpuvar.h comp-c-include
+./usr/include/x86/dbregs.h comp-c-include
./usr/include/x86/float.h comp-c-include
./usr/include/x86/fpu.h comp-c-include
./usr/include/x86/ieee.h comp-c-include
diff -r bac6f032bf7c -r ad781831d207 sys/arch/amd64/amd64/machdep.c
--- a/sys/arch/amd64/amd64/machdep.c Thu Dec 15 11:32:03 2016 +0000
+++ b/sys/arch/amd64/amd64/machdep.c Thu Dec 15 12:04:17 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.237 2016/12/12 02:51:24 pgoyette Exp $ */
+/* $NetBSD: machdep.c,v 1.238 2016/12/15 12:04:17 kamil Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011
@@ -111,7 +111,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.237 2016/12/12 02:51:24 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.238 2016/12/15 12:04:17 kamil Exp $");
/* #define XENDEBUG_LOW */
@@ -482,6 +482,7 @@
pmap_kernel()->pm_ldt_sel = GSYSSEL(GLDT_SEL, SEL_KPL);
pcb->pcb_cr0 = rcr0() & ~CR0_TS;
l->l_md.md_regs = (struct trapframe *)pcb->pcb_rsp0 - 1;
+ memset(l->l_md.md_watchpoint, 0, sizeof(*l->l_md.md_watchpoint));
#if !defined(XEN)
lldt(pmap_kernel()->pm_ldt_sel);
@@ -1316,6 +1317,8 @@
l->l_proc->p_flag &= ~PK_32;
+ memset(l->l_md.md_watchpoint, 0, sizeof(*l->l_md.md_watchpoint));
+
tf = l->l_md.md_regs;
tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
diff -r bac6f032bf7c -r ad781831d207 sys/arch/amd64/amd64/netbsd32_machdep.c
--- a/sys/arch/amd64/amd64/netbsd32_machdep.c Thu Dec 15 11:32:03 2016 +0000
+++ b/sys/arch/amd64/amd64/netbsd32_machdep.c Thu Dec 15 12:04:17 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_machdep.c,v 1.97 2016/10/19 09:44:00 skrll Exp $ */
+/* $NetBSD: netbsd32_machdep.c,v 1.98 2016/12/15 12:04:17 kamil Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.97 2016/10/19 09:44:00 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.98 2016/12/15 12:04:17 kamil Exp $");
#ifdef _KERNEL_OPT
#include "opt_compat_netbsd.h"
@@ -129,6 +129,8 @@
p->p_flag |= PK_32;
+ memset(l->l_md.md_watchpoint, 0, sizeof(*l->l_md.md_watchpoint));
+
tf = l->l_md.md_regs;
tf->tf_ds = LSEL(LUDATA32_SEL, SEL_UPL);
tf->tf_es = LSEL(LUDATA32_SEL, SEL_UPL);
diff -r bac6f032bf7c -r ad781831d207 sys/arch/amd64/amd64/process_machdep.c
--- a/sys/arch/amd64/amd64/process_machdep.c Thu Dec 15 11:32:03 2016 +0000
+++ b/sys/arch/amd64/amd64/process_machdep.c Thu Dec 15 12:04:17 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: process_machdep.c,v 1.29 2014/02/15 22:20:41 dsl Exp $ */
+/* $NetBSD: process_machdep.c,v 1.30 2016/12/15 12:04:17 kamil Exp $ */
/*-
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -49,11 +49,21 @@
*
* process_set_pc(proc)
* Set the process's program counter.
+ *
+ * process_count_watchpoints(proc, retval)
+ * Return the number of supported hardware watchpoints.
+ *
+ * process_read_watchpoint(proc, watchpoint)
+ * Read hardware watchpoint of the given index.
+ *
+ * process_write_watchpoint(proc, watchpoint)
+ * Write hardware watchpoint of the given index.
+ *
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.29 2014/02/15 22:20:41 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.30 2016/12/15 12:04:17 kamil Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -66,6 +76,7 @@
#include <machine/psl.h>
#include <machine/reg.h>
#include <machine/segments.h>
+#include <x86/dbregs.h>
#include <x86/fpu.h>
static inline struct trapframe *process_frame(struct lwp *);
@@ -157,3 +168,81 @@
return (0);
}
+
+int
+process_count_watchpoints(struct lwp *l, register_t *retval)
+{
+
+ *retval = X86_HW_WATCHPOINTS;
+
+ return (0);
+}
+
+int
+process_read_watchpoint(struct lwp *l, struct ptrace_watchpoint *pw)
+{
+
+ pw->pw_md.md_address =
+ (void*)(intptr_t)l->l_md.md_watchpoint[pw->pw_index].address;
+ pw->pw_md.md_condition = l->l_md.md_watchpoint[pw->pw_index].condition;
+ pw->pw_md.md_length = l->l_md.md_watchpoint[pw->pw_index].length;
+
+ return (0);
+}
+
+static void
+update_mdl_x86_hw_watchpoints(struct lwp *l)
+{
+ size_t i;
+
+ for (i = 0; i < X86_HW_WATCHPOINTS; i++) {
+ if (l->l_md.md_watchpoint[0].address != 0) {
+ return;
+ }
+ }
+ l->l_md.md_flags &= ~MDL_X86_HW_WATCHPOINTS;
+}
+
+int
+process_write_watchpoint(struct lwp *l, struct ptrace_watchpoint *pw)
+{
+
+ if (pw->pw_index > X86_HW_WATCHPOINTS)
+ return (EINVAL);
+
+ if (pw->pw_md.md_address == 0) {
+ l->l_md.md_watchpoint[pw->pw_index].address = 0;
+ update_mdl_x86_hw_watchpoints(l);
+ return (0);
+ }
+
+ if ((vaddr_t)pw->pw_md.md_address > VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+
+ switch (pw->pw_md.md_condition) {
+ case X86_HW_WATCHPOINT_DR7_CONDITION_EXECUTION:
+ case X86_HW_WATCHPOINT_DR7_CONDITION_DATA_WRITE:
+ case X86_HW_WATCHPOINT_DR7_CONDITION_DATA_READWRITE:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ switch (pw->pw_md.md_length) {
+ case X86_HW_WATCHPOINT_DR7_LENGTH_BYTE:
+ case X86_HW_WATCHPOINT_DR7_LENGTH_TWOBYTES:
+ case X86_HW_WATCHPOINT_DR7_LENGTH_FOURBYTES:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ l->l_md.md_watchpoint[pw->pw_index].address =
+ (vaddr_t)pw->pw_md.md_address;
+ l->l_md.md_watchpoint[pw->pw_index].condition = pw->pw_md.md_condition;
+ l->l_md.md_watchpoint[pw->pw_index].length = pw->pw_md.md_length;
+
+ l->l_md.md_flags |= MDL_X86_HW_WATCHPOINTS;
+
+ return (0);
+}
diff -r bac6f032bf7c -r ad781831d207 sys/arch/amd64/amd64/trap.c
--- a/sys/arch/amd64/amd64/trap.c Thu Dec 15 11:32:03 2016 +0000
+++ b/sys/arch/amd64/amd64/trap.c Thu Dec 15 12:04:17 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.87 2016/10/26 22:02:14 christos Exp $ */
+/* $NetBSD: trap.c,v 1.88 2016/12/15 12:04:17 kamil Exp $ */
/*-
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.87 2016/10/26 22:02:14 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.88 2016/12/15 12:04:17 kamil Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
@@ -673,6 +673,19 @@
}
case T_TRCTRAP:
+ /*
+ * Ignore debug register trace traps due to
+ * accesses in the user's address space, which
+ * can happen under several conditions such as
+ * if a user sets a watchpoint on a buffer and
+ * then passes that buffer to a system call.
+ * We still want to get TRCTRAPS for addresses
+ * in kernel space because that is useful when
+ * debugging the kernel.
+ */
+ if (user_trap_x86_hw_watchpoint())
+ break;
+
/* Check whether they single-stepped into a lcall. */
if (frame->tf_rip == (uint64_t)IDTVEC(oosyscall) ||
frame->tf_rip == (uint64_t)IDTVEC(osyscall) ||
diff -r bac6f032bf7c -r ad781831d207 sys/arch/amd64/conf/files.amd64
--- a/sys/arch/amd64/conf/files.amd64 Thu Dec 15 11:32:03 2016 +0000
+++ b/sys/arch/amd64/conf/files.amd64 Thu Dec 15 12:04:17 2016 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files.amd64,v 1.87 2015/09/06 07:17:14 uebayasi Exp $
+# $NetBSD: files.amd64,v 1.88 2016/12/15 12:04:17 kamil Exp $
#
# new style config file for amd64 architecture
#
@@ -49,6 +49,7 @@
file arch/amd64/amd64/process_machdep.c machdep
file arch/amd64/amd64/trap.c machdep
file arch/x86/x86/fpu.c machdep
+file arch/x86/x86/dbregs.c machdep
file arch/x86/x86/convert_xmm_s87.c machdep
file arch/amd64/amd64/lock_stubs.S machdep
file dev/cons.c machdep
diff -r bac6f032bf7c -r ad781831d207 sys/arch/amd64/include/proc.h
--- a/sys/arch/amd64/include/proc.h Thu Dec 15 11:32:03 2016 +0000
+++ b/sys/arch/amd64/include/proc.h Thu Dec 15 12:04:17 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: proc.h,v 1.19 2014/02/20 18:19:10 dsl Exp $ */
+/* $NetBSD: proc.h,v 1.20 2016/12/15 12:04:17 kamil Exp $ */
/*
* Copyright (c) 1991 Regents of the University of California.
@@ -38,6 +38,7 @@
#include <machine/frame.h>
#include <machine/pcb.h>
+#include <x86/dbregs.h>
/*
* Machine-dependent part of the lwp structure for amd64.
@@ -51,10 +52,12 @@
struct vm_page *md_gc_ptp; /* pages from pmap g/c */
int md_flags; /* machine-dependent flags */
volatile int md_astpending;
+ struct x86_hw_watchpoint md_watchpoint[X86_HW_WATCHPOINTS];
};
-#define MDL_COMPAT32 0x0008 /* i386, always return via iret */
-#define MDL_IRET 0x0010 /* force return via iret, not sysret */
+#define MDL_COMPAT32 0x0008 /* i386, always return via iret */
Home |
Main Index |
Thread Index |
Old Index