Author: zbb
Date: Sun May 29 17:33:49 2016
New Revision: 300968
URL: https://svnweb.freebsd.org/changeset/base/300968

Log:
  Fix debug_monitor code for older ARMs (ARM11)
  
  - Enable monitor mode prior to accessing watchpoint
    registers for v6, v6.1 architectures.
  - Fix configuration scheme for v6, v6.1 and v7 Debug Archs
  - Enable monitor unconditionally and for good instead
    of enabling and disabling it (needed for single stepping
    on on v6/v6.1)
  
  Tested on RPI-B and Arndale
  
  Differential Revision: https://reviews.freebsd.org/D6008

Modified:
  head/sys/arm/arm/debug_monitor.c

Modified: head/sys/arm/arm/debug_monitor.c
==============================================================================
--- head/sys/arm/arm/debug_monitor.c    Sun May 29 17:32:19 2016        
(r300967)
+++ head/sys/arm/arm/debug_monitor.c    Sun May 29 17:33:49 2016        
(r300968)
@@ -82,8 +82,6 @@ static boolean_t dbg_ossr;    /* OS Save an
 static uint32_t dbg_watchpoint_num;
 static uint32_t dbg_breakpoint_num;
 
-static int dbg_ref_count_mme; /* Times monitor mode was enabled */
-
 /* ID_DFR0 - Debug Feature Register 0 */
 #define        ID_DFR0_CP_DEBUG_M_SHIFT        0
 #define        ID_DFR0_CP_DEBUG_M_MASK         (0xF << 
