Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Dave Kleikamp and committed by
Benjamin Herrenschmidt
3162d92d 172ae2e7

+301
+134
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..
+77
arch/powerpc/include/asm/ptrace.h
··· 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 { ··· 299 293 #define PPC_PTRACE_POKEUSR_3264 0x90 300 294 301 295 #define PTRACE_SINGLEBLOCK 0x100 /* resume execution until next branch */ 296 + 297 + #define PPC_PTRACE_GETHWDBGINFO 0x89 298 + #define PPC_PTRACE_SETHWDEBUG 0x88 299 + #define PPC_PTRACE_DELHWDEBUG 0x87 300 + 301 + #ifndef __ASSEMBLY__ 302 + 303 + struct ppc_debug_info { 304 + uint32_t version; /* Only version 1 exists to date */ 305 + uint32_t num_instruction_bps; 306 + uint32_t num_data_bps; 307 + uint32_t num_condition_regs; 308 + uint32_t data_bp_alignment; 309 + uint32_t sizeof_condition; /* size of the DVC register */ 310 + uint64_t features; 311 + }; 312 + 313 + #endif /* __ASSEMBLY__ */ 314 + 315 + /* 316 + * features will have bits indication whether there is support for: 317 + */ 318 + #define PPC_DEBUG_FEATURE_INSN_BP_RANGE 0x0000000000000001 319 + #define PPC_DEBUG_FEATURE_INSN_BP_MASK 0x0000000000000002 320 + #define PPC_DEBUG_FEATURE_DATA_BP_RANGE 0x0000000000000004 321 + #define PPC_DEBUG_FEATURE_DATA_BP_MASK 0x0000000000000008 322 + 323 + #ifndef __ASSEMBLY__ 324 + 325 + struct ppc_hw_breakpoint { 326 + uint32_t version; /* currently, version must be 1 */ 327 + uint32_t trigger_type; /* only some combinations allowed */ 328 + uint32_t addr_mode; /* address match mode */ 329 + uint32_t condition_mode; /* break/watchpoint condition flags */ 330 + uint64_t addr; /* break/watchpoint address */ 331 + uint64_t addr2; /* range end or mask */ 332 + uint64_t condition_value; /* contents of the DVC register */ 333 + }; 334 + 335 + #endif /* __ASSEMBLY__ */ 336 + 337 + /* 338 + * Trigger Type 339 + */ 340 + #define PPC_BREAKPOINT_TRIGGER_EXECUTE 0x00000001 341 + #define PPC_BREAKPOINT_TRIGGER_READ 0x00000002 342 + #define PPC_BREAKPOINT_TRIGGER_WRITE 0x00000004 343 + #define PPC_BREAKPOINT_TRIGGER_RW \ 344 + (PPC_BREAKPOINT_TRIGGER_READ | PPC_BREAKPOINT_TRIGGER_WRITE) 345 + 346 + /* 347 + * Address Mode 348 + */ 349 + #define PPC_BREAKPOINT_MODE_EXACT 0x00000000 350 + #define PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE 0x00000001 351 + #define PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE 0x00000002 352 + #define PPC_BREAKPOINT_MODE_MASK 0x00000003 353 + 354 + /* 355 + * Condition Mode 356 + */ 357 + #define PPC_BREAKPOINT_CONDITION_MODE 0x00000003 358 + #define PPC_BREAKPOINT_CONDITION_NONE 0x00000000 359 + #define PPC_BREAKPOINT_CONDITION_AND 0x00000001 360 + #define PPC_BREAKPOINT_CONDITION_EXACT PPC_BREAKPOINT_CONDITION_AND 361 + #define PPC_BREAKPOINT_CONDITION_OR 0x00000002 362 + #define PPC_BREAKPOINT_CONDITION_AND_OR 0x00000003 363 + #define PPC_BREAKPOINT_CONDITION_BE_ALL 0x00ff0000 364 + #define PPC_BREAKPOINT_CONDITION_BE_SHIFT 16 365 + #define PPC_BREAKPOINT_CONDITION_BE(n) \ 366 + (1<<((n)+PPC_BREAKPOINT_CONDITION_BE_SHIFT)) 302 367 303 368 #endif /* _ASM_POWERPC_PTRACE_H */
+90
arch/powerpc/kernel/ptrace.c
··· 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 ··· 971 925 [TS_FPRWIDTH * (index - PT_FPR0)] = data; 972 926 ret = 0; 973 927 } 928 + break; 929 + } 930 + 931 + case PPC_PTRACE_GETHWDBGINFO: { 932 + struct ppc_debug_info dbginfo; 933 + 934 + dbginfo.version = 1; 935 + dbginfo.num_instruction_bps = 0; 936 + dbginfo.num_data_bps = 1; 937 + dbginfo.num_condition_regs = 0; 938 + #ifdef CONFIG_PPC64 939 + dbginfo.data_bp_alignment = 8; 940 + #else 941 + dbginfo.data_bp_alignment = 4; 942 + #endif 943 + dbginfo.sizeof_condition = 0; 944 + dbginfo.features = 0; 945 + 946 + if (!access_ok(VERIFY_WRITE, data, 947 + sizeof(struct ppc_debug_info))) 948 + return -EFAULT; 949 + ret = __copy_to_user((struct ppc_debug_info __user *)data, 950 + &dbginfo, sizeof(struct ppc_debug_info)) ? 951 + -EFAULT : 0; 952 + break; 953 + } 954 + 955 + case PPC_PTRACE_SETHWDEBUG: { 956 + struct ppc_hw_breakpoint bp_info; 957 + 958 + if (!access_ok(VERIFY_READ, data, 959 + sizeof(struct ppc_hw_breakpoint))) 960 + return -EFAULT; 961 + ret = __copy_from_user(&bp_info, 962 + (struct ppc_hw_breakpoint __user *)data, 963 + sizeof(struct ppc_hw_breakpoint)) ? 964 + -EFAULT : 0; 965 + if (!ret) 966 + ret = ppc_set_hwdebug(child, &bp_info); 967 + break; 968 + } 969 + 970 + case PPC_PTRACE_DELHWDEBUG: { 971 + ret = ppc_del_hwdebug(child, addr, data); 974 972 break; 975 973 } 976 974