Title: [5244] trunk: Task[#3428] Update hardware breakpoint code in kgdb.
Revision
5244
Author
sonicz
Date
2008-09-04 05:03:55 -0500 (Thu, 04 Sep 2008)

Log Message

Task[#3428] Update hardware breakpoint code in kgdb.

Modified Paths

Diff

Modified: trunk/arch/blackfin/kernel/kgdb.c (5243 => 5244)


--- trunk/arch/blackfin/kernel/kgdb.c	2008-09-04 07:47:21 UTC (rev 5243)
+++ trunk/arch/blackfin/kernel/kgdb.c	2008-09-04 10:03:55 UTC (rev 5244)
@@ -204,58 +204,89 @@
 	unsigned int dataacc:2;
 	unsigned short count;
 	unsigned int addr;
-} breakinfo[HW_BREAKPOINT_NUM];
+} breakinfo[HW_WATCHPOINT_NUM];
 
 int bfin_set_hw_break(unsigned long addr, int len, enum kgdb_bptype type)
 {
 	int breakno;
+	int bfin_type;
+	int dataacc = 0;
 
 	switch (type) {
 	case BP_HARDWARE_BREAKPOINT:
-		for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++)
-			if (!breakinfo[breakno].occupied) {
-				breakinfo[breakno].occupied = 1;
-				breakinfo[breakno].enabled = 1;
-				breakinfo[breakno].type = 1;
-				breakinfo[breakno].addr = addr;
-				return 0;
-			}
+		bfin_type = TYPE_INST_WATCHPOINT;
 		break;
 	case BP_WRITE_WATCHPOINT:
+		dataacc = 1;
+		bfin_type = TYPE_DATA_WATCHPOINT;
+		break;
 	case BP_READ_WATCHPOINT:
+		dataacc = 2;
+		bfin_type = TYPE_DATA_WATCHPOINT;
+		break;
 	case BP_ACCESS_WATCHPOINT:
+		dataacc = 3;
+		bfin_type = TYPE_DATA_WATCHPOINT;
 		break;
 	default:
-		break;
+		return -ENOSPC;
 	};
 
+	for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++)
+		if (bfin_type == breakinfo[breakno].type
+			&& !breakinfo[breakno].occupied) {
+			breakinfo[breakno].occupied = 1;
+			breakinfo[breakno].enabled = 1;
+			breakinfo[breakno].addr = addr;
+			breakinfo[breakno].dataacc = dataacc;
+			breakinfo[breakno].count = 0;
+			return 0;
+		}
+
 	return -ENOSPC;
 }
 
 int bfin_remove_hw_break(unsigned long addr, int len, enum kgdb_bptype type)
 {
 	int breakno;
+	int bfin_type;
 
 	switch (type) {
 	case BP_HARDWARE_BREAKPOINT:
-		for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++)
-			if (breakinfo[breakno].addr == addr)
-				memset(&(breakinfo[breakno]), 0,
-					sizeof(struct hw_breakpoint));
+		bfin_type = TYPE_INST_WATCHPOINT;
+		break;
 	case BP_WRITE_WATCHPOINT:
 	case BP_READ_WATCHPOINT:
 	case BP_ACCESS_WATCHPOINT:
+		bfin_type = TYPE_DATA_WATCHPOINT;
 		break;
 	default:
-		break;
+		return 0;
 	};
 
