Commit 3162d92dfb79a0b5fc03380b8819fa5f870ebf1e

Authored by Dave Kleikamp
Committed by Benjamin Herrenschmidt
1 parent 172ae2e7f8

powerpc: Extended ptrace interface

powerpc: Extended ptrace interface

From: Dave Kleikamp <shaggy@linux.vnet.ibm.com>

Based on patches originally written by Torez Smith.

Add a new extended ptrace interface so that user-space has a single
interface for powerpc, without having to know the specific layout
of the debug registers.

Implement:
PPC_PTRACE_GETHWDEBUGINFO
PPC_PTRACE_SETHWDEBUG
PPC_PTRACE_DELHWDEBUG

Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
Acked-by: David Gibson <dwg@au1.ibm.com>
Cc: Torez Smith  <lnxtorez@linux.vnet.ibm.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Cc: Kumar Gala <galak@kernel.crashing.org>
Cc: Sergio Durigan Junior <sergiodj@br.ibm.com>
Cc: Thiago Jung Bauermann <bauerman@br.ibm.com>
Cc: linuxppc-dev list <Linuxppc-dev@ozlabs.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Showing 3 changed files with 301 additions and 0 deletions Side-by-side Diff

Documentation/powerpc/ptrace.txt
  1 +GDB intends to support the following hardware debug features of BookE
  2 +processors:
  3 +
  4 +4 hardware breakpoints (IAC)
  5 +2 hardware watchpoints (read, write and read-write) (DAC)
  6 +2 value conditions for the hardware watchpoints (DVC)
  7 +
  8 +For that, we need to extend ptrace so that GDB can query and set these
  9 +resources. Since we're extending, we're trying to create an interface
  10 +that's extendable and that covers both BookE and server processors, so
  11 +that GDB doesn't need to special-case each of them. We added the
  12 +following 3 new ptrace requests.
  13 +
  14 +1. PTRACE_PPC_GETHWDEBUGINFO
  15 +
  16 +Query for GDB to discover the hardware debug features. The main info to
  17 +be returned here is the minimum alignment for the hardware watchpoints.
  18 +BookE processors don't have restrictions here, but server processors have
  19 +an 8-byte alignment restriction for hardware watchpoints. We'd like to avoid
  20 +adding special cases to GDB based on what it sees in AUXV.
  21 +
  22 +Since we're at it, we added other useful info that the kernel can return to
  23 +GDB: this query will return the number of hardware breakpoints, hardware
  24 +watchpoints and whether it supports a range of addresses and a condition.
  25 +The query will fill the following structure provided by the requesting process:
  26 +
  27 +struct ppc_debug_info {
  28 + unit32_t version;
  29 + unit32_t num_instruction_bps;
  30 + unit32_t num_data_bps;
  31 + unit32_t num_condition_regs;
  32 + unit32_t data_bp_alignment;
  33 + unit32_t sizeof_condition; /* size of the DVC register */
  34 + uint64_t features; /* bitmask of the individual flags */
  35 +};
  36 +
  37 +features will have bits indicating whether there is support for:
  38 +
  39 +#define PPC_DEBUG_FEATURE_INSN_BP_RANGE 0x1
  40 +#define PPC_DEBUG_FEATURE_INSN_BP_MASK 0x2
  41 +#define PPC_DEBUG_FEATURE_DATA_BP_RANGE 0x4
  42 +#define PPC_DEBUG_FEATURE_DATA_BP_MASK 0x8
  43 +
  44 +2. PTRACE_SETHWDEBUG
  45 +
  46 +Sets a hardware breakpoint or watchpoint, according to the provided structure:
  47 +
  48 +struct ppc_hw_breakpoint {
  49 + uint32_t version;
  50 +#define PPC_BREAKPOINT_TRIGGER_EXECUTE 0x1
  51 +#define PPC_BREAKPOINT_TRIGGER_READ 0x2
  52 +#define PPC_BREAKPOINT_TRIGGER_WRITE 0x4
  53 + uint32_t trigger_type; /* only some combinations allowed */
  54 +#define PPC_BREAKPOINT_MODE_EXACT 0x0
  55 +#define PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE 0x1
  56 +#define PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE 0x2
  57 +#define PPC_BREAKPOINT_MODE_MASK 0x3
  58 + uint32_t addr_mode; /* address match mode */
  59 +
  60 +#define PPC_BREAKPOINT_CONDITION_MODE 0x3
  61 +#define PPC_BREAKPOINT_CONDITION_NONE 0x0
  62 +#define PPC_BREAKPOINT_CONDITION_AND 0x1
  63 +#define PPC_BREAKPOINT_CONDITION_EXACT 0x1 /* different name for the same thing as above */
  64 +#define PPC_BREAKPOINT_CONDITION_OR 0x2
  65 +#define PPC_BREAKPOINT_CONDITION_AND_OR 0x3
  66 +#define PPC_BREAKPOINT_CONDITION_BE_ALL 0x00ff0000 /* byte enable bits */
  67 +#define PPC_BREAKPOINT_CONDITION_BE(n) (1<<((n)+16))
  68 + uint32_t condition_mode; /* break/watchpoint condition flags */
  69 +
  70 + uint64_t addr;
  71 + uint64_t addr2;
  72 + uint64_t condition_value;
  73 +};
  74 +
  75 +A request specifies one event, not necessarily just one register to be set.
  76 +For instance, if the request is for a watchpoint with a condition, both the
  77 +DAC and DVC registers will be set in the same request.
  78 +
  79 +With this GDB can ask for all kinds of hardware breakpoints and watchpoints
  80 +that the BookE supports. COMEFROM breakpoints available in server processors
  81 +are not contemplated, but that is out of the scope of this work.
  82 +
  83 +ptrace will return an integer (handle) uniquely identifying the breakpoint or
  84 +watchpoint just created. This integer will be used in the PTRACE_DELHWDEBUG
  85 +request to ask for its removal. Return -ENOSPC if the requested breakpoint
  86 +can't be allocated on the registers.
  87 +
  88 +Some examples of using the structure to:
  89 +
  90 +- set a breakpoint in the first breakpoint register
  91 +
  92 + p.version = PPC_DEBUG_CURRENT_VERSION;
  93 + p.trigger_type = PPC_BREAKPOINT_TRIGGER_EXECUTE;
  94 + p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
  95 + p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
  96 + p.addr = (uint64_t) address;
  97 + p.addr2 = 0;
  98 + p.condition_value = 0;
  99 +
  100 +- set a watchpoint which triggers on reads in the second watchpoint register
  101 +
  102 + p.version = PPC_DEBUG_CURRENT_VERSION;
  103 + p.trigger_type = PPC_BREAKPOINT_TRIGGER_READ;
  104 + p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
  105 + p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
  106 + p.addr = (uint64_t) address;
  107 + p.addr2 = 0;
  108 + p.condition_value = 0;
  109 +
  110 +- set a watchpoint which triggers only with a specific value
  111 +
  112 + p.version = PPC_DEBUG_CURRENT_VERSION;
  113 + p.trigger_type = PPC_BREAKPOINT_TRIGGER_READ;
  114 + p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
  115 + p.condition_mode = PPC_BREAKPOINT_CONDITION_AND | PPC_BREAKPOINT_CONDITION_BE_ALL;
  116 + p.addr = (uint64_t) address;
  117 + p.addr2 = 0;
  118 + p.condition_value = (uint64_t) condition;
  119 +
  120 +- set a ranged hardware breakpoint
  121 +
  122 + p.version = PPC_DEBUG_CURRENT_VERSION;
  123 + p.trigger_type = PPC_BREAKPOINT_TRIGGER_EXECUTE;
  124 + p.addr_mode = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
  125 + p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
  126 + p.addr = (uint64_t) begin_range;
  127 + p.addr2 = (uint64_t) end_range;
  128 + p.condition_value = 0;
  129 +
  130 +3. PTRACE_DELHWDEBUG
  131 +
  132 +Takes an integer which identifies an existing breakpoint or watchpoint
  133 +(i.e., the value returned from PTRACE_SETHWDEBUG), and deletes the
  134 +corresponding breakpoint or watchpoint..
