From owner-p4-projects@FreeBSD.ORG Mon Jul 9 16:53:49 2007 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 13E0C16A400; Mon, 9 Jul 2007 16:53:48 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 6B6C816A473 for ; Mon, 9 Jul 2007 16:53:48 +0000 (UTC) (envelope-from marcel@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id 52E8513C45B for ; Mon, 9 Jul 2007 16:53:48 +0000 (UTC) (envelope-from marcel@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.8/8.13.8) with ESMTP id l69GrmlX080325 for ; Mon, 9 Jul 2007 16:53:48 GMT (envelope-from marcel@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.8/8.13.8/Submit) id l69GrlYv080322 for perforce@freebsd.org; Mon, 9 Jul 2007 16:53:47 GMT (envelope-from marcel@freebsd.org) Date: Mon, 9 Jul 2007 16:53:47 GMT Message-Id: <200707091653.l69GrlYv080322@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to marcel@freebsd.org using -f From: Marcel Moolenaar To: Perforce Change Reviews Cc: Subject: PERFORCE change 123213 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Jul 2007 16:53:49 -0000 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 #include #include +#include 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 #include #include +#include #include #include @@ -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 #include #include +#include #include @@ -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