File Index
Files and directories
Sign in
FILE

arch_timer_edge_cases.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * arch_timer_edge_cases.c - Tests the aarch64 timer IRQ functionality.
   4 *
   5 * The test validates some edge cases related to the arch-timer:
   6 * - timers above the max TVAL value.
   7 * - timers in the past
   8 * - moving counters ahead and behind pending timers.
   9 * - reprograming timers.
  10 * - timers fired multiple times.
  11 * - masking/unmasking using the timer control mask.
  12 *
  13 * Copyright (c) 2021, Google LLC.
  14 */
  15
  16#define _GNU_SOURCE
  17
  18#include <pthread.h>
  19#include <sys/sysinfo.h>
  20
  21#include "arch_timer.h"
  22#include "gic.h"
  23#include "vgic.h"
  24
  25/* Depends on counter width. */
  26static uint64_t CVAL_MAX;
  27/* tval is a signed 32-bit int. */
  28static const int32_t TVAL_MAX = INT32_MAX;
  29static const int32_t TVAL_MIN = INT32_MIN;
  30
  31/* After how much time we say there is no IRQ. */
  32static const uint32_t TIMEOUT_NO_IRQ_US = 50000;
  33
  34/* Counter value to use as the starting one for most tests. Set to CVAL_MAX/2 */
  35static uint64_t DEF_CNT;
  36
  37/* Number of runs. */
  38static const uint32_t NR_TEST_ITERS_DEF = 5;
  39
  40/* Default wait test time in ms. */
  41static const uint32_t WAIT_TEST_MS = 10;
  42
  43/* Default "long" wait test time in ms. */
  44static const uint32_t LONG_WAIT_TEST_MS = 100;
  45
  46/* Shared with IRQ handler. */
  47struct test_vcpu_shared_data {
  48	atomic_t handled;
  49	atomic_t spurious;
  50} shared_data;
  51
  52struct test_args {
  53	/* Virtual or physical timer and counter tests. */
  54	enum arch_timer timer;
  55	/* Delay used for most timer tests. */
  56	uint64_t wait_ms;
  57	/* Delay used in the test_long_timer_delays test. */
  58	uint64_t long_wait_ms;
  59	/* Number of iterations. */
  60	int iterations;
  61	/* Whether to test the physical timer. */
  62	bool test_physical;
  63	/* Whether to test the virtual timer. */
  64	bool test_virtual;
  65};
  66
  67struct test_args test_args = {
  68	.wait_ms = WAIT_TEST_MS,
  69	.long_wait_ms = LONG_WAIT_TEST_MS,
  70	.iterations = NR_TEST_ITERS_DEF,
  71	.test_physical = true,
  72	.test_virtual = true,
  73};
  74
  75static int vtimer_irq, ptimer_irq;
  76
  77enum sync_cmd {
  78	SET_COUNTER_VALUE,
  79	USERSPACE_USLEEP,
  80	USERSPACE_SCHED_YIELD,
  81	USERSPACE_MIGRATE_SELF,
  82	NO_USERSPACE_CMD,
  83};
  84
  85typedef void (*sleep_method_t)(enum arch_timer timer, uint64_t usec);
  86
  87static void sleep_poll(enum arch_timer timer, uint64_t usec);
  88static void sleep_sched_poll(enum arch_timer timer, uint64_t usec);
  89static void sleep_in_userspace(enum arch_timer timer, uint64_t usec);
  90static void sleep_migrate(enum arch_timer timer, uint64_t usec);
  91
  92sleep_method_t sleep_method[] = {
  93	sleep_poll,
  94	sleep_sched_poll,
  95	sleep_migrate,
  96	sleep_in_userspace,
  97};
  98
  99typedef void (*irq_wait_method_t)(void);
 100
 101static void wait_for_non_spurious_irq(void);
 102static void wait_poll_for_irq(void);
 103static void wait_sched_poll_for_irq(void);
 104static void wait_migrate_poll_for_irq(void);
 105
 106irq_wait_method_t irq_wait_method[] = {
 107	wait_for_non_spurious_irq,
 108	wait_poll_for_irq,
 109	wait_sched_poll_for_irq,
 110	wait_migrate_poll_for_irq,
 111};
 112
 113enum timer_view {
 114	TIMER_CVAL,
 115	TIMER_TVAL,
 116};
 117
 118static void assert_irqs_handled(uint32_t n)
 119{
 120	int h = atomic_read(&shared_data.handled);
 121
 122	__GUEST_ASSERT(h == n, "Handled %d IRQS but expected %d", h, n);
 123}
 124
 125static void userspace_cmd(uint64_t cmd)
 126{
 127	GUEST_SYNC_ARGS(cmd, 0, 0, 0, 0);
 128}
 129
 130static void userspace_migrate_vcpu(void)
 131{
 132	userspace_cmd(USERSPACE_MIGRATE_SELF);
 133}
 134
 135static void userspace_sleep(uint64_t usecs)
 136{
 137	GUEST_SYNC_ARGS(USERSPACE_USLEEP, usecs, 0, 0, 0);
 138}
 139
 140static void set_counter(enum arch_timer timer, uint64_t counter)
 141{
 142	GUEST_SYNC_ARGS(SET_COUNTER_VALUE, counter, timer, 0, 0);
 143}
 144
 145static void guest_irq_handler(struct ex_regs *regs)
 146{
 147	unsigned int intid = gic_get_and_ack_irq();
 148	enum arch_timer timer;
 149	uint64_t cnt, cval;
 150	uint32_t ctl;
 151	bool timer_condition, istatus;
 152
 153	if (intid == IAR_SPURIOUS) {
 154		atomic_inc(&shared_data.spurious);
 155		goto out;
 156	}
 157
 158	if (intid == ptimer_irq)
 159		timer = PHYSICAL;
 160	else if (intid == vtimer_irq)
 161		timer = VIRTUAL;
 162	else
 163		goto out;
 164
 165	ctl = timer_get_ctl(timer);
 166	cval = timer_get_cval(timer);
 167	cnt = timer_get_cntct(timer);
 168	timer_condition = cnt >= cval;
 169	istatus = (ctl & CTL_ISTATUS) && (ctl & CTL_ENABLE);
 170	GUEST_ASSERT_EQ(timer_condition, istatus);
 171
 172	/* Disable and mask the timer. */
 173	timer_set_ctl(timer, CTL_IMASK);
 174
 175	atomic_inc(&shared_data.handled);
 176
 177out:
 178	gic_set_eoi(intid);
 179}
 180
 181static void set_cval_irq(enum arch_timer timer, uint64_t cval_cycles,
 182			 uint32_t ctl)
 183{
 184	atomic_set(&shared_data.handled, 0);
 185	atomic_set(&shared_data.spurious, 0);
 186	timer_set_cval(timer, cval_cycles);
 187	timer_set_ctl(timer, ctl);
 188}
 189
 190static void set_tval_irq(enum arch_timer timer, uint64_t tval_cycles,
 191			 uint32_t ctl)
 192{
 193	atomic_set(&shared_data.handled, 0);
 194	atomic_set(&shared_data.spurious, 0);
 195	timer_set_tval(timer, tval_cycles);
 196	timer_set_ctl(timer, ctl);
 197}
 198
 199static void set_xval_irq(enum arch_timer timer, uint64_t xval, uint32_t ctl,
 200			 enum timer_view tv)
 201{
 202	switch (tv) {
 203	case TIMER_CVAL:
 204		set_cval_irq(timer, xval, ctl);
 205		break;
 206	case TIMER_TVAL:
 207		set_tval_irq(timer, xval, ctl);
 208		break;
 209	default:
 210		GUEST_FAIL("Could not get timer %d", timer);
 211	}
 212}
 213
 214/*
 215 * Note that this can theoretically hang forever, so we rely on having
 216 * a timeout mechanism in the "runner", like:
 217 * tools/testing/selftests/kselftest/runner.sh.
 218 */
 219static void wait_for_non_spurious_irq(void)
 220{
 221	int h;
 222
 223	local_irq_disable();
 224
 225	for (h = atomic_read(&shared_data.handled); h == atomic_read(&shared_data.handled);) {
 226		wfi();
 227		local_irq_enable();
 228		isb(); /* handle IRQ */
 229		local_irq_disable();
 230	}
 231}
 232
 233/*
 234 * Wait for an non-spurious IRQ by polling in the guest or in
 235 * userspace (e.g. userspace_cmd=USERSPACE_SCHED_YIELD).
 236 *
 237 * Note that this can theoretically hang forever, so we rely on having
 238 * a timeout mechanism in the "runner", like:
 239 * tools/testing/selftests/kselftest/runner.sh.
 240 */
 241static void poll_for_non_spurious_irq(enum sync_cmd usp_cmd)
 242{
 243	int h;
 244
 245	local_irq_disable();
 246
 247	h = atomic_read(&shared_data.handled);
 248
 249	local_irq_enable();
 250	while (h == atomic_read(&shared_data.handled)) {
 251		if (usp_cmd == NO_USERSPACE_CMD)
 252			cpu_relax();
 253		else
 254			userspace_cmd(usp_cmd);
 255	}
 256	local_irq_disable();
 257}
 258
 259static void wait_poll_for_irq(void)
 260{
 261	poll_for_non_spurious_irq(NO_USERSPACE_CMD);
 262}
 263
 264static void wait_sched_poll_for_irq(void)
 265{
 266	poll_for_non_spurious_irq(USERSPACE_SCHED_YIELD);
 267}
 268
 269static void wait_migrate_poll_for_irq(void)
 270{
 271	poll_for_non_spurious_irq(USERSPACE_MIGRATE_SELF);
 272}
 273
 274/*
 275 * Sleep for usec microseconds by polling in the guest or in
 276 * userspace (e.g. userspace_cmd=USERSPACE_SCHEDULE).
 277 */
 278static void guest_poll(enum arch_timer test_timer, uint64_t usec,
 279		       enum sync_cmd usp_cmd)
 280{
 281	uint64_t cycles = usec_to_cycles(usec);
 282	/* Whichever timer we are testing with, sleep with the other. */
 283	enum arch_timer sleep_timer = 1 - test_timer;
 284	uint64_t start = timer_get_cntct(sleep_timer);
 285
 286	while ((timer_get_cntct(sleep_timer) - start) < cycles) {
 287		if (usp_cmd == NO_USERSPACE_CMD)
 288			cpu_relax();
 289		else
 290			userspace_cmd(usp_cmd);
 291	}
 292}
 293
 294static void sleep_poll(enum arch_timer timer, uint64_t usec)
 295{
 296	guest_poll(timer, usec, NO_USERSPACE_CMD);
 297}
 298
 299static void sleep_sched_poll(enum arch_timer timer, uint64_t usec)
 300{
 301	guest_poll(timer, usec, USERSPACE_SCHED_YIELD);
 302}
 303
 304static void sleep_migrate(enum arch_timer timer, uint64_t usec)
 305{
 306	guest_poll(timer, usec, USERSPACE_MIGRATE_SELF);
 307}
 308
 309static void sleep_in_userspace(enum arch_timer timer, uint64_t usec)
 310{
 311	userspace_sleep(usec);
 312}
 313
 314/*
 315 * Reset the timer state to some nice values like the counter not being close
 316 * to the edge, and the control register masked and disabled.
 317 */
 318static void reset_timer_state(enum arch_timer timer, uint64_t cnt)
 319{
 320	set_counter(timer, cnt);
 321	timer_set_ctl(timer, CTL_IMASK);
 322}
 323
 324static void test_timer_xval(enum arch_timer timer, uint64_t xval,
 325			    enum timer_view tv, irq_wait_method_t wm, bool reset_state,
 326			    uint64_t reset_cnt)
 327{
 328	local_irq_disable();
 329
 330	if (reset_state)
 331		reset_timer_state(timer, reset_cnt);
 332
 333	set_xval_irq(timer, xval, CTL_ENABLE, tv);
 334
 335	/* This method re-enables IRQs to handle the one we're looking for. */
 336	wm();
 337
 338	assert_irqs_handled(1);
 339	local_irq_enable();
 340}
 341
 342/*
 343 * The test_timer_* functions will program the timer, wait for it, and assert
 344 * the firing of the correct IRQ.
 345 *
 346 * These functions don't have a timeout and return as soon as they receive an
 347 * IRQ. They can hang (forever), so we rely on having a timeout mechanism in
 348 * the "runner", like: tools/testing/selftests/kselftest/runner.sh.
 349 */
 350
 351static void test_timer_cval(enum arch_timer timer, uint64_t cval,
 352			    irq_wait_method_t wm, bool reset_state,
 353			    uint64_t reset_cnt)
 354{
 355	test_timer_xval(timer, cval, TIMER_CVAL, wm, reset_state, reset_cnt);
 356}
 357
 358static void test_timer_tval(enum arch_timer timer, int32_t tval,
 359			    irq_wait_method_t wm, bool reset_state,
 360			    uint64_t reset_cnt)
 361{
 362	test_timer_xval(timer, (uint64_t) tval, TIMER_TVAL, wm, reset_state,
 363			reset_cnt);
 364}
 365
 366static void test_xval_check_no_irq(enum arch_timer timer, uint64_t xval,
 367				   uint64_t usec, enum timer_view timer_view,
 368				   sleep_method_t guest_sleep)
 369{
 370	local_irq_disable();
 371
 372	set_xval_irq(timer, xval, CTL_ENABLE | CTL_IMASK, timer_view);
 373	guest_sleep(timer, usec);
 374
 375	local_irq_enable();
 376	isb();
 377
 378	/* Assume success (no IRQ) after waiting usec microseconds */
 379	assert_irqs_handled(0);
 380}
 381
 382static void test_cval_no_irq(enum arch_timer timer, uint64_t cval,
 383			     uint64_t usec, sleep_method_t wm)
 384{
 385	test_xval_check_no_irq(timer, cval, usec, TIMER_CVAL, wm);
 386}
 387
 388static void test_tval_no_irq(enum arch_timer timer, int32_t tval, uint64_t usec,
 389			     sleep_method_t wm)
 390{
 391	/* tval will be cast to an int32_t in test_xval_check_no_irq */
 392	test_xval_check_no_irq(timer, (uint64_t) tval, usec, TIMER_TVAL, wm);
 393}
 394
 395/* Test masking/unmasking a timer using the timer mask (not the IRQ mask). */
 396static void test_timer_control_mask_then_unmask(enum arch_timer timer)
 397{
 398	reset_timer_state(timer, DEF_CNT);
 399	set_tval_irq(timer, -1, CTL_ENABLE | CTL_IMASK);
 400
 401	/* Unmask the timer, and then get an IRQ. */
 402	local_irq_disable();
 403	timer_set_ctl(timer, CTL_ENABLE);
 404	/* This method re-enables IRQs to handle the one we're looking for. */
 405	wait_for_non_spurious_irq();
 406
 407	assert_irqs_handled(1);
 408	local_irq_enable();
 409}
 410
 411/* Check that timer control masks actually mask a timer being fired. */
 412static void test_timer_control_masks(enum arch_timer timer)
 413{
 414	reset_timer_state(timer, DEF_CNT);
 415
 416	/* Local IRQs are not masked at this point. */
 417
 418	set_tval_irq(timer, -1, CTL_ENABLE | CTL_IMASK);
 419
 420	/* Assume no IRQ after waiting TIMEOUT_NO_IRQ_US microseconds */
 421	sleep_poll(timer, TIMEOUT_NO_IRQ_US);
 422
 423	assert_irqs_handled(0);
 424	timer_set_ctl(timer, CTL_IMASK);
 425}
 426
 427static void test_fire_a_timer_multiple_times(enum arch_timer timer,
 428					     irq_wait_method_t wm, int num)
 429{
 430	int i;
 431
 432	local_irq_disable();
 433	reset_timer_state(timer, DEF_CNT);
 434
 435	set_tval_irq(timer, 0, CTL_ENABLE);
 436
 437	for (i = 1; i <= num; i++) {
 438		/* This method re-enables IRQs to handle the one we're looking for. */
 439		wm();
 440
 441		/* The IRQ handler masked and disabled the timer.
 442		 * Enable and unmmask it again.
 443		 */
 444		timer_set_ctl(timer, CTL_ENABLE);
 445
 446		assert_irqs_handled(i);
 447	}
 448
 449	local_irq_enable();
 450}
 451
 452static void test_timers_fired_multiple_times(enum arch_timer timer)
 453{
 454	int i;
 455
 456	for (i = 0; i < ARRAY_SIZE(irq_wait_method); i++)
 457		test_fire_a_timer_multiple_times(timer, irq_wait_method[i], 10);
 458}
 459
 460/*
 461 * Set a timer for tval=delta_1_ms then reprogram it to
 462 * tval=delta_2_ms. Check that we get the timer fired. There is no
 463 * timeout for the wait: we use the wfi instruction.
 464 */
 465static void test_reprogramming_timer(enum arch_timer timer, irq_wait_method_t wm,
 466				     int32_t delta_1_ms, int32_t delta_2_ms)
 467{
 468	local_irq_disable();
 469	reset_timer_state(timer, DEF_CNT);
 470
 471	/* Program the timer to DEF_CNT + delta_1_ms. */
 472	set_tval_irq(timer, msec_to_cycles(delta_1_ms), CTL_ENABLE);
 473
 474	/* Reprogram the timer to DEF_CNT + delta_2_ms. */
 475	timer_set_tval(timer, msec_to_cycles(delta_2_ms));
 476
 477	/* This method re-enables IRQs to handle the one we're looking for. */
 478	wm();
 479
 480	/* The IRQ should arrive at DEF_CNT + delta_2_ms (or after). */
 481	GUEST_ASSERT(timer_get_cntct(timer) >=
 482		     DEF_CNT + msec_to_cycles(delta_2_ms));
 483
 484	local_irq_enable();
 485	assert_irqs_handled(1);
 486};
 487
 488static void test_reprogram_timers(enum arch_timer timer)
 489{
 490	int i;
 491	uint64_t base_wait = test_args.wait_ms;
 492
 493	for (i = 0; i < ARRAY_SIZE(irq_wait_method); i++) {
 494		/*
 495		 * Ensure reprogramming works whether going from a
 496		 * longer time to a shorter or vice versa.
 497		 */
 498		test_reprogramming_timer(timer, irq_wait_method[i], 2 * base_wait,
 499					 base_wait);
 500		test_reprogramming_timer(timer, irq_wait_method[i], base_wait,
 501					 2 * base_wait);
 502	}
 503}
 504
 505static void test_basic_functionality(enum arch_timer timer)
 506{
 507	int32_t tval = (int32_t) msec_to_cycles(test_args.wait_ms);
 508	uint64_t cval = DEF_CNT + msec_to_cycles(test_args.wait_ms);
 509	int i;
 510
 511	for (i = 0; i < ARRAY_SIZE(irq_wait_method); i++) {
 512		irq_wait_method_t wm = irq_wait_method[i];
 513
 514		test_timer_cval(timer, cval, wm, true, DEF_CNT);
 515		test_timer_tval(timer, tval, wm, true, DEF_CNT);
 516	}
 517}
 518
 519/*
 520 * This test checks basic timer behavior without actually firing timers, things
 521 * like: the relationship between cval and tval, tval down-counting.
 522 */
 523static void timers_sanity_checks(enum arch_timer timer, bool use_sched)
 524{
 525	reset_timer_state(timer, DEF_CNT);
 526
 527	local_irq_disable();
 528
 529	/* cval in the past */
 530	timer_set_cval(timer,
 531		       timer_get_cntct(timer) -
 532		       msec_to_cycles(test_args.wait_ms));
 533	if (use_sched)
 534		userspace_migrate_vcpu();
 535	GUEST_ASSERT(timer_get_tval(timer) < 0);
 536
 537	/* tval in the past */
 538	timer_set_tval(timer, -1);
 539	if (use_sched)
 540		userspace_migrate_vcpu();
 541	GUEST_ASSERT(timer_get_cval(timer) < timer_get_cntct(timer));
 542
 543	/* tval larger than TVAL_MAX. This requires programming with
 544	 * timer_set_cval instead so the value is expressible
 545	 */
 546	timer_set_cval(timer,
 547		       timer_get_cntct(timer) + TVAL_MAX +
 548		       msec_to_cycles(test_args.wait_ms));
 549	if (use_sched)
 550		userspace_migrate_vcpu();
 551	GUEST_ASSERT(timer_get_tval(timer) <= 0);
 552
 553	/*
 554	 * tval larger than 2 * TVAL_MAX.
 555	 * Twice the TVAL_MAX completely loops around the TVAL.
 556	 */
 557	timer_set_cval(timer,
 558		       timer_get_cntct(timer) + 2ULL * TVAL_MAX +
 559		       msec_to_cycles(test_args.wait_ms));
 560	if (use_sched)
 561		userspace_migrate_vcpu();
 562	GUEST_ASSERT(timer_get_tval(timer) <=
 563		       msec_to_cycles(test_args.wait_ms));
 564
 565	/* negative tval that rollovers from 0. */
 566	set_counter(timer, msec_to_cycles(1));
 567	timer_set_tval(timer, -1 * msec_to_cycles(test_args.wait_ms));
 568	if (use_sched)
 569		userspace_migrate_vcpu();
 570	GUEST_ASSERT(timer_get_cval(timer) >= (CVAL_MAX - msec_to_cycles(test_args.wait_ms)));
 571
 572	/* tval should keep down-counting from 0 to -1. */
 573	timer_set_tval(timer, 0);
 574	sleep_poll(timer, 1);
 575	GUEST_ASSERT(timer_get_tval(timer) < 0);
 576
 577	local_irq_enable();
 578
 579	/* Mask and disable any pending timer. */
 580	timer_set_ctl(timer, CTL_IMASK);
 581}
 582
 583static void test_timers_sanity_checks(enum arch_timer timer)
 584{
 585	timers_sanity_checks(timer, false);
 586	/* Check how KVM saves/restores these edge-case values. */
 587	timers_sanity_checks(timer, true);
 588}
 589
 590static void test_set_cnt_after_tval_max(enum arch_timer timer, irq_wait_method_t wm)
 591{
 592	local_irq_disable();
 593	reset_timer_state(timer, DEF_CNT);
 594
 595	set_cval_irq(timer,
 596		     (uint64_t) TVAL_MAX +
 597		     msec_to_cycles(test_args.wait_ms) / 2, CTL_ENABLE);
 598
 599	set_counter(timer, TVAL_MAX);
 600
 601	/* This method re-enables IRQs to handle the one we're looking for. */
 602	wm();
 603
 604	assert_irqs_handled(1);
 605	local_irq_enable();
 606}
 607
 608/* Test timers set for: cval = now + TVAL_MAX + wait_ms / 2 */
 609static void test_timers_above_tval_max(enum arch_timer timer)
 610{
 611	uint64_t cval;
 612	int i;
 613
 614	/*
 615	 * Test that the system is not implementing cval in terms of
 616	 * tval.  If that was the case, setting a cval to "cval = now
 617	 * + TVAL_MAX + wait_ms" would wrap to "cval = now +
 618	 * wait_ms", and the timer would fire immediately. Test that it
 619	 * doesn't.
 620	 */
 621	for (i = 0; i < ARRAY_SIZE(sleep_method); i++) {
 622		reset_timer_state(timer, DEF_CNT);
 623		cval = timer_get_cntct(timer) + TVAL_MAX +
 624			msec_to_cycles(test_args.wait_ms);
 625		test_cval_no_irq(timer, cval,
 626				 msecs_to_usecs(test_args.wait_ms) +
 627				 TIMEOUT_NO_IRQ_US, sleep_method[i]);
 628	}
 629
 630	for (i = 0; i < ARRAY_SIZE(irq_wait_method); i++) {
 631		/* Get the IRQ by moving the counter forward. */
 632		test_set_cnt_after_tval_max(timer, irq_wait_method[i]);
 633	}
 634}
 635
 636/*
 637 * Template function to be used by the test_move_counter_ahead_* tests.  It
 638 * sets the counter to cnt_1, the [c|t]val, the counter to cnt_2, and
 639 * then waits for an IRQ.
 640 */
 641static void test_set_cnt_after_xval(enum arch_timer timer, uint64_t cnt_1,
 642				    uint64_t xval, uint64_t cnt_2,
 643				    irq_wait_method_t wm, enum timer_view tv)
 644{
 645	local_irq_disable();
 646
 647	set_counter(timer, cnt_1);
 648	timer_set_ctl(timer, CTL_IMASK);
 649
 650	set_xval_irq(timer, xval, CTL_ENABLE, tv);
 651	set_counter(timer, cnt_2);
 652	/* This method re-enables IRQs to handle the one we're looking for. */
 653	wm();
 654
 655	assert_irqs_handled(1);
 656	local_irq_enable();
 657}
 658
 659/*
 660 * Template function to be used by the test_move_counter_ahead_* tests.  It
 661 * sets the counter to cnt_1, the [c|t]val, the counter to cnt_2, and
 662 * then waits for an IRQ.
 663 */
 664static void test_set_cnt_after_xval_no_irq(enum arch_timer timer,
 665					   uint64_t cnt_1, uint64_t xval,
 666					   uint64_t cnt_2,
 667					   sleep_method_t guest_sleep,
 668					   enum timer_view tv)
 669{
 670	local_irq_disable();
 671
 672	set_counter(timer, cnt_1);
 673	timer_set_ctl(timer, CTL_IMASK);
 674
 675	set_xval_irq(timer, xval, CTL_ENABLE, tv);
 676	set_counter(timer, cnt_2);
 677	guest_sleep(timer, TIMEOUT_NO_IRQ_US);
 678
 679	local_irq_enable();
 680	isb();
 681
 682	/* Assume no IRQ after waiting TIMEOUT_NO_IRQ_US microseconds */
 683	assert_irqs_handled(0);
 684	timer_set_ctl(timer, CTL_IMASK);
 685}
 686
 687static void test_set_cnt_after_tval(enum arch_timer timer, uint64_t cnt_1,
 688				    int32_t tval, uint64_t cnt_2,
 689				    irq_wait_method_t wm)
 690{
 691	test_set_cnt_after_xval(timer, cnt_1, tval, cnt_2, wm, TIMER_TVAL);
 692}
 693
 694static void test_set_cnt_after_cval(enum arch_timer timer, uint64_t cnt_1,
 695				    uint64_t cval, uint64_t cnt_2,
 696				    irq_wait_method_t wm)
 697{
 698	test_set_cnt_after_xval(timer, cnt_1, cval, cnt_2, wm, TIMER_CVAL);
 699}
 700
 701static void test_set_cnt_after_tval_no_irq(enum arch_timer timer,
 702					   uint64_t cnt_1, int32_t tval,
 703					   uint64_t cnt_2, sleep_method_t wm)
 704{
 705	test_set_cnt_after_xval_no_irq(timer, cnt_1, tval, cnt_2, wm,
 706				       TIMER_TVAL);
 707}
 708
 709static void test_set_cnt_after_cval_no_irq(enum arch_timer timer,
 710					   uint64_t cnt_1, uint64_t cval,
 711					   uint64_t cnt_2, sleep_method_t wm)
 712{
 713	test_set_cnt_after_xval_no_irq(timer, cnt_1, cval, cnt_2, wm,
 714				       TIMER_CVAL);
 715}
 716
 717/* Set a timer and then move the counter ahead of it. */
 718static void test_move_counters_ahead_of_timers(enum arch_timer timer)
 719{
 720	int i;
 721	int32_t tval;
 722
 723	for (i = 0; i < ARRAY_SIZE(irq_wait_method); i++) {
 724		irq_wait_method_t wm = irq_wait_method[i];
 725
 726		test_set_cnt_after_cval(timer, 0, DEF_CNT, DEF_CNT + 1, wm);
 727		test_set_cnt_after_cval(timer, CVAL_MAX, 1, 2, wm);
 728
 729		/* Move counter ahead of negative tval. */
 730		test_set_cnt_after_tval(timer, 0, -1, DEF_CNT + 1, wm);
 731		test_set_cnt_after_tval(timer, 0, -1, TVAL_MAX, wm);
 732		tval = TVAL_MAX;
 733		test_set_cnt_after_tval(timer, 0, tval, (uint64_t) tval + 1,
 734					wm);
 735	}
 736}
 737
 738/*
 739 * Program a timer, mask it, and then change the tval or counter to cancel it.
 740 * Unmask it and check that nothing fires.
 741 */
 742static void test_move_counters_behind_timers(enum arch_timer timer)
 743{
 744	int i;
 745
 746	for (i = 0; i < ARRAY_SIZE(sleep_method); i++) {
 747		sleep_method_t sm = sleep_method[i];
 748
 749		test_set_cnt_after_cval_no_irq(timer, DEF_CNT, DEF_CNT - 1, 0,
 750					       sm);
 751		test_set_cnt_after_tval_no_irq(timer, DEF_CNT, -1, 0, sm);
 752	}
 753}
 754
 755static void test_timers_in_the_past(enum arch_timer timer)
 756{
 757	int32_t tval = -1 * (int32_t) msec_to_cycles(test_args.wait_ms);
 758	uint64_t cval;
 759	int i;
 760
 761	for (i = 0; i < ARRAY_SIZE(irq_wait_method); i++) {
 762		irq_wait_method_t wm = irq_wait_method[i];
 763
 764		/* set a timer wait_ms the past. */
 765		cval = DEF_CNT - msec_to_cycles(test_args.wait_ms);
 766		test_timer_cval(timer, cval, wm, true, DEF_CNT);
 767		test_timer_tval(timer, tval, wm, true, DEF_CNT);
 768
 769		/* Set a timer to counter=0 (in the past) */
 770		test_timer_cval(timer, 0, wm, true, DEF_CNT);
 771
 772		/* Set a time for tval=0 (now) */
 773		test_timer_tval(timer, 0, wm, true, DEF_CNT);
 774
 775		/* Set a timer to as far in the past as possible */
 776		test_timer_tval(timer, TVAL_MIN, wm, true, DEF_CNT);
 777	}
 778
 779	/*
 780	 * Set the counter to wait_ms, and a tval to -wait_ms. There should be no
 781	 * IRQ as that tval means cval=CVAL_MAX-wait_ms.
 782	 */
 783	for (i = 0; i < ARRAY_SIZE(sleep_method); i++) {
 784		sleep_method_t sm = sleep_method[i];
 785
 786		set_counter(timer, msec_to_cycles(test_args.wait_ms));
 787		test_tval_no_irq(timer, tval, TIMEOUT_NO_IRQ_US, sm);
 788	}
 789}
 790
 791static void test_long_timer_delays(enum arch_timer timer)
 792{
 793	int32_t tval = (int32_t) msec_to_cycles(test_args.long_wait_ms);
 794	uint64_t cval = DEF_CNT + msec_to_cycles(test_args.long_wait_ms);
 795	int i;
 796
 797	for (i = 0; i < ARRAY_SIZE(irq_wait_method); i++) {
 798		irq_wait_method_t wm = irq_wait_method[i];
 799
 800		test_timer_cval(timer, cval, wm, true, DEF_CNT);
 801		test_timer_tval(timer, tval, wm, true, DEF_CNT);
 802	}
 803}
 804
 805static void guest_run_iteration(enum arch_timer timer)
 806{
 807	test_basic_functionality(timer);
 808	test_timers_sanity_checks(timer);
 809
 810	test_timers_above_tval_max(timer);
 811	test_timers_in_the_past(timer);
 812
 813	test_move_counters_ahead_of_timers(timer);
 814	test_move_counters_behind_timers(timer);
 815	test_reprogram_timers(timer);
 816
 817	test_timers_fired_multiple_times(timer);
 818
 819	test_timer_control_mask_then_unmask(timer);
 820	test_timer_control_masks(timer);
 821}
 822
 823static void guest_code(enum arch_timer timer)
 824{
 825	int i;
 826
 827	local_irq_disable();
 828
 829	gic_init(GIC_V3, 1);
 830
 831	timer_set_ctl(VIRTUAL, CTL_IMASK);
 832	timer_set_ctl(PHYSICAL, CTL_IMASK);
 833
 834	gic_irq_enable(vtimer_irq);
 835	gic_irq_enable(ptimer_irq);
 836	local_irq_enable();
 837
 838	for (i = 0; i < test_args.iterations; i++) {
 839		GUEST_SYNC(i);
 840		guest_run_iteration(timer);
 841	}
 842
 843	test_long_timer_delays(timer);
 844	GUEST_DONE();
 845}
 846
 847static cpu_set_t default_cpuset;
 848
 849static uint32_t next_pcpu(void)
 850{
 851	uint32_t max = get_nprocs();
 852	uint32_t cur = sched_getcpu();
 853	uint32_t next = cur;
 854	cpu_set_t cpuset = default_cpuset;
 855
 856	TEST_ASSERT(max > 1, "Need at least two physical cpus");
 857
 858	do {
 859		next = (next + 1) % CPU_SETSIZE;
 860	} while (!CPU_ISSET(next, &cpuset));
 861
 862	return next;
 863}
 864
 865static void kvm_set_cntxct(struct kvm_vcpu *vcpu, uint64_t cnt,
 866			   enum arch_timer timer)
 867{
 868	if (timer == PHYSICAL)
 869		vcpu_set_reg(vcpu, KVM_REG_ARM_PTIMER_CNT, cnt);
 870	else
 871		vcpu_set_reg(vcpu, KVM_REG_ARM_TIMER_CNT, cnt);
 872}
 873
 874static void handle_sync(struct kvm_vcpu *vcpu, struct ucall *uc)
 875{
 876	enum sync_cmd cmd = uc->args[1];
 877	uint64_t val = uc->args[2];
 878	enum arch_timer timer = uc->args[3];
 879
 880	switch (cmd) {
 881	case SET_COUNTER_VALUE:
 882		kvm_set_cntxct(vcpu, val, timer);
 883		break;
 884	case USERSPACE_USLEEP:
 885		usleep(val);
 886		break;
 887	case USERSPACE_SCHED_YIELD:
 888		sched_yield();
 889		break;
 890	case USERSPACE_MIGRATE_SELF:
 891		pin_self_to_cpu(next_pcpu());
 892		break;
 893	default:
 894		break;
 895	}
 896}
 897
 898static void test_run(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
 899{
 900	struct ucall uc;
 901
 902	/* Start on CPU 0 */
 903	pin_self_to_cpu(0);
 904
 905	while (true) {
 906		vcpu_run(vcpu);
 907		switch (get_ucall(vcpu, &uc)) {
 908		case UCALL_SYNC:
 909			handle_sync(vcpu, &uc);
 910			break;
 911		case UCALL_DONE:
 912			goto out;
 913		case UCALL_ABORT:
 914			REPORT_GUEST_ASSERT(uc);
 915			goto out;
 916		default:
 917			TEST_FAIL("Unexpected guest exit\n");
 918		}
 919	}
 920
 921 out:
 922	return;
 923}
 924
 925static void test_init_timer_irq(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
 926{
 927	ptimer_irq = vcpu_get_ptimer_irq(vcpu);
 928	vtimer_irq = vcpu_get_vtimer_irq(vcpu);
 929
 930	sync_global_to_guest(vm, ptimer_irq);
 931	sync_global_to_guest(vm, vtimer_irq);
 932
 933	pr_debug("ptimer_irq: %d; vtimer_irq: %d\n", ptimer_irq, vtimer_irq);
 934}
 935
 936static void test_vm_create(struct kvm_vm **vm, struct kvm_vcpu **vcpu,
 937			   enum arch_timer timer)
 938{
 939	*vm = vm_create_with_one_vcpu(vcpu, guest_code);
 940	TEST_ASSERT(*vm, "Failed to create the test VM\n");
 941
 942	vm_init_descriptor_tables(*vm);
 943	vm_install_exception_handler(*vm, VECTOR_IRQ_CURRENT,
 944				     guest_irq_handler);
 945
 946	vcpu_init_descriptor_tables(*vcpu);
 947	vcpu_args_set(*vcpu, 1, timer);
 948
 949	test_init_timer_irq(*vm, *vcpu);
 950
 951	sync_global_to_guest(*vm, test_args);
 952	sync_global_to_guest(*vm, CVAL_MAX);
 953	sync_global_to_guest(*vm, DEF_CNT);
 954}
 955
 956static void test_vm_cleanup(struct kvm_vm *vm)
 957{
 958	kvm_vm_free(vm);
 959}
 960
 961static void test_print_help(char *name)
 962{
 963	pr_info("Usage: %s [-h] [-b] [-i iterations] [-l long_wait_ms] [-p] [-v]\n"
 964		, name);
 965	pr_info("\t-i: Number of iterations (default: %u)\n",
 966		NR_TEST_ITERS_DEF);
 967	pr_info("\t-b: Test both physical and virtual timers (default: true)\n");
 968	pr_info("\t-l: Delta (in ms) used for long wait time test (default: %u)\n",
 969	     LONG_WAIT_TEST_MS);
 970	pr_info("\t-w: Delta (in ms) used for wait times (default: %u)\n",
 971		WAIT_TEST_MS);
 972	pr_info("\t-p: Test physical timer (default: true)\n");
 973	pr_info("\t-v: Test virtual timer (default: true)\n");
 974	pr_info("\t-h: Print this help message\n");
 975}
 976
 977static bool parse_args(int argc, char *argv[])
 978{
 979	int opt;
 980
 981	while ((opt = getopt(argc, argv, "bhi:l:pvw:")) != -1) {
 982		switch (opt) {
 983		case 'b':
 984			test_args.test_physical = true;
 985			test_args.test_virtual = true;
 986			break;
 987		case 'i':
 988			test_args.iterations =
 989			    atoi_positive("Number of iterations", optarg);
 990			break;
 991		case 'l':
 992			test_args.long_wait_ms =
 993			    atoi_positive("Long wait time", optarg);
 994			break;
 995		case 'p':
 996			test_args.test_physical = true;
 997			test_args.test_virtual = false;
 998			break;
 999		case 'v':
1000			test_args.test_virtual = true;
1001			test_args.test_physical = false;
1002			break;
1003		case 'w':
1004			test_args.wait_ms = atoi_positive("Wait time", optarg);
1005			break;
1006		case 'h':
1007		default:
1008			goto err;
1009		}
1010	}
1011
1012	return true;
1013
1014 err:
1015	test_print_help(argv[0]);
1016	return false;
1017}
1018
1019static void set_counter_defaults(void)
1020{
1021	const uint64_t MIN_ROLLOVER_SECS = 40ULL * 365 * 24 * 3600;
1022	uint64_t freq = read_sysreg(CNTFRQ_EL0);
1023	int width = ilog2(MIN_ROLLOVER_SECS * freq);
1024
1025	width = clamp(width, 56, 64);
1026	CVAL_MAX = GENMASK_ULL(width - 1, 0);
1027	DEF_CNT = CVAL_MAX / 2;
1028}
1029
1030int main(int argc, char *argv[])
1031{
1032	struct kvm_vcpu *vcpu;
1033	struct kvm_vm *vm;
1034
1035	/* Tell stdout not to buffer its content */
1036	setbuf(stdout, NULL);
1037
1038	TEST_REQUIRE(kvm_supports_vgic_v3());
1039
1040	if (!parse_args(argc, argv))
1041		exit(KSFT_SKIP);
1042
1043	sched_getaffinity(0, sizeof(default_cpuset), &default_cpuset);
1044	set_counter_defaults();
1045
1046	if (test_args.test_virtual) {
1047		test_vm_create(&vm, &vcpu, VIRTUAL);
1048		test_run(vm, vcpu);
1049		test_vm_cleanup(vm);
1050	}
1051
1052	if (test_args.test_physical) {
1053		test_vm_create(&vm, &vcpu, PHYSICAL);
1054		test_run(vm, vcpu);
1055		test_vm_cleanup(vm);
1056	}
1057
1058	return 0;
1059}
~/ Read-only file preview.