This is the mail archive of the gdb@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: GDB Watchpoints and the PTRACE interface for different ppc processors


I think the logic for deciding what bits to set for a specific processor
should be in the kernel.

It looks like we are most of the way there already.  If we change the
kernel code to force the 0x4 bit to 1 on 970 (and other processors with a
DABR), rather than failing the request if it isn't set, then gdb can use a
single code path for all PowerPC processors (i.e. the code you currently
have for 440).

In other words the interface will be that the 0x1 bit says to trap on read,
the 0x2 bit says to trap on write, and the rest of the bits (30 or 62) give
the address.  On some processors (e.g. 970) the kernel will mask off one
more bit of the address (so the trap will occur for accesses to any byte
within an 8-byte region rather than a 4-byte region).  Thus gdb will have
to have code to check the address and silently continue if the access was
not to the address being watched (presumably it already has this code).

How does that sound?

Paul.
--
Paul Mackerras, Ph.D.
PowerPC Linux Kernel Architect
STSM
IBM Linux Technology Center OzLabs
Canberra, Australia


                                                                           
             Luis Machado                                                  
             <luisgpm@linux.vn                                             
             et.ibm.com>                                                To 
                                       Paul Mackerras/Australia/IBM@IBMAU  
             30/08/07 05:33 AM                                          cc 
                                       gdb@sourceware.org                  
                                                                   Subject 
             Please respond to         GDB Watchpoints and the PTRACE      
             luisgpm@linux.vne         interface for different ppc         
                 t.ibm.com             processors                          
                                                                           
                                                                           
                                                                           
                                                                           
                                                                           
                                                                           




Hi Paul,

I'm writting this in the hope of getting a better solution to the
current PTRACE interface problem we are facing on GDB while trying to
cope with two different processors that have different debug register
formats (PowerPC 440 and PowerPC 970).

The main question is, should GDB deal with all the bit-setting logic for
each specific processor and send the PTRACE parameters ready to be
assigned to the task's debug register? Or should the kernel receive high
level definitions of watchpoints (GDB would just request a read
watchpoint, or a write watchpoint) through PTRACE and would have all the
logic required to set the correct bits for each specific processor?

Follows below a detailed explanation of the problem.

I was originally working on supporting Hardware Watchpoints on the
PowerPC 440 processors. These processors carry a DBCR0 register that
controls the two possible modes of operation for a watchpoint:
read/write. So we have two bits that must to be set in that specific
register in order to enable the mode we want.

These bits are located in the middle of the register. If i'm not
mistaken, they are located on bits 13 and 14, in a 32-bit wide DBCR0.

So, this is how we set the watchpoint on gdb's side for the 440's:

=============GDB code=======================
long dabr_value;

  dabr_value = addr & ~3; /* Clear the 2 bits we're going to use */

  switch (rw)
    {
    case hw_read:
      /* Set read bit.  */
      dabr_value |= 1;
      break;
    case hw_write:
      /* Set write bit.  */
      dabr_value |= 2;
      break;
    case hw_access:
      /* Set read, write bits.  */
      dabr_value |= 3;
      break;
    }

ptrace (PTRACE_SET_DEBUGREG, tid, 0, dabr_value);

============================================

So, basically we set two bits (the last bits, 30 and 31) for read/write
modes and send that information to the kernel through PTRACE request
PTRACE_SET_DEBUGREG.

On the kernel side we have the following:

===========Kernel code============
if (data & 1)
             task->thread.dbcr0 |= DBCR_D1R;
if (data & 2)
             task->thread.dbcr0 |= DBCR_D1W;
==================================

In this code, the kernel checks the previously set bits (30 and 31) on
data (dabr_value) and move the bit values to the correct position (13
and 14) through two defined constants (DBCR_D1R and DBCR_D1W). This
magic happens inside the kernel. Additionally, there are other bits that
are set automatically by the kernel without GDB knowing that.

This covers the case for the PowerPC 440 processors.

As for the 970/970FX (JS20/21), we have a different debug register,
called DABR, that we use to set hardware watchpoints. We still have to
set the read/write bits for it, but in this case, the bits are located
in the last bits (62 and 63) in a 64-bit wide register, different than
the 440's bits positions.

Additionaly, for the 970, we also set a third flag in GDB, the
"Breakpoint Translation Enable" flag (bit 61).

So, for the 970's case, we have the following GDB code:

=============GDB code=======================
long dabr_value;

  ptid_t ptid = inferior_ptid;

  dabr_value = addr & ~7; /* Clear the 3 bits we're going to use */

  switch (rw)
    {
    case hw_read:
      /* Set read bit + translate bit.  */
      dabr_value |= 5;
      break;
    case hw_write:
      /* Set write bit + translate bit.  */
      dabr_value |= 6;
      break;
    case hw_access:
      /* Set read, write bits + translate bit.  */
      dabr_value |= 7;
      break;
    }

ptrace (PTRACE_SET_DEBUGREG, tid, 0, dabr_value);
============================================

In here we're using 3 bits to set the needed flags. The kernel code for
the 970's is the following.

===========Kernel code============
task->thread.dabr = data;
==================================

So, the kernel-side just assigns the parameter we've passed via PTRACE
on GDB to the task's debug register. There is no bit position shifting
involved in this case (as opposed to the 440's kernel code), and GDB is
also setting an additional flag (Breakpoint translation enable).

Best regards,
--
Luis Machado
IBM Linux Technology Center
e-mail: luisgpm@linux.vnet.ibm.com




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]