powerpc: Change hardware breakpoint to allow longer ranges
authorMichael Neuling <mikey@neuling.org>
Thu, 24 Jan 2013 15:02:59 +0000 (15:02 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 29 Jan 2013 00:35:08 +0000 (11:35 +1100)
Change the hardware breakpoint code so that we can support wider ranged
breakpoints.

This means both ptrace and perf hardware breakpoints can use upto 512 byte long
breakpoints when using the DAWR and only 8 byte when using the DABR.

Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/include/asm/hw_breakpoint.h
arch/powerpc/kernel/hw_breakpoint.c

index 96437e5014e1839b550fe13b23d00ec95494ca45..eb0f4ac75c4cea9a39b2ba4391afbfd5ca980caa 100644 (file)
@@ -57,8 +57,6 @@ struct pmu;
 struct perf_sample_data;
 
 #define HW_BREAKPOINT_ALIGN 0x7
-/* Maximum permissible length of any HW Breakpoint */
-#define HW_BREAKPOINT_LEN 0x8
 
 extern int hw_breakpoint_slots(int type);
 extern int arch_bp_generic_fields(int type, int *gen_bp_type);
index 2a3e8dd547ec89381df4148391a3742ea56a1463..a949bdfc9623b5bd9bbfca9dfdc0ec2b37214417 100644 (file)
@@ -142,7 +142,7 @@ int arch_bp_generic_fields(int type, int *gen_bp_type)
  */
 int arch_validate_hwbkpt_settings(struct perf_event *bp)
 {
-       int ret = -EINVAL;
+       int ret = -EINVAL, length_max;
        struct arch_hw_breakpoint *info = counter_arch_bp(bp);
 
        if (!bp)
@@ -171,8 +171,16 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
         * HW_BREAKPOINT_ALIGN by rounding off to the lower address, the
         * 'symbolsize' should satisfy the check below.
         */
+       length_max = 8; /* DABR */
+       if (cpu_has_feature(CPU_FTR_DAWR)) {
+               length_max = 512 ; /* 64 doublewords */
+               /* DAWR region can't cross 512 boundary */
+               if ((bp->attr.bp_addr >> 10) != 
+                   ((bp->attr.bp_addr + bp->attr.bp_len) >> 10))
+                       return -EINVAL;
+       }
        if (info->len >
-           (HW_BREAKPOINT_LEN - (info->address & HW_BREAKPOINT_ALIGN)))
+           (length_max - (info->address & HW_BREAKPOINT_ALIGN)))
                return -EINVAL;
        return 0;
 }