Date: Mon, 9 Jul 2007 16:53:47 GMT From: Marcel Moolenaar <marcel@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 123213 for review Message-ID: <200707091653.l69GrlYv080322@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=123213 Change 123213 by marcel@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200707091653.l69GrlYv080322>