select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
select HAVE_REGS_AND_STACK_ACCESS_API
- select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S
+ select HAVE_HW_BREAKPOINT if PERF_EVENTS && (PPC_BOOK3S || PPC_8xx)
select ARCH_WANT_IPC_PARSE_VERSION
select SPARSE_IRQ
select IRQ_DOMAIN
#define SPRN_EIE 80 /* External interrupt enable (EE=1, RI=1) */
#define SPRN_EID 81 /* External interrupt disable (EE=0, RI=1) */
+/* Debug registers */
+#define SPRN_CMPE 152
+#define SPRN_CMPF 153
+#define SPRN_LCTRL1 156
+#define SPRN_LCTRL2 157
+#define SPRN_BAR 159
+
/* Commands. Only the first few are available to the instruction cache.
*/
#define IDC_ENABLE 0x02000000 /* Cache enable */
andis. r10,r5,0x4000
beq+ 1f
tlbie r4
+itlbie:
/* 0x400 is InstructionAccess exception, needed by bad_page_fault() */
1: EXC_XFER_LITE(0x400, handle_page_fault)
andis. r10,r5,0x4000
beq+ 1f
tlbie r4
+dtlbie:
1: li r10,RPN_PATTERN
mtspr SPRN_DAR,r10 /* Tag DAR, to be used in DTLB Error */
/* 0x300 is DataAccess exception, needed by bad_page_fault() */
* support of breakpoints and such. Someday I will get around to
* using them.
*/
- EXCEPTION(0x1c00, Trap_1c, unknown_exception, EXC_XFER_EE)
+ . = 0x1c00
+DataBreakpoint:
+ EXCEPTION_PROLOG_0
+ mfcr r10
+ mfspr r11, SPRN_SRR0
+ cmplwi cr0, r11, (dtlbie - PAGE_OFFSET)@l
+ cmplwi cr7, r11, (itlbie - PAGE_OFFSET)@l
+ beq- cr0, 11f
+ beq- cr7, 11f
+ EXCEPTION_PROLOG_1
+ EXCEPTION_PROLOG_2
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ mfspr r4,SPRN_BAR
+ stw r4,_DAR(r11)
+ mfspr r5,SPRN_DSISR
+ EXC_XFER_EE(0x1c00, do_break)
+11:
+ mtcr r10
+ EXCEPTION_EPILOG_0
+ rfi
+
EXCEPTION(0x1d00, Trap_1d, unknown_exception, EXC_XFER_EE)
EXCEPTION(0x1e00, Trap_1e, unknown_exception, EXC_XFER_EE)
EXCEPTION(0x1f00, Trap_1f, unknown_exception, EXC_XFER_EE)
lis r8, IDC_ENABLE@h
mtspr SPRN_DC_CST, r8
#endif
+ /* Disable debug mode entry on data breakpoints */
+ mfspr r8, SPRN_DER
+ rlwinm r8, r8, 0, ~0x8
+ mtspr SPRN_DER, r8
blr
int rc = NOTIFY_STOP;
struct perf_event *bp;
struct pt_regs *regs = args->regs;
+#ifndef CONFIG_PPC_8xx
int stepped = 1;
- struct arch_hw_breakpoint *info;
unsigned int instr;
+#endif
+ struct arch_hw_breakpoint *info;
unsigned long dar = regs->dar;
/* Disable breakpoints during exception handling */
(dar - bp->attr.bp_addr < bp->attr.bp_len)))
info->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ;
+#ifndef CONFIG_PPC_8xx
/* Do not emulate user-space instructions, instead single-step them */
if (user_mode(regs)) {
current->thread.last_hit_ubp = bp;
perf_event_disable_inatomic(bp);
goto out;
}
+#endif
/*
* As a policy, the callback is invoked in a 'trigger-after-execute'
* fashion
mtspr(SPRN_DABRX, dabrx);
return 0;
}
+#elif defined(CONFIG_PPC_8xx)
+static inline int __set_dabr(unsigned long dabr, unsigned long dabrx)
+{
+ unsigned long addr = dabr & ~HW_BRK_TYPE_DABR;
+ unsigned long lctrl1 = 0x90000000; /* compare type: equal on E & F */
+ unsigned long lctrl2 = 0x8e000002; /* watchpoint 1 on cmp E | F */
+
+ if ((dabr & HW_BRK_TYPE_RDWR) == HW_BRK_TYPE_READ)
+ lctrl1 |= 0xa0000;
+ else if ((dabr & HW_BRK_TYPE_RDWR) == HW_BRK_TYPE_WRITE)
+ lctrl1 |= 0xf0000;
+ else if ((dabr & HW_BRK_TYPE_RDWR) == 0)
+ lctrl2 = 0;
+
+ mtspr(SPRN_LCTRL2, 0);
+ mtspr(SPRN_CMPE, addr);
+ mtspr(SPRN_CMPF, addr + 4);
+ mtspr(SPRN_LCTRL1, lctrl1);
+ mtspr(SPRN_LCTRL2, lctrl2);
+
+ return 0;
+}
#else
static inline int __set_dabr(unsigned long dabr, unsigned long dabrx)
{