xref: /kvm-unit-tests/arm/debug.c (revision 69de9b3194ca8bc8341f93a1134316dbd26c3434)
1*69de9b31SRicardo Koller #include <libcflat.h>
2*69de9b31SRicardo Koller #include <errata.h>
3*69de9b31SRicardo Koller #include <asm/setup.h>
4*69de9b31SRicardo Koller #include <asm/processor.h>
5*69de9b31SRicardo Koller #include <asm/delay.h>
6*69de9b31SRicardo Koller #include <asm/smp.h>
7*69de9b31SRicardo Koller #include <asm/barrier.h>
8*69de9b31SRicardo Koller #include <asm/io.h>
9*69de9b31SRicardo Koller 
10*69de9b31SRicardo Koller #define MDSCR_KDE		(1 << 13)
11*69de9b31SRicardo Koller #define MDSCR_MDE		(1 << 15)
12*69de9b31SRicardo Koller 
13*69de9b31SRicardo Koller #define DBGBCR_LEN8		(0xff << 5)
14*69de9b31SRicardo Koller #define DBGBCR_EXEC		(0x0 << 3)
15*69de9b31SRicardo Koller #define DBGBCR_EL1		(0x1 << 1)
16*69de9b31SRicardo Koller #define DBGBCR_E		(0x1 << 0)
17*69de9b31SRicardo Koller 
18*69de9b31SRicardo Koller #define SPSR_D			(1 << 9)
19*69de9b31SRicardo Koller 
20*69de9b31SRicardo Koller #define ESR_EC_HW_BP_CURRENT    0x31
21*69de9b31SRicardo Koller 
22*69de9b31SRicardo Koller #define ID_AA64DFR0_BRPS_SHIFT	12
23*69de9b31SRicardo Koller #define ID_AA64DFR0_BRPS_MASK	0xf
24*69de9b31SRicardo Koller 
25*69de9b31SRicardo Koller static volatile uint64_t hw_bp_idx, hw_bp_addr[16];
26*69de9b31SRicardo Koller 
27*69de9b31SRicardo Koller static void hw_bp_handler(struct pt_regs *regs, unsigned int esr)
28*69de9b31SRicardo Koller {
29*69de9b31SRicardo Koller 	hw_bp_addr[hw_bp_idx++] = regs->pc;
30*69de9b31SRicardo Koller 	regs->pstate |= SPSR_D;
31*69de9b31SRicardo Koller }
32*69de9b31SRicardo Koller 
33*69de9b31SRicardo Koller static int get_num_hw_bp(void)
34*69de9b31SRicardo Koller {
35*69de9b31SRicardo Koller 	uint64_t reg = read_sysreg(id_aa64dfr0_el1);
36*69de9b31SRicardo Koller 	/* Number of breakpoints, minus 1 */
37*69de9b31SRicardo Koller 	uint8_t brps = (reg >> ID_AA64DFR0_BRPS_SHIFT) & ID_AA64DFR0_BRPS_MASK;
38*69de9b31SRicardo Koller 
39*69de9b31SRicardo Koller 	return brps + 1;
40*69de9b31SRicardo Koller }
41*69de9b31SRicardo Koller 
42*69de9b31SRicardo Koller static void write_dbgbcr(int n, uint32_t bcr)
43*69de9b31SRicardo Koller {
44*69de9b31SRicardo Koller 	switch (n) {
45*69de9b31SRicardo Koller 	case 0:
46*69de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr0_el1); break;
47*69de9b31SRicardo Koller 	case 1:
48*69de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr1_el1); break;
49*69de9b31SRicardo Koller 	case 2:
50*69de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr2_el1); break;
51*69de9b31SRicardo Koller 	case 3:
52*69de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr3_el1); break;
53*69de9b31SRicardo Koller 	case 4:
54*69de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr4_el1); break;
55*69de9b31SRicardo Koller 	case 5:
56*69de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr5_el1); break;
57*69de9b31SRicardo Koller 	case 6:
58*69de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr6_el1); break;
59*69de9b31SRicardo Koller 	case 7:
60*69de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr7_el1); break;
61*69de9b31SRicardo Koller 	case 8:
62*69de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr8_el1); break;
63*69de9b31SRicardo Koller 	case 9:
64*69de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr9_el1); break;
65*69de9b31SRicardo Koller 	case 10:
66*69de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr10_el1); break;
67*69de9b31SRicardo Koller 	case 11:
68*69de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr11_el1); break;
69*69de9b31SRicardo Koller 	case 12:
70*69de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr12_el1); break;
71*69de9b31SRicardo Koller 	case 13:
72*69de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr13_el1); break;
73*69de9b31SRicardo Koller 	case 14:
74*69de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr14_el1); break;
75*69de9b31SRicardo Koller 	case 15:
76*69de9b31SRicardo Koller 		write_sysreg(bcr, dbgbcr15_el1); break;
77*69de9b31SRicardo Koller 	default:
78*69de9b31SRicardo Koller 		report_abort("Invalid bcr");
79*69de9b31SRicardo Koller 	}
80*69de9b31SRicardo Koller }
81*69de9b31SRicardo Koller 
82*69de9b31SRicardo Koller static void write_dbgbvr(int n, uint64_t bvr)
83*69de9b31SRicardo Koller {
84*69de9b31SRicardo Koller 	switch (n) {
85*69de9b31SRicardo Koller 	case 0:
86*69de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr0_el1); break;
87*69de9b31SRicardo Koller 	case 1:
88*69de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr1_el1); break;
89*69de9b31SRicardo Koller 	case 2:
90*69de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr2_el1); break;
91*69de9b31SRicardo Koller 	case 3:
92*69de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr3_el1); break;
93*69de9b31SRicardo Koller 	case 4:
94*69de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr4_el1); break;
95*69de9b31SRicardo Koller 	case 5:
96*69de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr5_el1); break;
97*69de9b31SRicardo Koller 	case 6:
98*69de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr6_el1); break;
99*69de9b31SRicardo Koller 	case 7:
100*69de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr7_el1); break;
101*69de9b31SRicardo Koller 	case 8:
102*69de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr8_el1); break;
103*69de9b31SRicardo Koller 	case 9:
104*69de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr9_el1); break;
105*69de9b31SRicardo Koller 	case 10:
106*69de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr10_el1); break;
107*69de9b31SRicardo Koller 	case 11:
108*69de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr11_el1); break;
109*69de9b31SRicardo Koller 	case 12:
110*69de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr12_el1); break;
111*69de9b31SRicardo Koller 	case 13:
112*69de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr13_el1); break;
113*69de9b31SRicardo Koller 	case 14:
114*69de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr14_el1); break;
115*69de9b31SRicardo Koller 	case 15:
116*69de9b31SRicardo Koller 		write_sysreg(bvr, dbgbvr15_el1); break;
117*69de9b31SRicardo Koller 	default:
118*69de9b31SRicardo Koller 		report_abort("invalid bvr");
119*69de9b31SRicardo Koller 	}
120*69de9b31SRicardo Koller }
121*69de9b31SRicardo Koller 
122*69de9b31SRicardo Koller static void reset_debug_state(void)
123*69de9b31SRicardo Koller {
124*69de9b31SRicardo Koller 	int i, num_bp = get_num_hw_bp();
125*69de9b31SRicardo Koller 
126*69de9b31SRicardo Koller 	asm volatile("msr daifset, #8");
127*69de9b31SRicardo Koller 
128*69de9b31SRicardo Koller 	write_sysreg(0, osdlr_el1);
129*69de9b31SRicardo Koller 	write_sysreg(0, oslar_el1);
130*69de9b31SRicardo Koller 	isb();
131*69de9b31SRicardo Koller 
132*69de9b31SRicardo Koller 	write_sysreg(0, mdscr_el1);
133*69de9b31SRicardo Koller 	for (i = 0; i < num_bp; i++) {
134*69de9b31SRicardo Koller 		write_dbgbvr(i, 0);
135*69de9b31SRicardo Koller 		write_dbgbcr(i, 0);
136*69de9b31SRicardo Koller 	}
137*69de9b31SRicardo Koller 	isb();
138*69de9b31SRicardo Koller }
139*69de9b31SRicardo Koller 
140*69de9b31SRicardo Koller static void do_migrate(void)
141*69de9b31SRicardo Koller {
142*69de9b31SRicardo Koller 	puts("Now migrate the VM, then press a key to continue...\n");
143*69de9b31SRicardo Koller 	(void)getchar();
144*69de9b31SRicardo Koller 	report_info("Migration complete");
145*69de9b31SRicardo Koller }
146*69de9b31SRicardo Koller 
147*69de9b31SRicardo Koller static void test_hw_bp(bool migrate)
148*69de9b31SRicardo Koller {
149*69de9b31SRicardo Koller 	extern unsigned char hw_bp0;
150*69de9b31SRicardo Koller 	uint32_t bcr;
151*69de9b31SRicardo Koller 	uint32_t mdscr;
152*69de9b31SRicardo Koller 	uint64_t addr;
153*69de9b31SRicardo Koller 	int num_bp = get_num_hw_bp();
154*69de9b31SRicardo Koller 	int i;
155*69de9b31SRicardo Koller 
156*69de9b31SRicardo Koller 	install_exception_handler(EL1H_SYNC, ESR_EC_HW_BP_CURRENT, hw_bp_handler);
157*69de9b31SRicardo Koller 
158*69de9b31SRicardo Koller 	reset_debug_state();
159*69de9b31SRicardo Koller 
160*69de9b31SRicardo Koller 	bcr = DBGBCR_LEN8 | DBGBCR_EXEC | DBGBCR_EL1 | DBGBCR_E;
161*69de9b31SRicardo Koller 	for (i = 0, addr = (uint64_t)&hw_bp0; i < num_bp; i++, addr += 4) {
162*69de9b31SRicardo Koller 		write_dbgbcr(i, bcr);
163*69de9b31SRicardo Koller 		write_dbgbvr(i, addr);
164*69de9b31SRicardo Koller 	}
165*69de9b31SRicardo Koller 	isb();
166*69de9b31SRicardo Koller 
167*69de9b31SRicardo Koller 	asm volatile("msr daifclr, #8");
168*69de9b31SRicardo Koller 
169*69de9b31SRicardo Koller 	mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_MDE;
170*69de9b31SRicardo Koller 	write_sysreg(mdscr, mdscr_el1);
171*69de9b31SRicardo Koller 	isb();
172*69de9b31SRicardo Koller 
173*69de9b31SRicardo Koller 	if (migrate) {
174*69de9b31SRicardo Koller 		do_migrate();
175*69de9b31SRicardo Koller 		report(num_bp == get_num_hw_bp(), "brps match after migrate");
176*69de9b31SRicardo Koller 	}
177*69de9b31SRicardo Koller 
178*69de9b31SRicardo Koller 	hw_bp_idx = 0;
179*69de9b31SRicardo Koller 
180*69de9b31SRicardo Koller 	/* Trap on up to 16 debug exception unmask instructions. */
181*69de9b31SRicardo Koller 	asm volatile("hw_bp0:\n"
182*69de9b31SRicardo Koller 	     "msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n"
183*69de9b31SRicardo Koller 	     "msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n"
184*69de9b31SRicardo Koller 	     "msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n"
185*69de9b31SRicardo Koller 	     "msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n");
186*69de9b31SRicardo Koller 
187*69de9b31SRicardo Koller 	for (i = 0, addr = (uint64_t)&hw_bp0; i < num_bp; i++, addr += 4)
188*69de9b31SRicardo Koller 		report(hw_bp_addr[i] == addr, "hw breakpoint: %d", i);
189*69de9b31SRicardo Koller }
190*69de9b31SRicardo Koller 
191*69de9b31SRicardo Koller int main(int argc, char **argv)
192*69de9b31SRicardo Koller {
193*69de9b31SRicardo Koller 	if (argc < 2)
194*69de9b31SRicardo Koller 		report_abort("no test specified");
195*69de9b31SRicardo Koller 
196*69de9b31SRicardo Koller 	if (strcmp(argv[1], "bp") == 0) {
197*69de9b31SRicardo Koller 		report_prefix_push(argv[1]);
198*69de9b31SRicardo Koller 		test_hw_bp(false);
199*69de9b31SRicardo Koller 		report_prefix_pop();
200*69de9b31SRicardo Koller 	} else if (strcmp(argv[1], "bp-migration") == 0) {
201*69de9b31SRicardo Koller 		report_prefix_push(argv[1]);
202*69de9b31SRicardo Koller 		test_hw_bp(true);
203*69de9b31SRicardo Koller 		report_prefix_pop();
204*69de9b31SRicardo Koller 	} else {
205*69de9b31SRicardo Koller 		report_abort("Unknown subtest '%s'", argv[1]);
206*69de9b31SRicardo Koller 	}
207*69de9b31SRicardo Koller 
208*69de9b31SRicardo Koller 	return report_summary();
209*69de9b31SRicardo Koller }
210