19c2ddfe5SMichael Neuling // SPDX-License-Identifier: GPL-2.0+
29c2ddfe5SMichael Neuling
39c2ddfe5SMichael Neuling /*
49c2ddfe5SMichael Neuling * Ptrace test for hw breakpoints
59c2ddfe5SMichael Neuling *
69c2ddfe5SMichael Neuling * Based on tools/testing/selftests/breakpoints/breakpoint_test.c
79c2ddfe5SMichael Neuling *
89c2ddfe5SMichael Neuling * This test forks and the parent then traces the child doing various
99c2ddfe5SMichael Neuling * types of ptrace enabled breakpoints
109c2ddfe5SMichael Neuling *
119c2ddfe5SMichael Neuling * Copyright (C) 2018 Michael Neuling, IBM Corporation.
129c2ddfe5SMichael Neuling */
139c2ddfe5SMichael Neuling
149c2ddfe5SMichael Neuling #include <sys/ptrace.h>
159c2ddfe5SMichael Neuling #include <unistd.h>
169c2ddfe5SMichael Neuling #include <stddef.h>
179c2ddfe5SMichael Neuling #include <sys/user.h>
189c2ddfe5SMichael Neuling #include <stdio.h>
199c2ddfe5SMichael Neuling #include <stdlib.h>
209c2ddfe5SMichael Neuling #include <signal.h>
219c2ddfe5SMichael Neuling #include <sys/types.h>
229c2ddfe5SMichael Neuling #include <sys/wait.h>
23ac234524SRavi Bangoria #include <sys/syscall.h>
24ac234524SRavi Bangoria #include <linux/limits.h>
259c2ddfe5SMichael Neuling #include "ptrace.h"
26aecfd680SBenjamin Gray #include "reg.h"
279c2ddfe5SMichael Neuling
285dc7b419SRavi Bangoria #define SPRN_PVR 0x11F
295dc7b419SRavi Bangoria #define PVR_8xx 0x00500000
305dc7b419SRavi Bangoria
315dc7b419SRavi Bangoria bool is_8xx;
325dc7b419SRavi Bangoria
33c2837acfSRavi Bangoria /*
34c2837acfSRavi Bangoria * Use volatile on all global var so that compiler doesn't
35c2837acfSRavi Bangoria * optimise their load/stores. Otherwise selftest can fail.
36c2837acfSRavi Bangoria */
37c2837acfSRavi Bangoria static volatile __u64 glvar;
38c2837acfSRavi Bangoria
39c2837acfSRavi Bangoria #define DAWR_MAX_LEN 512
40c2837acfSRavi Bangoria static volatile __u8 big_var[DAWR_MAX_LEN] __attribute__((aligned(512)));
41c2837acfSRavi Bangoria
42c2837acfSRavi Bangoria #define A_LEN 6
43c2837acfSRavi Bangoria #define B_LEN 6
44c2837acfSRavi Bangoria struct gstruct {
45c2837acfSRavi Bangoria __u8 a[A_LEN]; /* double word aligned */
46c2837acfSRavi Bangoria __u8 b[B_LEN]; /* double word unaligned */
479c2ddfe5SMichael Neuling };
48c2837acfSRavi Bangoria static volatile struct gstruct gstruct __attribute__((aligned(512)));
499c2ddfe5SMichael Neuling
50ac234524SRavi Bangoria static volatile char cwd[PATH_MAX] __attribute__((aligned(8)));
519c2ddfe5SMichael Neuling
get_dbginfo(pid_t child_pid,struct ppc_debug_info * dbginfo)52c2837acfSRavi Bangoria static void get_dbginfo(pid_t child_pid, struct ppc_debug_info *dbginfo)
539c2ddfe5SMichael Neuling {
54c2837acfSRavi Bangoria if (ptrace(PPC_PTRACE_GETHWDBGINFO, child_pid, NULL, dbginfo)) {
55c2837acfSRavi Bangoria perror("Can't get breakpoint info");
569c2ddfe5SMichael Neuling exit(-1);
579c2ddfe5SMichael Neuling }
589c2ddfe5SMichael Neuling }
599c2ddfe5SMichael Neuling
dawr_present(struct ppc_debug_info * dbginfo)60c2837acfSRavi Bangoria static bool dawr_present(struct ppc_debug_info *dbginfo)
619c2ddfe5SMichael Neuling {
62c2837acfSRavi Bangoria return !!(dbginfo->features & PPC_DEBUG_FEATURE_DATA_BP_DAWR);
639c2ddfe5SMichael Neuling }
649c2ddfe5SMichael Neuling
write_var(int len)659c2ddfe5SMichael Neuling static void write_var(int len)
669c2ddfe5SMichael Neuling {
67*c3062edeSBenjamin Gray volatile __u8 *pcvar;
68*c3062edeSBenjamin Gray volatile __u16 *psvar;
69*c3062edeSBenjamin Gray volatile __u32 *pivar;
70*c3062edeSBenjamin Gray volatile __u64 *plvar;
719c2ddfe5SMichael Neuling
729c2ddfe5SMichael Neuling switch (len) {
739c2ddfe5SMichael Neuling case 1:
74*c3062edeSBenjamin Gray pcvar = (volatile __u8 *)&glvar;
75c2837acfSRavi Bangoria *pcvar = 0xff;
769c2ddfe5SMichael Neuling break;
779c2ddfe5SMichael Neuling case 2:
78*c3062edeSBenjamin Gray psvar = (volatile __u16 *)&glvar;
79c2837acfSRavi Bangoria *psvar = 0xffff;
809c2ddfe5SMichael Neuling break;
819c2ddfe5SMichael Neuling case 4:
82*c3062edeSBenjamin Gray pivar = (volatile __u32 *)&glvar;
83c2837acfSRavi Bangoria *pivar = 0xffffffff;
849c2ddfe5SMichael Neuling break;
859c2ddfe5SMichael Neuling case 8:
86*c3062edeSBenjamin Gray plvar = (volatile __u64 *)&glvar;
87c2837acfSRavi Bangoria *plvar = 0xffffffffffffffffLL;
889c2ddfe5SMichael Neuling break;
899c2ddfe5SMichael Neuling }
909c2ddfe5SMichael Neuling }
919c2ddfe5SMichael Neuling
read_var(int len)929c2ddfe5SMichael Neuling static void read_var(int len)
939c2ddfe5SMichael Neuling {
94c2837acfSRavi Bangoria __u8 cvar __attribute__((unused));
95c2837acfSRavi Bangoria __u16 svar __attribute__((unused));
96c2837acfSRavi Bangoria __u32 ivar __attribute__((unused));
97c2837acfSRavi Bangoria __u64 lvar __attribute__((unused));
989c2ddfe5SMichael Neuling
999c2ddfe5SMichael Neuling switch (len) {
1009c2ddfe5SMichael Neuling case 1:
101*c3062edeSBenjamin Gray cvar = (volatile __u8)glvar;
1029c2ddfe5SMichael Neuling break;
1039c2ddfe5SMichael Neuling case 2:
104*c3062edeSBenjamin Gray svar = (volatile __u16)glvar;
1059c2ddfe5SMichael Neuling break;
1069c2ddfe5SMichael Neuling case 4:
107*c3062edeSBenjamin Gray ivar = (volatile __u32)glvar;
1089c2ddfe5SMichael Neuling break;
1099c2ddfe5SMichael Neuling case 8:
110*c3062edeSBenjamin Gray lvar = (volatile __u64)glvar;
1119c2ddfe5SMichael Neuling break;
1129c2ddfe5SMichael Neuling }
1139c2ddfe5SMichael Neuling }
1149c2ddfe5SMichael Neuling
test_workload(void)115c2837acfSRavi Bangoria static void test_workload(void)
1169c2ddfe5SMichael Neuling {
117c2837acfSRavi Bangoria __u8 cvar __attribute__((unused));
118c2837acfSRavi Bangoria __u32 ivar __attribute__((unused));
119c2837acfSRavi Bangoria int len = 0;
1209c2ddfe5SMichael Neuling
121c2837acfSRavi Bangoria if (ptrace(PTRACE_TRACEME, 0, NULL, 0)) {
122c2837acfSRavi Bangoria perror("Child can't be traced?");
123c2837acfSRavi Bangoria exit(-1);
1249c2ddfe5SMichael Neuling }
1259c2ddfe5SMichael Neuling
1269c2ddfe5SMichael Neuling /* Wake up father so that it sets up the first test */
1279c2ddfe5SMichael Neuling kill(getpid(), SIGUSR1);
1289c2ddfe5SMichael Neuling
129c2837acfSRavi Bangoria /* PTRACE_SET_DEBUGREG, WO test */
130c2837acfSRavi Bangoria for (len = 1; len <= sizeof(glvar); len <<= 1)
1319c2ddfe5SMichael Neuling write_var(len);
1329c2ddfe5SMichael Neuling
133c2837acfSRavi Bangoria /* PTRACE_SET_DEBUGREG, RO test */
134c2837acfSRavi Bangoria for (len = 1; len <= sizeof(glvar); len <<= 1)
1359c2ddfe5SMichael Neuling read_var(len);
1369c2ddfe5SMichael Neuling
137c2837acfSRavi Bangoria /* PTRACE_SET_DEBUGREG, RW test */
138c2837acfSRavi Bangoria for (len = 1; len <= sizeof(glvar); len <<= 1) {
139c2837acfSRavi Bangoria if (rand() % 2)
140c2837acfSRavi Bangoria read_var(len);
141c2837acfSRavi Bangoria else
1429c2ddfe5SMichael Neuling write_var(len);
1439c2ddfe5SMichael Neuling }
1449c2ddfe5SMichael Neuling
145ac234524SRavi Bangoria /* PTRACE_SET_DEBUGREG, Kernel Access Userspace test */
146ac234524SRavi Bangoria syscall(__NR_getcwd, &cwd, PATH_MAX);
147ac234524SRavi Bangoria
148c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_EXACT, WO test */
149c2837acfSRavi Bangoria write_var(1);
150c2837acfSRavi Bangoria
151c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_EXACT, RO test */
152c2837acfSRavi Bangoria read_var(1);
153c2837acfSRavi Bangoria
154c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_EXACT, RW test */
155c2837acfSRavi Bangoria if (rand() % 2)
156c2837acfSRavi Bangoria write_var(1);
157c2837acfSRavi Bangoria else
158c2837acfSRavi Bangoria read_var(1);
159c2837acfSRavi Bangoria
160ac234524SRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_EXACT, Kernel Access Userspace test */
161ac234524SRavi Bangoria syscall(__NR_getcwd, &cwd, PATH_MAX);
162ac234524SRavi Bangoria
163c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW ALIGNED, WO test */
164c2837acfSRavi Bangoria gstruct.a[rand() % A_LEN] = 'a';
165c2837acfSRavi Bangoria
166c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW ALIGNED, RO test */
167c2837acfSRavi Bangoria cvar = gstruct.a[rand() % A_LEN];
168c2837acfSRavi Bangoria
169c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW ALIGNED, RW test */
170c2837acfSRavi Bangoria if (rand() % 2)
171c2837acfSRavi Bangoria gstruct.a[rand() % A_LEN] = 'a';
172c2837acfSRavi Bangoria else
173c2837acfSRavi Bangoria cvar = gstruct.a[rand() % A_LEN];
174c2837acfSRavi Bangoria
175c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW UNALIGNED, WO test */
176c2837acfSRavi Bangoria gstruct.b[rand() % B_LEN] = 'b';
177c2837acfSRavi Bangoria
178c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW UNALIGNED, RO test */
179c2837acfSRavi Bangoria cvar = gstruct.b[rand() % B_LEN];
180c2837acfSRavi Bangoria
181c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW UNALIGNED, RW test */
182c2837acfSRavi Bangoria if (rand() % 2)
183c2837acfSRavi Bangoria gstruct.b[rand() % B_LEN] = 'b';
184c2837acfSRavi Bangoria else
185c2837acfSRavi Bangoria cvar = gstruct.b[rand() % B_LEN];
186c2837acfSRavi Bangoria
187c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW UNALIGNED, DAR OUTSIDE, RW test */
188c2837acfSRavi Bangoria if (rand() % 2)
189c2837acfSRavi Bangoria *((int *)(gstruct.a + 4)) = 10;
190c2837acfSRavi Bangoria else
191c2837acfSRavi Bangoria ivar = *((int *)(gstruct.a + 4));
192c2837acfSRavi Bangoria
193c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG. DAWR_MAX_LEN. RW test */
194c2837acfSRavi Bangoria if (rand() % 2)
195c2837acfSRavi Bangoria big_var[rand() % DAWR_MAX_LEN] = 'a';
196c2837acfSRavi Bangoria else
197c2837acfSRavi Bangoria cvar = big_var[rand() % DAWR_MAX_LEN];
198dae4ff80SRavi Bangoria
199dae4ff80SRavi Bangoria /* PPC_PTRACE_SETHWDEBUG 2, MODE_RANGE, DW ALIGNED, WO test */
200dae4ff80SRavi Bangoria gstruct.a[rand() % A_LEN] = 'a';
201dae4ff80SRavi Bangoria
202dae4ff80SRavi Bangoria /* PPC_PTRACE_SETHWDEBUG 2, MODE_RANGE, DW UNALIGNED, RO test */
203dae4ff80SRavi Bangoria cvar = gstruct.b[rand() % B_LEN];
204dae4ff80SRavi Bangoria
205dae4ff80SRavi Bangoria /* PPC_PTRACE_SETHWDEBUG 2, MODE_RANGE, DAWR Overlap, WO test */
206dae4ff80SRavi Bangoria gstruct.a[rand() % A_LEN] = 'a';
207dae4ff80SRavi Bangoria
208dae4ff80SRavi Bangoria /* PPC_PTRACE_SETHWDEBUG 2, MODE_RANGE, DAWR Overlap, RO test */
209dae4ff80SRavi Bangoria cvar = gstruct.a[rand() % A_LEN];
210c2837acfSRavi Bangoria }
211c2837acfSRavi Bangoria
check_success(pid_t child_pid,const char * name,const char * type,unsigned long saddr,int len)212c2837acfSRavi Bangoria static void check_success(pid_t child_pid, const char *name, const char *type,
213c2837acfSRavi Bangoria unsigned long saddr, int len)
2149c2ddfe5SMichael Neuling {
2159c2ddfe5SMichael Neuling int status;
216c2837acfSRavi Bangoria siginfo_t siginfo;
217c2837acfSRavi Bangoria unsigned long eaddr = (saddr + len - 1) | 0x7;
218c2837acfSRavi Bangoria
219c2837acfSRavi Bangoria saddr &= ~0x7;
2209c2ddfe5SMichael Neuling
2219c2ddfe5SMichael Neuling /* Wait for the child to SIGTRAP */
2229c2ddfe5SMichael Neuling wait(&status);
2239c2ddfe5SMichael Neuling
224c2837acfSRavi Bangoria ptrace(PTRACE_GETSIGINFO, child_pid, NULL, &siginfo);
2259c2ddfe5SMichael Neuling
226c2837acfSRavi Bangoria if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGTRAP ||
227c2837acfSRavi Bangoria (unsigned long)siginfo.si_addr < saddr ||
228c2837acfSRavi Bangoria (unsigned long)siginfo.si_addr > eaddr) {
229c2837acfSRavi Bangoria printf("%s, %s, len: %d: Fail\n", name, type, len);
230c2837acfSRavi Bangoria exit(-1);
2319c2ddfe5SMichael Neuling }
2329c2ddfe5SMichael Neuling
233c2837acfSRavi Bangoria printf("%s, %s, len: %d: Ok\n", name, type, len);
234c2837acfSRavi Bangoria
2355dc7b419SRavi Bangoria if (!is_8xx) {
236c2837acfSRavi Bangoria /*
237c2837acfSRavi Bangoria * For ptrace registered watchpoint, signal is generated
238c2837acfSRavi Bangoria * before executing load/store. Singlestep the instruction
239c2837acfSRavi Bangoria * and then continue the test.
240c2837acfSRavi Bangoria */
241c2837acfSRavi Bangoria ptrace(PTRACE_SINGLESTEP, child_pid, NULL, 0);
242c2837acfSRavi Bangoria wait(NULL);
2439c2ddfe5SMichael Neuling }
2445dc7b419SRavi Bangoria }
2459c2ddfe5SMichael Neuling
ptrace_set_debugreg(pid_t child_pid,unsigned long wp_addr)246c2837acfSRavi Bangoria static void ptrace_set_debugreg(pid_t child_pid, unsigned long wp_addr)
2479c2ddfe5SMichael Neuling {
248c2837acfSRavi Bangoria if (ptrace(PTRACE_SET_DEBUGREG, child_pid, 0, wp_addr)) {
249c2837acfSRavi Bangoria perror("PTRACE_SET_DEBUGREG failed");
250c2837acfSRavi Bangoria exit(-1);
251c2837acfSRavi Bangoria }
2529c2ddfe5SMichael Neuling }
2539c2ddfe5SMichael Neuling
ptrace_sethwdebug(pid_t child_pid,struct ppc_hw_breakpoint * info)254c2837acfSRavi Bangoria static int ptrace_sethwdebug(pid_t child_pid, struct ppc_hw_breakpoint *info)
255c2837acfSRavi Bangoria {
256c2837acfSRavi Bangoria int wh = ptrace(PPC_PTRACE_SETHWDEBUG, child_pid, 0, info);
2579c2ddfe5SMichael Neuling
258c2837acfSRavi Bangoria if (wh <= 0) {
259c2837acfSRavi Bangoria perror("PPC_PTRACE_SETHWDEBUG failed");
260c2837acfSRavi Bangoria exit(-1);
261c2837acfSRavi Bangoria }
262c2837acfSRavi Bangoria return wh;
263c2837acfSRavi Bangoria }
264c2837acfSRavi Bangoria
ptrace_delhwdebug(pid_t child_pid,int wh)265c2837acfSRavi Bangoria static void ptrace_delhwdebug(pid_t child_pid, int wh)
266c2837acfSRavi Bangoria {
267c2837acfSRavi Bangoria if (ptrace(PPC_PTRACE_DELHWDEBUG, child_pid, 0, wh) < 0) {
268c2837acfSRavi Bangoria perror("PPC_PTRACE_DELHWDEBUG failed");
269c2837acfSRavi Bangoria exit(-1);
270c2837acfSRavi Bangoria }
271c2837acfSRavi Bangoria }
272c2837acfSRavi Bangoria
273c2837acfSRavi Bangoria #define DABR_READ_SHIFT 0
274c2837acfSRavi Bangoria #define DABR_WRITE_SHIFT 1
275c2837acfSRavi Bangoria #define DABR_TRANSLATION_SHIFT 2
276c2837acfSRavi Bangoria
test_set_debugreg(pid_t child_pid)277c2837acfSRavi Bangoria static int test_set_debugreg(pid_t child_pid)
278c2837acfSRavi Bangoria {
279c2837acfSRavi Bangoria unsigned long wp_addr = (unsigned long)&glvar;
280c2837acfSRavi Bangoria char *name = "PTRACE_SET_DEBUGREG";
281c2837acfSRavi Bangoria int len;
282c2837acfSRavi Bangoria
283c2837acfSRavi Bangoria /* PTRACE_SET_DEBUGREG, WO test*/
284c2837acfSRavi Bangoria wp_addr &= ~0x7UL;
285c2837acfSRavi Bangoria wp_addr |= (1UL << DABR_WRITE_SHIFT);
286c2837acfSRavi Bangoria wp_addr |= (1UL << DABR_TRANSLATION_SHIFT);
287c2837acfSRavi Bangoria for (len = 1; len <= sizeof(glvar); len <<= 1) {
288c2837acfSRavi Bangoria ptrace_set_debugreg(child_pid, wp_addr);
2899c2ddfe5SMichael Neuling ptrace(PTRACE_CONT, child_pid, NULL, 0);
290c2837acfSRavi Bangoria check_success(child_pid, name, "WO", wp_addr, len);
291c2837acfSRavi Bangoria }
2929c2ddfe5SMichael Neuling
293c2837acfSRavi Bangoria /* PTRACE_SET_DEBUGREG, RO test */
294c2837acfSRavi Bangoria wp_addr &= ~0x7UL;
295c2837acfSRavi Bangoria wp_addr |= (1UL << DABR_READ_SHIFT);
296c2837acfSRavi Bangoria wp_addr |= (1UL << DABR_TRANSLATION_SHIFT);
297c2837acfSRavi Bangoria for (len = 1; len <= sizeof(glvar); len <<= 1) {
298c2837acfSRavi Bangoria ptrace_set_debugreg(child_pid, wp_addr);
2999c2ddfe5SMichael Neuling ptrace(PTRACE_CONT, child_pid, NULL, 0);
300c2837acfSRavi Bangoria check_success(child_pid, name, "RO", wp_addr, len);
301c2837acfSRavi Bangoria }
3029c2ddfe5SMichael Neuling
303c2837acfSRavi Bangoria /* PTRACE_SET_DEBUGREG, RW test */
304c2837acfSRavi Bangoria wp_addr &= ~0x7UL;
305c2837acfSRavi Bangoria wp_addr |= (1Ul << DABR_READ_SHIFT);
306c2837acfSRavi Bangoria wp_addr |= (1UL << DABR_WRITE_SHIFT);
307c2837acfSRavi Bangoria wp_addr |= (1UL << DABR_TRANSLATION_SHIFT);
308c2837acfSRavi Bangoria for (len = 1; len <= sizeof(glvar); len <<= 1) {
309c2837acfSRavi Bangoria ptrace_set_debugreg(child_pid, wp_addr);
3109c2ddfe5SMichael Neuling ptrace(PTRACE_CONT, child_pid, NULL, 0);
311c2837acfSRavi Bangoria check_success(child_pid, name, "RW", wp_addr, len);
312c2837acfSRavi Bangoria }
313c2837acfSRavi Bangoria
314c2837acfSRavi Bangoria ptrace_set_debugreg(child_pid, 0);
315c2837acfSRavi Bangoria return 0;
316c2837acfSRavi Bangoria }
317c2837acfSRavi Bangoria
test_set_debugreg_kernel_userspace(pid_t child_pid)318ac234524SRavi Bangoria static int test_set_debugreg_kernel_userspace(pid_t child_pid)
319ac234524SRavi Bangoria {
320ac234524SRavi Bangoria unsigned long wp_addr = (unsigned long)cwd;
321ac234524SRavi Bangoria char *name = "PTRACE_SET_DEBUGREG";
322ac234524SRavi Bangoria
323ac234524SRavi Bangoria /* PTRACE_SET_DEBUGREG, Kernel Access Userspace test */
324ac234524SRavi Bangoria wp_addr &= ~0x7UL;
325ac234524SRavi Bangoria wp_addr |= (1Ul << DABR_READ_SHIFT);
326ac234524SRavi Bangoria wp_addr |= (1UL << DABR_WRITE_SHIFT);
327ac234524SRavi Bangoria wp_addr |= (1UL << DABR_TRANSLATION_SHIFT);
328ac234524SRavi Bangoria ptrace_set_debugreg(child_pid, wp_addr);
329ac234524SRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
330ac234524SRavi Bangoria check_success(child_pid, name, "Kernel Access Userspace", wp_addr, 8);
331ac234524SRavi Bangoria
332ac234524SRavi Bangoria ptrace_set_debugreg(child_pid, 0);
333ac234524SRavi Bangoria return 0;
334ac234524SRavi Bangoria }
335ac234524SRavi Bangoria
get_ppc_hw_breakpoint(struct ppc_hw_breakpoint * info,int type,unsigned long addr,int len)336c2837acfSRavi Bangoria static void get_ppc_hw_breakpoint(struct ppc_hw_breakpoint *info, int type,
337c2837acfSRavi Bangoria unsigned long addr, int len)
338c2837acfSRavi Bangoria {
339c2837acfSRavi Bangoria info->version = 1;
340c2837acfSRavi Bangoria info->trigger_type = type;
341c2837acfSRavi Bangoria info->condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
342c2837acfSRavi Bangoria info->addr = (__u64)addr;
343c2837acfSRavi Bangoria info->addr2 = (__u64)addr + len;
344c2837acfSRavi Bangoria info->condition_value = 0;
345c2837acfSRavi Bangoria if (!len)
346c2837acfSRavi Bangoria info->addr_mode = PPC_BREAKPOINT_MODE_EXACT;
347c2837acfSRavi Bangoria else
348c2837acfSRavi Bangoria info->addr_mode = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
349c2837acfSRavi Bangoria }
350c2837acfSRavi Bangoria
test_sethwdebug_exact(pid_t child_pid)351c2837acfSRavi Bangoria static void test_sethwdebug_exact(pid_t child_pid)
352c2837acfSRavi Bangoria {
353c2837acfSRavi Bangoria struct ppc_hw_breakpoint info;
354c2837acfSRavi Bangoria unsigned long wp_addr = (unsigned long)&glvar;
355c2837acfSRavi Bangoria char *name = "PPC_PTRACE_SETHWDEBUG, MODE_EXACT";
356c2837acfSRavi Bangoria int len = 1; /* hardcoded in kernel */
357c2837acfSRavi Bangoria int wh;
358c2837acfSRavi Bangoria
359c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_EXACT, WO test */
360c2837acfSRavi Bangoria get_ppc_hw_breakpoint(&info, PPC_BREAKPOINT_TRIGGER_WRITE, wp_addr, 0);
361c2837acfSRavi Bangoria wh = ptrace_sethwdebug(child_pid, &info);
362c2837acfSRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
363c2837acfSRavi Bangoria check_success(child_pid, name, "WO", wp_addr, len);
364c2837acfSRavi Bangoria ptrace_delhwdebug(child_pid, wh);
365c2837acfSRavi Bangoria
366c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_EXACT, RO test */
367c2837acfSRavi Bangoria get_ppc_hw_breakpoint(&info, PPC_BREAKPOINT_TRIGGER_READ, wp_addr, 0);
368c2837acfSRavi Bangoria wh = ptrace_sethwdebug(child_pid, &info);
369c2837acfSRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
370c2837acfSRavi Bangoria check_success(child_pid, name, "RO", wp_addr, len);
371c2837acfSRavi Bangoria ptrace_delhwdebug(child_pid, wh);
372c2837acfSRavi Bangoria
373c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_EXACT, RW test */
374c2837acfSRavi Bangoria get_ppc_hw_breakpoint(&info, PPC_BREAKPOINT_TRIGGER_RW, wp_addr, 0);
375c2837acfSRavi Bangoria wh = ptrace_sethwdebug(child_pid, &info);
376c2837acfSRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
377c2837acfSRavi Bangoria check_success(child_pid, name, "RW", wp_addr, len);
378c2837acfSRavi Bangoria ptrace_delhwdebug(child_pid, wh);
379c2837acfSRavi Bangoria }
380c2837acfSRavi Bangoria
test_sethwdebug_exact_kernel_userspace(pid_t child_pid)381ac234524SRavi Bangoria static void test_sethwdebug_exact_kernel_userspace(pid_t child_pid)
382ac234524SRavi Bangoria {
383ac234524SRavi Bangoria struct ppc_hw_breakpoint info;
384ac234524SRavi Bangoria unsigned long wp_addr = (unsigned long)&cwd;
385ac234524SRavi Bangoria char *name = "PPC_PTRACE_SETHWDEBUG, MODE_EXACT";
386ac234524SRavi Bangoria int len = 1; /* hardcoded in kernel */
387ac234524SRavi Bangoria int wh;
388ac234524SRavi Bangoria
389ac234524SRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_EXACT, Kernel Access Userspace test */
390ac234524SRavi Bangoria get_ppc_hw_breakpoint(&info, PPC_BREAKPOINT_TRIGGER_WRITE, wp_addr, 0);
391ac234524SRavi Bangoria wh = ptrace_sethwdebug(child_pid, &info);
392ac234524SRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
393ac234524SRavi Bangoria check_success(child_pid, name, "Kernel Access Userspace", wp_addr, len);
394ac234524SRavi Bangoria ptrace_delhwdebug(child_pid, wh);
395ac234524SRavi Bangoria }
396ac234524SRavi Bangoria
test_sethwdebug_range_aligned(pid_t child_pid)397c2837acfSRavi Bangoria static void test_sethwdebug_range_aligned(pid_t child_pid)
398c2837acfSRavi Bangoria {
399c2837acfSRavi Bangoria struct ppc_hw_breakpoint info;
400c2837acfSRavi Bangoria unsigned long wp_addr;
401c2837acfSRavi Bangoria char *name = "PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW ALIGNED";
402c2837acfSRavi Bangoria int len;
403c2837acfSRavi Bangoria int wh;
404c2837acfSRavi Bangoria
405c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW ALIGNED, WO test */
406c2837acfSRavi Bangoria wp_addr = (unsigned long)&gstruct.a;
407c2837acfSRavi Bangoria len = A_LEN;
408c2837acfSRavi Bangoria get_ppc_hw_breakpoint(&info, PPC_BREAKPOINT_TRIGGER_WRITE, wp_addr, len);
409c2837acfSRavi Bangoria wh = ptrace_sethwdebug(child_pid, &info);
410c2837acfSRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
411c2837acfSRavi Bangoria check_success(child_pid, name, "WO", wp_addr, len);
412c2837acfSRavi Bangoria ptrace_delhwdebug(child_pid, wh);
413c2837acfSRavi Bangoria
414c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW ALIGNED, RO test */
415c2837acfSRavi Bangoria wp_addr = (unsigned long)&gstruct.a;
416c2837acfSRavi Bangoria len = A_LEN;
417c2837acfSRavi Bangoria get_ppc_hw_breakpoint(&info, PPC_BREAKPOINT_TRIGGER_READ, wp_addr, len);
418c2837acfSRavi Bangoria wh = ptrace_sethwdebug(child_pid, &info);
419c2837acfSRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
420c2837acfSRavi Bangoria check_success(child_pid, name, "RO", wp_addr, len);
421c2837acfSRavi Bangoria ptrace_delhwdebug(child_pid, wh);
422c2837acfSRavi Bangoria
423c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW ALIGNED, RW test */
424c2837acfSRavi Bangoria wp_addr = (unsigned long)&gstruct.a;
425c2837acfSRavi Bangoria len = A_LEN;
426c2837acfSRavi Bangoria get_ppc_hw_breakpoint(&info, PPC_BREAKPOINT_TRIGGER_RW, wp_addr, len);
427c2837acfSRavi Bangoria wh = ptrace_sethwdebug(child_pid, &info);
428c2837acfSRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
429c2837acfSRavi Bangoria check_success(child_pid, name, "RW", wp_addr, len);
430c2837acfSRavi Bangoria ptrace_delhwdebug(child_pid, wh);
431c2837acfSRavi Bangoria }
432c2837acfSRavi Bangoria
test_multi_sethwdebug_range(pid_t child_pid)433dae4ff80SRavi Bangoria static void test_multi_sethwdebug_range(pid_t child_pid)
434dae4ff80SRavi Bangoria {
435dae4ff80SRavi Bangoria struct ppc_hw_breakpoint info1, info2;
436dae4ff80SRavi Bangoria unsigned long wp_addr1, wp_addr2;
437dae4ff80SRavi Bangoria char *name1 = "PPC_PTRACE_SETHWDEBUG 2, MODE_RANGE, DW ALIGNED";
438dae4ff80SRavi Bangoria char *name2 = "PPC_PTRACE_SETHWDEBUG 2, MODE_RANGE, DW UNALIGNED";
439dae4ff80SRavi Bangoria int len1, len2;
440dae4ff80SRavi Bangoria int wh1, wh2;
441dae4ff80SRavi Bangoria
442dae4ff80SRavi Bangoria wp_addr1 = (unsigned long)&gstruct.a;
443dae4ff80SRavi Bangoria wp_addr2 = (unsigned long)&gstruct.b;
444dae4ff80SRavi Bangoria len1 = A_LEN;
445dae4ff80SRavi Bangoria len2 = B_LEN;
446dae4ff80SRavi Bangoria get_ppc_hw_breakpoint(&info1, PPC_BREAKPOINT_TRIGGER_WRITE, wp_addr1, len1);
447dae4ff80SRavi Bangoria get_ppc_hw_breakpoint(&info2, PPC_BREAKPOINT_TRIGGER_READ, wp_addr2, len2);
448dae4ff80SRavi Bangoria
449dae4ff80SRavi Bangoria /* PPC_PTRACE_SETHWDEBUG 2, MODE_RANGE, DW ALIGNED, WO test */
450dae4ff80SRavi Bangoria wh1 = ptrace_sethwdebug(child_pid, &info1);
451dae4ff80SRavi Bangoria
452dae4ff80SRavi Bangoria /* PPC_PTRACE_SETHWDEBUG 2, MODE_RANGE, DW UNALIGNED, RO test */
453dae4ff80SRavi Bangoria wh2 = ptrace_sethwdebug(child_pid, &info2);
454dae4ff80SRavi Bangoria
455dae4ff80SRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
456dae4ff80SRavi Bangoria check_success(child_pid, name1, "WO", wp_addr1, len1);
457dae4ff80SRavi Bangoria
458dae4ff80SRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
459dae4ff80SRavi Bangoria check_success(child_pid, name2, "RO", wp_addr2, len2);
460dae4ff80SRavi Bangoria
461dae4ff80SRavi Bangoria ptrace_delhwdebug(child_pid, wh1);
462dae4ff80SRavi Bangoria ptrace_delhwdebug(child_pid, wh2);
463dae4ff80SRavi Bangoria }
464dae4ff80SRavi Bangoria
test_multi_sethwdebug_range_dawr_overlap(pid_t child_pid)465dae4ff80SRavi Bangoria static void test_multi_sethwdebug_range_dawr_overlap(pid_t child_pid)
466dae4ff80SRavi Bangoria {
467dae4ff80SRavi Bangoria struct ppc_hw_breakpoint info1, info2;
468dae4ff80SRavi Bangoria unsigned long wp_addr1, wp_addr2;
469dae4ff80SRavi Bangoria char *name = "PPC_PTRACE_SETHWDEBUG 2, MODE_RANGE, DAWR Overlap";
470dae4ff80SRavi Bangoria int len1, len2;
471dae4ff80SRavi Bangoria int wh1, wh2;
472dae4ff80SRavi Bangoria
473dae4ff80SRavi Bangoria wp_addr1 = (unsigned long)&gstruct.a;
474dae4ff80SRavi Bangoria wp_addr2 = (unsigned long)&gstruct.a;
475dae4ff80SRavi Bangoria len1 = A_LEN;
476dae4ff80SRavi Bangoria len2 = A_LEN;
477dae4ff80SRavi Bangoria get_ppc_hw_breakpoint(&info1, PPC_BREAKPOINT_TRIGGER_WRITE, wp_addr1, len1);
478dae4ff80SRavi Bangoria get_ppc_hw_breakpoint(&info2, PPC_BREAKPOINT_TRIGGER_READ, wp_addr2, len2);
479dae4ff80SRavi Bangoria
480dae4ff80SRavi Bangoria /* PPC_PTRACE_SETHWDEBUG 2, MODE_RANGE, DAWR Overlap, WO test */
481dae4ff80SRavi Bangoria wh1 = ptrace_sethwdebug(child_pid, &info1);
482dae4ff80SRavi Bangoria
483dae4ff80SRavi Bangoria /* PPC_PTRACE_SETHWDEBUG 2, MODE_RANGE, DAWR Overlap, RO test */
484dae4ff80SRavi Bangoria wh2 = ptrace_sethwdebug(child_pid, &info2);
485dae4ff80SRavi Bangoria
486dae4ff80SRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
487dae4ff80SRavi Bangoria check_success(child_pid, name, "WO", wp_addr1, len1);
488dae4ff80SRavi Bangoria
489dae4ff80SRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
490dae4ff80SRavi Bangoria check_success(child_pid, name, "RO", wp_addr2, len2);
491dae4ff80SRavi Bangoria
492dae4ff80SRavi Bangoria ptrace_delhwdebug(child_pid, wh1);
493dae4ff80SRavi Bangoria ptrace_delhwdebug(child_pid, wh2);
494dae4ff80SRavi Bangoria }
495dae4ff80SRavi Bangoria
test_sethwdebug_range_unaligned(pid_t child_pid)496c2837acfSRavi Bangoria static void test_sethwdebug_range_unaligned(pid_t child_pid)
497c2837acfSRavi Bangoria {
498c2837acfSRavi Bangoria struct ppc_hw_breakpoint info;
499c2837acfSRavi Bangoria unsigned long wp_addr;
500c2837acfSRavi Bangoria char *name = "PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW UNALIGNED";
501c2837acfSRavi Bangoria int len;
502c2837acfSRavi Bangoria int wh;
503c2837acfSRavi Bangoria
504c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW UNALIGNED, WO test */
505c2837acfSRavi Bangoria wp_addr = (unsigned long)&gstruct.b;
506c2837acfSRavi Bangoria len = B_LEN;
507c2837acfSRavi Bangoria get_ppc_hw_breakpoint(&info, PPC_BREAKPOINT_TRIGGER_WRITE, wp_addr, len);
508c2837acfSRavi Bangoria wh = ptrace_sethwdebug(child_pid, &info);
509c2837acfSRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
510c2837acfSRavi Bangoria check_success(child_pid, name, "WO", wp_addr, len);
511c2837acfSRavi Bangoria ptrace_delhwdebug(child_pid, wh);
512c2837acfSRavi Bangoria
513c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW UNALIGNED, RO test */
514c2837acfSRavi Bangoria wp_addr = (unsigned long)&gstruct.b;
515c2837acfSRavi Bangoria len = B_LEN;
516c2837acfSRavi Bangoria get_ppc_hw_breakpoint(&info, PPC_BREAKPOINT_TRIGGER_READ, wp_addr, len);
517c2837acfSRavi Bangoria wh = ptrace_sethwdebug(child_pid, &info);
518c2837acfSRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
519c2837acfSRavi Bangoria check_success(child_pid, name, "RO", wp_addr, len);
520c2837acfSRavi Bangoria ptrace_delhwdebug(child_pid, wh);
521c2837acfSRavi Bangoria
522c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW UNALIGNED, RW test */
523c2837acfSRavi Bangoria wp_addr = (unsigned long)&gstruct.b;
524c2837acfSRavi Bangoria len = B_LEN;
525c2837acfSRavi Bangoria get_ppc_hw_breakpoint(&info, PPC_BREAKPOINT_TRIGGER_RW, wp_addr, len);
526c2837acfSRavi Bangoria wh = ptrace_sethwdebug(child_pid, &info);
527c2837acfSRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
528c2837acfSRavi Bangoria check_success(child_pid, name, "RW", wp_addr, len);
529c2837acfSRavi Bangoria ptrace_delhwdebug(child_pid, wh);
530c2837acfSRavi Bangoria
531c2837acfSRavi Bangoria }
532c2837acfSRavi Bangoria
test_sethwdebug_range_unaligned_dar(pid_t child_pid)533c2837acfSRavi Bangoria static void test_sethwdebug_range_unaligned_dar(pid_t child_pid)
534c2837acfSRavi Bangoria {
535c2837acfSRavi Bangoria struct ppc_hw_breakpoint info;
536c2837acfSRavi Bangoria unsigned long wp_addr;
537c2837acfSRavi Bangoria char *name = "PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW UNALIGNED, DAR OUTSIDE";
538c2837acfSRavi Bangoria int len;
539c2837acfSRavi Bangoria int wh;
540c2837acfSRavi Bangoria
541c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW UNALIGNED, DAR OUTSIDE, RW test */
542c2837acfSRavi Bangoria wp_addr = (unsigned long)&gstruct.b;
543c2837acfSRavi Bangoria len = B_LEN;
544c2837acfSRavi Bangoria get_ppc_hw_breakpoint(&info, PPC_BREAKPOINT_TRIGGER_WRITE, wp_addr, len);
545c2837acfSRavi Bangoria wh = ptrace_sethwdebug(child_pid, &info);
546c2837acfSRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
547c2837acfSRavi Bangoria check_success(child_pid, name, "RW", wp_addr, len);
548c2837acfSRavi Bangoria ptrace_delhwdebug(child_pid, wh);
549c2837acfSRavi Bangoria }
550c2837acfSRavi Bangoria
test_sethwdebug_dawr_max_range(pid_t child_pid)551c2837acfSRavi Bangoria static void test_sethwdebug_dawr_max_range(pid_t child_pid)
552c2837acfSRavi Bangoria {
553c2837acfSRavi Bangoria struct ppc_hw_breakpoint info;
554c2837acfSRavi Bangoria unsigned long wp_addr;
555c2837acfSRavi Bangoria char *name = "PPC_PTRACE_SETHWDEBUG, DAWR_MAX_LEN";
556c2837acfSRavi Bangoria int len;
557c2837acfSRavi Bangoria int wh;
558c2837acfSRavi Bangoria
559c2837acfSRavi Bangoria /* PPC_PTRACE_SETHWDEBUG, DAWR_MAX_LEN, RW test */
560c2837acfSRavi Bangoria wp_addr = (unsigned long)big_var;
561c2837acfSRavi Bangoria len = DAWR_MAX_LEN;
562c2837acfSRavi Bangoria get_ppc_hw_breakpoint(&info, PPC_BREAKPOINT_TRIGGER_RW, wp_addr, len);
563c2837acfSRavi Bangoria wh = ptrace_sethwdebug(child_pid, &info);
564c2837acfSRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
565c2837acfSRavi Bangoria check_success(child_pid, name, "RW", wp_addr, len);
566c2837acfSRavi Bangoria ptrace_delhwdebug(child_pid, wh);
5679c2ddfe5SMichael Neuling }
5689c2ddfe5SMichael Neuling
5699c2ddfe5SMichael Neuling /* Set the breakpoints and check the child successfully trigger them */
570c2837acfSRavi Bangoria static void
run_tests(pid_t child_pid,struct ppc_debug_info * dbginfo,bool dawr)571c2837acfSRavi Bangoria run_tests(pid_t child_pid, struct ppc_debug_info *dbginfo, bool dawr)
5729c2ddfe5SMichael Neuling {
573c2837acfSRavi Bangoria test_set_debugreg(child_pid);
574ac234524SRavi Bangoria test_set_debugreg_kernel_userspace(child_pid);
575c2837acfSRavi Bangoria test_sethwdebug_exact(child_pid);
576ac234524SRavi Bangoria test_sethwdebug_exact_kernel_userspace(child_pid);
577ac234524SRavi Bangoria if (dbginfo->features & PPC_DEBUG_FEATURE_DATA_BP_RANGE) {
578c2837acfSRavi Bangoria test_sethwdebug_range_aligned(child_pid);
579a426ea9bSChristophe Leroy if (dawr || is_8xx) {
580c2837acfSRavi Bangoria test_sethwdebug_range_unaligned(child_pid);
581c2837acfSRavi Bangoria test_sethwdebug_range_unaligned_dar(child_pid);
582c2837acfSRavi Bangoria test_sethwdebug_dawr_max_range(child_pid);
583dae4ff80SRavi Bangoria if (dbginfo->num_data_bps > 1) {
584dae4ff80SRavi Bangoria test_multi_sethwdebug_range(child_pid);
585dae4ff80SRavi Bangoria test_multi_sethwdebug_range_dawr_overlap(child_pid);
586dae4ff80SRavi Bangoria }
5879c2ddfe5SMichael Neuling }
5889c2ddfe5SMichael Neuling }
5899c2ddfe5SMichael Neuling }
5909c2ddfe5SMichael Neuling
ptrace_hwbreak(void)5919c2ddfe5SMichael Neuling static int ptrace_hwbreak(void)
5929c2ddfe5SMichael Neuling {
593c2837acfSRavi Bangoria pid_t child_pid;
594c2837acfSRavi Bangoria struct ppc_debug_info dbginfo;
5959c2ddfe5SMichael Neuling bool dawr;
5969c2ddfe5SMichael Neuling
597c2837acfSRavi Bangoria child_pid = fork();
598c2837acfSRavi Bangoria if (!child_pid) {
599c2837acfSRavi Bangoria test_workload();
6009c2ddfe5SMichael Neuling return 0;
6019c2ddfe5SMichael Neuling }
6029c2ddfe5SMichael Neuling
6039c2ddfe5SMichael Neuling wait(NULL);
6049c2ddfe5SMichael Neuling
605c2837acfSRavi Bangoria get_dbginfo(child_pid, &dbginfo);
60668877ff2SBenjamin Gray SKIP_IF_MSG(dbginfo.num_data_bps == 0, "No data breakpoints present");
6079c2ddfe5SMichael Neuling
608c2837acfSRavi Bangoria dawr = dawr_present(&dbginfo);
609c2837acfSRavi Bangoria run_tests(child_pid, &dbginfo, dawr);
6109c2ddfe5SMichael Neuling
611c2837acfSRavi Bangoria /* Let the child exit first. */
612c2837acfSRavi Bangoria ptrace(PTRACE_CONT, child_pid, NULL, 0);
6139c2ddfe5SMichael Neuling wait(NULL);
6149c2ddfe5SMichael Neuling
615c2837acfSRavi Bangoria /*
616c2837acfSRavi Bangoria * Testcases exits immediately with -1 on any failure. If
617c2837acfSRavi Bangoria * it has reached here, it means all tests were successful.
618c2837acfSRavi Bangoria */
619c2837acfSRavi Bangoria return TEST_PASS;
6209c2ddfe5SMichael Neuling }
6219c2ddfe5SMichael Neuling
main(int argc,char ** argv,char ** envp)6229c2ddfe5SMichael Neuling int main(int argc, char **argv, char **envp)
6239c2ddfe5SMichael Neuling {
624aecfd680SBenjamin Gray is_8xx = mfspr(SPRN_PVR) == PVR_8xx;
6255dc7b419SRavi Bangoria
6269c2ddfe5SMichael Neuling return test_harness(ptrace_hwbreak, "ptrace-hwbreak");
6279c2ddfe5SMichael Neuling }
628