powerpc/watchpoint/xmon: Support 2nd DAWR
Add support for 2nd DAWR in xmon. With this, we can have two simultaneous breakpoints from xmon. Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Reviewed-by: Michael Neuling <mikey@neuling.org> Link: https://lore.kernel.org/r/20200514111741.97993-17-ravi.bangoria@linux.ibm.com
This commit is contained in:
parent
514db915e7
commit
30df74d67d
@ -112,7 +112,7 @@ struct bpt {
|
|||||||
#define BP_DABR 4
|
#define BP_DABR 4
|
||||||
|
|
||||||
static struct bpt bpts[NBPTS];
|
static struct bpt bpts[NBPTS];
|
||||||
static struct bpt dabr;
|
static struct bpt dabr[HBP_NUM_MAX];
|
||||||
static struct bpt *iabr;
|
static struct bpt *iabr;
|
||||||
static unsigned bpinstr = 0x7fe00008; /* trap */
|
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)
|
static int xmon_break_match(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
|
if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
|
||||||
return 0;
|
return 0;
|
||||||
if (dabr.enabled == 0)
|
for (i = 0; i < nr_wp_slots(); i++) {
|
||||||
return 0;
|
if (dabr[i].enabled)
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
found:
|
||||||
xmon_core(regs, 0);
|
xmon_core(regs, 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -948,13 +955,16 @@ static void insert_bpts(void)
|
|||||||
|
|
||||||
static void insert_cpu_bpts(void)
|
static void insert_cpu_bpts(void)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
struct arch_hw_breakpoint brk;
|
struct arch_hw_breakpoint brk;
|
||||||
|
|
||||||
if (dabr.enabled) {
|
for (i = 0; i < nr_wp_slots(); i++) {
|
||||||
brk.address = dabr.address;
|
if (dabr[i].enabled) {
|
||||||
brk.type = (dabr.enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
|
brk.address = dabr[i].address;
|
||||||
brk.len = DABR_MAX_LEN;
|
brk.type = (dabr[i].enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
|
||||||
__set_breakpoint(0, &brk);
|
brk.len = 8;
|
||||||
|
__set_breakpoint(i, &brk);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iabr)
|
if (iabr)
|
||||||
@ -1366,6 +1376,35 @@ static long check_bp_loc(unsigned long addr)
|
|||||||
return 1;
|
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 =
|
static char *breakpoint_help_string =
|
||||||
"Breakpoint command usage:\n"
|
"Breakpoint command usage:\n"
|
||||||
"b show breakpoints\n"
|
"b show breakpoints\n"
|
||||||
@ -1399,10 +1438,9 @@ bpt_cmds(void)
|
|||||||
printf("Hardware data breakpoint not supported on this cpu\n");
|
printf("Hardware data breakpoint not supported on this cpu\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (dabr.enabled) {
|
i = find_free_data_bpt();
|
||||||
printf("Couldn't find free breakpoint register\n");
|
if (i < 0)
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
mode = 7;
|
mode = 7;
|
||||||
cmd = inchar();
|
cmd = inchar();
|
||||||
if (cmd == 'r')
|
if (cmd == 'r')
|
||||||
@ -1411,15 +1449,15 @@ bpt_cmds(void)
|
|||||||
mode = 6;
|
mode = 6;
|
||||||
else
|
else
|
||||||
termch = cmd;
|
termch = cmd;
|
||||||
dabr.address = 0;
|
dabr[i].address = 0;
|
||||||
dabr.enabled = 0;
|
dabr[i].enabled = 0;
|
||||||
if (scanhex(&dabr.address)) {
|
if (scanhex(&dabr[i].address)) {
|
||||||
if (!is_kernel_addr(dabr.address)) {
|
if (!is_kernel_addr(dabr[i].address)) {
|
||||||
printf(badaddr);
|
printf(badaddr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dabr.address &= ~HW_BRK_TYPE_DABR;
|
dabr[i].address &= ~HW_BRK_TYPE_DABR;
|
||||||
dabr.enabled = mode | BP_DABR;
|
dabr[i].enabled = mode | BP_DABR;
|
||||||
}
|
}
|
||||||
|
|
||||||
force_enable_xmon();
|
force_enable_xmon();
|
||||||
@ -1458,7 +1496,9 @@ bpt_cmds(void)
|
|||||||
for (i = 0; i < NBPTS; ++i)
|
for (i = 0; i < NBPTS; ++i)
|
||||||
bpts[i].enabled = 0;
|
bpts[i].enabled = 0;
|
||||||
iabr = NULL;
|
iabr = NULL;
|
||||||
dabr.enabled = 0;
|
for (i = 0; i < nr_wp_slots(); i++)
|
||||||
|
dabr[i].enabled = 0;
|
||||||
|
|
||||||
printf("All breakpoints cleared\n");
|
printf("All breakpoints cleared\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1492,14 +1532,7 @@ bpt_cmds(void)
|
|||||||
if (xmon_is_ro || !scanhex(&a)) {
|
if (xmon_is_ro || !scanhex(&a)) {
|
||||||
/* print all breakpoints */
|
/* print all breakpoints */
|
||||||
printf(" type address\n");
|
printf(" type address\n");
|
||||||
if (dabr.enabled) {
|
print_data_bpts();
|
||||||
printf(" data "REG" [", dabr.address);
|
|
||||||
if (dabr.enabled & 1)
|
|
||||||
printf("r");
|
|
||||||
if (dabr.enabled & 2)
|
|
||||||
printf("w");
|
|
||||||
printf("]\n");
|
|
||||||
}
|
|
||||||
for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
|
for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
|
||||||
if (!bp->enabled)
|
if (!bp->enabled)
|
||||||
continue;
|
continue;
|
||||||
@ -1959,8 +1992,13 @@ static void dump_207_sprs(void)
|
|||||||
|
|
||||||
printf("hfscr = %.16lx dhdes = %.16lx rpr = %.16lx\n",
|
printf("hfscr = %.16lx dhdes = %.16lx rpr = %.16lx\n",
|
||||||
mfspr(SPRN_HFSCR), mfspr(SPRN_DHDES), mfspr(SPRN_RPR));
|
mfspr(SPRN_HFSCR), mfspr(SPRN_DHDES), mfspr(SPRN_RPR));
|
||||||
printf("dawr = %.16lx dawrx = %.16lx ciabr = %.16lx\n",
|
printf("dawr0 = %.16lx dawrx0 = %.16lx\n",
|
||||||
mfspr(SPRN_DAWR0), mfspr(SPRN_DAWRX0), mfspr(SPRN_CIABR));
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3909,10 +3947,9 @@ static void clear_all_bpt(void)
|
|||||||
bpts[i].enabled = 0;
|
bpts[i].enabled = 0;
|
||||||
|
|
||||||
/* Clear any data or iabr breakpoints */
|
/* Clear any data or iabr breakpoints */
|
||||||
if (iabr || dabr.enabled) {
|
iabr = NULL;
|
||||||
iabr = NULL;
|
for (i = 0; i < nr_wp_slots(); i++)
|
||||||
dabr.enabled = 0;
|
dabr[i].enabled = 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
Loading…
Reference in New Issue
Block a user