Module Name:    src
Committed By:   cliff
Date:           Thu Apr 14 05:09:34 UTC 2011

Modified Files:
        src/sys/arch/mips/mips: db_interface.c

Log Message:
- option MIPS_DDB_WATCH is dedprecated, removed; now using
(MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 for conditional
compile of db_mach_watch stuff
- MIPS CPU (COP0) watchpoint support moved from db_interface.c
to cpu_subr.c, cpu.h; ddb_mach_watch &etc now use those cpu functions.
- ddb_cpu now volatile
- 'struct db_mach_watch' definition &etc moved to mips/include/db_machdep.h
- db_mach_watch_tab is replaced by curcpu()->ci_watch_tab
to allow per-cpu watchpoint control
- improve MP function in kdb_trap()
- fix conditions for printing cp0 regs


To generate a diff of this commit:
cvs rdiff -u -r1.70 -r1.71 src/sys/arch/mips/mips/db_interface.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/mips/mips/db_interface.c
diff -u src/sys/arch/mips/mips/db_interface.c:1.70 src/sys/arch/mips/mips/db_interface.c:1.71
--- src/sys/arch/mips/mips/db_interface.c:1.70	Wed Apr  6 05:53:27 2011
+++ src/sys/arch/mips/mips/db_interface.c	Thu Apr 14 05:09:34 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: db_interface.c,v 1.70 2011/04/06 05:53:27 matt Exp $	*/
+/*	$NetBSD: db_interface.c,v 1.71 2011/04/14 05:09:34 cliff Exp $	*/
 
 /*
  * Mach Operating System
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.70 2011/04/06 05:53:27 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.71 2011/04/14 05:09:34 cliff Exp $");
 
 #include "opt_multiprocessor.h"
 #include "opt_cputype.h"	/* which mips CPUs do we support? */
@@ -67,34 +67,15 @@
 #endif
 
 #define NOCPU   ~0
-u_int ddb_cpu = NOCPU;
+volatile u_int ddb_cpu = NOCPU;
 
 int		db_active = 0;
 db_regs_t	ddb_regs;
 
-#ifdef MIPS_DDB_WATCH
-struct db_mach_watch {
-	register_t	addr;
-	register_t	mask;
-	uint32_t	asid;
-	uint32_t	mode;
-};
-/* mode bits */
-#define DB_WATCH_WRITE	__BIT(0)
-#define DB_WATCH_READ	__BIT(1)
-#define DB_WATCH_EXEC	__BIT(2)
-#define DB_WATCH_MASK	__BIT(3)
-#define DB_WATCH_ASID	__BIT(4)
-#define DB_WATCH_RWX	(DB_WATCH_EXEC|DB_WATCH_READ|DB_WATCH_WRITE)
-
-#define DBNWATCH	1
-static volatile struct db_mach_watch db_mach_watch_tab[DBNWATCH];
-
-static void db_mach_watch_set(int, register_t, register_t, uint32_t, uint32_t,
-	bool);
+#if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
 static void db_watch_cmd(db_expr_t, bool, db_expr_t, const char *);
 static void db_unwatch_cmd(db_expr_t, bool, db_expr_t, const char *);
-#endif	/* MIPS_DDB_WATCH */
+#endif	/* (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 */
 
 #ifdef MULTIPROCESSOR
 static void db_mach_cpu(db_expr_t, bool, db_expr_t, const char *);
@@ -146,6 +127,8 @@
 		break;
 	}
 
+	s = splhigh();
+
 #ifdef MULTIPROCESSOR
 	bool first_in_ddb = false;
 	const u_int cpu_me = cpu_number();
@@ -155,26 +138,25 @@
 		cpu_pause_others();
 	} else {
 		if (old_ddb_cpu != cpu_me) {
+			KASSERT(cpu_is_paused(cpu_me));
 			cpu_pause(regs);
+			splx(s);
 			return 1;
 		}
 	}
+	KASSERT(! cpu_is_paused(cpu_me));
 #endif
 
-	/* Should switch to kdb`s own stack here. */
 	ddb_regs = *regs;
-
-	s = splhigh();
 	db_active++;
 	cnpollc(1);
 	db_trap(type & ~T_USER, 0 /*code*/);
 	cnpollc(0);
 	db_active--;
-	splx(s);
+	*regs = ddb_regs;
 
 #ifdef MULTIPROCESSOR
-	if (ddb_cpu == cpu_me) {
-		ddb_cpu = NOCPU;
+	if (atomic_cas_uint(&ddb_cpu, cpu_me, NOCPU) == cpu_me) {
 		cpu_resume_others();
 	} else {
 		cpu_resume(ddb_cpu);
@@ -183,9 +165,8 @@
 	}
 #endif
 
-	*regs = ddb_regs;
-
-	return (1);
+	splx(s);
+	return 1;
 }
 
 void
@@ -411,10 +392,12 @@
 		SHOW32(MIPS_COP_0_COUNT, "count");
 	}
 
-	if ((cp0flags & MIPS_CP0FL_EIRR) != 0)
-		SHOW64SEL(9, 6, "eirr");
-	if ((cp0flags & MIPS_CP0FL_EIMR) != 0)
-		SHOW64SEL(9, 7, "eimr");
+	if ((cp0flags & MIPS_CP0FL_USE) != 0) {
+		if ((cp0flags & MIPS_CP0FL_EIRR) != 0)
+			SHOW64SEL(9, 6, "eirr");
+		if ((cp0flags & MIPS_CP0FL_EIMR) != 0)
+			SHOW64SEL(9, 7, "eimr");
+	}
 
 	if (CPUIS64BITS) {
 		SHOW64(MIPS_COP_0_TLB_HI, "entryhi");
@@ -479,146 +462,98 @@
 			else
 				SHOW32(MIPS_COP_0_LLADDR, "lladdr");
 		}
+	}
 
-		SHOW32(MIPS_COP_0_WATCH_HI, "watchhi");
-		if (CPUIS64BITS)
-			SHOW64(MIPS_COP_0_WATCH_LO, "watchlo");
-		else
-			SHOW32(MIPS_COP_0_WATCH_LO, "watchlo");
-
+#if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
+	for (int i=0; i < curcpu()->ci_cpuwatch_count; i++) {
+		uint32_t r = mipsNN_cp0_watchlo_read(i);
+		printf("  %s%d:%*s %#x\n", "watchlo", i, FLDWIDTH - 8, "", r);
+	}
+	for (int i=0; i < curcpu()->ci_cpuwatch_count; i++) {
 		if (CPUIS64BITS) {
-			SHOW64(MIPS_COP_0_TLB_XCONTEXT, "xcontext");
-		}
-
-		if (CPUISMIPSNN) {
-			if (CPUIS64BITS) {
-				SHOW64(MIPS_COP_0_PERFCNT, "perfcnt");
-			} else {
-				SHOW32(MIPS_COP_0_PERFCNT, "perfcnt");
-			}
+			uint32_t r = mipsNN_cp0_watchhi_read(i);
+			printf("  %s%d:%*s %#x\n",
+				"watchhi", i, FLDWIDTH - 8, "", r);
+		} else {
+			uint64_t r = mipsNN_cp0_watchhi_read(i);
+			printf("  %s%d:%*s %#" PRIx64 "\n",
+				"watchhi", i, FLDWIDTH - 8, "", r);
 		}
+	}
+#endif
 
-		if (((cp0flags & MIPS_CP0FL_USE) == 0) ||
-		    ((cp0flags & MIPS_CP0FL_ECC) != 0))
-			SHOW32(MIPS_COP_0_ECC, "ecc");
-
-		if (((cp0flags & MIPS_CP0FL_USE) == 0) ||
-		    ((cp0flags & MIPS_CP0FL_CACHE_ERR) != 0))
-			SHOW32(MIPS_COP_0_CACHE_ERR, "cacherr");
-
-		SHOW32(MIPS_COP_0_TAG_LO, "cachelo");
-		SHOW32(MIPS_COP_0_TAG_HI, "cachehi");
+	if (CPUIS64BITS) {
+		SHOW64(MIPS_COP_0_TLB_XCONTEXT, "xcontext");
+	}
 
