[Midnightbsd-cvs] src [9443] trunk/sys/amd64: Fix the hardware watchpoints on SMP amd64.

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sun Mar 5 14:23:13 EST 2017


Revision: 9443
          http://svnweb.midnightbsd.org/src/?rev=9443
Author:   laffer1
Date:     2017-03-05 14:23:13 -0500 (Sun, 05 Mar 2017)
Log Message:
-----------
Fix the hardware watchpoints on SMP amd64.

Modified Paths:
--------------
    trunk/sys/amd64/amd64/db_trace.c
    trunk/sys/amd64/amd64/mp_machdep.c
    trunk/sys/amd64/include/pcpu.h

Modified: trunk/sys/amd64/amd64/db_trace.c
===================================================================
--- trunk/sys/amd64/amd64/db_trace.c	2017-03-05 19:22:44 UTC (rev 9442)
+++ trunk/sys/amd64/amd64/db_trace.c	2017-03-05 19:23:13 UTC (rev 9443)
@@ -33,6 +33,7 @@
 #include <sys/systm.h>
 #include <sys/kdb.h>
 #include <sys/proc.h>
+#include <sys/smp.h>
 #include <sys/stack.h>
 #include <sys/sysent.h>
 
@@ -63,6 +64,8 @@
 static db_varfcn_t db_rsp;
 static db_varfcn_t db_ss;
 
+CTASSERT(sizeof(struct dbreg) == sizeof(((struct pcpu *)NULL)->pc_dbreg));
+
 /*
  * Machine register set.
  */
