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, "");
}
}