Re: bph / bpha not working.
"jidong xiao" <[email protected]> Thu, 8 May 2008 17:03:35 +0800
| Newsgroups | gmane.linux.kernel.debugging |
|---|---|
| Message-ID | <[email protected]> |
On Mon, May 5, 2008 at 6:44 PM, Konstantin Baydarov <[email protected]> wrote: > Yes It's known issue. > On Mon, 05 May 2008 13:06:11 +0300 > Avi Nehori <[email protected]> wrote: > > > Hi, > > I'm trying to set a watch point with bpha as follows : > > bpha address dataw 4 > > but the watchpoint is never called when the memory address is changed. > > is it a know bug ? > > is there a patch ? > > Here is my previous mail (http://oss.sgi.com/archives/kdb/2007-11/msg00037.html) with patch that fixes bpha problem: > Global HW BP don't work: > 1) Install global HW BP > [email protected]:~# > [email protected]:~# D > Entering kdb (current=0xc04433a0, pid 0) on processor 0 due to Keyboard Entry > [0]kdb> bpha do_sync > Forced Instruction(Register) BP #0 at 0xc0181539 (do_sync) > is enabled in dr0 globally > [0]kdb> go > > -bash: D: command not found > [email protected]:~# > > 1) Try CPU 0 > [email protected]:~# > [email protected]:~# taskset -c 0 sync > Instruction(Register) breakpoint #0 at 0xc0181539 > 0xc0181539 do_sync: push %ebx > > Entering kdb (0xc1b6d030, pid 1319) on processor 0 due to Debug @ 0xc0181539 > [0]kdb> go > [email protected]:~# > - OK > > 1) Try CPU 1 > [email protected]:~# > [email protected]:~# taskset -c 1 sync > [email protected]:~# > - Doesn't work. > > Signed-off-by: Konstantin Baydarov <[email protected]> > Description: > This patch adds support for global hardware breakpoints to KDB on x86 > targets. Hardware breakpoints are installed by setting per CPU db > registers. So to make a hardware breakpoint global it should be > installed in db registers on every CPU in system. So global hw bp > can't be handle by kdb_bp_install_global and kdb_bp_remove_global > because these functions are called only on "monarch" CPU, > kdb_bp_install_local and kdb_bp_remove_local should be used instead > because these are called for all CPUs. > > Main changes: > - kdb_hardbreaks[KDB_MAXHARDBPT] - The processor architecture > hardware breakpoint registers descriptors is defined for every > CPU: > static kdbhard_bp_t kdb_hardbreaks[NR_CPUS][KDB_MAXHARDBPT]; > > - "kdb_bp_t" (main breakpint structure) contains hardware > breakpoint registers for every CPU: > kdbhard_bp_t* bp_hard[NR_CPUS]; > > - global hardware breakpoint installation and removal is handled > by kdb_bp_install_local and kdb_bp_remove_local which are > executed on every CPU > > - kdba_allocbp andkdba_freebp are static, now kdba_alloc_hwbp and > kdba_free_hwbp are used for allocating/freeing hardware breakpoint > registers. If the hardware breakpoint is global then > kdba_alloc_hwbp tries to allocate hardware breakpoint registers on > every CPU. If there is no free hardware breakpoint on a CPU the > allocation fails. > > - bph_installed was added to the hardware breakpoint descriptor to > track per CPU hardware breakpoint installation. > > Patch against kernel 2.6.24-rc2 > > Index: linux-2.6.24-rc2/arch/x86/kdb/kdba_bp_32.c > =================================================================== > --- linux-2.6.24-rc2.orig/arch/x86/kdb/kdba_bp_32.c > +++ linux-2.6.24-rc2/arch/x86/kdb/kdba_bp_32.c > @@ -22,10 +22,10 @@ static char *kdba_rwtypes[] = { "Instruc > > /* > * Table describing processor architecture hardware > - * breakpoint registers. > + * breakpoint registers for every CPU. > */ > > -static kdbhard_bp_t kdb_hardbreaks[KDB_MAXHARDBPT]; > +static kdbhard_bp_t kdb_hardbreaks[NR_CPUS][KDB_MAXHARDBPT]; > > /* > + * kdba_free_hwbp > + * > + * Frees allocated hw registers descriptors for bp. > + * If hw bp is global, hw registers descriptors will be freed > + * on every CPU. > + * > + * Parameters: > + * bp - hardware bp > + * Outputs: > + * None. > + * Returns: > + * None > + * Locking: > + * None. > + * Remarks: > + * Should be called with correct bp->bp_template > + */ > + > +void > +kdba_free_hwbp(kdb_bp_t *bp) > +{ > + int i; > + > + /* When kernel enters KDB, first, all local bps > + * are removed, so here we don't need to clear > + * debug registers. > + */ > + > + if (bp->bp_global){ > + for (i = 0; i < NR_CPUS; ++i) { > + if (!cpu_online(i)) > + continue; > + if (bp->bp_hard[i]) > + kdba_freebp(bp->bp_hard[i]); > + bp->bp_hard[i] = 0; > + } > + } else { > + kdba_freebp(bp->bp_hard[bp->bp_cpu]); > + bp->bp_hard[bp->bp_cpu] = NULL; > + } > + bp->bp_hardtype = 0; > +} > + > +/* > * kdba_initbp > * > * Initialize the breakpoint table for the hardware breakpoint > @@ -653,7 +749,7 @@ kdba_freebp(kdbhard_bp_t *bph) > void > kdba_initbp(void) > { > - int i; > + int i,j; > kdbhard_bp_t *bph; > > /* > @@ -662,9 +758,15 @@ kdba_initbp(void) > > memset(kdb_hardbreaks, '\0', sizeof(kdb_hardbreaks)); > > - for(i=0,bph=kdb_hardbreaks; i<KDB_MAXHARDBPT; i++, bph++) { > - bph->bph_reg = i; > - bph->bph_free = 1; > + for (i = 0; i < NR_CPUS; ++i) { > + /* Called early so we don't know actual > + * ammount of CPUs > + */ > + for(j=0; j < KDB_MAXHARDBPT; j++) { > + bph=&(kdb_hardbreaks[i][j]); > + bph->bph_reg = j; > + bph->bph_free = 1; > + } > } > } > > @@ -698,6 +800,8 @@ kdba_initbp(void) > int > kdba_installbp(struct pt_regs *regs, kdb_bp_t *bp) > { > + int cpu = smp_processor_id(); > + > /* > * Install the breakpoint, if it is not already installed. > */ > @@ -707,15 +811,27 @@ kdba_installbp(struct pt_regs *regs, kdb > } > if (!KDB_STATE(SSBPT)) > bp->bp_delay = 0; > - if (!bp->bp_installed) { > - if (bp->bp_hardtype) { > + > + if (bp->bp_hardtype) { > + if (KDB_DEBUG(BP) && !bp->bp_global && cpu != bp->bp_cpu){ > + kdb_printf("kdba_removebp: cpu != bp->bp_cpu for local hw bp\n"); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "s/kdba_removebp/kdba_installbp/", right? > + } > + > + if (KDB_DEBUG(BP) && !bp->bp_hard[cpu]){ > + kdb_printf("kdba_removebp: Error - bp_hard[smp_processor_id()] is emply\n"); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ And here. > + return 1; > + } > + > + if (!bp->bp_hard[cpu]->bph_installed){ > kdba_installdbreg(bp); > - bp->bp_installed = 1; > + bp->bp_hard[cpu]->bph_installed = 1; > if (KDB_DEBUG(BP)) { > kdb_printf("kdba_installbp hardware reg %ld at " kdb_bfd_vma_fmt "\n", > - bp->bp_hard->bph_reg, bp->bp_addr); > + bp->bp_hard[cpu]->bph_reg, bp->bp_addr); > } > - } else if (bp->bp_delay) { > + } > + } else if (!bp->bp_installed) { > + if (bp->bp_delay) { > if (KDB_DEBUG(BP)) > kdb_printf("kdba_installbp delayed bp\n"); > kdba_handle_bp(regs, bp); > @@ -753,6 +869,8 @@ kdba_installbp(struct pt_regs *regs, kdb > int > kdba_removebp(kdb_bp_t *bp) > { > + int cpu = smp_processor_id(); > + > /* > * For hardware breakpoints, remove it from the active register, > * for software breakpoints, restore the instruction stream. --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe.