xref: /kvm-unit-tests/arm/debug.c (revision 843fa9e274e3a1a91b9b21f75e058a479f57ab29)
169de9b31SRicardo Koller #include <libcflat.h>
269de9b31SRicardo Koller #include <errata.h>
369de9b31SRicardo Koller #include <asm/setup.h>
469de9b31SRicardo Koller #include <asm/processor.h>
569de9b31SRicardo Koller #include <asm/delay.h>
669de9b31SRicardo Koller #include <asm/smp.h>
769de9b31SRicardo Koller #include <asm/barrier.h>
869de9b31SRicardo Koller #include <asm/io.h>
969de9b31SRicardo Koller 
1069de9b31SRicardo Koller #define MDSCR_KDE		(1 << 13)
1169de9b31SRicardo Koller #define MDSCR_MDE		(1 << 15)
12*843fa9e2SRicardo Koller #define MDSCR_SS		(1 << 0)
1369de9b31SRicardo Koller 
1469de9b31SRicardo Koller #define DBGBCR_LEN8		(0xff << 5)
1569de9b31SRicardo Koller #define DBGBCR_EXEC		(0x0 << 3)
1669de9b31SRicardo Koller #define DBGBCR_EL1		(0x1 << 1)
1769de9b31SRicardo Koller #define DBGBCR_E		(0x1 << 0)
1869de9b31SRicardo Koller 
19*843fa9e2SRicardo Koller #define DBGWCR_LEN8		(0xff << 5)
20*843fa9e2SRicardo Koller #define DBGWCR_RD		(0x1 << 3)
21*843fa9e2SRicardo Koller #define DBGWCR_WR		(0x2 << 3)
22*843fa9e2SRicardo Koller #define DBGWCR_EL1		(0x1 << 1)
23*843fa9e2SRicardo Koller #define DBGWCR_E		(0x1 << 0)
24*843fa9e2SRicardo Koller 
2569de9b31SRicardo Koller #define SPSR_D			(1 << 9)
2669de9b31SRicardo Koller 
2769de9b31SRicardo Koller #define ESR_EC_HW_BP_CURRENT    0x31
28*843fa9e2SRicardo Koller #define ESR_EC_WP_CURRENT       0x35
2969de9b31SRicardo Koller 
3069de9b31SRicardo Koller #define ID_AA64DFR0_BRPS_SHIFT	12
3169de9b31SRicardo Koller #define ID_AA64DFR0_BRPS_MASK	0xf
32*843fa9e2SRicardo Koller #define ID_AA64DFR0_WRPS_SHIFT	20
33*843fa9e2SRicardo Koller #define ID_AA64DFR0_WRPS_MASK	0xf
3469de9b31SRicardo Koller 
3569de9b31SRicardo Koller static volatile uint64_t hw_bp_idx, hw_bp_addr[16];
36*843fa9e2SRicardo Koller static volatile uint64_t wp_idx, wp_data_addr[16];
3769de9b31SRicardo Koller 
3869de9b31SRicardo Koller static void hw_bp_handler(struct pt_regs *regs, unsigned int esr)
3969de9b31SRicardo Koller {
4069de9b31SRicardo Koller 	hw_bp_addr[hw_bp_idx++] = regs->pc;
4169de9b31SRicardo Koller 	regs->pstate |= SPSR_D;
4269de9b31SRicardo Koller }
4369de9b31SRicardo Koller 
44*843fa9e2SRicardo Koller static void wp_handler(struct pt_regs *regs, unsigned int esr)
45*843fa9e2SRicardo Koller {
46*843fa9e2SRicardo Koller 	wp_data_addr[wp_idx++] = read_sysreg(far_el1);
47*843fa9e2SRicardo Koller 	regs->pstate |= SPSR_D;
48*843fa9e2SRicardo Koller }
49*843fa9e2SRicardo Koller 
5069de9b31SRicardo Koller static int get_num_hw_bp(void)
5169de9b31SRicardo Koller {
5269de9b31SRicardo Koller 	uint64_t reg = read_sysreg(id_aa64dfr0_el1);
5369de9b31SRicardo Koller 	/* Number of breakpoints, minus 1 */
5469de9b31SRicardo Koller 	uint8_t brps = (reg >> ID_AA64DFR0_BRPS_SHIFT) & ID_AA64DFR0_BRPS_MASK;
5569de9b31SRicardo Koller 
5669de9b31SRicardo Koller 	return brps + 1;
5769de9b31SRicardo Koller }
5869de9b31SRicardo Koller 
59*843fa9e2SRicardo Koller static int get_num_wp(void)
60*843fa9e2SRicardo Koller {
61*843fa9e2SRicardo Koller 	uint64_t reg = read_sysreg(id_aa64dfr0_el1);
62*843fa9e2SRicardo Koller 	/* Number of watchpoints, minus 1 */
63*843fa9e2SRicardo Koller 	uint8_t wrps = (reg >> ID_AA64DFR0_WRPS_SHIFT) & ID_AA64DFR0_WRPS_MASK;
64*843fa9e2SRicardo Koller 
65*843fa9e2SRicardo Koller 	return wrps + 1;
66*843fa9e2SRicardo Koller }
67*843fa9e2SRicardo Koller 
6869de9b31SRicardo Koller static void write_dbgbcr(int n, uint32_t bcr)
6969de9b31SRicardo Koller {
7069de9b31SRicardo Koller 	switch (n) {
7169de9b31SRicardo Koller 	case 0:
7269de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr0_el1); break;
7369de9b31SRicardo Koller 	case 1:
7469de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr1_el1); break;
7569de9b31SRicardo Koller 	case 2:
7669de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr2_el1); break;
7769de9b31SRicardo Koller 	case 3:
7869de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr3_el1); break;
7969de9b31SRicardo Koller 	case 4:
8069de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr4_el1); break;
8169de9b31SRicardo Koller 	case 5:
8269de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr5_el1); break;
8369de9b31SRicardo Koller 	case 6:
8469de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr6_el1); break;
8569de9b31SRicardo Koller 	case 7:
8669de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr7_el1); break;
8769de9b31SRicardo Koller 	case 8:
8869de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr8_el1); break;
8969de9b31SRicardo Koller 	case 9:
9069de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr9_el1); break;
9169de9b31SRicardo Koller 	case 10:
9269de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr10_el1); break;
9369de9b31SRicardo Koller 	case 11:
9469de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr11_el1); break;
9569de9b31SRicardo Koller 	case 12:
9669de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr12_el1); break;
9769de9b31SRicardo Koller 	case 13:
9869de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr13_el1); break;
9969de9b31SRicardo Koller 	case 14:
10069de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr14_el1); break;
10169de9b31SRicardo Koller 	case 15:
10269de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr15_el1); break;
10369de9b31SRicardo Koller 	default:
10469de9b31SRicardo Koller 		report_abort("Invalid bcr");
10569de9b31SRicardo Koller 	}
10669de9b31SRicardo Koller }
10769de9b31SRicardo Koller 
10869de9b31SRicardo Koller static void write_dbgbvr(int n, uint64_t bvr)
10969de9b31SRicardo Koller {
11069de9b31SRicardo Koller 	switch (n) {
11169de9b31SRicardo Koller 	case 0:
11269de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr0_el1); break;
11369de9b31SRicardo Koller 	case 1:
11469de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr1_el1); break;
11569de9b31SRicardo Koller 	case 2:
11669de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr2_el1); break;
11769de9b31SRicardo Koller 	case 3:
11869de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr3_el1); break;
11969de9b31SRicardo Koller 	case 4:
12069de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr4_el1); break;
12169de9b31SRicardo Koller 	case 5:
12269de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr5_el1); break;
12369de9b31SRicardo Koller 	case 6:
12469de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr6_el1); break;
12569de9b31SRicardo Koller 	case 7:
12669de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr7_el1); break;
12769de9b31SRicardo Koller 	case 8:
12869de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr8_el1); break;
12969de9b31SRicardo Koller 	case 9:
13069de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr9_el1); break;
13169de9b31SRicardo Koller 	case 10:
13269de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr10_el1); break;
13369de9b31SRicardo Koller 	case 11:
13469de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr11_el1); break;
13569de9b31SRicardo Koller 	case 12:
13669de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr12_el1); break;
13769de9b31SRicardo Koller 	case 13:
13869de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr13_el1); break;
13969de9b31SRicardo Koller 	case 14:
14069de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr14_el1); break;
14169de9b31SRicardo Koller 	case 15:
14269de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr15_el1); break;
14369de9b31SRicardo Koller 	default:
14469de9b31SRicardo Koller 		report_abort("invalid bvr");
14569de9b31SRicardo Koller 	}
14669de9b31SRicardo Koller }
14769de9b31SRicardo Koller 
148*843fa9e2SRicardo Koller static void write_dbgwcr(int n, uint32_t wcr)
149*843fa9e2SRicardo Koller {
150*843fa9e2SRicardo Koller 	switch (n) {
151*843fa9e2SRicardo Koller 	case 0:
152*843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr0_el1); break;
153*843fa9e2SRicardo Koller 	case 1:
154*843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr1_el1); break;
155*843fa9e2SRicardo Koller 	case 2:
156*843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr2_el1); break;
157*843fa9e2SRicardo Koller 	case 3:
158*843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr3_el1); break;
159*843fa9e2SRicardo Koller 	case 4:
160*843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr4_el1); break;
161*843fa9e2SRicardo Koller 	case 5:
162*843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr5_el1); break;
163*843fa9e2SRicardo Koller 	case 6:
164*843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr6_el1); break;
165*843fa9e2SRicardo Koller 	case 7:
166*843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr7_el1); break;
167*843fa9e2SRicardo Koller 	case 8:
168*843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr8_el1); break;
169*843fa9e2SRicardo Koller 	case 9:
170*843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr9_el1); break;
171*843fa9e2SRicardo Koller 	case 10:
172*843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr10_el1); break;
173*843fa9e2SRicardo Koller 	case 11:
174*843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr11_el1); break;
175*843fa9e2SRicardo Koller 	case 12:
176*843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr12_el1); break;
177*843fa9e2SRicardo Koller 	case 13:
178*843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr13_el1); break;
179*843fa9e2SRicardo Koller 	case 14:
180*843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr14_el1); break;
181*843fa9e2SRicardo Koller 	case 15:
182*843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr15_el1); break;
183*843fa9e2SRicardo Koller 	default:
184*843fa9e2SRicardo Koller 		report_abort("Invalid wcr");
185*843fa9e2SRicardo Koller 	}
186*843fa9e2SRicardo Koller }
187*843fa9e2SRicardo Koller 
188*843fa9e2SRicardo Koller static void write_dbgwvr(int n, uint64_t wvr)
189*843fa9e2SRicardo Koller {
190*843fa9e2SRicardo Koller 	switch (n) {
191*843fa9e2SRicardo Koller 	case 0:
192*843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr0_el1); break;
193*843fa9e2SRicardo Koller 	case 1:
194*843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr1_el1); break;
195*843fa9e2SRicardo Koller 	case 2:
196*843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr2_el1); break;
197*843fa9e2SRicardo Koller 	case 3:
198*843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr3_el1); break;
199*843fa9e2SRicardo Koller 	case 4:
200*843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr4_el1); break;
201*843fa9e2SRicardo Koller 	case 5:
202*843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr5_el1); break;
203*843fa9e2SRicardo Koller 	case 6:
204*843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr6_el1); break;
205*843fa9e2SRicardo Koller 	case 7:
206*843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr7_el1); break;
207*843fa9e2SRicardo Koller 	case 8:
208*843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr8_el1); break;
209*843fa9e2SRicardo Koller 	case 9:
210*843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr9_el1); break;
211*843fa9e2SRicardo Koller 	case 10:
212*843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr10_el1); break;
213*843fa9e2SRicardo Koller 	case 11:
214*843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr11_el1); break;
215*843fa9e2SRicardo Koller 	case 12:
216*843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr12_el1); break;
217*843fa9e2SRicardo Koller 	case 13:
218*843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr13_el1); break;
219*843fa9e2SRicardo Koller 	case 14:
220*843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr14_el1); break;
221*843fa9e2SRicardo Koller 	case 15:
222*843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr15_el1); break;
223*843fa9e2SRicardo Koller 	default:
224*843fa9e2SRicardo Koller 		report_abort("invalid wvr");
225*843fa9e2SRicardo Koller 	}
226*843fa9e2SRicardo Koller }
227*843fa9e2SRicardo Koller 
22869de9b31SRicardo Koller static void reset_debug_state(void)
22969de9b31SRicardo Koller {
23069de9b31SRicardo Koller 	int i, num_bp = get_num_hw_bp();
231*843fa9e2SRicardo Koller 	int num_wp = get_num_wp();
23269de9b31SRicardo Koller 
23369de9b31SRicardo Koller 	asm volatile("msr daifset, #8");
23469de9b31SRicardo Koller 
23569de9b31SRicardo Koller 	write_sysreg(0, osdlr_el1);
23669de9b31SRicardo Koller 	write_sysreg(0, oslar_el1);
23769de9b31SRicardo Koller 	isb();
23869de9b31SRicardo Koller 
23969de9b31SRicardo Koller 	write_sysreg(0, mdscr_el1);
24069de9b31SRicardo Koller 	for (i = 0; i < num_bp; i++) {
24169de9b31SRicardo Koller 		write_dbgbvr(i, 0);
24269de9b31SRicardo Koller 		write_dbgbcr(i, 0);
24369de9b31SRicardo Koller 	}
244*843fa9e2SRicardo Koller 	for (i = 0; i < num_wp; i++) {
245*843fa9e2SRicardo Koller 		write_dbgwvr(i, 0);
246*843fa9e2SRicardo Koller 		write_dbgwcr(i, 0);
247*843fa9e2SRicardo Koller 	}
24869de9b31SRicardo Koller 	isb();
24969de9b31SRicardo Koller }
25069de9b31SRicardo Koller 
25169de9b31SRicardo Koller static void do_migrate(void)
25269de9b31SRicardo Koller {
25369de9b31SRicardo Koller 	puts("Now migrate the VM, then press a key to continue...\n");
25469de9b31SRicardo Koller 	(void)getchar();
25569de9b31SRicardo Koller 	report_info("Migration complete");
25669de9b31SRicardo Koller }
25769de9b31SRicardo Koller 
25869de9b31SRicardo Koller static void test_hw_bp(bool migrate)
25969de9b31SRicardo Koller {
26069de9b31SRicardo Koller 	extern unsigned char hw_bp0;
26169de9b31SRicardo Koller 	uint32_t bcr;
26269de9b31SRicardo Koller 	uint32_t mdscr;
26369de9b31SRicardo Koller 	uint64_t addr;
26469de9b31SRicardo Koller 	int num_bp = get_num_hw_bp();
26569de9b31SRicardo Koller 	int i;
26669de9b31SRicardo Koller 
26769de9b31SRicardo Koller 	install_exception_handler(EL1H_SYNC, ESR_EC_HW_BP_CURRENT, hw_bp_handler);
26869de9b31SRicardo Koller 
26969de9b31SRicardo Koller 	reset_debug_state();
27069de9b31SRicardo Koller 
27169de9b31SRicardo Koller 	bcr = DBGBCR_LEN8 | DBGBCR_EXEC | DBGBCR_EL1 | DBGBCR_E;
27269de9b31SRicardo Koller 	for (i = 0, addr = (uint64_t)&hw_bp0; i < num_bp; i++, addr += 4) {
27369de9b31SRicardo Koller 		write_dbgbcr(i, bcr);
27469de9b31SRicardo Koller 		write_dbgbvr(i, addr);
27569de9b31SRicardo Koller 	}
27669de9b31SRicardo Koller 	isb();
27769de9b31SRicardo Koller 
27869de9b31SRicardo Koller 	asm volatile("msr daifclr, #8");
27969de9b31SRicardo Koller 
28069de9b31SRicardo Koller 	mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_MDE;
28169de9b31SRicardo Koller 	write_sysreg(mdscr, mdscr_el1);
28269de9b31SRicardo Koller 	isb();
28369de9b31SRicardo Koller 
28469de9b31SRicardo Koller 	if (migrate) {
28569de9b31SRicardo Koller 		do_migrate();
28669de9b31SRicardo Koller 		report(num_bp == get_num_hw_bp(), "brps match after migrate");
28769de9b31SRicardo Koller 	}
28869de9b31SRicardo Koller 
28969de9b31SRicardo Koller 	hw_bp_idx = 0;
29069de9b31SRicardo Koller 
29169de9b31SRicardo Koller 	/* Trap on up to 16 debug exception unmask instructions. */
29269de9b31SRicardo Koller 	asm volatile("hw_bp0:\n"
29369de9b31SRicardo Koller 	     "msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n"
29469de9b31SRicardo Koller 	     "msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n"
29569de9b31SRicardo Koller 	     "msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n"
29669de9b31SRicardo Koller 	     "msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n");
29769de9b31SRicardo Koller 
29869de9b31SRicardo Koller 	for (i = 0, addr = (uint64_t)&hw_bp0; i < num_bp; i++, addr += 4)
29969de9b31SRicardo Koller 		report(hw_bp_addr[i] == addr, "hw breakpoint: %d", i);
30069de9b31SRicardo Koller }
30169de9b31SRicardo Koller 
302*843fa9e2SRicardo Koller static volatile char write_data[16];
303*843fa9e2SRicardo Koller 
304*843fa9e2SRicardo Koller static void test_wp(bool migrate)
305*843fa9e2SRicardo Koller {
306*843fa9e2SRicardo Koller 	uint32_t wcr;
307*843fa9e2SRicardo Koller 	uint32_t mdscr;
308*843fa9e2SRicardo Koller 	int num_wp = get_num_wp();
309*843fa9e2SRicardo Koller 	int i;
310*843fa9e2SRicardo Koller 
311*843fa9e2SRicardo Koller 	install_exception_handler(EL1H_SYNC, ESR_EC_WP_CURRENT, wp_handler);
312*843fa9e2SRicardo Koller 
313*843fa9e2SRicardo Koller 	reset_debug_state();
314*843fa9e2SRicardo Koller 
315*843fa9e2SRicardo Koller 	wcr = DBGWCR_LEN8 | DBGWCR_RD | DBGWCR_WR | DBGWCR_EL1 | DBGWCR_E;
316*843fa9e2SRicardo Koller 	for (i = 0; i < num_wp; i++) {
317*843fa9e2SRicardo Koller 		write_dbgwcr(i, wcr);
318*843fa9e2SRicardo Koller 		write_dbgwvr(i, (uint64_t)&write_data[i]);
319*843fa9e2SRicardo Koller 	}
320*843fa9e2SRicardo Koller 	isb();
321*843fa9e2SRicardo Koller 
322*843fa9e2SRicardo Koller 	asm volatile("msr daifclr, #8");
323*843fa9e2SRicardo Koller 
324*843fa9e2SRicardo Koller 	mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_MDE;
325*843fa9e2SRicardo Koller 	write_sysreg(mdscr, mdscr_el1);
326*843fa9e2SRicardo Koller 	isb();
327*843fa9e2SRicardo Koller 
328*843fa9e2SRicardo Koller 	if (migrate) {
329*843fa9e2SRicardo Koller 		do_migrate();
330*843fa9e2SRicardo Koller 		report(num_wp == get_num_wp(), "wrps match after migrate");
331*843fa9e2SRicardo Koller 	}
332*843fa9e2SRicardo Koller 
333*843fa9e2SRicardo Koller 	wp_idx = 0;
334*843fa9e2SRicardo Koller 
335*843fa9e2SRicardo Koller 	for (i = 0; i < num_wp; i++) {
336*843fa9e2SRicardo Koller 		write_data[i] = i;
337*843fa9e2SRicardo Koller 		asm volatile("msr daifclr, #8");
338*843fa9e2SRicardo Koller 	}
339*843fa9e2SRicardo Koller 
340*843fa9e2SRicardo Koller 	for (i = 0; i < num_wp; i++) {
341*843fa9e2SRicardo Koller 		report(wp_data_addr[i] == (uint64_t)&write_data[i],
342*843fa9e2SRicardo Koller 			"watchpoint received: %d", i);
343*843fa9e2SRicardo Koller 		report(write_data[i] == i, "watchpoint data: %d", i);
344*843fa9e2SRicardo Koller 	}
345*843fa9e2SRicardo Koller }
346*843fa9e2SRicardo Koller 
34769de9b31SRicardo Koller int main(int argc, char **argv)
34869de9b31SRicardo Koller {
34969de9b31SRicardo Koller 	if (argc < 2)
35069de9b31SRicardo Koller 		report_abort("no test specified");
35169de9b31SRicardo Koller 
35269de9b31SRicardo Koller 	if (strcmp(argv[1], "bp") == 0) {
35369de9b31SRicardo Koller 		report_prefix_push(argv[1]);
35469de9b31SRicardo Koller 		test_hw_bp(false);
35569de9b31SRicardo Koller 		report_prefix_pop();
35669de9b31SRicardo Koller 	} else if (strcmp(argv[1], "bp-migration") == 0) {
35769de9b31SRicardo Koller 		report_prefix_push(argv[1]);
35869de9b31SRicardo Koller 		test_hw_bp(true);
35969de9b31SRicardo Koller 		report_prefix_pop();
360*843fa9e2SRicardo Koller 	} else if (strcmp(argv[1], "wp") == 0) {
361*843fa9e2SRicardo Koller 		report_prefix_push(argv[1]);
362*843fa9e2SRicardo Koller 		test_wp(false);
363*843fa9e2SRicardo Koller 		report_prefix_pop();
364*843fa9e2SRicardo Koller 	} else if (strcmp(argv[1], "wp-migration") == 0) {
365*843fa9e2SRicardo Koller 		report_prefix_push(argv[1]);
366*843fa9e2SRicardo Koller 		test_wp(true);
367*843fa9e2SRicardo Koller 		report_prefix_pop();
36869de9b31SRicardo Koller 	} else {
36969de9b31SRicardo Koller 		report_abort("Unknown subtest '%s'", argv[1]);
37069de9b31SRicardo Koller 	}
37169de9b31SRicardo Koller 
37269de9b31SRicardo Koller 	return report_summary();
37369de9b31SRicardo Koller }
374