PERFORCE change 123213 for review

Marcel Moolenaar marcel at FreeBSD.org
Mon Jul 9 16:53:49 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=123213

Change 123213 by marcel at marcel_xcllnt on 2007/07/09 16:53:19

	Add hardware watchpoint support. Rough implementation.

Affected files ...

.. //depot/projects/powerpc/contrib/gdb/gdb/config/powerpc/nm-fbsd.h#2 edit
.. //depot/projects/powerpc/contrib/gdb/gdb/ppcfbsd-nat.c#3 edit
.. //depot/projects/powerpc/sys/powerpc/include/pcb.h#4 edit
.. //depot/projects/powerpc/sys/powerpc/include/reg.h#5 edit
.. //depot/projects/powerpc/sys/powerpc/include/spr.h#3 edit
.. //depot/projects/powerpc/sys/powerpc/powerpc/genassym.c#5 edit
.. //depot/projects/powerpc/sys/powerpc/powerpc/machdep.c#11 edit
.. //depot/projects/powerpc/sys/powerpc/powerpc/swtch.S#2 edit
.. //depot/projects/powerpc/sys/powerpc/powerpc/trap.c#7 edit
.. //depot/projects/powerpc/sys/powerpc/powerpc/vm_machdep.c#7 edit

Differences ...

==== //depot/projects/powerpc/contrib/gdb/gdb/config/powerpc/nm-fbsd.h#2 (text+ko) ====

@@ -15,4 +15,22 @@
 /* Override child_pid_to_exec_file in 'inftarg.c'.  */
 #define	CHILD_PID_TO_EXEC_FILE
 
+/*
+ * Hardware watchpoint support.
+ */
+#define TARGET_HAS_HARDWARE_WATCHPOINTS
+
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot)	\
+	ppc_can_use_hwatch(type, cnt, ot)
+
+#define TARGET_REGION_OK_FOR_HW_WATCHPOINT(addr, len)		\
+	ppc_region_ok_for_hwatch(addr, len)
+
+#define target_insert_watchpoint	ppc_insert_watchpoint
+#define target_remove_watchpoint	ppc_remove_watchpoint
+
+#define HAVE_NONSTEPPABLE_WATCHPOINT	1
+
+#define STOPPED_BY_WATCHPOINT(W)	ppc_stopped_by_hwatch()
+
 #endif /* NM_FBSD_H */

==== //depot/projects/powerpc/contrib/gdb/gdb/ppcfbsd-nat.c#3 (text+ko) ====

@@ -160,6 +160,67 @@
   ppcfbsd_supply_fpreg (fpregs, -1);
 }
 
+/*
+ * hardware watchpoint support.
+ */
+
+int
+ppc_can_use_hwatch(int type, int count, int type_used)
+{
+
+	// printf("XXX: %s(%d, %d, %d)\n", __func__, type, count, type_used);
+	return ((type == bp_hardware_watchpoint && count == 1) ? 1 : 0);
+}
+
+int
+ppc_region_ok_for_hwatch(CORE_ADDR addr, int len)
+{
+
+	// printf("XXX: %s(%lld, %d)\n", __func__, addr, len);
+	return ((addr >> 3 == (addr + len - 1) >> 3) ? 1 : 0);
+}
+
+int
+ppc_stopped_by_hwatch(void)
+{
+	struct dbreg dbreg;
+
+	// printf("XXX: %s(%d)\n", __func__, ws);
+	if (ptrace(PT_GETDBREGS, PIDGET(inferior_ptid),
+	    (PTRACE_ARG3_TYPE)&dbreg, 0) == -1)
+		return (0);
+	if (dbreg.dabr == 0)
+		return (0);
+	return ((dbreg.wppc == read_pc()) ? 1 : 0);
+}
+
+int
+ppc_insert_watchpoint(CORE_ADDR addr, int len, int type)
+{
+	struct dbreg dbreg;
+
+	// printf("XXX: %s(%lld, %d, %d)\n", __func__, addr, len, type);
+	dbreg.dabr = addr & ~7U;
+	dbreg.dabr |= 0x6;
+	if (ptrace(PT_SETDBREGS, PIDGET(inferior_ptid),
+	    (PTRACE_ARG3_TYPE)&dbreg, 0) == -1)
+		return (errno);
+	return (0);
+}
+
+int
+ppc_remove_watchpoint(CORE_ADDR addr, int len, int type)
+{
+	struct dbreg dbreg;
+
+	// printf("XXX: %s(%lld, %d, %d)\n", __func__, addr, len, type);
+	dbreg.dabr = 0;
+	if (ptrace(PT_SETDBREGS, PIDGET(inferior_ptid), 
+	    (PTRACE_ARG3_TYPE)&dbreg, 0) == -1)
+		return (errno);
+	return (0);
+}
+
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 void _initialize_ppcfbsd_nat (void);
 

