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)
 {