svn commit: r251050 - in stable/9/sys/amd64: amd64 include

Konstantin Belousov kib at FreeBSD.org
Tue May 28 05:36:19 UTC 2013


Author: kib
Date: Tue May 28 05:36:18 2013
New Revision: 251050
URL: http://svnweb.freebsd.org/changeset/base/251050

Log:
  MFC r250851:
  Fix the hardware watchpoints on SMP amd64.

Modified:
  stable/9/sys/amd64/amd64/db_trace.c
  stable/9/sys/amd64/amd64/mp_machdep.c
  stable/9/sys/amd64/include/md_var.h
  stable/9/sys/amd64/include/pcpu.h
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/amd64/amd64/db_trace.c
==============================================================================
--- stable/9/sys/amd64/amd64/db_trace.c	Tue May 28 05:25:10 2013	(r251049)
+++ stable/9/sys/amd64/amd64/db_trace.c	Tue May 28 05:36:18 2013	(r251050)
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
 #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_frame;
 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,64 +594,82 @@ db_md_set_watchpoint(addr, size)
 	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++;
 	}
 
 	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)
 				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--;
 		}
 	}
 
-	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_md_list_watchpoints()
 	}
 	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: stable/9/sys/amd64/amd64/mp_machdep.c
==============================================================================
--- stable/9/sys/amd64/amd64/mp_machdep.c	Tue May 28 05:25:10 2013	(r251049)
+++ stable/9/sys/amd64/amd64/mp_machdep.c	Tue May 28 05:36:18 2013	(r251050)
@@ -28,6 +28,7 @@
 __FBSDID("$FreeBSD$");
 
 #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 @@ cpustop_handler(void)
 	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: stable/9/sys/amd64/include/md_var.h
==============================================================================
--- stable/9/sys/amd64/include/md_var.h	Tue May 28 05:25:10 2013	(r251049)
+++ stable/9/sys/amd64/include/md_var.h	Tue May 28 05:36:18 2013	(r251050)
@@ -117,5 +117,6 @@ void	minidumpsys(struct dumperinfo *);
 struct savefpu *get_pcb_user_save_td(struct thread *td);
 struct savefpu *get_pcb_user_save_pcb(struct pcb *pcb);
 struct pcb *get_pcb_td(struct thread *td);
+void	amd64_db_resume_dbreg(void);
 
 #endif /* !_MACHINE_MD_VAR_H_ */

Modified: stable/9/sys/amd64/include/pcpu.h
==============================================================================
--- stable/9/sys/amd64/include/pcpu.h	Tue May 28 05:25:10 2013	(r251049)
+++ stable/9/sys/amd64/include/pcpu.h	Tue May 28 05:36:18 2013	(r251050)
@@ -77,7 +77,12 @@
 	/* 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
 


More information about the svn-src-stable-9 mailing list