==== //depot/projects/powerpc/sys/powerpc/include/pcb.h#4 (text+ko) ====

@@ -48,7 +48,12 @@
 	faultbuf	*pcb_onfault;		/* For use during
 						    copyin/copyout */
 	int		pcb_flags;
-#define	PCB_FPU		1	/* Process had FPU initialized */
+#define	PCB_FPU		1		/* Process had FPU initialized */
+#define	PCB_DBREGS	2		/* Process had DB registers */
+
+	register_t	pcb_dabr;
+	register_t	pcb_wppc;
+
 	struct fpu {
 		double	fpr[32];
 		double	fpscr;	/* FPSCR stored as double for easier access */

==== //depot/projects/powerpc/sys/powerpc/include/reg.h#5 (text+ko) ====

@@ -21,7 +21,8 @@
 };
 
 struct dbreg {
-	unsigned long	junk;
+	register_t	dabr;
+	register_t	wppc;
 };
 
 #ifdef _KERNEL

==== //depot/projects/powerpc/sys/powerpc/include/spr.h#3 (text+ko) ====

@@ -404,6 +404,7 @@
 #define	  MSSCR0_EMODE		  0x00200000 /* 10: MPX bus mode (read-only) */
 #define	  MSSCR0_ABD		  0x00100000 /* 11: address bus driven (read-only) */
 #define	  MSSCR0_MBZ		  0x000fffff /* 12-31: must be zero */
+#define	SPR_DABRX		0x3f7	/* .6. DABR extension */
 #define	SPR_DAC2		0x3f7	/* 4.. Data Address Compare 2 */
 #define	SPR_L2PM		0x3f8	/* .6. L2 Private Memory Control Register */
 #define	SPR_L2CR		0x3f9	/* .6. L2 Control Register */

==== //depot/projects/powerpc/sys/powerpc/powerpc/genassym.c#5 (text+ko) ====

@@ -54,6 +54,7 @@
 #include <machine/pcb.h>
 #include <machine/pmap.h>
 #include <machine/sigframe.h>
+#include <machine/spr.h>
 
 ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread));
 ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb));
@@ -134,8 +135,10 @@
 ASSYM(PCB_LR, offsetof(struct pcb, pcb_lr));
 ASSYM(PCB_USR, offsetof(struct pcb, pcb_usr));
 ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
+ASSYM(PCB_DABR, offsetof(struct pcb, pcb_dabr));
 ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
 ASSYM(PCB_FPU, PCB_FPU);
+ASSYM(PCB_DBREGS, PCB_DBREGS);
 
 ASSYM(TD_PROC, offsetof(struct thread, td_proc));
 ASSYM(TD_PCB, offsetof(struct thread, td_pcb));
@@ -152,3 +155,5 @@
 ASSYM(SF_UC, offsetof(struct sigframe, sf_uc));
 
 ASSYM(MAXCOMLEN, MAXCOMLEN);
+
+ASSYM(SPR_DABR, SPR_DABR);

==== //depot/projects/powerpc/sys/powerpc/powerpc/machdep.c#11 (text+ko) ====

@@ -114,6 +114,7 @@
 #include <machine/powerpc.h>
 #include <machine/reg.h>
 #include <machine/sigframe.h>
+#include <machine/spr.h>
 #include <machine/trap.h>
 #include <machine/vmparam.h>
 
@@ -791,6 +792,22 @@
 
 	tf->srr0 = entry;
 	tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
+
+	/*
+	 * Reset the hardware debug registers if they were in use.
+	 * They won't have any meaning for the newly exec'd process.  
+	 */
+	if (td->td_pcb->pcb_flags & PCB_DBREGS) {
+		if (td->td_pcb == PCPU_GET(curpcb)) {
+			/*
+			 * Clear the debug registers on the running
+			 * CPU, otherwise they will end up affecting
+			 * the next process we switch to.
+			 */
+			mtspr(SPR_DABR, 0);
+		}
+	}
+
 	td->td_pcb->pcb_flags = 0;
 }
 
