1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_util.h>
3 #include <kvm_util.h>
4 #include <processor.h>
5 #include <linux/bitfield.h>
6 
7 #define MDSCR_KDE	(1 << 13)
8 #define MDSCR_MDE	(1 << 15)
9 #define MDSCR_SS	(1 << 0)
10 
11 #define DBGBCR_LEN8	(0xff << 5)
12 #define DBGBCR_EXEC	(0x0 << 3)
13 #define DBGBCR_EL1	(0x1 << 1)
14 #define DBGBCR_E	(0x1 << 0)
15 
16 #define DBGWCR_LEN8	(0xff << 5)
17 #define DBGWCR_RD	(0x1 << 3)
18 #define DBGWCR_WR	(0x2 << 3)
19 #define DBGWCR_EL1	(0x1 << 1)
20 #define DBGWCR_E	(0x1 << 0)
21 
22 #define SPSR_D		(1 << 9)
23 #define SPSR_SS		(1 << 21)
24 
25 extern unsigned char sw_bp, sw_bp2, hw_bp, hw_bp2, bp_svc, bp_brk, hw_wp, ss_start;
26 extern unsigned char iter_ss_begin, iter_ss_end;
27 static volatile uint64_t sw_bp_addr, hw_bp_addr;
28 static volatile uint64_t wp_addr, wp_data_addr;
29 static volatile uint64_t svc_addr;
30 static volatile uint64_t ss_addr[4], ss_idx;
31 #define  PC(v)  ((uint64_t)&(v))
32 
33 #define GEN_DEBUG_WRITE_REG(reg_name)			\
34 static void write_##reg_name(int num, uint64_t val)	\
35 {							\
36 	switch (num) {					\
37 	case 0:						\
38 		write_sysreg(val, reg_name##0_el1);	\
39 		break;					\
40 	case 1:						\
41 		write_sysreg(val, reg_name##1_el1);	\
42 		break;					\
43 	case 2:						\
44 		write_sysreg(val, reg_name##2_el1);	\
45 		break;					\
46 	case 3:						\
47 		write_sysreg(val, reg_name##3_el1);	\
48 		break;					\
49 	case 4:						\
50 		write_sysreg(val, reg_name##4_el1);	\
51 		break;					\
52 	case 5:						\
53 		write_sysreg(val, reg_name##5_el1);	\
54 		break;					\
55 	case 6:						\
56 		write_sysreg(val, reg_name##6_el1);	\
57 		break;					\
58 	case 7:						\
59 		write_sysreg(val, reg_name##7_el1);	\
60 		break;					\
61 	case 8:						\
62 		write_sysreg(val, reg_name##8_el1);	\
63 		break;					\
64 	case 9:						\
65 		write_sysreg(val, reg_name##9_el1);	\
66 		break;					\
67 	case 10:					\
68 		write_sysreg(val, reg_name##10_el1);	\
69 		break;					\
70 	case 11:					\
71 		write_sysreg(val, reg_name##11_el1);	\
72 		break;					\
73 	case 12:					\
74 		write_sysreg(val, reg_name##12_el1);	\
75 		break;					\
76 	case 13:					\
77 		write_sysreg(val, reg_name##13_el1);	\
78 		break;					\
79 	case 14:					\
80 		write_sysreg(val, reg_name##14_el1);	\
81 		break;					\
82 	case 15:					\
83 		write_sysreg(val, reg_name##15_el1);	\
84 		break;					\
85 	default:					\
86 		GUEST_ASSERT(0);			\
87 	}						\
88 }
89 
90 /* Define write_dbgbcr()/write_dbgbvr()/write_dbgwcr()/write_dbgwvr() */
91 GEN_DEBUG_WRITE_REG(dbgbcr)
92 GEN_DEBUG_WRITE_REG(dbgbvr)
93 GEN_DEBUG_WRITE_REG(dbgwcr)
94 GEN_DEBUG_WRITE_REG(dbgwvr)
95 
96 static void reset_debug_state(void)
97 {
98 	asm volatile("msr daifset, #8");
99 
100 	write_sysreg(0, osdlr_el1);
101 	write_sysreg(0, oslar_el1);
102 	isb();
103 
104 	write_sysreg(0, mdscr_el1);
105 	/* This test only uses the first bp and wp slot. */
106 	write_sysreg(0, dbgbvr0_el1);
107 	write_sysreg(0, dbgbcr0_el1);
108 	write_sysreg(0, dbgwcr0_el1);
109 	write_sysreg(0, dbgwvr0_el1);
110 	isb();
111 }
112 
113 static void enable_os_lock(void)
114 {
115 	write_sysreg(1, oslar_el1);
116 	isb();
117 
118 	GUEST_ASSERT(read_sysreg(oslsr_el1) & 2);
119 }
120 
121 static void install_wp(uint64_t addr)
122 {
123 	uint32_t wcr;
124 	uint32_t mdscr;
125 
126 	wcr = DBGWCR_LEN8 | DBGWCR_RD | DBGWCR_WR | DBGWCR_EL1 | DBGWCR_E;
127 	write_dbgwcr(0, wcr);
128 	write_dbgwvr(0, addr);
129 
130 	isb();
131 
132 	asm volatile("msr daifclr, #8");
133 
134 	mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_MDE;
135 	write_sysreg(mdscr, mdscr_el1);
136 	isb();
137 }
138 
139 static void install_hw_bp(uint64_t addr)
140 {
141 	uint32_t bcr;
142 	uint32_t mdscr;
143 
144 	bcr = DBGBCR_LEN8 | DBGBCR_EXEC | DBGBCR_EL1 | DBGBCR_E;
145 	write_dbgbcr(0, bcr);
146 	write_dbgbvr(0, addr);
147 	isb();
148 
149 	asm volatile("msr daifclr, #8");
150 
151 	mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_MDE;
152 	write_sysreg(mdscr, mdscr_el1);
153 	isb();
154 }
155 
156 static void install_ss(void)
157 {
158 	uint32_t mdscr;
159 
160 	asm volatile("msr daifclr, #8");
161 
162 	mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_SS;
163 	write_sysreg(mdscr, mdscr_el1);
164 	isb();
165 }
166 
167 static volatile char write_data;
168 
169 static void guest_code(void)
170 {
171 	GUEST_SYNC(0);
172 
173 	/* Software-breakpoint */
174 	reset_debug_state();
175 	asm volatile("sw_bp: brk #0");
176 	GUEST_ASSERT_EQ(sw_bp_addr, PC(sw_bp));
177 
178 	GUEST_SYNC(1);
179 
180 	/* Hardware-breakpoint */
181 	reset_debug_state();
182 	install_hw_bp(PC(hw_bp));
183 	asm volatile("hw_bp: nop");
184 	GUEST_ASSERT_EQ(hw_bp_addr, PC(hw_bp));
185 
186 	GUEST_SYNC(2);
187 
188 	/* Hardware-breakpoint + svc */
189 	reset_debug_state();
190 	install_hw_bp(PC(bp_svc));
191 	asm volatile("bp_svc: svc #0");
192 	GUEST_ASSERT_EQ(hw_bp_addr, PC(bp_svc));
193 	GUEST_ASSERT_EQ(svc_addr, PC(bp_svc) + 4);
194 
195 	GUEST_SYNC(3);
196 
197 	/* Hardware-breakpoint + software-breakpoint */
198 	reset_debug_state();
199 	install_hw_bp(PC(bp_brk));
200 	asm volatile("bp_brk: brk #0");
201 	GUEST_ASSERT_EQ(sw_bp_addr, PC(bp_brk));
202 	GUEST_ASSERT_EQ(hw_bp_addr, PC(bp_brk));
203 
204 	GUEST_SYNC(4);
205 
206 	/* Watchpoint */
207 	reset_debug_state();
208 	install_wp(PC(write_data));
209 	write_data = 'x';
210 	GUEST_ASSERT_EQ(write_data, 'x');
211 	GUEST_ASSERT_EQ(wp_data_addr, PC(write_data));
212 
213 	GUEST_SYNC(5);
214 
215 	/* Single-step */
216 	reset_debug_state();
217 	install_ss();
218 	ss_idx = 0;
219 	asm volatile("ss_start:\n"
220 		     "mrs x0, esr_el1\n"
221 		     "add x0, x0, #1\n"
222 		     "msr daifset, #8\n"
223 		     : : : "x0");
224 	GUEST_ASSERT_EQ(ss_addr[0], PC(ss_start));
225 	GUEST_ASSERT_EQ(ss_addr[1], PC(ss_start) + 4);
226 	GUEST_ASSERT_EQ(ss_addr[2], PC(ss_start) + 8);
227 
228 	GUEST_SYNC(6);
229 
230 	/* OS Lock does not block software-breakpoint */
231 	reset_debug_state();
232 	enable_os_lock();
233 	sw_bp_addr = 0;
234 	asm volatile("sw_bp2: brk #0");
235 	GUEST_ASSERT_EQ(sw_bp_addr, PC(sw_bp2));
236 
237 	GUEST_SYNC(7);
238 
239 	/* OS Lock blocking hardware-breakpoint */
240 	reset_debug_state();
241 	enable_os_lock();
242 	install_hw_bp(PC(hw_bp2));
243 	hw_bp_addr = 0;
244 	asm volatile("hw_bp2: nop");
245 	GUEST_ASSERT_EQ(hw_bp_addr, 0);
246 
247 	GUEST_SYNC(8);
248 
249 	/* OS Lock blocking watchpoint */
250 	reset_debug_state();
251 	enable_os_lock();
252 	write_data = '\0';
253 	wp_data_addr = 0;
254 	install_wp(PC(write_data));
255 	write_data = 'x';
256 	GUEST_ASSERT_EQ(write_data, 'x');
257 	GUEST_ASSERT_EQ(wp_data_addr, 0);
258 
259 	GUEST_SYNC(9);
260 
261 	/* OS Lock blocking single-step */
262 	reset_debug_state();
263 	enable_os_lock();
264 	ss_addr[0] = 0;
265 	install_ss();
266 	ss_idx = 0;
267 	asm volatile("mrs x0, esr_el1\n\t"
268 		     "add x0, x0, #1\n\t"
269 		     "msr daifset, #8\n\t"
270 		     : : : "x0");
271 	GUEST_ASSERT_EQ(ss_addr[0], 0);
272 
273 	GUEST_DONE();
274 }
275 
276 static void guest_sw_bp_handler(struct ex_regs *regs)
277 {
278 	sw_bp_addr = regs->pc;
279 	regs->pc += 4;
280 }
281 
282 static void guest_hw_bp_handler(struct ex_regs *regs)
283 {
284 	hw_bp_addr = regs->pc;
285 	regs->pstate |= SPSR_D;
286 }
287 
288 static void guest_wp_handler(struct ex_regs *regs)
289 {
290 	wp_data_addr = read_sysreg(far_el1);
291 	wp_addr = regs->pc;
292 	regs->pstate |= SPSR_D;
293 }
294 
295 static void guest_ss_handler(struct ex_regs *regs)
296 {
297 	GUEST_ASSERT_1(ss_idx < 4, ss_idx);
298 	ss_addr[ss_idx++] = regs->pc;
299 	regs->pstate |= SPSR_SS;
300 }
301 
302 static void guest_svc_handler(struct ex_regs *regs)
303 {
304 	svc_addr = regs->pc;
305 }
306 
307 enum single_step_op {
308 	SINGLE_STEP_ENABLE = 0,
309 	SINGLE_STEP_DISABLE = 1,
310 };
311 
312 static void guest_code_ss(int test_cnt)
313 {
314 	uint64_t i;
315 	uint64_t bvr, wvr, w_bvr, w_wvr;
316 
317 	for (i = 0; i < test_cnt; i++) {
318 		/* Bits [1:0] of dbg{b,w}vr are RES0 */
319 		w_bvr = i << 2;
320 		w_wvr = i << 2;
321 
322 		/* Enable Single Step execution */
323 		GUEST_SYNC(SINGLE_STEP_ENABLE);
324 
325 		/*
326 		 * The userspace will veriry that the pc is as expected during
327 		 * single step execution between iter_ss_begin and iter_ss_end.
328 		 */
329 		asm volatile("iter_ss_begin:nop\n");
330 
331 		write_sysreg(w_bvr, dbgbvr0_el1);
332 		write_sysreg(w_wvr, dbgwvr0_el1);
333 		bvr = read_sysreg(dbgbvr0_el1);
334 		wvr = read_sysreg(dbgwvr0_el1);
335 
336 		asm volatile("iter_ss_end:\n");
337 
338 		/* Disable Single Step execution */
339 		GUEST_SYNC(SINGLE_STEP_DISABLE);
340 
341 		GUEST_ASSERT(bvr == w_bvr);
342 		GUEST_ASSERT(wvr == w_wvr);
343 	}
344 	GUEST_DONE();
345 }
346 
347 static int debug_version(struct kvm_vcpu *vcpu)
348 {
349 	uint64_t id_aa64dfr0;
350 
351 	vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64DFR0_EL1), &id_aa64dfr0);
352 	return FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_DEBUGVER), id_aa64dfr0);
353 }
354 
355 static void test_guest_debug_exceptions(void)
356 {
357 	struct kvm_vcpu *vcpu;
358 	struct kvm_vm *vm;
359 	struct ucall uc;
360 	int stage;
361 
362 	vm = vm_create_with_one_vcpu(&vcpu, guest_code);
363 	ucall_init(vm, NULL);
364 
365 	vm_init_descriptor_tables(vm);
366 	vcpu_init_descriptor_tables(vcpu);
367 
368 	vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT,
369 				ESR_EC_BRK_INS, guest_sw_bp_handler);
370 	vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT,
371 				ESR_EC_HW_BP_CURRENT, guest_hw_bp_handler);
372 	vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT,
373 				ESR_EC_WP_CURRENT, guest_wp_handler);
374 	vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT,
375 				ESR_EC_SSTEP_CURRENT, guest_ss_handler);
376 	vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT,
377 				ESR_EC_SVC64, guest_svc_handler);
378 
379 	for (stage = 0; stage < 11; stage++) {
380 		vcpu_run(vcpu);
381 
382 		switch (get_ucall(vcpu, &uc)) {
383 		case UCALL_SYNC:
384 			TEST_ASSERT(uc.args[1] == stage,
385 				"Stage %d: Unexpected sync ucall, got %lx",
386 				stage, (ulong)uc.args[1]);
387 			break;
388 		case UCALL_ABORT:
389 			REPORT_GUEST_ASSERT_2(uc, "values: %#lx, %#lx");
390 			break;
391 		case UCALL_DONE:
392 			goto done;
393 		default:
394 			TEST_FAIL("Unknown ucall %lu", uc.cmd);
395 		}
396 	}
397 
398 done:
399 	kvm_vm_free(vm);
400 }
401 
402 void test_single_step_from_userspace(int test_cnt)
403 {
404 	struct kvm_vcpu *vcpu;
405 	struct kvm_vm *vm;
406 	struct ucall uc;
407 	struct kvm_run *run;
408 	uint64_t pc, cmd;
409 	uint64_t test_pc = 0;
410 	bool ss_enable = false;
411 	struct kvm_guest_debug debug = {};
412 
413 	vm = vm_create_with_one_vcpu(&vcpu, guest_code_ss);
414 	ucall_init(vm, NULL);
415 	run = vcpu->run;
416 	vcpu_args_set(vcpu, 1, test_cnt);
417 
418 	while (1) {
419 		vcpu_run(vcpu);
420 		if (run->exit_reason != KVM_EXIT_DEBUG) {
421 			cmd = get_ucall(vcpu, &uc);
422 			if (cmd == UCALL_ABORT) {
423 				REPORT_GUEST_ASSERT(uc);
424 				/* NOT REACHED */
425 			} else if (cmd == UCALL_DONE) {
426 				break;
427 			}
428 
429 			TEST_ASSERT(cmd == UCALL_SYNC,
430 				    "Unexpected ucall cmd 0x%lx", cmd);
431 
432 			if (uc.args[1] == SINGLE_STEP_ENABLE) {
433 				debug.control = KVM_GUESTDBG_ENABLE |
434 						KVM_GUESTDBG_SINGLESTEP;
435 				ss_enable = true;
436 			} else {
437 				debug.control = SINGLE_STEP_DISABLE;
438 				ss_enable = false;
439 			}
440 
441 			vcpu_guest_debug_set(vcpu, &debug);
442 			continue;
443 		}
444 
445 		TEST_ASSERT(ss_enable, "Unexpected KVM_EXIT_DEBUG");
446 
447 		/* Check if the current pc is expected. */
448 		vcpu_get_reg(vcpu, ARM64_CORE_REG(regs.pc), &pc);
449 		TEST_ASSERT(!test_pc || pc == test_pc,
450 			    "Unexpected pc 0x%lx (expected 0x%lx)",
451 			    pc, test_pc);
452 
453 		/*
454 		 * If the current pc is between iter_ss_bgin and
455 		 * iter_ss_end, the pc for the next KVM_EXIT_DEBUG should
456 		 * be the current pc + 4.
457 		 */
458 		if ((pc >= (uint64_t)&iter_ss_begin) &&
459 		    (pc < (uint64_t)&iter_ss_end))
460 			test_pc = pc + 4;
461 		else
462 			test_pc = 0;
463 	}
464 
465 	kvm_vm_free(vm);
466 }
467 
468 static void help(char *name)
469 {
470 	puts("");
471 	printf("Usage: %s [-h] [-i iterations of the single step test]\n", name);
472 	puts("");
473 	exit(0);
474 }
475 
476 int main(int argc, char *argv[])
477 {
478 	struct kvm_vcpu *vcpu;
479 	struct kvm_vm *vm;
480 	int opt;
481 	int ss_iteration = 10000;
482 
483 	vm = vm_create_with_one_vcpu(&vcpu, guest_code);
484 	__TEST_REQUIRE(debug_version(vcpu) >= 6,
485 		       "Armv8 debug architecture not supported.");
486 	kvm_vm_free(vm);
487 
488 	while ((opt = getopt(argc, argv, "i:")) != -1) {
489 		switch (opt) {
490 		case 'i':
491 			ss_iteration = atoi(optarg);
492 			break;
493 		case 'h':
494 		default:
495 			help(argv[0]);
496 			break;
497 		}
498 	}
499 
500 	test_guest_debug_exceptions();
501 	test_single_step_from_userspace(ss_iteration);
502 
503 	return 0;
504 }
505