xref: /kvm-unit-tests/arm/debug.c (revision e526bc786e9878c3880ae4b09b01a4572756e492)
169de9b31SRicardo Koller #include <libcflat.h>
27cefda52SNico Boehr #include <migrate.h>
369de9b31SRicardo Koller #include <errata.h>
469de9b31SRicardo Koller #include <asm/setup.h>
569de9b31SRicardo Koller #include <asm/processor.h>
669de9b31SRicardo Koller #include <asm/delay.h>
769de9b31SRicardo Koller #include <asm/smp.h>
869de9b31SRicardo Koller #include <asm/barrier.h>
969de9b31SRicardo Koller #include <asm/io.h>
1069de9b31SRicardo Koller 
1169de9b31SRicardo Koller #define MDSCR_KDE		(1 << 13)
1269de9b31SRicardo Koller #define MDSCR_MDE		(1 << 15)
13843fa9e2SRicardo Koller #define MDSCR_SS		(1 << 0)
1469de9b31SRicardo Koller 
1569de9b31SRicardo Koller #define DBGBCR_LEN8		(0xff << 5)
1669de9b31SRicardo Koller #define DBGBCR_EXEC		(0x0 << 3)
1769de9b31SRicardo Koller #define DBGBCR_EL1		(0x1 << 1)
1869de9b31SRicardo Koller #define DBGBCR_E		(0x1 << 0)
1969de9b31SRicardo Koller 
20843fa9e2SRicardo Koller #define DBGWCR_LEN8		(0xff << 5)
21843fa9e2SRicardo Koller #define DBGWCR_RD		(0x1 << 3)
22843fa9e2SRicardo Koller #define DBGWCR_WR		(0x2 << 3)
23843fa9e2SRicardo Koller #define DBGWCR_EL1		(0x1 << 1)
24843fa9e2SRicardo Koller #define DBGWCR_E		(0x1 << 0)
25843fa9e2SRicardo Koller 
2669de9b31SRicardo Koller #define SPSR_D			(1 << 9)
27ac97ac81SRicardo Koller #define SPSR_SS			(1 << 21)
2869de9b31SRicardo Koller 
2969de9b31SRicardo Koller #define ESR_EC_HW_BP_CURRENT    0x31
30ac97ac81SRicardo Koller #define ESR_EC_SSTEP_CURRENT    0x33
31843fa9e2SRicardo Koller #define ESR_EC_WP_CURRENT       0x35
3269de9b31SRicardo Koller 
3369de9b31SRicardo Koller #define ID_AA64DFR0_BRPS_SHIFT	12
3469de9b31SRicardo Koller #define ID_AA64DFR0_BRPS_MASK	0xf
35843fa9e2SRicardo Koller #define ID_AA64DFR0_WRPS_SHIFT	20
36843fa9e2SRicardo Koller #define ID_AA64DFR0_WRPS_MASK	0xf
3769de9b31SRicardo Koller 
3869de9b31SRicardo Koller static volatile uint64_t hw_bp_idx, hw_bp_addr[16];
39843fa9e2SRicardo Koller static volatile uint64_t wp_idx, wp_data_addr[16];
40ac97ac81SRicardo Koller static volatile uint64_t ss_addr[4], ss_idx;
4169de9b31SRicardo Koller 
hw_bp_handler(struct pt_regs * regs,unsigned int esr)4269de9b31SRicardo Koller static void hw_bp_handler(struct pt_regs *regs, unsigned int esr)
4369de9b31SRicardo Koller {
4469de9b31SRicardo Koller 	hw_bp_addr[hw_bp_idx++] = regs->pc;
4569de9b31SRicardo Koller 	regs->pstate |= SPSR_D;
4669de9b31SRicardo Koller }
4769de9b31SRicardo Koller 
wp_handler(struct pt_regs * regs,unsigned int esr)48843fa9e2SRicardo Koller static void wp_handler(struct pt_regs *regs, unsigned int esr)
49843fa9e2SRicardo Koller {
50843fa9e2SRicardo Koller 	wp_data_addr[wp_idx++] = read_sysreg(far_el1);
51843fa9e2SRicardo Koller 	regs->pstate |= SPSR_D;
52843fa9e2SRicardo Koller }
53843fa9e2SRicardo Koller 
ss_handler(struct pt_regs * regs,unsigned int esr)54ac97ac81SRicardo Koller static void ss_handler(struct pt_regs *regs, unsigned int esr)
55ac97ac81SRicardo Koller {
56ac97ac81SRicardo Koller 	ss_addr[ss_idx++] = regs->pc;
57ac97ac81SRicardo Koller 	regs->pstate |= SPSR_SS;
58ac97ac81SRicardo Koller }
59ac97ac81SRicardo Koller 
get_num_hw_bp(void)6069de9b31SRicardo Koller static int get_num_hw_bp(void)
6169de9b31SRicardo Koller {
6269de9b31SRicardo Koller 	uint64_t reg = read_sysreg(id_aa64dfr0_el1);
6369de9b31SRicardo Koller 	/* Number of breakpoints, minus 1 */
6469de9b31SRicardo Koller 	uint8_t brps = (reg >> ID_AA64DFR0_BRPS_SHIFT) & ID_AA64DFR0_BRPS_MASK;
6569de9b31SRicardo Koller 
6669de9b31SRicardo Koller 	return brps + 1;
6769de9b31SRicardo Koller }
6869de9b31SRicardo Koller 
get_num_wp(void)69843fa9e2SRicardo Koller static int get_num_wp(void)
70843fa9e2SRicardo Koller {
71843fa9e2SRicardo Koller 	uint64_t reg = read_sysreg(id_aa64dfr0_el1);
72843fa9e2SRicardo Koller 	/* Number of watchpoints, minus 1 */
73843fa9e2SRicardo Koller 	uint8_t wrps = (reg >> ID_AA64DFR0_WRPS_SHIFT) & ID_AA64DFR0_WRPS_MASK;
74843fa9e2SRicardo Koller 
75843fa9e2SRicardo Koller 	return wrps + 1;
76843fa9e2SRicardo Koller }
77843fa9e2SRicardo Koller 
write_dbgbcr(int n,uint32_t bcr)7869de9b31SRicardo Koller static void write_dbgbcr(int n, uint32_t bcr)
7969de9b31SRicardo Koller {
8069de9b31SRicardo Koller 	switch (n) {
8169de9b31SRicardo Koller 	case 0:
8269de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr0_el1); break;
8369de9b31SRicardo Koller 	case 1:
8469de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr1_el1); break;
8569de9b31SRicardo Koller 	case 2:
8669de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr2_el1); break;
8769de9b31SRicardo Koller 	case 3:
8869de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr3_el1); break;
8969de9b31SRicardo Koller 	case 4:
9069de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr4_el1); break;
9169de9b31SRicardo Koller 	case 5:
9269de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr5_el1); break;
9369de9b31SRicardo Koller 	case 6:
9469de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr6_el1); break;
9569de9b31SRicardo Koller 	case 7:
9669de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr7_el1); break;
9769de9b31SRicardo Koller 	case 8:
9869de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr8_el1); break;
9969de9b31SRicardo Koller 	case 9:
10069de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr9_el1); break;
10169de9b31SRicardo Koller 	case 10:
10269de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr10_el1); break;
10369de9b31SRicardo Koller 	case 11:
10469de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr11_el1); break;
10569de9b31SRicardo Koller 	case 12:
10669de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr12_el1); break;
10769de9b31SRicardo Koller 	case 13:
10869de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr13_el1); break;
10969de9b31SRicardo Koller 	case 14:
11069de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr14_el1); break;
11169de9b31SRicardo Koller 	case 15:
11269de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr15_el1); break;
11369de9b31SRicardo Koller 	default:
11469de9b31SRicardo Koller 		report_abort("Invalid bcr");
11569de9b31SRicardo Koller 	}
11669de9b31SRicardo Koller }
11769de9b31SRicardo Koller 
write_dbgbvr(int n,uint64_t bvr)11869de9b31SRicardo Koller static void write_dbgbvr(int n, uint64_t bvr)
11969de9b31SRicardo Koller {
12069de9b31SRicardo Koller 	switch (n) {
12169de9b31SRicardo Koller 	case 0:
12269de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr0_el1); break;
12369de9b31SRicardo Koller 	case 1:
12469de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr1_el1); break;
12569de9b31SRicardo Koller 	case 2:
12669de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr2_el1); break;
12769de9b31SRicardo Koller 	case 3:
12869de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr3_el1); break;
12969de9b31SRicardo Koller 	case 4:
13069de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr4_el1); break;
13169de9b31SRicardo Koller 	case 5:
13269de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr5_el1); break;
13369de9b31SRicardo Koller 	case 6:
13469de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr6_el1); break;
13569de9b31SRicardo Koller 	case 7:
13669de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr7_el1); break;
13769de9b31SRicardo Koller 	case 8:
13869de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr8_el1); break;
13969de9b31SRicardo Koller 	case 9:
14069de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr9_el1); break;
14169de9b31SRicardo Koller 	case 10:
14269de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr10_el1); break;
14369de9b31SRicardo Koller 	case 11:
14469de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr11_el1); break;
14569de9b31SRicardo Koller 	case 12:
14669de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr12_el1); break;
14769de9b31SRicardo Koller 	case 13:
14869de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr13_el1); break;
14969de9b31SRicardo Koller 	case 14:
15069de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr14_el1); break;
15169de9b31SRicardo Koller 	case 15:
15269de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr15_el1); break;
15369de9b31SRicardo Koller 	default:
15469de9b31SRicardo Koller 		report_abort("invalid bvr");
15569de9b31SRicardo Koller 	}
15669de9b31SRicardo Koller }
15769de9b31SRicardo Koller 
write_dbgwcr(int n,uint32_t wcr)158843fa9e2SRicardo Koller static void write_dbgwcr(int n, uint32_t wcr)
159843fa9e2SRicardo Koller {
160843fa9e2SRicardo Koller 	switch (n) {
161843fa9e2SRicardo Koller 	case 0:
162843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr0_el1); break;
163843fa9e2SRicardo Koller 	case 1:
164843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr1_el1); break;
165843fa9e2SRicardo Koller 	case 2:
166843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr2_el1); break;
167843fa9e2SRicardo Koller 	case 3:
168843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr3_el1); break;
169843fa9e2SRicardo Koller 	case 4:
170843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr4_el1); break;
171843fa9e2SRicardo Koller 	case 5:
172843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr5_el1); break;
173843fa9e2SRicardo Koller 	case 6:
174843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr6_el1); break;
175843fa9e2SRicardo Koller 	case 7:
176843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr7_el1); break;
177843fa9e2SRicardo Koller 	case 8:
178843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr8_el1); break;
179843fa9e2SRicardo Koller 	case 9:
180843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr9_el1); break;
181843fa9e2SRicardo Koller 	case 10:
182843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr10_el1); break;
183843fa9e2SRicardo Koller 	case 11:
184843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr11_el1); break;
185843fa9e2SRicardo Koller 	case 12:
186843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr12_el1); break;
187843fa9e2SRicardo Koller 	case 13:
188843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr13_el1); break;
189843fa9e2SRicardo Koller 	case 14:
190843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr14_el1); break;
191843fa9e2SRicardo Koller 	case 15:
192843fa9e2SRicardo Koller 		write_sysreg(wcr, dbgwcr15_el1); break;
193843fa9e2SRicardo Koller 	default:
194843fa9e2SRicardo Koller 		report_abort("Invalid wcr");
195843fa9e2SRicardo Koller 	}
196843fa9e2SRicardo Koller }
197843fa9e2SRicardo Koller 
write_dbgwvr(int n,uint64_t wvr)198843fa9e2SRicardo Koller static void write_dbgwvr(int n, uint64_t wvr)
199843fa9e2SRicardo Koller {
200843fa9e2SRicardo Koller 	switch (n) {
201843fa9e2SRicardo Koller 	case 0:
202843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr0_el1); break;
203843fa9e2SRicardo Koller 	case 1:
204843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr1_el1); break;
205843fa9e2SRicardo Koller 	case 2:
206843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr2_el1); break;
207843fa9e2SRicardo Koller 	case 3:
208843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr3_el1); break;
209843fa9e2SRicardo Koller 	case 4:
210843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr4_el1); break;
211843fa9e2SRicardo Koller 	case 5:
212843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr5_el1); break;
213843fa9e2SRicardo Koller 	case 6:
214843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr6_el1); break;
215843fa9e2SRicardo Koller 	case 7:
216843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr7_el1); break;
217843fa9e2SRicardo Koller 	case 8:
218843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr8_el1); break;
219843fa9e2SRicardo Koller 	case 9:
220843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr9_el1); break;
221843fa9e2SRicardo Koller 	case 10:
222843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr10_el1); break;
223843fa9e2SRicardo Koller 	case 11:
224843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr11_el1); break;
225843fa9e2SRicardo Koller 	case 12:
226843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr12_el1); break;
227843fa9e2SRicardo Koller 	case 13:
228843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr13_el1); break;
229843fa9e2SRicardo Koller 	case 14:
230843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr14_el1); break;
231843fa9e2SRicardo Koller 	case 15:
232843fa9e2SRicardo Koller 		write_sysreg(wvr, dbgwvr15_el1); break;
233843fa9e2SRicardo Koller 	default:
234843fa9e2SRicardo Koller 		report_abort("invalid wvr");
235843fa9e2SRicardo Koller 	}
236843fa9e2SRicardo Koller }
237843fa9e2SRicardo Koller 
reset_debug_state(void)23869de9b31SRicardo Koller static void reset_debug_state(void)
23969de9b31SRicardo Koller {
24069de9b31SRicardo Koller 	int i, num_bp = get_num_hw_bp();
241843fa9e2SRicardo Koller 	int num_wp = get_num_wp();
24269de9b31SRicardo Koller 
24369de9b31SRicardo Koller 	asm volatile("msr daifset, #8");
24469de9b31SRicardo Koller 
24569de9b31SRicardo Koller 	write_sysreg(0, osdlr_el1);
24669de9b31SRicardo Koller 	write_sysreg(0, oslar_el1);
24769de9b31SRicardo Koller 	isb();
24869de9b31SRicardo Koller 
24969de9b31SRicardo Koller 	write_sysreg(0, mdscr_el1);
25069de9b31SRicardo Koller 	for (i = 0; i < num_bp; i++) {
25169de9b31SRicardo Koller 		write_dbgbvr(i, 0);
25269de9b31SRicardo Koller 		write_dbgbcr(i, 0);
25369de9b31SRicardo Koller 	}
254843fa9e2SRicardo Koller 	for (i = 0; i < num_wp; i++) {
255843fa9e2SRicardo Koller 		write_dbgwvr(i, 0);
256843fa9e2SRicardo Koller 		write_dbgwcr(i, 0);
257843fa9e2SRicardo Koller 	}
25869de9b31SRicardo Koller 	isb();
25969de9b31SRicardo Koller }
26069de9b31SRicardo Koller 
test_hw_bp(bool migrate)26130333fbcSRicardo Koller static noinline void test_hw_bp(bool migrate)
26269de9b31SRicardo Koller {
26369de9b31SRicardo Koller 	extern unsigned char hw_bp0;
26469de9b31SRicardo Koller 	uint32_t bcr;
26569de9b31SRicardo Koller 	uint32_t mdscr;
26669de9b31SRicardo Koller 	uint64_t addr;
26769de9b31SRicardo Koller 	int num_bp = get_num_hw_bp();
26869de9b31SRicardo Koller 	int i;
26969de9b31SRicardo Koller 
27069de9b31SRicardo Koller 	install_exception_handler(EL1H_SYNC, ESR_EC_HW_BP_CURRENT, hw_bp_handler);
27169de9b31SRicardo Koller 
27269de9b31SRicardo Koller 	reset_debug_state();
27369de9b31SRicardo Koller 
27469de9b31SRicardo Koller 	bcr = DBGBCR_LEN8 | DBGBCR_EXEC | DBGBCR_EL1 | DBGBCR_E;
27569de9b31SRicardo Koller 	for (i = 0, addr = (uint64_t)&hw_bp0; i < num_bp; i++, addr += 4) {
27669de9b31SRicardo Koller 		write_dbgbcr(i, bcr);
27769de9b31SRicardo Koller 		write_dbgbvr(i, addr);
27869de9b31SRicardo Koller 	}
27969de9b31SRicardo Koller 	isb();
28069de9b31SRicardo Koller 
28169de9b31SRicardo Koller 	asm volatile("msr daifclr, #8");
28269de9b31SRicardo Koller 
28369de9b31SRicardo Koller 	mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_MDE;
28469de9b31SRicardo Koller 	write_sysreg(mdscr, mdscr_el1);
28569de9b31SRicardo Koller 	isb();
28669de9b31SRicardo Koller 
28769de9b31SRicardo Koller 	if (migrate) {
2887cefda52SNico Boehr 		migrate_once();
28969de9b31SRicardo Koller 		report(num_bp == get_num_hw_bp(), "brps match after migrate");
29069de9b31SRicardo Koller 	}
29169de9b31SRicardo Koller 
29269de9b31SRicardo Koller 	hw_bp_idx = 0;
29369de9b31SRicardo Koller 
29469de9b31SRicardo Koller 	/* Trap on up to 16 debug exception unmask instructions. */
295*79521ee7SNikos Nikoleris 	asm volatile(
296*79521ee7SNikos Nikoleris 		".globl hw_bp0\n"
297*79521ee7SNikos Nikoleris 		"hw_bp0:\n"
29869de9b31SRicardo Koller 			"msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n"
29969de9b31SRicardo Koller 			"msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n"
30069de9b31SRicardo Koller 			"msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n"
301*79521ee7SNikos Nikoleris 			"msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n"
302*79521ee7SNikos Nikoleris 		);
30369de9b31SRicardo Koller 
30469de9b31SRicardo Koller 	for (i = 0, addr = (uint64_t)&hw_bp0; i < num_bp; i++, addr += 4)
30569de9b31SRicardo Koller 		report(hw_bp_addr[i] == addr, "hw breakpoint: %d", i);
30669de9b31SRicardo Koller }
30769de9b31SRicardo Koller 
308843fa9e2SRicardo Koller static volatile char write_data[16];
309843fa9e2SRicardo Koller 
test_wp(bool migrate)31030333fbcSRicardo Koller static noinline void test_wp(bool migrate)
311843fa9e2SRicardo Koller {
312843fa9e2SRicardo Koller 	uint32_t wcr;
313843fa9e2SRicardo Koller 	uint32_t mdscr;
314843fa9e2SRicardo Koller 	int num_wp = get_num_wp();
315843fa9e2SRicardo Koller 	int i;
316843fa9e2SRicardo Koller 
317843fa9e2SRicardo Koller 	install_exception_handler(EL1H_SYNC, ESR_EC_WP_CURRENT, wp_handler);
318843fa9e2SRicardo Koller 
319843fa9e2SRicardo Koller 	reset_debug_state();
320843fa9e2SRicardo Koller 
321843fa9e2SRicardo Koller 	wcr = DBGWCR_LEN8 | DBGWCR_RD | DBGWCR_WR | DBGWCR_EL1 | DBGWCR_E;
322843fa9e2SRicardo Koller 	for (i = 0; i < num_wp; i++) {
323843fa9e2SRicardo Koller 		write_dbgwcr(i, wcr);
324843fa9e2SRicardo Koller 		write_dbgwvr(i, (uint64_t)&write_data[i]);
325843fa9e2SRicardo Koller 	}
326843fa9e2SRicardo Koller 	isb();
327843fa9e2SRicardo Koller 
328843fa9e2SRicardo Koller 	asm volatile("msr daifclr, #8");
329843fa9e2SRicardo Koller 
330843fa9e2SRicardo Koller 	mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_MDE;
331843fa9e2SRicardo Koller 	write_sysreg(mdscr, mdscr_el1);
332843fa9e2SRicardo Koller 	isb();
333843fa9e2SRicardo Koller 
334843fa9e2SRicardo Koller 	if (migrate) {
3357cefda52SNico Boehr 		migrate_once();
336843fa9e2SRicardo Koller 		report(num_wp == get_num_wp(), "wrps match after migrate");
337843fa9e2SRicardo Koller 	}
338843fa9e2SRicardo Koller 
339843fa9e2SRicardo Koller 	wp_idx = 0;
340843fa9e2SRicardo Koller 
341843fa9e2SRicardo Koller 	for (i = 0; i < num_wp; i++) {
342843fa9e2SRicardo Koller 		write_data[i] = i;
343843fa9e2SRicardo Koller 		asm volatile("msr daifclr, #8");
344843fa9e2SRicardo Koller 	}
345843fa9e2SRicardo Koller 
346843fa9e2SRicardo Koller 	for (i = 0; i < num_wp; i++) {
347843fa9e2SRicardo Koller 		report(wp_data_addr[i] == (uint64_t)&write_data[i],
348843fa9e2SRicardo Koller 			"watchpoint received: %d", i);
349843fa9e2SRicardo Koller 		report(write_data[i] == i, "watchpoint data: %d", i);
350843fa9e2SRicardo Koller 	}
351843fa9e2SRicardo Koller }
352843fa9e2SRicardo Koller 
test_ss(bool migrate)35330333fbcSRicardo Koller static noinline void test_ss(bool migrate)
354ac97ac81SRicardo Koller {
355ac97ac81SRicardo Koller 	extern unsigned char ss_start;
356ac97ac81SRicardo Koller 	uint32_t mdscr;
357ac97ac81SRicardo Koller 
358ac97ac81SRicardo Koller 	install_exception_handler(EL1H_SYNC, ESR_EC_SSTEP_CURRENT, ss_handler);
359ac97ac81SRicardo Koller 
360ac97ac81SRicardo Koller 	reset_debug_state();
361ac97ac81SRicardo Koller 
362ac97ac81SRicardo Koller 	ss_idx = 0;
363ac97ac81SRicardo Koller 
364ac97ac81SRicardo Koller 	mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_SS;
365ac97ac81SRicardo Koller 	write_sysreg(mdscr, mdscr_el1);
366ac97ac81SRicardo Koller 	isb();
367ac97ac81SRicardo Koller 
3687cefda52SNico Boehr 	if (migrate)
3697cefda52SNico Boehr 		migrate_once();
370ac97ac81SRicardo Koller 
371ac97ac81SRicardo Koller 	asm volatile("msr daifclr, #8");
372ac97ac81SRicardo Koller 
373*79521ee7SNikos Nikoleris 	asm volatile(
374*79521ee7SNikos Nikoleris 		".globl ss_start\n"
375*79521ee7SNikos Nikoleris 		"ss_start:\n"
376ac97ac81SRicardo Koller 			"mrs x0, esr_el1\n"
377ac97ac81SRicardo Koller 			"add x0, x0, #1\n"
378ac97ac81SRicardo Koller 			"msr daifset, #8\n"
379*79521ee7SNikos Nikoleris 			: : : "x0"
380*79521ee7SNikos Nikoleris 		);
381ac97ac81SRicardo Koller 
382ac97ac81SRicardo Koller 	report(ss_addr[0] == (uint64_t)&ss_start, "single step");
383ac97ac81SRicardo Koller }
384ac97ac81SRicardo Koller 
main(int argc,char ** argv)38569de9b31SRicardo Koller int main(int argc, char **argv)
38669de9b31SRicardo Koller {
38769de9b31SRicardo Koller 	if (argc < 2)
38869de9b31SRicardo Koller 		report_abort("no test specified");
38969de9b31SRicardo Koller 
39069de9b31SRicardo Koller 	if (strcmp(argv[1], "bp") == 0) {
39169de9b31SRicardo Koller 		report_prefix_push(argv[1]);
39269de9b31SRicardo Koller 		test_hw_bp(false);
39369de9b31SRicardo Koller 		report_prefix_pop();
39469de9b31SRicardo Koller 	} else if (strcmp(argv[1], "bp-migration") == 0) {
39569de9b31SRicardo Koller 		report_prefix_push(argv[1]);
39669de9b31SRicardo Koller 		test_hw_bp(true);
39769de9b31SRicardo Koller 		report_prefix_pop();
398843fa9e2SRicardo Koller 	} else if (strcmp(argv[1], "wp") == 0) {
399843fa9e2SRicardo Koller 		report_prefix_push(argv[1]);
400843fa9e2SRicardo Koller 		test_wp(false);
401843fa9e2SRicardo Koller 		report_prefix_pop();
402843fa9e2SRicardo Koller 	} else if (strcmp(argv[1], "wp-migration") == 0) {
403843fa9e2SRicardo Koller 		report_prefix_push(argv[1]);
404843fa9e2SRicardo Koller 		test_wp(true);
405843fa9e2SRicardo Koller 		report_prefix_pop();
406ac97ac81SRicardo Koller 	} else if (strcmp(argv[1], "ss") == 0) {
407ac97ac81SRicardo Koller 		report_prefix_push(argv[1]);
408ac97ac81SRicardo Koller 		test_ss(false);
409ac97ac81SRicardo Koller 		report_prefix_pop();
410ac97ac81SRicardo Koller 	} else if (strcmp(argv[1], "ss-migration") == 0) {
411ac97ac81SRicardo Koller 		report_prefix_push(argv[1]);
412ac97ac81SRicardo Koller 		test_ss(true);
413ac97ac81SRicardo Koller 		report_prefix_pop();
41469de9b31SRicardo Koller 	} else {
41569de9b31SRicardo Koller 		report_abort("Unknown subtest '%s'", argv[1]);
41669de9b31SRicardo Koller 	}
41769de9b31SRicardo Koller 
41869de9b31SRicardo Koller 	return report_summary();
41969de9b31SRicardo Koller }
420