Skip to content

Commit 85ce9a5

Browse files
mikeympe
authored andcommitted
powerpc: Update ptrace to use ppc_breakpoint_available()
This updates the ptrace code to use ppc_breakpoint_available(). We now advertise via PPC_PTRACE_GETHWDBGINFO zero breakpoints when the DAWR is missing (ie. POWER9). This results in GDB falling back to software emulation of the breakpoint (which is slow). For the features advertised by PPC_PTRACE_GETHWDBGINFO, we keep advertising DAWR as if we don't GDB assumes 1 breakpoint irrespective of the number of breakpoints advertised. GDB then fails later when trying to set this one breakpoint. Signed-off-by: Michael Neuling <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent 404b27d commit 85ce9a5

File tree

2 files changed

+17
-2
lines changed

2 files changed

+17
-2
lines changed

arch/powerpc/kernel/hw_breakpoint.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <asm/hw_breakpoint.h>
3434
#include <asm/processor.h>
3535
#include <asm/sstep.h>
36+
#include <asm/debug.h>
3637
#include <linux/uaccess.h>
3738

3839
/*
@@ -171,6 +172,8 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
171172
* HW_BREAKPOINT_ALIGN by rounding off to the lower address, the
172173
* 'symbolsize' should satisfy the check below.
173174
*/
175+
if (!ppc_breakpoint_available())
176+
return -ENODEV;
174177
length_max = 8; /* DABR */
175178
if (cpu_has_feature(CPU_FTR_DAWR)) {
176179
length_max = 512 ; /* 64 doublewords */

arch/powerpc/kernel/ptrace.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <asm/switch_to.h>
4242
#include <asm/tm.h>
4343
#include <asm/asm-prototypes.h>
44+
#include <asm/debug.h>
4445

4546
#define CREATE_TRACE_POINTS
4647
#include <trace/events/syscalls.h>
@@ -2378,6 +2379,7 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
23782379
struct perf_event_attr attr;
23792380
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
23802381
#ifndef CONFIG_PPC_ADV_DEBUG_REGS
2382+
bool set_bp = true;
23812383
struct arch_hw_breakpoint hw_brk;
23822384
#endif
23832385

@@ -2411,9 +2413,10 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
24112413
hw_brk.address = data & (~HW_BRK_TYPE_DABR);
24122414
hw_brk.type = (data & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
24132415
hw_brk.len = 8;
2416+
set_bp = (data) && (hw_brk.type & HW_BRK_TYPE_RDWR);
24142417
#ifdef CONFIG_HAVE_HW_BREAKPOINT
24152418
bp = thread->ptrace_bps[0];
2416-
if ((!data) || !(hw_brk.type & HW_BRK_TYPE_RDWR)) {
2419+
if (!set_bp) {
24172420
if (bp) {
24182421
unregister_hw_breakpoint(bp);
24192422
thread->ptrace_bps[0] = NULL;
@@ -2450,6 +2453,9 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
24502453
return PTR_ERR(bp);
24512454
}
24522455

2456+
#else /* !CONFIG_HAVE_HW_BREAKPOINT */
2457+
if (set_bp && (!ppc_breakpoint_available()))
2458+
return -ENODEV;
24532459
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
24542460
task->thread.hw_brk = hw_brk;
24552461
#else /* CONFIG_PPC_ADV_DEBUG_REGS */
@@ -2904,6 +2910,9 @@ static long ppc_set_hwdebug(struct task_struct *child,
29042910
if (child->thread.hw_brk.address)
29052911
return -ENOSPC;
29062912

2913+
if (!ppc_breakpoint_available())
2914+
return -ENODEV;
2915+
29072916
child->thread.hw_brk = brk;
29082917

29092918
return 1;
@@ -3052,7 +3061,10 @@ long arch_ptrace(struct task_struct *child, long request,
30523061
#endif
30533062
#else /* !CONFIG_PPC_ADV_DEBUG_REGS */
30543063
dbginfo.num_instruction_bps = 0;
3055-
dbginfo.num_data_bps = 1;
3064+
if (ppc_breakpoint_available())
3065+
dbginfo.num_data_bps = 1;
3066+
else
3067+
dbginfo.num_data_bps = 0;
30563068
dbginfo.num_condition_regs = 0;
30573069
#ifdef CONFIG_PPC64
30583070
dbginfo.data_bp_alignment = 8;

0 commit comments

Comments
 (0)