+	if (CPUISMIPSNN) {
 		if (CPUIS64BITS) {
-			SHOW64(MIPS_COP_0_ERROR_PC, "errorpc");
+			SHOW64(MIPS_COP_0_PERFCNT, "perfcnt");
 		} else {
-			SHOW32(MIPS_COP_0_ERROR_PC, "errorpc");
+			SHOW32(MIPS_COP_0_PERFCNT, "perfcnt");
 		}
 	}
-}
 
-#ifdef MIPS_DDB_WATCH
-void
-db_mach_watch_set_all(void)
-{
-	volatile struct db_mach_watch *wp;
-	int i;
+	if (((cp0flags & MIPS_CP0FL_USE) == 0) ||
+	    ((cp0flags & MIPS_CP0FL_ECC) != 0))
+		SHOW32(MIPS_COP_0_ECC, "ecc");
 
-	for (i=0; i < DBNWATCH; i++) {
-		wp = &db_mach_watch_tab[i];
-		db_mach_watch_set(i, wp->addr, wp->mask, wp->asid, wp->mode,
-			true);
-	}
-}
+	if (((cp0flags & MIPS_CP0FL_USE) == 0) ||
+	    ((cp0flags & MIPS_CP0FL_CACHE_ERR) != 0))
+		SHOW32(MIPS_COP_0_CACHE_ERR, "cacherr");
 
-/*
- * db_mach_watch_set - write the COP0 registers
- */
-static void
-db_mach_watch_set(int wnum, register_t addr, register_t mask, uint32_t asid,
-	uint32_t mode, bool quiet)
-{
-	uint32_t watchhi;
-	register_t watchlo;
-	const char *strhi = (quiet) ? NULL : "watchhi";
-	const char *strlo = (quiet) ? NULL : "watchlo";
-
-	KASSERT(wnum == 0);	/* TBD */
-
-	watchlo = addr;
-	if (mode & DB_WATCH_WRITE)
-		watchlo |= __BIT(0);
-	if (mode & DB_WATCH_READ)
-		watchlo |= __BIT(1);
-	if (mode & DB_WATCH_EXEC)
-		watchlo |= __BIT(2);
-
-	if (mode & DB_WATCH_ASID)
-		watchhi = asid << 16;	/* addr qualified by asid */
-	else
-		watchhi = __BIT(30);	/* addr not qualified by asid (Global)*/
-	if (mode & DB_WATCH_MASK)
-		watchhi |= mask;	/* set "dont care" addr match bits */
-
-	SET32(MIPS_COP_0_WATCH_HI, strhi, watchhi);
+	SHOW32(MIPS_COP_0_TAG_LO, "cachelo");
+	SHOW32(MIPS_COP_0_TAG_HI, "cachehi");
 
 	if (CPUIS64BITS) {
-		MIPS64_SET64(MIPS_COP_0_WATCH_LO, 0, strlo, watchlo);
+		SHOW64(MIPS_COP_0_ERROR_PC, "errorpc");
 	} else {
-		SET32(MIPS_COP_0_WATCH_LO, strlo, (uint32_t)watchlo);
+		SHOW32(MIPS_COP_0_ERROR_PC, "errorpc");
 	}
 }
 
+#if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
 static void
 db_watch_cmd(db_expr_t address, bool have_addr, db_expr_t count,
 		 const char *modif)
 {
-	volatile struct db_mach_watch *wp;
+	struct cpu_info * const ci = curcpu();
+	cpu_watchpoint_t *cwp;
 	register_t mask=0;
 	uint32_t asid;
 	uint32_t mode;
 	db_expr_t value;
-	int wnum;
 	char str[6];
 
 	if (!have_addr) {
 		db_printf("%-3s %-5s %-16s %4s %4s\n",
 			"#", "MODE", "ADDR", "MASK", "ASID");
-		for (int i=0; i < DBNWATCH; i++) {
-			wp = &db_mach_watch_tab[i];
-			mode = wp->mode;
-			if ((mode & DB_WATCH_RWX) == 0)
+		for (int i=0; i < ci->ci_cpuwatch_count; i++) {
+			cwp = &ci->ci_cpuwatch_tab[i];
+			mode = cwp->cw_mode;
+			if ((mode & CPUWATCH_RWX) == 0)
 				continue;	/* empty/disabled/invalid */
-			str[0] = (mode & DB_WATCH_READ)  ?  'r' : '-';
-			str[1] = (mode & DB_WATCH_WRITE) ?  'w' : '-';
-			str[2] = (mode & DB_WATCH_EXEC)  ?  'x' : '-';
-			str[3] = (mode & DB_WATCH_MASK)  ?  'm' : '-';
-			str[4] = (mode & DB_WATCH_ASID)  ?  'a' : 'g';
+			str[0] = (mode & CPUWATCH_READ)  ?  'r' : '-';
+			str[1] = (mode & CPUWATCH_WRITE) ?  'w' : '-';
+			str[2] = (mode & CPUWATCH_EXEC)  ?  'x' : '-';
+			str[3] = (mode & CPUWATCH_MASK)  ?  'm' : '-';
+			str[4] = (mode & CPUWATCH_ASID)  ?  'a' : 'g';
 			str[5] = '\0';
 			db_printf("%2d: %s %16" PRIxREGISTER
 				  " %4" PRIxREGISTER " %4x\n",
-					i, str, wp->addr, wp->mask, wp->asid);
+				  i, str, cwp->cw_addr, cwp->cw_mask, cwp->cw_asid);
 		}
 		db_flush_lex();
 		return;
 	}
 
-	/*
-	 * find an empty slot
-	 * no lock for the table since only 1 CPU active in ddb at a time
-	 * (other CPUs are paused)
-	 */
-	for (int i=0; i < DBNWATCH; i++) {
-		wp = &db_mach_watch_tab[i];	/* empty/disabled/invalid */
-		if ((wp->mode & DB_WATCH_RWX) == 0) {
-			wnum = i;
-			goto found;
-		}
+	cwp = cpuwatch_alloc();
+	if (cwp == NULL) {
+		db_printf("no watchpoint available\n");
+		db_flush_lex();
+		return;
 	}
-	db_printf("no watchpoint available\n");
-	db_flush_lex();
-	return;
- found:
+
 	/*
 	 * parse modif to define mode
 	 */
@@ -627,19 +562,19 @@
 	for (int i=0; modif[i] != '\0'; i++) {
 		switch(modif[i]) {
 		case 'w':
-			mode |= DB_WATCH_WRITE;
+			mode |= CPUWATCH_WRITE;
 			break;
 		case 'm':
-			mode |= DB_WATCH_MASK;
+			mode |= CPUWATCH_MASK;
 			break;
 		case 'r':
-			mode |= DB_WATCH_READ;
+			mode |= CPUWATCH_READ;
 			break;
 		case 'x':
-			mode |= DB_WATCH_EXEC;
+			mode |= CPUWATCH_EXEC;
 			break;
 		case 'a':
-			mode |= DB_WATCH_ASID;
+			mode |= CPUWATCH_ASID;
 			break;
 		}
 	}
@@ -652,7 +587,7 @@
 	/*
 	 * if mask mode is requested get the mask,
 	 */
-	if (mode & DB_WATCH_MASK) {
+	if (mode & CPUWATCH_MASK) {
 		if (! db_expression(&value)) {
 			db_printf("mask missing\n");
 			db_flush_lex();
@@ -665,7 +600,7 @@
 	 * if asid mode is requested, get the asid;
 	 * otherwise use global mode (and set asid=0)
 	 */
-	if (mode & DB_WATCH_ASID) {
+	if (mode & CPUWATCH_ASID) {
 		if (! db_expression(&value)) {
 			db_printf("asid missing\n");
 			db_flush_lex();
@@ -676,7 +611,7 @@
 		asid = 0;
 	}
 
-	if (mode & (DB_WATCH_MASK|DB_WATCH_ASID))
+	if (mode & (CPUWATCH_MASK|CPUWATCH_ASID))
 		db_skip_to_eol();
 	else
 		db_flush_lex();
@@ -685,31 +620,32 @@
 	 * store to the (volatile) table entry
 	 * other CPUs can see this and load when resuming from pause
 	 */
-	wp->addr = (register_t)address;
-	wp->mask = (register_t)mask;
-	wp->asid = asid;
-	wp->mode = mode;
+	cwp->cw_addr = (register_t)address;
+	cwp->cw_mask = (register_t)mask;
+	cwp->cw_asid = asid;
+	cwp->cw_mode = mode;
 
-	db_mach_watch_set(wnum, (register_t)address, mask, asid, mode, false);
+	/*
+	 * program the CPU watchpoint regs
+	 */
+	cpuwatch_set(cwp);
 }
 
 static void
 db_unwatch_cmd(db_expr_t address, bool have_addr, db_expr_t count,
 		 const char *modif)
 {
-	volatile struct db_mach_watch *wp;
+	struct cpu_info * const ci = curcpu();
+	cpu_watchpoint_t *cwp;
 	int i, n;
 	bool unwatch_all = !have_addr;
 
 	n = 0;
-	for (i=0; i < DBNWATCH; i++) {
-		wp = &db_mach_watch_tab[i];
-		if (unwatch_all || (wp->addr == (register_t)address)) {
+	for (i=0; i < ci->ci_cpuwatch_count; i++) {
+		cwp = &ci->ci_cpuwatch_tab[i];
+		if (unwatch_all || (cwp->cw_addr == (register_t)address)) {
+			cpuwatch_free(cwp);
 			n++;
-			wp->mode = 0;
-			wp->asid = 0;
-			wp->addr = 0;
-			db_mach_watch_set(i, 0, 0, 0, 0, false);
 		}
 	}
 	if (n == 0)
@@ -717,7 +653,7 @@
 			(register_t)address);
 
 }
-#endif	/* MIPS_DDB_WATCH */
+#endif	/* (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 */
 
 #ifdef MIPS64_XLS
 void
@@ -787,14 +723,14 @@
 	{ DDB_ADD_CMD("cp0",	db_cp0dump_cmd,	0,
 		"Dump CP0 registers.",
 		NULL, NULL) },
-#ifdef MIPS_DDB_WATCH
+#if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
 	{ DDB_ADD_CMD("watch",	db_watch_cmd,		CS_MORE,
 		"set cp0 watchpoint",
 		"address <mask> <asid> </rwxma>", NULL) },
 	{ DDB_ADD_CMD("unwatch",db_unwatch_cmd,		0,
 		"delete cp0 watchpoint",
 		"address", NULL) },
-#endif	/* MIPS_DDB_WATCH */
+#endif	/* (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 */
 	{ DDB_ADD_CMD("kvtop",	db_kvtophys_cmd,	0,
 		"Print the physical address for a given kernel virtual address",
 		"address", 
@@ -1029,8 +965,7 @@
 			db_printf("CPU %ld not paused\n", (long)addr);
 			return;
 		}
-		/* no locking needed - all other cpus are paused */
-		ddb_cpu = cpu_index(ci);
+		(void)atomic_cas_uint(&ddb_cpu, cpu_number(), cpu_index(ci));
 		db_continue_cmd(0, false, 0, "");
 	}
 }

Reply via email to