Commit 30df74d6 authored by Ravi Bangoria's avatar Ravi Bangoria Committed by Michael Ellerman
Browse files

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: default avatarRavi Bangoria <ravi.bangoria@linux.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Reviewed-by: default avatarMichael Neuling <mikey@neuling.org>
Link: https://lore.kernel.org/r/20200514111741.97993-17-ravi.bangoria@linux.ibm.com
parent 514db915
Loading
Loading
Loading
Loading
+69 −32
Original line number Diff line number Diff line
@@ -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)
	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;
	}
	for (i = 0; i < nr_wp_slots(); i++)
		dabr[i].enabled = 0;
}

#ifdef CONFIG_DEBUG_FS