ps3-debugging: Setup DABR register
For debugging only.
Helper routine to setup DABR (Data Address Breakpoint) register
for kernel use.
diff --git a/arch/powerpc/include/asm/ps3.h b/arch/powerpc/include/asm/ps3.h
index a19f831..2a5e9c0 100644
--- a/arch/powerpc/include/asm/ps3.h
+++ b/arch/powerpc/include/asm/ps3.h
@@ -528,4 +528,13 @@
void ps3_early_mm_init(void);
+/* kernel debug routines */
+
+#define DABR_TRANSLATION (1UL << 2)
+#define DABR_DATA_WRITE (1UL << 1)
+#define DABR_DATA_READ (1UL << 0)
+
+int ps3_debug_setup_dabr(u64 address, unsigned int dabr_flags,
+ unsigned int dabrx);
+
#endif
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 5dd056d..f48afdc 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -610,6 +610,9 @@
{
siginfo_t info;
+ printk("%s:%d: address %016lxh, code %08lxh\n",
+ __func__, __LINE__, address, error_code);
+
current->thread.trap_nr = TRAP_HWBKPT;
if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
11, SIGSEGV) == NOTIFY_STOP)
@@ -621,6 +624,13 @@
/* Clear the breakpoint */
hw_breakpoint_disable();
+ if (!user_mode(regs)) {
+ show_regs(regs);
+ printk("%s:%d: done: address %016lxh\n", __func__, __LINE__,
+ address);
+ return;
+ }
+
/* Deliver the signal to userspace */
info.si_signo = SIGTRAP;
info.si_errno = 0;
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 62a50d6..a211976 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -257,7 +257,8 @@
* The kernel should never take an execute fault nor should it
* take a page fault to a kernel address.
*/
- if (!user_mode(regs) && (is_exec || (address >= TASK_SIZE))) {
+ if (!user_mode(regs) && (is_exec || (address >= TASK_SIZE)) &&
+ !(error_code & DSISR_DABRMATCH)) {
rc = SIGSEGV;
goto bail;
}
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 6244bc8..ed4fb3e 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -190,6 +190,38 @@
return lv1_set_dabr(dabr, dabrx) ? -1 : 0;
}
+/**
+ * ps3_debug_setup_dabr - Setup the DABR for kernel use.
+ * @dabr_flags: DABR_DATA_WRITE, DABR_DATA_READ, DABR_TRANSLATION
+ * @dabrx: DABRX_BTI, DABRX_KERNEL, DABRX_USER
+ */
+
+int ps3_debug_setup_dabr(u64 address, unsigned int dabr_flags,
+ unsigned int dabrx)
+{
+ int result;
+ u64 reg;
+
+ BUG_ON(dabr_flags
+ & ~(DABR_DATA_WRITE | DABR_DATA_READ | DABR_TRANSLATION));
+
+ /* PS3 seems to need DABR_TRANSLATION set to work */
+
+ reg = (address & -8L) | dabr_flags | DABR_TRANSLATION;
+
+ printk("%s: address %016llxh, flags %xh = %016llxh\n", __func__,
+ address, dabr_flags, reg);
+
+ result = ps3_set_dabr(reg, dabrx);
+
+ if (result)
+ printk("%s: failed: %d %s\n", __func__, result,
+ ps3_result(result));
+
+ return result;
+}
+EXPORT_SYMBOL_GPL(ps3_debug_setup_dabr);
+
static void __init ps3_setup_arch(void)
{
u64 tmp;