+	for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++)
+		if (bfin_type == breakinfo[breakno].type
+			&& breakinfo[breakno].occupied
+			&& breakinfo[breakno].addr == addr)
+			breakinfo[breakno].occupied = 0;
+
 	return 0;
 }
 
 void bfin_remove_all_hw_break(void)
 {
-	memset(breakinfo, 0, sizeof(struct hw_breakpoint)*HW_BREAKPOINT_NUM);
+	int breakno;
+
+	bfin_write_WPIACTL(0);
+	bfin_write_WPDACTL(0);
+	CSYNC();
+
+	memset(breakinfo, 0, sizeof(struct hw_breakpoint)*HW_WATCHPOINT_NUM);
+
+	for (breakno = 0; breakno < HW_INST_WATCHPOINT_NUM; breakno++)
+		breakinfo[breakno].type = TYPE_INST_WATCHPOINT;
+	for (; breakno < HW_WATCHPOINT_NUM; breakno++)
+		breakinfo[breakno].type = TYPE_DATA_WATCHPOINT;
 }
 
 /*
@@ -270,105 +301,84 @@
 void bfin_correct_hw_break(void)
 {
 	int breakno;
-	int correctit;
-	uint32_t wpdactl = bfin_read_WPDACTL();
+	unsigned int wpiactl = 0;
+	unsigned int wpdactl = 0;
 
-	correctit = 0;
-	for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++) {
-		if (breakinfo[breakno].type == 1) {
+	for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++)
+		if (breakinfo[breakno].enabled)
 			switch (breakno) {
 			case 0:
-				if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN0)) {
-					correctit = 1;
-					wpdactl &= ~(WPIREN01|EMUSW0);
-					wpdactl |= WPIAEN0|WPICNTEN0;
-					bfin_write_WPIA0(breakinfo[breakno].addr);
-					bfin_write_WPIACNT0(breakinfo[breakno].skip);
-				} else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN0)) {
-					correctit = 1;
-					wpdactl &= ~WPIAEN0;
-				}
+				wpiactl |= WPIAEN0|WPICNTEN0;
+				wpiactl |= WPPWR;
+				bfin_write_WPIA0(breakinfo[breakno].addr);
+				bfin_write_WPIACNT0(breakinfo[breakno].count
+					+ breakinfo->skip);
 				break;
-
 			case 1:
-				if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN1)) {
-					correctit = 1;
-					wpdactl &= ~(WPIREN01|EMUSW1);
-					wpdactl |= WPIAEN1|WPICNTEN1;
-					bfin_write_WPIA1(breakinfo[breakno].addr);
-					bfin_write_WPIACNT1(breakinfo[breakno].skip);
-				} else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN1)) {
-					correctit = 1;
-					wpdactl &= ~WPIAEN1;
-				}
+				wpiactl |= WPIAEN1|WPICNTEN1;
+				wpiactl |= WPPWR;
+				bfin_write_WPIA1(breakinfo[breakno].addr);
+				bfin_write_WPIACNT1(breakinfo[breakno].count
+					+ breakinfo->skip);
 				break;
-
 			case 2:
-				if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN2)) {
-					correctit = 1;
-					wpdactl &= ~(WPIREN23|EMUSW2);
-					wpdactl |= WPIAEN2|WPICNTEN2;
-					bfin_write_WPIA2(breakinfo[breakno].addr);
-					bfin_write_WPIACNT2(breakinfo[breakno].skip);
-				} else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN2)) {
-					correctit = 1;
-					wpdactl &= ~WPIAEN2;
-				}
+				wpiactl |= WPIAEN2|WPICNTEN2;
+				wpiactl |= WPPWR;
+				bfin_write_WPIA2(breakinfo[breakno].addr);
+				bfin_write_WPIACNT2(breakinfo[breakno].count
+					+ breakinfo->skip);
 				break;
-
 			case 3:
-				if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN3)) {
-					correctit = 1;
-					wpdactl &= ~(WPIREN23|EMUSW3);
-					wpdactl |= WPIAEN3|WPICNTEN3;
-					bfin_write_WPIA3(breakinfo[breakno].addr);
-					bfin_write_WPIACNT3(breakinfo[breakno].skip);
-				} else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN3)) {
-					correctit = 1;
-					wpdactl &= ~WPIAEN3;
-				}
+				wpiactl |= WPIAEN3|WPICNTEN3;
+				wpiactl |= WPPWR;
+				bfin_write_WPIA3(breakinfo[breakno].addr);
+				bfin_write_WPIACNT3(breakinfo[breakno].count
+					+ breakinfo->skip);
 				break;
 			case 4:
-				if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN4)) {
-					correctit = 1;
-					wpdactl &= ~(WPIREN45|EMUSW4);
-					wpdactl |= WPIAEN4|WPICNTEN4;
-					bfin_write_WPIA4(breakinfo[breakno].addr);
-					bfin_write_WPIACNT4(breakinfo[breakno].skip);
-				} else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN4)) {
-					correctit = 1;
-					wpdactl &= ~WPIAEN4;
-				}
+				wpiactl |= WPIAEN4|WPICNTEN4;
+				wpiactl |= WPPWR;
+				bfin_write_WPIA4(breakinfo[breakno].addr);
+				bfin_write_WPIACNT4(breakinfo[breakno].count
+					+ breakinfo->skip);
 				break;
 			case 5:
-				if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN5)) {
-					correctit = 1;
-					wpdactl &= ~(WPIREN45|EMUSW5);
-					wpdactl |= WPIAEN5|WPICNTEN5;
-					bfin_write_WPIA5(breakinfo[breakno].addr);
-					bfin_write_WPIACNT5(breakinfo[breakno].skip);
-				} else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN5)) {
-					correctit = 1;
-					wpdactl &= ~WPIAEN5;
-				}
+				wpiactl |= WPIAEN5|WPICNTEN5;
+				wpiactl |= WPPWR;
+				bfin_write_WPIA5(breakinfo[breakno].addr);
+				bfin_write_WPIACNT5(breakinfo[breakno].count
+					+ breakinfo->skip);
 				break;
-			}
-		}
-	}
-	if (correctit) {
-		wpdactl &= ~WPAND;
-		wpdactl |= WPPWR;
-		/*printk("correct_hw_break: wpdactl=0x%x\n", wpdactl);*/
-		bfin_write_WPDACTL(wpdactl);
-		CSYNC();
-		/*kgdb_show_info();*/
-	}
+			case 6:
+				wpdactl |= WPDAEN0|WPDCNTEN0;
+				wpdactl |= breakinfo[breakno].dataacc
+					<< WPDACC0_OFFSET;
+				bfin_write_WPDA0(breakinfo[breakno].addr);
+				bfin_write_WPDACNT0(breakinfo[breakno].count
+					+ breakinfo->skip);
+				break;
+			case 7:
+				wpdactl |= WPDAEN1|WPDCNTEN1;
+				wpdactl |= breakinfo[breakno].dataacc
+					<< WPDACC1_OFFSET;
+				bfin_write_WPDA1(breakinfo[breakno].addr);
+				bfin_write_WPDACNT1(breakinfo[breakno].count
+					+ breakinfo->skip);
+				break;
+			};
+
+	/*printk("correct_hw_break: wpdactl=0x%x\n", wpdactl);*/
+	bfin_write_WPIACTL(wpiactl);
+	bfin_write_WPDACTL(wpdactl);
+	CSYNC();
+	/*kgdb_show_info();*/
 }
 
 void kgdb_disable_hw_debug(struct pt_regs *regs)
 {
 	/* Disable hardware debugging while we are in kgdb */
-	bfin_write_WPIACTL(bfin_read_WPIACTL() & ~0x1);
+	bfin_write_WPIACTL(0);
+	bfin_write_WPDACTL(0);
 	CSYNC();
 }
 