arch/powerpc/include/asm/ptrace.h
... ... @@ -24,6 +24,12 @@
24 24 * 2 of the License, or (at your option) any later version.
25 25 */
26 26  
  27 +#ifdef __KERNEL__
  28 +#include <linux/types.h>
  29 +#else
  30 +#include <stdint.h>
  31 +#endif
  32 +
27 33 #ifndef __ASSEMBLY__
28 34  
29 35 struct pt_regs {
... ... @@ -293,6 +299,77 @@
293 299 #define PPC_PTRACE_POKEUSR_3264 0x90
294 300  
295 301 #define PTRACE_SINGLEBLOCK 0x100 /* resume execution until next branch */
  302 +
  303 +#define PPC_PTRACE_GETHWDBGINFO 0x89
  304 +#define PPC_PTRACE_SETHWDEBUG 0x88
  305 +#define PPC_PTRACE_DELHWDEBUG 0x87
  306 +
  307 +#ifndef __ASSEMBLY__
  308 +
  309 +struct ppc_debug_info {
  310 + uint32_t version; /* Only version 1 exists to date */
  311 + uint32_t num_instruction_bps;
  312 + uint32_t num_data_bps;
  313 + uint32_t num_condition_regs;
  314 + uint32_t data_bp_alignment;
  315 + uint32_t sizeof_condition; /* size of the DVC register */
  316 + uint64_t features;
  317 +};
  318 +
  319 +#endif /* __ASSEMBLY__ */
  320 +
  321 +/*
  322 + * features will have bits indication whether there is support for:
  323 + */
  324 +#define PPC_DEBUG_FEATURE_INSN_BP_RANGE 0x0000000000000001
  325 +#define PPC_DEBUG_FEATURE_INSN_BP_MASK 0x0000000000000002
  326 +#define PPC_DEBUG_FEATURE_DATA_BP_RANGE 0x0000000000000004
  327 +#define PPC_DEBUG_FEATURE_DATA_BP_MASK 0x0000000000000008
  328 +
  329 +#ifndef __ASSEMBLY__
  330 +
  331 +struct ppc_hw_breakpoint {
  332 + uint32_t version; /* currently, version must be 1 */
  333 + uint32_t trigger_type; /* only some combinations allowed */
  334 + uint32_t addr_mode; /* address match mode */
  335 + uint32_t condition_mode; /* break/watchpoint condition flags */
  336 + uint64_t addr; /* break/watchpoint address */
  337 + uint64_t addr2; /* range end or mask */
  338 + uint64_t condition_value; /* contents of the DVC register */
  339 +};
  340 +
  341 +#endif /* __ASSEMBLY__ */
  342 +
  343 +/*
  344 + * Trigger Type
  345 + */
  346 +#define PPC_BREAKPOINT_TRIGGER_EXECUTE 0x00000001
  347 +#define PPC_BREAKPOINT_TRIGGER_READ 0x00000002
  348 +#define PPC_BREAKPOINT_TRIGGER_WRITE 0x00000004
  349 +#define PPC_BREAKPOINT_TRIGGER_RW \
  350 + (PPC_BREAKPOINT_TRIGGER_READ | PPC_BREAKPOINT_TRIGGER_WRITE)
  351 +
  352 +/*
  353 + * Address Mode
  354 + */
  355 +#define PPC_BREAKPOINT_MODE_EXACT 0x00000000
  356 +#define PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE 0x00000001
  357 +#define PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE 0x00000002
  358 +#define PPC_BREAKPOINT_MODE_MASK 0x00000003
  359 +
  360 +/*
  361 + * Condition Mode
  362 + */
  363 +#define PPC_BREAKPOINT_CONDITION_MODE 0x00000003
  364 +#define PPC_BREAKPOINT_CONDITION_NONE 0x00000000
  365 +#define PPC_BREAKPOINT_CONDITION_AND 0x00000001
  366 +#define PPC_BREAKPOINT_CONDITION_EXACT PPC_BREAKPOINT_CONDITION_AND
  367 +#define PPC_BREAKPOINT_CONDITION_OR 0x00000002
  368 +#define PPC_BREAKPOINT_CONDITION_AND_OR 0x00000003
  369 +#define PPC_BREAKPOINT_CONDITION_BE_ALL 0x00ff0000
  370 +#define PPC_BREAKPOINT_CONDITION_BE_SHIFT 16
  371 +#define PPC_BREAKPOINT_CONDITION_BE(n) \
  372 + (1<<((n)+PPC_BREAKPOINT_CONDITION_BE_SHIFT))
296 373  
297 374 #endif /* _ASM_POWERPC_PTRACE_H */
arch/powerpc/kernel/ptrace.c
... ... @@ -835,6 +835,52 @@
835 835 user_disable_single_step(child);
836 836 }
837 837  
  838 +static long ppc_set_hwdebug(struct task_struct *child,
  839 + struct ppc_hw_breakpoint *bp_info)
  840 +{
  841 + /*
  842 + * We currently support one data breakpoint
  843 + */
  844 + if (((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0) ||
  845 + ((bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0) ||
  846 + (bp_info->trigger_type != PPC_BREAKPOINT_TRIGGER_WRITE) ||
  847 + (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) ||
  848 + (bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE))
  849 + return -EINVAL;
  850 +
  851 + if (child->thread.dabr)
  852 + return -ENOSPC;
  853 +
  854 + if ((unsigned long)bp_info->addr >= TASK_SIZE)
  855 + return -EIO;
  856 +
  857 + child->thread.dabr = (unsigned long)bp_info->addr;
  858 +#ifdef CONFIG_PPC_ADV_DEBUG_REGS
  859 + child->thread.dbcr0 = DBCR0_IDM;
  860 + if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ)
  861 + child->thread.dbcr0 |= DBSR_DAC1R;
  862 + if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
  863 + child->thread.dbcr0 |= DBSR_DAC1W;
  864 + child->thread.regs->msr |= MSR_DE;
  865 +#endif
  866 + return 1;
  867 +}
  868 +
  869 +static long ppc_del_hwdebug(struct task_struct *child, long addr, long data)
  870 +{
  871 + if (data != 1)
  872 + return -EINVAL;
  873 + if (child->thread.dabr == 0)
  874 + return -ENOENT;
  875 +
  876 + child->thread.dabr = 0;
  877 +#ifdef CONFIG_PPC_ADV_DEBUG_REGS
  878 + child->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | DBCR0_IDM);
  879 + child->thread.regs->msr &= ~MSR_DE;
  880 +#endif
  881 + return 0;
  882 +}
  883 +
838 884 /*
839 885 * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
840 886 * we mark them as obsolete now, they will be removed in a future version
... ... @@ -925,6 +971,50 @@
925 971 [TS_FPRWIDTH * (index - PT_FPR0)] = data;
926 972 ret = 0;
927 973 }
  974 + break;
  975 + }
  976 +
  977 + case PPC_PTRACE_GETHWDBGINFO: {
  978 + struct ppc_debug_info dbginfo;
  979 +
  980 + dbginfo.version = 1;
  981 + dbginfo.num_instruction_bps = 0;
  982 + dbginfo.num_data_bps = 1;
  983 + dbginfo.num_condition_regs = 0;
  984 +#ifdef CONFIG_PPC64
  985 + dbginfo.data_bp_alignment = 8;
  986 +#else
  987 + dbginfo.data_bp_alignment = 4;
  988 +#endif
  989 + dbginfo.sizeof_condition = 0;
  990 + dbginfo.features = 0;
  991 +
  992 + if (!access_ok(VERIFY_WRITE, data,
  993 + sizeof(struct ppc_debug_info)))
  994 + return -EFAULT;
  995 + ret = __copy_to_user((struct ppc_debug_info __user *)data,
  996 + &dbginfo, sizeof(struct ppc_debug_info)) ?
  997 + -EFAULT : 0;
  998 + break;
  999 + }
  1000 +
  1001 + case PPC_PTRACE_SETHWDEBUG: {
  1002 + struct ppc_hw_breakpoint bp_info;
  1003 +
  1004 + if (!access_ok(VERIFY_READ, data,
  1005 + sizeof(struct ppc_hw_breakpoint)))
  1006 + return -EFAULT;
  1007 + ret = __copy_from_user(&bp_info,
  1008 + (struct ppc_hw_breakpoint __user *)data,
  1009 + sizeof(struct ppc_hw_breakpoint)) ?
  1010 + -EFAULT : 0;
  1011 + if (!ret)
  1012 + ret = ppc_set_hwdebug(child, &bp_info);
  1013 + break;
  1014 + }
  1015 +
  1016 + case PPC_PTRACE_DELHWDEBUG: {
  1017 + ret = ppc_del_hwdebug(child, addr, data);
928 1018 break;
929 1019 }
930 1020