@@ -808,8 +825,12 @@
 int
 fill_dbregs(struct thread *td, struct dbreg *dbregs)
 {
-	/* No debug registers on PowerPC */
-	return (ENOSYS);
+	int has_dbregs;
+
+	has_dbregs = (td->td_pcb->pcb_flags & PCB_DBREGS) ? 1 : 0;
+	dbregs->dabr = (has_dbregs) ? td->td_pcb->pcb_dabr : 0;
+	dbregs->wppc = (has_dbregs) ? td->td_pcb->pcb_wppc : 0;
+	return (0);
 }
 
 int
@@ -841,8 +862,17 @@
 int
 set_dbregs(struct thread *td, struct dbreg *dbregs)
 {
-	/* No debug registers on PowerPC */
-	return (ENOSYS);
+
+	td->td_pcb->pcb_dabr = dbregs->dabr;
+	td->td_pcb->pcb_wppc = 0;
+	if (dbregs->dabr != 0)
+		td->td_pcb->pcb_flags |= PCB_DBREGS;
+	else
+		td->td_pcb->pcb_flags &= ~PCB_DBREGS;
+	mtspr(SPR_DABRX, 1);
+	if (td == curthread)
+		mtspr(SPR_DABR, dbregs->dabr);
+	return (0);
 }
 
 int

==== //depot/projects/powerpc/sys/powerpc/powerpc/swtch.S#2 (text+ko) ====

@@ -90,7 +90,16 @@
 	mr	%r14,%r3		/* Copy the old thread ptr... */
 	mr	%r15,%r4		/* and the new thread ptr in scratch */
 	
-	lwz	%r6,PCB_FLAGS(%r5)	/* Save FPU context if needed */
+	lwz	%r6,PCB_FLAGS(%r5)
+	/* Save and reset the DABR if needed */
+	andi.	%r16, %r6, PCB_DBREGS
+	beq	.L0
+	mfspr	%r16, SPR_DABR
+	stw	%r16, PCB_DABR(%r5)
+	li	%r16, 0
+	mtspr	SPR_DABR, %r16
+.L0:
+	/* Save FPU context if needed */
 	andi.	%r6, %r6, PCB_FPU
 	beq	.L1
 	bl	save_fpu
@@ -107,13 +116,18 @@
 	stw	%r17,PC_CURPCB(%r7)
 
 	lwz	%r6, PCB_FLAGS(%r17)	/* Restore FPU context if needed */
+	andi.	%r16, %r6, PCB_DBREGS
+	beq	.L2
+	lwz	%r16, PCB_DABR(%r17)
+	mtspr	SPR_DABR, %r16
+.L2:
 	andi.	%r6, %r6, PCB_FPU
-	beq	.L2
+	beq	.L3
 	mr	%r3,%r15		/* Pass curthread to enable_fpu */
 	bl	enable_fpu
 
 	/* thread to restore is in r3 */
-.L2:
+.L3:
 	mr	%r3,%r17		/* Recover PCB ptr */
 	lmw	%r12,PCB_CONTEXT(%r3)	/* Load the non-volatile GP regs */
 	mr	%r2,%r12

==== //depot/projects/powerpc/sys/powerpc/powerpc/trap.c#7 (text+ko) ====

@@ -176,6 +176,13 @@
 			break;
 
 		case EXC_DSI:
+			if (frame->dsisr & DSISR_DABR) {
+				td->td_pcb->pcb_wppc = frame->srr0;
+				frame->dar = td->td_pcb->pcb_dabr & ~7;
+				sig = SIGTRAP;
+				break;
+			}
+			/* FALLTHROUGH */
 		case EXC_ISI:
 			sig = trap_pfault(frame, 1);
 			break;

==== //depot/projects/powerpc/sys/powerpc/powerpc/vm_machdep.c#7 (text+ko) ====

@@ -90,6 +90,7 @@
 #include <machine/md_var.h>
 #include <machine/pcb.h>
 #include <machine/powerpc.h>
+#include <machine/spr.h>
 
 #include <dev/ofw/openfirm.h>
 
@@ -269,6 +270,12 @@
 void
 cpu_thread_exit(struct thread *td)
 {
+
+	/* Disable any hardware breakpoints. */
+	if (td->td_pcb->pcb_flags & PCB_DBREGS) {
+		mtspr(SPR_DABR, 0);
+		td->td_pcb->pcb_flags &= ~PCB_DBREGS;
+	}
 }
 
 void


More information about the p4-projects mailing list