diff --git a/sys/arch/mips/mips/db_interface.c b/sys/arch/mips/mips/db_interface.c index 28e0b93001eb..d719b66a8983 100644 --- a/sys/arch/mips/mips/db_interface.c +++ b/sys/arch/mips/mips/db_interface.c @@ -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 -__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 @@ __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.70 2011/04/06 05:53:27 matt Exp $ #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 @@ kdb_trap(int type, struct reg *regs) break; } + s = splhigh(); + #ifdef MULTIPROCESSOR bool first_in_ddb = false; const u_int cpu_me = cpu_number(); @@ -155,26 +138,25 @@ kdb_trap(int type, struct reg *regs) 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 @@ kdb_trap(int type, struct reg *regs) } #endif - *regs = ddb_regs; - - return (1); + splx(s); + return 1; } void @@ -411,10 +392,12 @@ db_cp0dump_cmd(db_expr_t addr, bool have_addr, db_expr_t count, 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 @@ db_cp0dump_cmd(db_expr_t addr, bool have_addr, db_expr_t count, 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"); - } - } - - 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_ERROR_PC, "errorpc"); + uint32_t r = mipsNN_cp0_watchhi_read(i); + printf(" %s%d:%*s %#x\n", + "watchhi", i, FLDWIDTH - 8, "", r); } else { - SHOW32(MIPS_COP_0_ERROR_PC, "errorpc"); + uint64_t r = mipsNN_cp0_watchhi_read(i); + printf(" %s%d:%*s %#" PRIx64 "\n", + "watchhi", i, FLDWIDTH - 8, "", r); } } -} - -#ifdef MIPS_DDB_WATCH -void -db_mach_watch_set_all(void) -{ - volatile struct db_mach_watch *wp; - int i; - - 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); - } -} - -/* - * 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); +#endif if (CPUIS64BITS) { - MIPS64_SET64(MIPS_COP_0_WATCH_LO, 0, strlo, watchlo); + SHOW64(MIPS_COP_0_TLB_XCONTEXT, "xcontext"); + } + + if (CPUISMIPSNN) { + if (CPUIS64BITS) { + SHOW64(MIPS_COP_0_PERFCNT, "perfcnt"); + } else { + SHOW32(MIPS_COP_0_PERFCNT, "perfcnt"); + } + } + + 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_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 @@ db_watch_cmd(db_expr_t address, bool have_addr, db_expr_t count, 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 @@ db_watch_cmd(db_expr_t address, bool have_addr, db_expr_t count, /* * 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 @@ db_watch_cmd(db_expr_t address, bool have_addr, db_expr_t count, * 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 @@ db_watch_cmd(db_expr_t address, bool have_addr, db_expr_t count, 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 @@ db_watch_cmd(db_expr_t address, bool have_addr, db_expr_t count, * 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 @@ db_unwatch_cmd(db_expr_t address, bool have_addr, db_expr_t count, (register_t)address); } -#endif /* MIPS_DDB_WATCH */ +#endif /* (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 */ #ifdef MIPS64_XLS void @@ -787,14 +723,14 @@ const struct db_command db_machine_command_table[] = { { 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 ", 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_mach_cpu(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) 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, ""); } }