@@ -430,21 +440,19 @@
 			kgdb_single_step = i + 1;
 		}
 
-		wp_status = bfin_read_WPSTAT();
-		CSYNC();
-
 		if (vector == VEC_WATCH) {
-			for (breakno = 0; breakno < 6; ++breakno) {
+			wp_status = bfin_read_WPSTAT();
+			for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++) {
 				if (wp_status & (1 << breakno)) {
 					breakinfo->skip = 1;
 					break;
 				}
 			}
+			bfin_write_WPSTAT(0);
 		}
+
 		bfin_correct_hw_break();
 
-		bfin_write_WPSTAT(0);
-
 		return 0;
 	}			/* switch */
 	return -1;		/* this means that we do not want to exit from the handler */

Modified: trunk/include/asm-blackfin/kgdb.h (5243 => 5244)


--- trunk/include/asm-blackfin/kgdb.h	2008-09-04 07:47:21 UTC (rev 5243)
+++ trunk/include/asm-blackfin/kgdb.h	2008-09-04 10:03:55 UTC (rev 5244)
@@ -130,7 +130,10 @@
 }
 #define BREAK_INSTR_SIZE	2
 #define CACHE_FLUSH_IS_SAFE	1
-#define HW_BREAKPOINT_NUM	6
+#define HW_INST_WATCHPOINT_NUM	6
+#define HW_WATCHPOINT_NUM	8
+#define TYPE_INST_WATCHPOINT	1
+#define TYPE_DATA_WATCHPOINT	2
 
 /* Instruction watchpoint address control register bits mask */
 #define WPPWR		0x1
@@ -167,11 +170,12 @@
 #define WPDAEN1		0x8
 #define WPDCNTEN0	0x10
 #define WPDCNTEN1	0x20
-#define WPDSRC0		0xc0
-#define WPDACC0		0x300
-#define WPDSRC1		0xc00
-#define WPDACC1		0x3000
 
+#define WPDSRC0_OFFSET	6
+#define WPDACC0_OFFSET	8
+#define WPDSRC1_OFFSET	10
+#define WPDACC1_OFFSET	12
+
 /* Watchpoint status register bits mask */
 #define STATIA0		0x1
 #define STATIA1		0x2
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
http://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to