Index: head/sys/arm/arm/debug_monitor.c =================================================================== --- head/sys/arm/arm/debug_monitor.c +++ head/sys/arm/arm/debug_monitor.c @@ -72,9 +72,8 @@ static int dbg_remove_xpoint(struct dbg_wb_conf *); static int dbg_setup_xpoint(struct dbg_wb_conf *); -static boolean_t dbg_capable; /* Indicates that machine is capable of using +static int dbg_capable_var; /* Indicates that machine is capable of using HW watchpoints/breakpoints */ -static boolean_t dbg_ready[MAXCPU]; /* Debug arch. reset performed on this CPU */ static uint32_t dbg_model; /* Debug Arch. Model */ static boolean_t dbg_ossr; /* OS Save and Restore implemented */ @@ -245,6 +244,13 @@ isb(); } +static __inline boolean_t +dbg_capable(void) +{ + + return (atomic_cmpset_int(&dbg_capable_var, 0, 0) == 0); +} + boolean_t kdb_cpu_pc_is_singlestep(db_addr_t pc) { @@ -253,7 +259,7 @@ * there will be no stepping capabilities * (SOFTWARE_SSTEP is not defined for __ARM_ARCH >= 6). */ - if (!dbg_capable) + if (!dbg_capable()) return (FALSE); if (dbg_find_slot(DBG_TYPE_BREAKPOINT, pc) != ~0U) @@ -270,7 +276,7 @@ uint32_t wcr; u_int i; - if (!dbg_capable) + if (!dbg_capable()) return; /* @@ -303,7 +309,7 @@ uint32_t wvr, wcr; u_int i; - if (!dbg_capable) + if (!dbg_capable()) return; dbg_remove_breakpoint(DBG_BKPT_BT_SLOT); @@ -423,7 +429,7 @@ boolean_t is_enabled; int i; - if (!dbg_capable) { + if (!dbg_capable()) { db_printf("Architecture does not support HW " "breakpoints/watchpoints\n"); return; @@ -591,24 +597,15 @@ uint32_t cr_size, cr_priv, cr_access; uint32_t reg_ctrl, reg_addr, ctrl, addr; boolean_t is_bkpt; - u_int cpuid, cpu; + u_int cpu; u_int i; - int err; - if (!dbg_capable) + if (!dbg_capable()) return (ENXIO); is_bkpt = (conf->type == DBG_TYPE_BREAKPOINT); typestr = is_bkpt ? "breakpoint" : "watchpoint"; - cpuid = PCPU_GET(cpuid); - if (!dbg_ready[cpuid]) { - err = dbg_reset_state(); - if (err != 0) - return (err); - dbg_ready[cpuid] = TRUE; - } - if (is_bkpt) { if (dbg_breakpoint_num == 0) { db_printf("Breakpoints not supported on this architecture\n"); @@ -698,7 +695,7 @@ d->dbg_wvr[i] = addr; d->dbg_wcr[i] = ctrl; /* Skip update command for the current CPU */ - if (cpu != cpuid) + if (cpu != PCPU_GET(cpuid)) pcpu->pc_dbreg_cmd = PC_DBREG_CMD_LOAD; } } @@ -715,23 +712,13 @@ struct dbreg *d; uint32_t reg_ctrl, reg_addr, addr; boolean_t is_bkpt; - u_int cpuid, cpu; + u_int cpu; u_int i; - int err; - if (!dbg_capable) + if (!dbg_capable()) return (ENXIO); is_bkpt = (conf->type == DBG_TYPE_BREAKPOINT); - - cpuid = PCPU_GET(cpuid); - if (!dbg_ready[cpuid]) { - err = dbg_reset_state(); - if (err != 0) - return (err); - dbg_ready[cpuid] = TRUE; - } - addr = conf->address; if (is_bkpt) { @@ -764,7 +751,7 @@ d->dbg_wvr[i] = 0; d->dbg_wcr[i] = 0; /* Skip update command for the current CPU */ - if (cpu != cpuid) + if (cpu != PCPU_GET(cpuid)) pcpu->pc_dbreg_cmd = PC_DBREG_CMD_LOAD; } /* Ensure all data is written before waking other CPUs */ @@ -966,7 +953,7 @@ if (err == 0) { err = dbg_enable_monitor(); if (err == 0) { - dbg_capable = TRUE; + atomic_set_int(&dbg_capable_var, 1); return; } } @@ -978,18 +965,50 @@ CTASSERT(sizeof(struct dbreg) == sizeof(((struct pcpu *)NULL)->pc_dbreg)); void +dbg_monitor_init_secondary(void) +{ + u_int cpuid; + int err; + /* + * This flag is set on the primary CPU + * and its meaning is valid for other CPUs too. + */ + if (!dbg_capable()) + return; + + cpuid = PCPU_GET(cpuid); + + err = dbg_reset_state(); + if (err != 0) { + /* + * Something is very wrong. + * WPs/BPs will not work correctly on this CPU. + */ + KASSERT(0, ("%s: Failed to reset Debug Architecture " + "state on CPU%d", __func__, cpuid)); + /* Disable HW debug capabilities for all CPUs */ + atomic_set_int(&dbg_capable_var, 0); + return; + } + err = dbg_enable_monitor(); + if (err != 0) { + KASSERT(0, ("%s: Failed to enable Debug Monitor" + " on CPU%d", __func__, cpuid)); + atomic_set_int(&dbg_capable_var, 0); + } +} + +void dbg_resume_dbreg(void) { struct dbreg *d; - u_int cpuid; u_int i; - int err; /* * This flag is set on the primary CPU * and its meaning is valid for other CPUs too. */ - if (!dbg_capable) + if (!dbg_capable()) return; atomic_thread_fence_acq(); @@ -997,21 +1016,6 @@ switch (PCPU_GET(dbreg_cmd)) { case PC_DBREG_CMD_LOAD: d = (struct dbreg *)PCPU_PTR(dbreg); - cpuid = PCPU_GET(cpuid); - - /* Reset Debug Architecture State if not done earlier */ - if (!dbg_ready[cpuid]) { - err = dbg_reset_state(); - if (err != 0) { - /* - * Something is very wrong. - * WPs/BPs will not work correctly in this CPU. - */ - panic("%s: Failed to reset Debug Architecture " - "state on CPU%d", __func__, cpuid); - } - dbg_ready[cpuid] = TRUE; - } /* Restore watchpoints */ for (i = 0; i < dbg_watchpoint_num; i++) { Index: head/sys/arm/arm/mp_machdep.c =================================================================== --- head/sys/arm/arm/mp_machdep.c +++ head/sys/arm/arm/mp_machdep.c @@ -23,6 +23,9 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include "opt_ddb.h" +#include "opt_smp.h" + #include __FBSDID("$FreeBSD$"); #include @@ -60,8 +63,6 @@ #include #endif -#include "opt_smp.h" - extern struct pcpu __pcpu[]; /* used to hold the AP's until we are ready to release them */ struct mtx ap_boot_mtx; @@ -176,6 +177,9 @@ pcpu_init(pc, cpu, sizeof(struct pcpu)); dpcpu_init(dpcpu[cpu - 1], cpu); +#if __ARM_ARCH >= 6 && defined(DDB) + dbg_monitor_init_secondary(); +#endif /* Signal our startup to BSP */ atomic_add_rel_32(&mp_naps, 1); Index: head/sys/arm/include/debug_monitor.h =================================================================== --- head/sys/arm/include/debug_monitor.h +++ head/sys/arm/include/debug_monitor.h @@ -45,6 +45,7 @@ #if __ARM_ARCH >= 6 void dbg_monitor_init(void); +void dbg_monitor_init_secondary(void); void dbg_show_watchpoint(void); int dbg_setup_watchpoint(db_expr_t, db_expr_t, enum dbg_access_t); int dbg_remove_watchpoint(db_expr_t, db_expr_t); @@ -69,7 +70,10 @@ dbg_monitor_init(void) { } - +static __inline void +dbg_monitor_init_secondary(void) +{ +} static __inline void dbg_resume_dbreg(void) {