ID_DFR0_CP_DEBUG_M_SHIFT)
@@ -250,6 +248,13 @@ dbg_wb_write_reg(int reg, int n, uint32_
 boolean_t
 kdb_cpu_pc_is_singlestep(db_addr_t pc)
 {
+       /*
+        * XXX: If the platform fails to enable its debug arch.
+        *      there will be no stepping capabilities
+        *      (SOFTWARE_SSTEP is not defined for __ARM_ARCH >= 6).
+        */
+       if (!dbg_capable)
+               return (FALSE);
 
        if (dbg_find_slot(DBG_TYPE_BREAKPOINT, pc) != ~0U)
                return (TRUE);
@@ -265,6 +270,9 @@ kdb_cpu_set_singlestep(void)
        uint32_t wcr;
        u_int i;
 
+       if (!dbg_capable)
+               return;
+
        /*
         * Disable watchpoints, e.g. stepping over watched instruction will
         * trigger break exception instead of single-step exception and locks
@@ -295,6 +303,9 @@ kdb_cpu_clear_singlestep(void)
        uint32_t wvr, wcr;
        u_int i;
 
+       if (!dbg_capable)
+               return;
+
        dbg_remove_breakpoint(DBG_BKPT_BT_SLOT);
        dbg_remove_breakpoint(DBG_BKPT_BNT_SLOT);
 
@@ -572,34 +583,6 @@ dbg_enable_monitor(void)
 }
 
 static int
-dbg_disable_monitor(void)
-{
-       uint32_t dbg_dscr;
-
-       if (!dbg_monitor_is_enabled())
-               return (0);
-
-       dbg_dscr = cp14_dbgdscrint_get();
-       switch (dbg_model) {
-       case ID_DFR0_CP_DEBUG_M_V6:
-       case ID_DFR0_CP_DEBUG_M_V6_1: /* fall through */
-               dbg_dscr &= ~DBGSCR_MDBG_EN;
-               cp14_dbgdscr_v6_set(dbg_dscr);
-               break;
-       case ID_DFR0_CP_DEBUG_M_V7: /* fall through */
-       case ID_DFR0_CP_DEBUG_M_V7_1:
-               dbg_dscr &= ~DBGSCR_MDBG_EN;
-               cp14_dbgdscr_v7_set(dbg_dscr);
-               break;
-       default:
-               return (ENXIO);
-       }
-       isb();
-
-       return (0);
-}
-
-static int
 dbg_setup_xpoint(struct dbg_wb_conf *conf)
 {
        struct pcpu *pcpu;
@@ -702,13 +685,6 @@ dbg_setup_xpoint(struct dbg_wb_conf *con
        dbg_wb_write_reg(reg_addr, i, addr);
        dbg_wb_write_reg(reg_ctrl, i, ctrl);
 
-       err = dbg_enable_monitor();
-       if (err != 0)
-               return (err);
-
-       /* Increment monitor enable counter */
-       dbg_ref_count_mme++;
-
        /*
         * Save watchpoint settings for all CPUs.
         * We don't need to do the same with breakpoints since HW breakpoints
@@ -775,19 +751,6 @@ dbg_remove_xpoint(struct dbg_wb_conf *co
        dbg_wb_write_reg(reg_ctrl, i, 0);
        dbg_wb_write_reg(reg_addr, i, 0);
 
-       /* Decrement monitor enable counter */
-       dbg_ref_count_mme--;
-       if (dbg_ref_count_mme < 0)
-               dbg_ref_count_mme = 0;
-
-       atomic_thread_fence_rel();
-
-       if (dbg_ref_count_mme == 0) {
-               err = dbg_disable_monitor();
-               if (err != 0)
-                       return (err);
-       }
-
        /*
         * Save watchpoint settings for all CPUs.
         * We don't need to do the same with breakpoints since HW breakpoints
@@ -827,7 +790,7 @@ dbg_get_ossr(void)
 {
 
        switch (dbg_model) {
-       case ID_DFR0_CP_DEBUG_M_V6_1:
+       case ID_DFR0_CP_DEBUG_M_V7:
                if ((cp14_dbgoslsr_get() & DBGOSLSR_OSLM0) != 0)
                        return (TRUE);
 
@@ -844,10 +807,8 @@ dbg_arch_supported(void)
 {
 
        switch (dbg_model) {
-#ifdef not_yet
        case ID_DFR0_CP_DEBUG_M_V6:
        case ID_DFR0_CP_DEBUG_M_V6_1:
-#endif
        case ID_DFR0_CP_DEBUG_M_V7:
        case ID_DFR0_CP_DEBUG_M_V7_1:   /* fall through */
                return (TRUE);
@@ -889,9 +850,16 @@ dbg_reset_state(void)
 
        switch (dbg_model) {
        case ID_DFR0_CP_DEBUG_M_V6:
-               /* v6 Debug logic reset upon power-up */
-               return (0);
-       case ID_DFR0_CP_DEBUG_M_V6_1:
+       case ID_DFR0_CP_DEBUG_M_V6_1: /* fall through */
+               /*
+                * Arch needs monitor mode selected and enabled
+                * to be able to access breakpoint/watchpoint registers.
+                */
+               err = dbg_enable_monitor();
+               if (err != 0)
+                       return (err);
+               goto vectr_clr;
+       case ID_DFR0_CP_DEBUG_M_V7:
                /* Is core power domain powered up? */
                if ((cp14_dbgprsr_get() & DBGPRSR_PU) == 0)
                        err = ENXIO;
@@ -902,8 +870,6 @@ dbg_reset_state(void)
                if (dbg_ossr)
                        goto vectr_clr;
                break;
-       case ID_DFR0_CP_DEBUG_M_V7:
-               break;
        case ID_DFR0_CP_DEBUG_M_V7_1:
                /* Is double lock set? */
                if ((cp14_dbgosdlr_get() & DBGPRSR_DLK) != 0)
@@ -998,8 +964,11 @@ dbg_monitor_init(void)
 
        err = dbg_reset_state();
        if (err == 0) {
-               dbg_capable = TRUE;
-               return;
+               err = dbg_enable_monitor();
+               if (err == 0) {
+                       dbg_capable = TRUE;
+                       return;
+               }
        }
 
        db_printf("HW Breakpoints/Watchpoints not enabled on CPU%d\n",
@@ -1050,21 +1019,6 @@ dbg_resume_dbreg(void)
                        dbg_wb_write_reg(DBG_REG_BASE_WCR, i, d->dbg_wcr[i]);
                }
 
-               if ((dbg_ref_count_mme > 0) && !dbg_monitor_is_enabled()) {
-                       err = dbg_enable_monitor();
-                       if (err != 0) {
-                               panic("%s: Failed to enable Debug Monitor "
-                                   "on CPU%d", __func__, cpuid);
-                       }
-               }
-               if ((dbg_ref_count_mme == 0) && dbg_monitor_is_enabled()) {
-                       err = dbg_disable_monitor();
-                       if (err != 0) {
-                               panic("%s: Failed to disable Debug Monitor "
-                                   "on CPU%d", __func__, cpuid);
-                       }
-               }
-
                PCPU_SET(dbreg_cmd, PC_DBREG_CMD_NONE);
                break;
        }
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to