Module Name: src Committed By: cliff Date: Thu Apr 14 05:08:51 UTC 2011
Modified Files: src/sys/arch/mips/mips: cpu_subr.c Log Message: - MIPS CPU (COP0) watchpoint support moved from db_interface.c to cpu_subr.c see the cpuwatch_* functions - ci_cpuwatch_count in allocated cpu_info is inherited from cpu_info_store - cpu_hatch() calls lsw_cpu_run (if not NULL) to optionally allow running MIPS chip-specific code after subordinate cpus have been set running - #ifdef DDB cpu_debug_dump() to allow compile when DDB not defined To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/sys/arch/mips/mips/cpu_subr.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/cpu_subr.c diff -u src/sys/arch/mips/mips/cpu_subr.c:1.6 src/sys/arch/mips/mips/cpu_subr.c:1.7 --- src/sys/arch/mips/mips/cpu_subr.c:1.6 Wed Apr 6 05:53:27 2011 +++ src/sys/arch/mips/mips/cpu_subr.c Thu Apr 14 05:08:51 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu_subr.c,v 1.6 2011/04/06 05:53:27 matt Exp $ */ +/* $NetBSD: cpu_subr.c,v 1.7 2011/04/14 05:08:51 cliff Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.6 2011/04/06 05:53:27 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.7 2011/04/14 05:08:51 cliff Exp $"); #include "opt_ddb.h" #include "opt_multiprocessor.h" @@ -101,7 +101,6 @@ static int cpu_ipi_wait(volatile __cpuset_t *, u_long); static void cpu_ipi_error(const char *, __cpuset_t, __cpuset_t); - static struct cpu_info *cpu_info_last = &cpu_info_store; struct cpu_info * @@ -151,6 +150,7 @@ ci->ci_cycles_per_hz = cpu_info_store.ci_cycles_per_hz; ci->ci_divisor_delay = cpu_info_store.ci_divisor_delay; ci->ci_divisor_recip = cpu_info_store.ci_divisor_recip; + ci->ci_cpuwatch_count = cpu_info_store.ci_cpuwatch_count; /* * Attach its TLB info (which must be direct-mapped) @@ -785,9 +785,6 @@ #endif break; } -#if defined(DDB) && defined(MIPS_DDB_WATCH) - db_mach_watch_set_all(); -#endif splx(s); } @@ -848,6 +845,7 @@ return CPUSET_HAS_P(cpus_paused, index); } +#ifdef DDB void cpu_debug_dump(void) { @@ -871,6 +869,7 @@ ci->ci_active_ipis, ci->ci_request_ipis); } } +#endif void cpu_hatch(struct cpu_info *ci) @@ -934,6 +933,13 @@ ci->ci_data.cpu_cc_skew = 0; /* + * Let this CPU do its own post-running initialization + * (for things that have to be done on the local CPU). + */ + if (mips_locoresw.lsw_cpu_run != NULL) + (*mips_locoresw.lsw_cpu_run)(ci); + + /* * Now turn on interrupts. */ spl0(); @@ -1007,3 +1013,136 @@ #endif return 0; } + + +#if (CPUWATCH_MAX != 8) +# error CPUWATCH_MAX +#endif + +/* + * cpuwatch_discover - determine how many COP0 watchpoints this CPU supports + */ +u_int +cpuwatch_discover(void) +{ + int i; + + for (i=0; i < CPUWATCH_MAX; i++) { + uint32_t watchhi = mipsNN_cp0_watchhi_read(i); + if ((watchhi & __BIT(31)) == 0) /* test 'M' bit */ + break; + } + return i + 1; +} + +void +cpuwatch_free(cpu_watchpoint_t *cwp) +{ +#ifdef DIAGNOSTIC + struct cpu_info * const ci = curcpu(); + KASSERT(cwp >= &ci->ci_cpuwatch_tab[0] && + cwp <= &ci->ci_cpuwatch_tab[ci->ci_cpuwatch_count-1]); +#endif + cwp->cw_mode = 0; + cwp->cw_asid = 0; + cwp->cw_addr = 0; + cpuwatch_clr(cwp); +} + +/* + * cpuwatch_alloc + * find an empty slot + * no locking for the table since it is CPU private + */ +cpu_watchpoint_t * +cpuwatch_alloc(void) +{ + struct cpu_info * const ci = curcpu(); + cpu_watchpoint_t *cwp; + + for (int i=0; i < ci->ci_cpuwatch_count; i++) { + cwp = &ci->ci_cpuwatch_tab[i]; + if ((cwp->cw_mode & CPUWATCH_RWX) == 0) + return cwp; + } + return NULL; +} + + +void +cpuwatch_set_all(void) +{ + struct cpu_info * const ci = curcpu(); + cpu_watchpoint_t *cwp; + int i; + + for (i=0; i < ci->ci_cpuwatch_count; i++) { + cwp = &ci->ci_cpuwatch_tab[i]; + if ((cwp->cw_mode & CPUWATCH_RWX) != 0) + cpuwatch_set(cwp); + } +} + +void +cpuwatch_clr_all(void) +{ + struct cpu_info * const ci = curcpu(); + cpu_watchpoint_t *cwp; + int i; + + for (i=0; i < ci->ci_cpuwatch_count; i++) { + cwp = &ci->ci_cpuwatch_tab[i]; + if ((cwp->cw_mode & CPUWATCH_RWX) != 0) + cpuwatch_clr(cwp); + } +} + +/* + * cpuwatch_set - establish a MIPS COP0 watchpoint + */ +void +cpuwatch_set(cpu_watchpoint_t *cwp) +{ + struct cpu_info * const ci = curcpu(); + uint32_t watchhi; + register_t watchlo; + int cwnum = cwp - &ci->ci_cpuwatch_tab[0]; + + KASSERT(cwp >= &ci->ci_cpuwatch_tab[0] && + cwp <= &ci->ci_cpuwatch_tab[ci->ci_cpuwatch_count-1]); + + watchlo = cwp->cw_addr; + if (cwp->cw_mode & CPUWATCH_WRITE) + watchlo |= __BIT(0); + if (cwp->cw_mode & CPUWATCH_READ) + watchlo |= __BIT(1); + if (cwp->cw_mode & CPUWATCH_EXEC) + watchlo |= __BIT(2); + + if (cwp->cw_mode & CPUWATCH_ASID) + watchhi = cwp->cw_asid << 16; /* addr qualified by asid */ + else + watchhi = __BIT(30); /* addr not qual. by asid (Global) */ + if (cwp->cw_mode & CPUWATCH_MASK) + watchhi |= cwp->cw_mask; /* set "dont care" addr match bits */ + + mipsNN_cp0_watchhi_write(cwnum, watchhi); + mipsNN_cp0_watchlo_write(cwnum, watchlo); +} + +/* + * cpuwatch_clr - disestablish a MIPS COP0 watchpoint + */ +void +cpuwatch_clr(cpu_watchpoint_t *cwp) +{ + struct cpu_info * const ci = curcpu(); + int cwnum = cwp - &ci->ci_cpuwatch_tab[0]; + + KASSERT(cwp >= &ci->ci_cpuwatch_tab[0] && + cwp <= &ci->ci_cpuwatch_tab[ci->ci_cpuwatch_count-1]); + + mipsNN_cp0_watchhi_write(cwnum, 0); + mipsNN_cp0_watchlo_write(cwnum, 0); +} +