@@ -591,14 +594,17 @@
 	db_expr_t addr;
 	db_expr_t size;
 {
-	struct dbreg d;
-	int avail, i, wsize;
+	struct dbreg *d;
+	struct pcpu *pc;
+	int avail, c, cpu, i, wsize;
 
-	fill_dbregs(NULL, &d);
+	d = (struct dbreg *)PCPU_PTR(dbreg);
+	cpu = PCPU_GET(cpuid);
+	fill_dbregs(NULL, d);
 
 	avail = 0;
-	for(i = 0; i < 4; i++) {
-		if (!DBREG_DR7_ENABLED(d.dr[7], i))
+	for (i = 0; i < 4; i++) {
+		if (!DBREG_DR7_ENABLED(d->dr[7], i))
 			avail++;
 	}
 
@@ -605,8 +611,8 @@
 	if (avail * 8 < size)
 		return (-1);
 
-	for (i = 0; i < 4 && (size > 0); i++) {
-		if (!DBREG_DR7_ENABLED(d.dr[7], i)) {
+	for (i = 0; i < 4 && size > 0; i++) {
+		if (!DBREG_DR7_ENABLED(d->dr[7], i)) {
 			if (size >= 8 || (avail == 1 && size > 4))
 				wsize = 8;
 			else if (size > 2)
@@ -613,8 +619,7 @@
 				wsize = 4;
 			else
 				wsize = size;
-			amd64_set_watch(i, addr, wsize,
-				       DBREG_DR7_WRONLY, &d);
+			amd64_set_watch(i, addr, wsize, DBREG_DR7_WRONLY, d);
 			addr += wsize;
 			size -= wsize;
 			avail--;
@@ -621,34 +626,50 @@
 		}
 	}
 
-	set_dbregs(NULL, &d);
+	set_dbregs(NULL, d);
+	CPU_FOREACH(c) {
+		if (c == cpu)
+			continue;
+		pc = pcpu_find(c);
+		memcpy(pc->pc_dbreg, d, sizeof(*d));
+		pc->pc_dbreg_cmd = PC_DBREG_CMD_LOAD;
+	}
 
-	return(0);
+	return (0);
 }
 
-
 int
 db_md_clr_watchpoint(addr, size)
 	db_expr_t addr;
 	db_expr_t size;
 {
-	struct dbreg d;
-	int i;
+	struct dbreg *d;
+	struct pcpu *pc;
+	int i, c, cpu;
 
-	fill_dbregs(NULL, &d);
+	d = (struct dbreg *)PCPU_PTR(dbreg);
+	cpu = PCPU_GET(cpuid);
+	fill_dbregs(NULL, d);
 
-	for(i = 0; i < 4; i++) {
-		if (DBREG_DR7_ENABLED(d.dr[7], i)) {
-			if ((DBREG_DRX((&d), i) >= addr) &&
-			    (DBREG_DRX((&d), i) < addr+size))
-				amd64_clr_watch(i, &d);
+	for (i = 0; i < 4; i++) {
+		if (DBREG_DR7_ENABLED(d->dr[7], i)) {
+			if (DBREG_DRX((d), i) >= addr &&
+			    DBREG_DRX((d), i) < addr + size)
+				amd64_clr_watch(i, d);
 
 		}
 	}
 
-	set_dbregs(NULL, &d);
+	set_dbregs(NULL, d);
+	CPU_FOREACH(c) {
+		if (c == cpu)
+			continue;
+		pc = pcpu_find(c);
+		memcpy(pc->pc_dbreg, d, sizeof(*d));
+		pc->pc_dbreg_cmd = PC_DBREG_CMD_LOAD;
+	}
 
-	return(0);
+	return (0);
 }
 
 
@@ -699,3 +720,17 @@
 	}
 	db_printf("\n");
 }
+
+void
+amd64_db_resume_dbreg(void)
+{
+	struct dbreg *d;
+
+	switch (PCPU_GET(dbreg_cmd)) {
+	case PC_DBREG_CMD_LOAD:
+		d = (struct dbreg *)PCPU_PTR(dbreg);
+		set_dbregs(NULL, d);
+		PCPU_SET(dbreg_cmd, PC_DBREG_CMD_NONE);
+		break;
+	}
+}

Modified: trunk/sys/amd64/amd64/mp_machdep.c
===================================================================
--- trunk/sys/amd64/amd64/mp_machdep.c	2017-03-05 19:22:44 UTC (rev 9442)
+++ trunk/sys/amd64/amd64/mp_machdep.c	2017-03-05 19:23:13 UTC (rev 9443)
@@ -28,6 +28,7 @@
 __MBSDID("$MidnightBSD$");
 
 #include "opt_cpu.h"
+#include "opt_ddb.h"
 #include "opt_kstack_pages.h"
 #include "opt_sched.h"
 #include "opt_smp.h"
@@ -1397,6 +1398,10 @@
 	CPU_CLR_ATOMIC(cpu, &started_cpus);
 	CPU_CLR_ATOMIC(cpu, &stopped_cpus);
 
+#ifdef DDB
+	amd64_db_resume_dbreg();
+#endif
+
 	if (cpu == 0 && cpustop_restartfunc != NULL) {
 		cpustop_restartfunc();
 		cpustop_restartfunc = NULL;

Modified: trunk/sys/amd64/include/pcpu.h
===================================================================
--- trunk/sys/amd64/include/pcpu.h	2017-03-05 19:22:44 UTC (rev 9442)
+++ trunk/sys/amd64/include/pcpu.h	2017-03-05 19:23:13 UTC (rev 9443)
@@ -77,8 +77,13 @@
 	/* Pointer to the CPU TSS descriptor */				\
 	struct system_segment_descriptor *pc_tss;			\
 	u_int	pc_cmci_mask		/* MCx banks for CMCI */	\
-	PCPU_XEN_FIELDS
+	PCPU_XEN_FIELDS;						\
+	uint64_t pc_dbreg[16];		/* ddb debugging regs */	\
+	int pc_dbreg_cmd;		/* ddb debugging reg cmd */	\
 
+#define	PC_DBREG_CMD_NONE	0
+#define	PC_DBREG_CMD_LOAD	1
+
 #ifdef _KERNEL
 
 #ifdef lint



More information about the Midnightbsd-cvs mailing list