Add support for 2nd DAWR in xmon. With this, we can have two
simultaneous breakpoints from xmon.

Signed-off-by: Ravi Bangoria <ravi.bango...@linux.ibm.com>
Reviewed-by: Michael Neuling <mi...@neuling.org>
---
 arch/powerpc/xmon/xmon.c | 101 ++++++++++++++++++++++++++-------------
 1 file changed, 69 insertions(+), 32 deletions(-)

diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 094bf4715f2c..de585204d1d2 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -112,7 +112,7 @@ struct bpt {
 #define BP_DABR                4
 
 static struct bpt bpts[NBPTS];
-static struct bpt dabr;
+static struct bpt dabr[HBP_NUM_MAX];
 static struct bpt *iabr;
 static unsigned bpinstr = 0x7fe00008;  /* trap */
 
@@ -784,10 +784,17 @@ static int xmon_sstep(struct pt_regs *regs)
 
 static int xmon_break_match(struct pt_regs *regs)
 {
+       int i;
+
        if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
                return 0;
-       if (dabr.enabled == 0)
-               return 0;
+       for (i = 0; i < nr_wp_slots(); i++) {
+               if (dabr[i].enabled)
+                       goto found;
+       }
+       return 0;
+
+found:
        xmon_core(regs, 0);
        return 1;
 }
@@ -948,13 +955,16 @@ static void insert_bpts(void)
 
 static void insert_cpu_bpts(void)
 {
+       int i;
        struct arch_hw_breakpoint brk;
 
-       if (dabr.enabled) {
-               brk.address = dabr.address;
-               brk.type = (dabr.enabled & HW_BRK_TYPE_DABR) | 
HW_BRK_TYPE_PRIV_ALL;
-               brk.len = DABR_MAX_LEN;
-               __set_breakpoint(0, &brk);
+       for (i = 0; i < nr_wp_slots(); i++) {
+               if (dabr[i].enabled) {
+                       brk.address = dabr[i].address;
+                       brk.type = (dabr[i].enabled & HW_BRK_TYPE_DABR) | 
HW_BRK_TYPE_PRIV_ALL;
+                       brk.len = 8;
+                       __set_breakpoint(i, &brk);
+               }
        }
 
        if (iabr)
@@ -1366,6 +1376,35 @@ static long check_bp_loc(unsigned long addr)
        return 1;
 }
 
+static int find_free_data_bpt(void)
+{
+       int i;
+
+       for (i = 0; i < nr_wp_slots(); i++) {
+               if (!dabr[i].enabled)
+                       return i;
+       }
+       printf("Couldn't find free breakpoint register\n");
+       return -1;
+}
+
+static void print_data_bpts(void)
+{
+       int i;
+
+       for (i = 0; i < nr_wp_slots(); i++) {
+               if (!dabr[i].enabled)
+                       continue;
+
+               printf("   data   "REG"  [", dabr[i].address);
+               if (dabr[i].enabled & 1)
+                       printf("r");
+               if (dabr[i].enabled & 2)
+                       printf("w");
+               printf("]\n");
+       }
+}
+
 static char *breakpoint_help_string =
     "Breakpoint command usage:\n"
     "b                show breakpoints\n"
@@ -1399,10 +1438,9 @@ bpt_cmds(void)
                        printf("Hardware data breakpoint not supported on this 
cpu\n");
                        break;
                }
-               if (dabr.enabled) {
-                       printf("Couldn't find free breakpoint register\n");
+               i = find_free_data_bpt();
+               if (i < 0)
                        break;
-               }
                mode = 7;
                cmd = inchar();
                if (cmd == 'r')
@@ -1411,15 +1449,15 @@ bpt_cmds(void)
                        mode = 6;
                else
                        termch = cmd;
-               dabr.address = 0;
-               dabr.enabled = 0;
-               if (scanhex(&dabr.address)) {
-                       if (!is_kernel_addr(dabr.address)) {
+               dabr[i].address = 0;
+               dabr[i].enabled = 0;
+               if (scanhex(&dabr[i].address)) {
+                       if (!is_kernel_addr(dabr[i].address)) {
                                printf(badaddr);
                                break;
                        }
-                       dabr.address &= ~HW_BRK_TYPE_DABR;
-                       dabr.enabled = mode | BP_DABR;
+                       dabr[i].address &= ~HW_BRK_TYPE_DABR;
+                       dabr[i].enabled = mode | BP_DABR;
                }
 
                force_enable_xmon();
@@ -1458,7 +1496,9 @@ bpt_cmds(void)
                        for (i = 0; i < NBPTS; ++i)
                                bpts[i].enabled = 0;
                        iabr = NULL;
-                       dabr.enabled = 0;
+                       for (i = 0; i < nr_wp_slots(); i++)
+                               dabr[i].enabled = 0;
+
                        printf("All breakpoints cleared\n");
                        break;
                }
@@ -1492,14 +1532,7 @@ bpt_cmds(void)
                if (xmon_is_ro || !scanhex(&a)) {
                        /* print all breakpoints */
                        printf("   type            address\n");
-                       if (dabr.enabled) {
-                               printf("   data   "REG"  [", dabr.address);
-                               if (dabr.enabled & 1)
-                                       printf("r");
-                               if (dabr.enabled & 2)
-                                       printf("w");
-                               printf("]\n");
-                       }
+                       print_data_bpts();
                        for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
                                if (!bp->enabled)
                                        continue;
@@ -1959,8 +1992,13 @@ static void dump_207_sprs(void)
 
        printf("hfscr  = %.16lx  dhdes = %.16lx rpr    = %.16lx\n",
                mfspr(SPRN_HFSCR), mfspr(SPRN_DHDES), mfspr(SPRN_RPR));
-       printf("dawr   = %.16lx  dawrx = %.16lx ciabr  = %.16lx\n",
-               mfspr(SPRN_DAWR0), mfspr(SPRN_DAWRX0), mfspr(SPRN_CIABR));
+       printf("dawr0  = %.16lx dawrx0 = %.16lx\n",
+              mfspr(SPRN_DAWR0), mfspr(SPRN_DAWRX0));
+       if (nr_wp_slots() > 1) {
+               printf("dawr1  = %.16lx dawrx1 = %.16lx\n",
+                      mfspr(SPRN_DAWR1), mfspr(SPRN_DAWRX1));
+       }
+       printf("ciabr  = %.16lx\n", mfspr(SPRN_CIABR));
 #endif
 }
 
@@ -3909,10 +3947,9 @@ static void clear_all_bpt(void)
                bpts[i].enabled = 0;
 
        /* Clear any data or iabr breakpoints */
-       if (iabr || dabr.enabled) {
-               iabr = NULL;
-               dabr.enabled = 0;
-       }
+       iabr = NULL;
+       for (i = 0; i < nr_wp_slots(); i++)
+               dabr[i].enabled = 0;
 }
 
 #ifdef CONFIG_DEBUG_FS
-- 
2.26.2

Reply via email to