git: 15dc1d44528a - main - x86: implement kdb watchpoint functions

Mitchell Horne mhorne at FreeBSD.org
Mon Mar 29 15:06:09 UTC 2021


The branch main has been updated by mhorne:

URL: https://cgit.FreeBSD.org/src/commit/?id=15dc1d44528a1e2693df41d5452d6ebb42ecafeb

commit 15dc1d44528a1e2693df41d5452d6ebb42ecafeb
Author:     Mitchell Horne <mhorne at FreeBSD.org>
AuthorDate: 2021-02-19 22:36:08 +0000
Commit:     Mitchell Horne <mhorne at FreeBSD.org>
CommitDate: 2021-03-29 15:05:43 +0000

    x86: implement kdb watchpoint functions
    
    Add wrappers around the dbreg interface that can be consumed by MI
    kernel debugger code. The dbreg functions themselves are updated to
    return error codes, not just -1. dbreg_set_watchpoint() is extended to
    accept access bits as an argument.
    
    Reviewed by:    jhb, kib, markj
    MFC after:      3 weeks
    Sponsored by:   NetApp, Inc.
    Sponsored by:   Klara, Inc.
    Differential Revision:  https://reviews.freebsd.org/D29155
---
 sys/amd64/amd64/db_trace.c |  3 ++-
 sys/amd64/include/kdb.h    |  3 +++
 sys/i386/include/kdb.h     |  3 +++
 sys/x86/include/x86_var.h  |  2 +-
 sys/x86/x86/dbreg.c        | 41 ++++++++++++++++++++++++++++++++++++++---
 5 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/sys/amd64/amd64/db_trace.c b/sys/amd64/amd64/db_trace.c
index 5c1cd41cda15..beeb5cd6e9f3 100644
--- a/sys/amd64/amd64/db_trace.c
+++ b/sys/amd64/amd64/db_trace.c
@@ -389,7 +389,8 @@ int
 db_md_set_watchpoint(db_expr_t addr, db_expr_t size)
 {
 
-	return (dbreg_set_watchpoint((vm_offset_t)addr, (vm_size_t)size));
+	return (dbreg_set_watchpoint((vm_offset_t)addr, (vm_size_t)size,
+	    DBREG_DR7_WRONLY));
 }
 
 int
diff --git a/sys/amd64/include/kdb.h b/sys/amd64/include/kdb.h
index 2fb158622eb4..03cb2205066f 100644
--- a/sys/amd64/include/kdb.h
+++ b/sys/amd64/include/kdb.h
@@ -36,6 +36,9 @@
 
 #define	KDB_STOPPEDPCB(pc)	&stoppcbs[pc->pc_cpuid]
 
+int kdb_cpu_set_watchpoint(vm_offset_t addr, vm_size_t size, int access);
+int kdb_cpu_clr_watchpoint(vm_offset_t addr, vm_size_t size);
+
 static __inline void
 kdb_cpu_clear_singlestep(void)
 {
diff --git a/sys/i386/include/kdb.h b/sys/i386/include/kdb.h
index beb2bd0e4132..29a23fde0aad 100644
--- a/sys/i386/include/kdb.h
+++ b/sys/i386/include/kdb.h
@@ -36,6 +36,9 @@
 
 #define	KDB_STOPPEDPCB(pc)	&stoppcbs[pc->pc_cpuid]
 
+int kdb_cpu_set_watchpoint(vm_offset_t addr, vm_size_t size, int access);
+int kdb_cpu_clr_watchpoint(vm_offset_t addr, vm_size_t size);
+
 static __inline void
 kdb_cpu_clear_singlestep(void)
 {
diff --git a/sys/x86/include/x86_var.h b/sys/x86/include/x86_var.h
index d60b4b2acbd8..3e5aa847304e 100644
--- a/sys/x86/include/x86_var.h
+++ b/sys/x86/include/x86_var.h
@@ -120,7 +120,7 @@ vm_paddr_t cpu_getmaxphyaddr(void);
 bool	cpu_mwait_usable(void);
 void	cpu_probe_amdc1e(void);
 void	cpu_setregs(void);
-int	dbreg_set_watchpoint(vm_offset_t addr, vm_size_t size);
+int	dbreg_set_watchpoint(vm_offset_t addr, vm_size_t size, int access);
 int	dbreg_clr_watchpoint(vm_offset_t addr, vm_size_t size);
 void	dbreg_list_watchpoints(void);
 bool	disable_wp(void);
diff --git a/sys/x86/x86/dbreg.c b/sys/x86/x86/dbreg.c
index 0d28ef8dba38..ef30cc2d614e 100644
--- a/sys/x86/x86/dbreg.c
+++ b/sys/x86/x86/dbreg.c
@@ -27,11 +27,13 @@
 #include "opt_ddb.h"
 
 #include <sys/types.h>
+#include <sys/kdb.h>
 #include <sys/pcpu.h>
 #include <sys/smp.h>
 #include <sys/systm.h>
 
 #include <machine/frame.h>
+#include <machine/kdb.h>
 #include <machine/md_var.h>
 
 #include <ddb/ddb.h>
@@ -127,7 +129,7 @@ dbreg_sync(struct dbreg *dp)
 }
 
 int
-dbreg_set_watchpoint(vm_offset_t addr, vm_size_t size)
+dbreg_set_watchpoint(vm_offset_t addr, vm_size_t size, int access)
 {
 	struct dbreg *d;
 	int avail, i, wsize;
@@ -140,6 +142,11 @@ dbreg_set_watchpoint(vm_offset_t addr, vm_size_t size)
 	d = &d_temp;
 #endif
 
+	/* Validate the access type */
+	if (access != DBREG_DR7_EXEC && access != DBREG_DR7_WRONLY &&
+	    access != DBREG_DR7_RDWR)
+		return (EINVAL);
+
 	fill_dbregs(NULL, d);
 
 	/*
@@ -153,7 +160,7 @@ dbreg_set_watchpoint(vm_offset_t addr, vm_size_t size)
 	}
 
 	if (avail * MAXWATCHSIZE < size)
-		return (-1);
+		return (EBUSY);
 
 	for (i = 0; i < NDBREGS && size > 0; i++) {
 		if (!DBREG_DR7_ENABLED(d->dr[7], i)) {
@@ -164,7 +171,7 @@ dbreg_set_watchpoint(vm_offset_t addr, vm_size_t size)
 				wsize = 4;
 			else
 				wsize = size;
-			dbreg_set_watchreg(i, addr, wsize, DBREG_DR7_WRONLY, d);
+			dbreg_set_watchreg(i, addr, wsize, access, d);
 			addr += wsize;
 			size -= wsize;
 			avail--;
@@ -265,3 +272,31 @@ amd64_db_resume_dbreg(void)
 	}
 }
 #endif
+
+int
+kdb_cpu_set_watchpoint(vm_offset_t addr, vm_size_t size, int access)
+{
+
+	/* Convert the KDB access type */
+	switch (access) {
+	case KDB_DBG_ACCESS_W:
+		access = DBREG_DR7_WRONLY;
+		break;
+	case KDB_DBG_ACCESS_RW:
+		access = DBREG_DR7_RDWR;
+		break;
+	case KDB_DBG_ACCESS_R:
+		/* FALLTHROUGH: read-only not supported */
+	default:
+		return (EINVAL);
+	}
+
+	return (dbreg_set_watchpoint(addr, size, access));
+}
+
+int
+kdb_cpu_clr_watchpoint(vm_offset_t addr, vm_size_t size)
+{
+
+	return (dbreg_clr_watchpoint(addr, size));
+}


More information about the dev-commits-src-main mailing list