Commit 85ce9a5d authored by Michael Neuling's avatar Michael Neuling Committed by Michael Ellerman

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: default avatarMichael Neuling <mikey@neuling.org>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 404b27d6
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <asm/hw_breakpoint.h> #include <asm/hw_breakpoint.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/sstep.h> #include <asm/sstep.h>
#include <asm/debug.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
/* /*
...@@ -171,6 +172,8 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) ...@@ -171,6 +172,8 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
* HW_BREAKPOINT_ALIGN by rounding off to the lower address, the * HW_BREAKPOINT_ALIGN by rounding off to the lower address, the
* 'symbolsize' should satisfy the check below. * 'symbolsize' should satisfy the check below.
*/ */
if (!ppc_breakpoint_available())
return -ENODEV;
length_max = 8; /* DABR */ length_max = 8; /* DABR */
if (cpu_has_feature(CPU_FTR_DAWR)) { if (cpu_has_feature(CPU_FTR_DAWR)) {
length_max = 512 ; /* 64 doublewords */ length_max = 512 ; /* 64 doublewords */
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <asm/switch_to.h> #include <asm/switch_to.h>
#include <asm/tm.h> #include <asm/tm.h>
#include <asm/asm-prototypes.h> #include <asm/asm-prototypes.h>
#include <asm/debug.h>
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/syscalls.h> #include <trace/events/syscalls.h>
...@@ -2378,6 +2379,7 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, ...@@ -2378,6 +2379,7 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
struct perf_event_attr attr; struct perf_event_attr attr;
#endif /* CONFIG_HAVE_HW_BREAKPOINT */ #endif /* CONFIG_HAVE_HW_BREAKPOINT */
#ifndef CONFIG_PPC_ADV_DEBUG_REGS #ifndef CONFIG_PPC_ADV_DEBUG_REGS
bool set_bp = true;
struct arch_hw_breakpoint hw_brk; struct arch_hw_breakpoint hw_brk;
#endif #endif
...@@ -2411,9 +2413,10 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, ...@@ -2411,9 +2413,10 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
hw_brk.address = data & (~HW_BRK_TYPE_DABR); hw_brk.address = data & (~HW_BRK_TYPE_DABR);
hw_brk.type = (data & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL; hw_brk.type = (data & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
hw_brk.len = 8; hw_brk.len = 8;
set_bp = (data) && (hw_brk.type & HW_BRK_TYPE_RDWR);
#ifdef CONFIG_HAVE_HW_BREAKPOINT #ifdef CONFIG_HAVE_HW_BREAKPOINT
bp = thread->ptrace_bps[0]; bp = thread->ptrace_bps[0];
if ((!data) || !(hw_brk.type & HW_BRK_TYPE_RDWR)) { if (!set_bp) {
if (bp) { if (bp) {
unregister_hw_breakpoint(bp); unregister_hw_breakpoint(bp);
thread->ptrace_bps[0] = NULL; thread->ptrace_bps[0] = NULL;
...@@ -2450,6 +2453,9 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, ...@@ -2450,6 +2453,9 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
return PTR_ERR(bp); return PTR_ERR(bp);
} }
#else /* !CONFIG_HAVE_HW_BREAKPOINT */
if (set_bp && (!ppc_breakpoint_available()))
return -ENODEV;
#endif /* CONFIG_HAVE_HW_BREAKPOINT */ #endif /* CONFIG_HAVE_HW_BREAKPOINT */
task->thread.hw_brk = hw_brk; task->thread.hw_brk = hw_brk;
#else /* CONFIG_PPC_ADV_DEBUG_REGS */ #else /* CONFIG_PPC_ADV_DEBUG_REGS */
...@@ -2904,6 +2910,9 @@ static long ppc_set_hwdebug(struct task_struct *child, ...@@ -2904,6 +2910,9 @@ static long ppc_set_hwdebug(struct task_struct *child,
if (child->thread.hw_brk.address) if (child->thread.hw_brk.address)
return -ENOSPC; return -ENOSPC;
if (!ppc_breakpoint_available())
return -ENODEV;
child->thread.hw_brk = brk; child->thread.hw_brk = brk;
return 1; return 1;
...@@ -3052,7 +3061,10 @@ long arch_ptrace(struct task_struct *child, long request, ...@@ -3052,7 +3061,10 @@ long arch_ptrace(struct task_struct *child, long request,
#endif #endif
#else /* !CONFIG_PPC_ADV_DEBUG_REGS */ #else /* !CONFIG_PPC_ADV_DEBUG_REGS */
dbginfo.num_instruction_bps = 0; dbginfo.num_instruction_bps = 0;
if (ppc_breakpoint_available())
dbginfo.num_data_bps = 1; dbginfo.num_data_bps = 1;
else
dbginfo.num_data_bps = 0;
dbginfo.num_condition_regs = 0; dbginfo.num_condition_regs = 0;
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
dbginfo.data_bp_alignment = 8; dbginfo.data_bp_alignment = 8;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment