152 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			152 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
GDB intends to support the following hardware debug features of BookE
 | 
						|
processors:
 | 
						|
 | 
						|
4 hardware breakpoints (IAC)
 | 
						|
2 hardware watchpoints (read, write and read-write) (DAC)
 | 
						|
2 value conditions for the hardware watchpoints (DVC)
 | 
						|
 | 
						|
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 added the
 | 
						|
following 3 new ptrace requests.
 | 
						|
 | 
						|
1. PTRACE_PPC_GETHWDEBUGINFO
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
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:
 | 
						|
 | 
						|
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 */
 | 
						|
};
 | 
						|
 | 
						|
features will have bits indicating whether there is support for:
 | 
						|
 | 
						|
#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
 | 
						|
#define PPC_DEBUG_FEATURE_DATA_BP_DAWR		0x10
 | 
						|
 | 
						|
2. PTRACE_SETHWDEBUG
 | 
						|
 | 
						|
Sets a hardware breakpoint or watchpoint, according to the provided structure:
 | 
						|
 | 
						|
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 */
 | 
						|
 | 
						|
#define PPC_BREAKPOINT_CONDITION_MODE   0x3
 | 
						|
#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 */
 | 
						|
 | 
						|
        uint64_t addr;
 | 
						|
        uint64_t addr2;
 | 
						|
        uint64_t condition_value;
 | 
						|
};
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
Some examples of using the structure to:
 | 
						|
 | 
						|
- set a breakpoint in the first breakpoint register
 | 
						|
 | 
						|
  p.version         = PPC_DEBUG_CURRENT_VERSION;
 | 
						|
  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_EXECUTE;
 | 
						|
  p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
 | 
						|
  p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
 | 
						|
  p.addr            = (uint64_t) address;
 | 
						|
  p.addr2           = 0;
 | 
						|
  p.condition_value = 0;
 | 
						|
 | 
						|
- set a watchpoint which triggers on reads in the second watchpoint register
 | 
						|
 | 
						|
  p.version         = PPC_DEBUG_CURRENT_VERSION;
 | 
						|
  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_READ;
 | 
						|
  p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
 | 
						|
  p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
 | 
						|
  p.addr            = (uint64_t) address;
 | 
						|
  p.addr2           = 0;
 | 
						|
  p.condition_value = 0;
 | 
						|
 | 
						|
- set a watchpoint which triggers only with a specific value
 | 
						|
 | 
						|
  p.version         = PPC_DEBUG_CURRENT_VERSION;
 | 
						|
  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_READ;
 | 
						|
  p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
 | 
						|
  p.condition_mode  = PPC_BREAKPOINT_CONDITION_AND | PPC_BREAKPOINT_CONDITION_BE_ALL;
 | 
						|
  p.addr            = (uint64_t) address;
 | 
						|
  p.addr2           = 0;
 | 
						|
  p.condition_value = (uint64_t) condition;
 | 
						|
 | 
						|
- set a ranged hardware breakpoint
 | 
						|
 | 
						|
  p.version         = PPC_DEBUG_CURRENT_VERSION;
 | 
						|
  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_EXECUTE;
 | 
						|
  p.addr_mode       = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
 | 
						|
  p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
 | 
						|
  p.addr            = (uint64_t) begin_range;
 | 
						|
  p.addr2           = (uint64_t) end_range;
 | 
						|
  p.condition_value = 0;
 | 
						|
 | 
						|
- set a watchpoint in server processors (BookS)
 | 
						|
 | 
						|
  p.version         = 1;
 | 
						|
  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_RW;
 | 
						|
  p.addr_mode       = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
 | 
						|
  or
 | 
						|
  p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
 | 
						|
 | 
						|
  p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
 | 
						|
  p.addr            = (uint64_t) begin_range;
 | 
						|
  /* For PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE addr2 needs to be specified, where
 | 
						|
   * addr2 - addr <= 8 Bytes.
 | 
						|
   */
 | 
						|
  p.addr2           = (uint64_t) end_range;
 | 
						|
  p.condition_value = 0;
 | 
						|
 | 
						|
3. PTRACE_DELHWDEBUG
 | 
						|
 | 
						|
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..
 |