Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 29 May 2016 17:33:49 +0000 (UTC)
From:      Zbigniew Bodek <zbb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r300968 - head/sys/arm/arm
Message-ID:  <201605291733.u4THXn93053932@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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;
 	}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201605291733.u4THXn93053932>