Re: [RFC:PATCH 00/03] powerpc: Expose BookE debug registers through extended ptrace interface

Kumar Gala
2009-12-11T02:32:40Z

On Dec 10, 2009, at 8:29 PM, Dave Kleikamp wrote:

> On Thu, 2009-12-10 at 20:24 -0600, Kumar Gala wrote:
>> On Dec 10, 2009, at 9:57 AM, Dave Kleikamp wrote:
>>=20
>>> These patches implement an extention to the ptrace interface =
proposed by
>>> Thiago Bauermann and the the PowerPC gdb team.
>>>=20
>>> GDB intends to support the following hardware debug features of =
BookE
>>> processors:
>>>=20
>>> 4 hardware breakpoints (IAC)
>>> 2 hardware watchpoints (read, write and read-write) (DAC)
>>> 2 value conditions for the hardware watchpoints (DVC)
>>>=20
>>> For that, we need to extend ptrace so that GDB can query and set =
these
>>> resources. Since we're extending, we're trying to create an =
interface
>>> that's extendable and that covers both BookE and server processors, =
so
>>> that GDB doesn't need to special-case each of them. We propose the
>>> following 3 new ptrace requests described below.
>>>=20
>>> There have been discussions of a generic hardware debug interface =
for the
>>> kernel which would hopefully contemplate all the functionality below =
and
>>> supersede it. But we need something that works now, and which =
enables GDB
>>> to be simpler and work with both Server and Embedded processors =
without
>>> special cases.
>>>=20
>>> 1. PTRACE_PPC_GETHWDEBUGINFO
>>>=20
>>> Query for GDB to discover the hardware debug features. The main info =
to
>>> be returned here is the minimum alignment for the hardware =
watchpoints.
>>> BookE processors don't have restrictions here, but server processors =
have
>>> an 8-byte alignment restriction for hardware watchpoints. We'd like =
to avoid
>>> adding special cases to GDB based on what it sees in AUXV.
>>>=20
>>> Since we're at it, we added other useful info that the kernel can =
return to
>>> GDB: this query will return the number of hardware breakpoints, =
hardware
>>> watchpoints and whether it supports a range of addresses and a =
condition.
>>> The query will fill the following structure provided by the =
requesting process:
>>>=20
>>> struct ppc_debug_info {
>>> unit32_t version;
>>> unit32_t num_instruction_bps;
>>> unit32_t num_data_bps;
>>> unit32_t num_condition_regs;
>>> unit32_t data_bp_alignment;
>>> unit32_t sizeof_condition; /* size of the DVC register */
>>> uint64_t features; /* bitmask of the individual flags */
>>> };
>>>=20
>>> features will have bits indicating whether there is support for:
>>>=20
>>> #define PPC_DEBUG_FEATURE_INSN_BP_RANGE 0x1
>>> #define PPC_DEBUG_FEATURE_INSN_BP_MASK 0x2
>>> #define PPC_DEBUG_FEATURE_DATA_BP_RANGE 0x4
>>> #define PPC_DEBUG_FEATURE_DATA_BP_MASK 0x8
>>>=20
>>> 2. PTRACE_SETHWDEBUG
>>>=20
>>> Sets a hardware breakpoint or watchpoint, according to the provided =
structure:
>>>=20
>>> struct ppc_hw_breakpoint {
>>> uint32_t version;
>>> #define PPC_BREAKPOINT_TRIGGER_EXECUTE 0x1
>>> #define PPC_BREAKPOINT_TRIGGER_READ 0x2
>>> #define PPC_BREAKPOINT_TRIGGER_WRITE 0x4
>>> uint32_t trigger_type; /* only some combinations allowed =
*/
>>> #define PPC_BREAKPOINT_MODE_EXACT 0x0
>>> #define PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE 0x1
>>> #define PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE 0x2
>>> #define PPC_BREAKPOINT_MODE_MASK 0x3
>>> uint32_t addr_mode; /* address match mode */
>>>=20
>>> #define PPC_BREAKPOINT_CONDITION_NONE 0x0
>>> #define PPC_BREAKPOINT_CONDITION_AND 0x1
>>> #define PPC_BREAKPOINT_CONDITION_EXACT 0x1 /* different name for =
the same thing as above */
>>> #define PPC_BREAKPOINT_CONDITION_OR 0x2
>>> #define PPC_BREAKPOINT_CONDITION_AND_OR 0x3
>>> #define PPC_BREAKPOINT_CONDITION_BE_ALL 0x00ff0000 /* byte enable =
bits */
>>> #define PPC_BREAKPOINT_CONDITION_BE(n) (1<<((n)+16))
>>> uint32_t condition_mode; /* break/watchpoint condition =
flags */
>>>=20
>>> uint64_t addr;
>>> uint64_t addr2;
>>> uint64_t condition_value;
>>> };
>>>=20
>>> A request specifies one event, not necessarily just one register to =
be set.
>>> For instance, if the request is for a watchpoint with a condition, =
both the
>>> DAC and DVC registers will be set in the same request.
>>>=20
>>> With this GDB can ask for all kinds of hardware breakpoints and =
watchpoints
>>> that the BookE supports. COMEFROM breakpoints available in server =
processors
>>> are not contemplated, but that is out of the scope of this work.
>>>=20
>>> ptrace will return an integer (handle) uniquely identifying the =
breakpoint or
>>> watchpoint just created. This integer will be used in the =
PTRACE_DELHWDEBUG
>>> request to ask for its removal. Return -ENOSPC if the requested =
breakpoint
>>> can't be allocated on the registers.
>>>=20
>>> Some examples of using the structure to:
>>>=20
>>> - set a breakpoint in the first breakpoint register
>>>=20
>>> p.version =3D PPC_DEBUG_CURRENT_VERSION;
>>> p.trigger_type =3D PPC_BREAKPOINT_TRIGGER_EXECUTE;
>>> p.addr_mode =3D PPC_BREAKPOINT_MODE_EXACT;
>>> p.condition_mode =3D PPC_BREAKPOINT_CONDITION_NONE;
>>> p.addr =3D (uint64_t) address;
>>> p.addr2 =3D 0;
>>> p.condition_value =3D 0;
>>>=20
>>> - set a watchpoint which triggers on reads in the second watchpoint =
register
>>>=20
>>> p.version =3D PPC_DEBUG_CURRENT_VERSION;
>>> p.trigger_type =3D PPC_BREAKPOINT_TRIGGER_READ;
>>> p.addr_mode =3D PPC_BREAKPOINT_MODE_EXACT;
>>> p.condition_mode =3D PPC_BREAKPOINT_CONDITION_NONE;
>>> p.addr =3D (uint64_t) address;
>>> p.addr2 =3D 0;
>>> p.condition_value =3D 0;
>>>=20
>>> - set a watchpoint which triggers only with a specific value
>>>=20
>>> p.version =3D PPC_DEBUG_CURRENT_VERSION;
>>> p.trigger_type =3D PPC_BREAKPOINT_TRIGGER_READ;
>>> p.addr_mode =3D PPC_BREAKPOINT_MODE_EXACT;
>>> p.condition_mode =3D PPC_BREAKPOINT_CONDITION_AND | =
PPC_BREAKPOINT_CONDITION_BE_ALL;
>>> p.addr =3D (uint64_t) address;
>>> p.addr2 =3D 0;
>>> p.condition_value =3D (uint64_t) condition;
>>>=20
>>> - set a ranged hardware breakpoint
>>>=20
>>> p.version =3D PPC_DEBUG_CURRENT_VERSION;
>>> p.trigger_type =3D PPC_BREAKPOINT_TRIGGER_EXECUTE;
>>> p.addr_mode =3D PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
>>> p.condition_mode =3D PPC_BREAKPOINT_CONDITION_NONE;
>>> p.addr =3D (uint64_t) begin_range;
>>> p.addr2 =3D (uint64_t) end_range;
>>> p.condition_value =3D 0;
>>>=20
>>> 3. PTRACE_DELHWDEBUG
>>>=20
>>> Takes an integer which identifies an existing breakpoint or =
watchpoint
>>> (i.e., the value returned from PTRACE_SETHWDEBUG), and deletes the
>>> corresponding breakpoint or watchpoint..
>>=20
>> This is a good write up. We should have it as a commit message for =
the first patch.
>=20
> I have to give credit to Thiago for this.
>=20
> Would it be worth adding to Documentation/powerpc/ ?

That would also work.

- k=