167730e6cSSean Christopherson // SPDX-License-Identifier: GPL-2.0-only
267730e6cSSean Christopherson /*
367730e6cSSean Christopherson * arch_timer_edge_cases.c - Tests the aarch64 timer IRQ functionality.
467730e6cSSean Christopherson *
567730e6cSSean Christopherson * The test validates some edge cases related to the arch-timer:
667730e6cSSean Christopherson * - timers above the max TVAL value.
767730e6cSSean Christopherson * - timers in the past
867730e6cSSean Christopherson * - moving counters ahead and behind pending timers.
967730e6cSSean Christopherson * - reprograming timers.
1067730e6cSSean Christopherson * - timers fired multiple times.
1167730e6cSSean Christopherson * - masking/unmasking using the timer control mask.
1267730e6cSSean Christopherson *
1367730e6cSSean Christopherson * Copyright (c) 2021, Google LLC.
1467730e6cSSean Christopherson */
1567730e6cSSean Christopherson
1667730e6cSSean Christopherson #define _GNU_SOURCE
1767730e6cSSean Christopherson
1867730e6cSSean Christopherson #include <pthread.h>
1967730e6cSSean Christopherson #include <sys/sysinfo.h>
2067730e6cSSean Christopherson
2167730e6cSSean Christopherson #include "arch_timer.h"
2267730e6cSSean Christopherson #include "gic.h"
2367730e6cSSean Christopherson #include "vgic.h"
2467730e6cSSean Christopherson
25fad4cf94SSebastian Ott /* Depends on counter width. */
26fad4cf94SSebastian Ott static uint64_t CVAL_MAX;
2767730e6cSSean Christopherson /* tval is a signed 32-bit int. */
2867730e6cSSean Christopherson static const int32_t TVAL_MAX = INT32_MAX;
2967730e6cSSean Christopherson static const int32_t TVAL_MIN = INT32_MIN;
3067730e6cSSean Christopherson
3167730e6cSSean Christopherson /* After how much time we say there is no IRQ. */
3267730e6cSSean Christopherson static const uint32_t TIMEOUT_NO_IRQ_US = 50000;
3367730e6cSSean Christopherson
34fad4cf94SSebastian Ott /* Counter value to use as the starting one for most tests. Set to CVAL_MAX/2 */
35fad4cf94SSebastian Ott static uint64_t DEF_CNT;
3667730e6cSSean Christopherson
3767730e6cSSean Christopherson /* Number of runs. */
3867730e6cSSean Christopherson static const uint32_t NR_TEST_ITERS_DEF = 5;
3967730e6cSSean Christopherson
4067730e6cSSean Christopherson /* Default wait test time in ms. */
4167730e6cSSean Christopherson static const uint32_t WAIT_TEST_MS = 10;
4267730e6cSSean Christopherson
4367730e6cSSean Christopherson /* Default "long" wait test time in ms. */
4467730e6cSSean Christopherson static const uint32_t LONG_WAIT_TEST_MS = 100;
4567730e6cSSean Christopherson
4667730e6cSSean Christopherson /* Shared with IRQ handler. */
4767730e6cSSean Christopherson struct test_vcpu_shared_data {
4867730e6cSSean Christopherson atomic_t handled;
4967730e6cSSean Christopherson atomic_t spurious;
5067730e6cSSean Christopherson } shared_data;
5167730e6cSSean Christopherson
5267730e6cSSean Christopherson struct test_args {
5367730e6cSSean Christopherson /* Virtual or physical timer and counter tests. */
5467730e6cSSean Christopherson enum arch_timer timer;
5567730e6cSSean Christopherson /* Delay used for most timer tests. */
5667730e6cSSean Christopherson uint64_t wait_ms;
5767730e6cSSean Christopherson /* Delay used in the test_long_timer_delays test. */
5867730e6cSSean Christopherson uint64_t long_wait_ms;
5967730e6cSSean Christopherson /* Number of iterations. */
6067730e6cSSean Christopherson int iterations;
6167730e6cSSean Christopherson /* Whether to test the physical timer. */
6267730e6cSSean Christopherson bool test_physical;
6367730e6cSSean Christopherson /* Whether to test the virtual timer. */
6467730e6cSSean Christopherson bool test_virtual;
6567730e6cSSean Christopherson };
6667730e6cSSean Christopherson
6767730e6cSSean Christopherson struct test_args test_args = {
6867730e6cSSean Christopherson .wait_ms = WAIT_TEST_MS,
6967730e6cSSean Christopherson .long_wait_ms = LONG_WAIT_TEST_MS,
7067730e6cSSean Christopherson .iterations = NR_TEST_ITERS_DEF,
7167730e6cSSean Christopherson .test_physical = true,
7267730e6cSSean Christopherson .test_virtual = true,
7367730e6cSSean Christopherson };
7467730e6cSSean Christopherson
7567730e6cSSean Christopherson static int vtimer_irq, ptimer_irq;
7667730e6cSSean Christopherson
7767730e6cSSean Christopherson enum sync_cmd {
7867730e6cSSean Christopherson SET_COUNTER_VALUE,
7967730e6cSSean Christopherson USERSPACE_USLEEP,
8067730e6cSSean Christopherson USERSPACE_SCHED_YIELD,
8167730e6cSSean Christopherson USERSPACE_MIGRATE_SELF,
8267730e6cSSean Christopherson NO_USERSPACE_CMD,
8367730e6cSSean Christopherson };
8467730e6cSSean Christopherson
8567730e6cSSean Christopherson typedef void (*sleep_method_t)(enum arch_timer timer, uint64_t usec);
8667730e6cSSean Christopherson
8767730e6cSSean Christopherson static void sleep_poll(enum arch_timer timer, uint64_t usec);
8867730e6cSSean Christopherson static void sleep_sched_poll(enum arch_timer timer, uint64_t usec);
8967730e6cSSean Christopherson static void sleep_in_userspace(enum arch_timer timer, uint64_t usec);
9067730e6cSSean Christopherson static void sleep_migrate(enum arch_timer timer, uint64_t usec);
9167730e6cSSean Christopherson
9267730e6cSSean Christopherson sleep_method_t sleep_method[] = {
9367730e6cSSean Christopherson sleep_poll,
9467730e6cSSean Christopherson sleep_sched_poll,
9567730e6cSSean Christopherson sleep_migrate,
9667730e6cSSean Christopherson sleep_in_userspace,
9767730e6cSSean Christopherson };
9867730e6cSSean Christopherson
9967730e6cSSean Christopherson typedef void (*irq_wait_method_t)(void);
10067730e6cSSean Christopherson
10167730e6cSSean Christopherson static void wait_for_non_spurious_irq(void);
10267730e6cSSean Christopherson static void wait_poll_for_irq(void);
10367730e6cSSean Christopherson static void wait_sched_poll_for_irq(void);
10467730e6cSSean Christopherson static void wait_migrate_poll_for_irq(void);
10567730e6cSSean Christopherson
10667730e6cSSean Christopherson irq_wait_method_t irq_wait_method[] = {
10767730e6cSSean Christopherson wait_for_non_spurious_irq,
10867730e6cSSean Christopherson wait_poll_for_irq,
10967730e6cSSean Christopherson wait_sched_poll_for_irq,
11067730e6cSSean Christopherson wait_migrate_poll_for_irq,
11167730e6cSSean Christopherson };
11267730e6cSSean Christopherson
11367730e6cSSean Christopherson enum timer_view {
11467730e6cSSean Christopherson TIMER_CVAL,
11567730e6cSSean Christopherson TIMER_TVAL,
11667730e6cSSean Christopherson };
11767730e6cSSean Christopherson
assert_irqs_handled(uint32_t n)11867730e6cSSean Christopherson static void assert_irqs_handled(uint32_t n)
11967730e6cSSean Christopherson {
12067730e6cSSean Christopherson int h = atomic_read(&shared_data.handled);
12167730e6cSSean Christopherson
12267730e6cSSean Christopherson __GUEST_ASSERT(h == n, "Handled %d IRQS but expected %d", h, n);
12367730e6cSSean Christopherson }
12467730e6cSSean Christopherson
userspace_cmd(uint64_t cmd)12567730e6cSSean Christopherson static void userspace_cmd(uint64_t cmd)
12667730e6cSSean Christopherson {
12767730e6cSSean Christopherson GUEST_SYNC_ARGS(cmd, 0, 0, 0, 0);
12867730e6cSSean Christopherson }
12967730e6cSSean Christopherson
userspace_migrate_vcpu(void)13067730e6cSSean Christopherson static void userspace_migrate_vcpu(void)
13167730e6cSSean Christopherson {
13267730e6cSSean Christopherson userspace_cmd(USERSPACE_MIGRATE_SELF);
13367730e6cSSean Christopherson }
13467730e6cSSean Christopherson
userspace_sleep(uint64_t usecs)13567730e6cSSean Christopherson static void userspace_sleep(uint64_t usecs)
13667730e6cSSean Christopherson {
13767730e6cSSean Christopherson GUEST_SYNC_ARGS(USERSPACE_USLEEP, usecs, 0, 0, 0);
13867730e6cSSean Christopherson }
13967730e6cSSean Christopherson
set_counter(enum arch_timer timer,uint64_t counter)14067730e6cSSean Christopherson static void set_counter(enum arch_timer timer, uint64_t counter)
14167730e6cSSean Christopherson {
14267730e6cSSean Christopherson GUEST_SYNC_ARGS(SET_COUNTER_VALUE, counter, timer, 0, 0);
14367730e6cSSean Christopherson }
14467730e6cSSean Christopherson
guest_irq_handler(struct ex_regs * regs)14567730e6cSSean Christopherson static void guest_irq_handler(struct ex_regs *regs)
14667730e6cSSean Christopherson {
14767730e6cSSean Christopherson unsigned int intid = gic_get_and_ack_irq();
14867730e6cSSean Christopherson enum arch_timer timer;
14967730e6cSSean Christopherson uint64_t cnt, cval;
15067730e6cSSean Christopherson uint32_t ctl;
15167730e6cSSean Christopherson bool timer_condition, istatus;
15267730e6cSSean Christopherson
15367730e6cSSean Christopherson if (intid == IAR_SPURIOUS) {
15467730e6cSSean Christopherson atomic_inc(&shared_data.spurious);
15567730e6cSSean Christopherson goto out;
15667730e6cSSean Christopherson }
15767730e6cSSean Christopherson
15867730e6cSSean Christopherson if (intid == ptimer_irq)
15967730e6cSSean Christopherson timer = PHYSICAL;
16067730e6cSSean Christopherson else if (intid == vtimer_irq)
16167730e6cSSean Christopherson timer = VIRTUAL;
16267730e6cSSean Christopherson else
16367730e6cSSean Christopherson goto out;
16467730e6cSSean Christopherson
16567730e6cSSean Christopherson ctl = timer_get_ctl(timer);
16667730e6cSSean Christopherson cval = timer_get_cval(timer);
16767730e6cSSean Christopherson cnt = timer_get_cntct(timer);
16867730e6cSSean Christopherson timer_condition = cnt >= cval;
16967730e6cSSean Christopherson istatus = (ctl & CTL_ISTATUS) && (ctl & CTL_ENABLE);
17067730e6cSSean Christopherson GUEST_ASSERT_EQ(timer_condition, istatus);
17167730e6cSSean Christopherson
17267730e6cSSean Christopherson /* Disable and mask the timer. */
17367730e6cSSean Christopherson timer_set_ctl(timer, CTL_IMASK);
17467730e6cSSean Christopherson
17567730e6cSSean Christopherson atomic_inc(&shared_data.handled);
17667730e6cSSean Christopherson
17767730e6cSSean Christopherson out:
17867730e6cSSean Christopherson gic_set_eoi(intid);
17967730e6cSSean Christopherson }
18067730e6cSSean Christopherson
set_cval_irq(enum arch_timer timer,uint64_t cval_cycles,uint32_t ctl)18167730e6cSSean Christopherson static void set_cval_irq(enum arch_timer timer, uint64_t cval_cycles,
18267730e6cSSean Christopherson uint32_t ctl)
18367730e6cSSean Christopherson {
18467730e6cSSean Christopherson atomic_set(&shared_data.handled, 0);
18567730e6cSSean Christopherson atomic_set(&shared_data.spurious, 0);
18667730e6cSSean Christopherson timer_set_cval(timer, cval_cycles);
18767730e6cSSean Christopherson timer_set_ctl(timer, ctl);
18867730e6cSSean Christopherson }
18967730e6cSSean Christopherson
set_tval_irq(enum arch_timer timer,uint64_t tval_cycles,uint32_t ctl)19067730e6cSSean Christopherson static void set_tval_irq(enum arch_timer timer, uint64_t tval_cycles,
19167730e6cSSean Christopherson uint32_t ctl)
19267730e6cSSean Christopherson {
19367730e6cSSean Christopherson atomic_set(&shared_data.handled, 0);
19467730e6cSSean Christopherson atomic_set(&shared_data.spurious, 0);
19567730e6cSSean Christopherson timer_set_tval(timer, tval_cycles);
19605ce38d4SSebastian Ott timer_set_ctl(timer, ctl);
19767730e6cSSean Christopherson }
19867730e6cSSean Christopherson
set_xval_irq(enum arch_timer timer,uint64_t xval,uint32_t ctl,enum timer_view tv)19967730e6cSSean Christopherson static void set_xval_irq(enum arch_timer timer, uint64_t xval, uint32_t ctl,
20067730e6cSSean Christopherson enum timer_view tv)
20167730e6cSSean Christopherson {
20267730e6cSSean Christopherson switch (tv) {
20367730e6cSSean Christopherson case TIMER_CVAL:
20467730e6cSSean Christopherson set_cval_irq(timer, xval, ctl);
20567730e6cSSean Christopherson break;
20667730e6cSSean Christopherson case TIMER_TVAL:
20767730e6cSSean Christopherson set_tval_irq(timer, xval, ctl);
20867730e6cSSean Christopherson break;
20967730e6cSSean Christopherson default:
21067730e6cSSean Christopherson GUEST_FAIL("Could not get timer %d", timer);
21167730e6cSSean Christopherson }
21267730e6cSSean Christopherson }
21367730e6cSSean Christopherson
21467730e6cSSean Christopherson /*
21567730e6cSSean Christopherson * Note that this can theoretically hang forever, so we rely on having
21667730e6cSSean Christopherson * a timeout mechanism in the "runner", like:
21767730e6cSSean Christopherson * tools/testing/selftests/kselftest/runner.sh.
21867730e6cSSean Christopherson */
wait_for_non_spurious_irq(void)21967730e6cSSean Christopherson static void wait_for_non_spurious_irq(void)
22067730e6cSSean Christopherson {
22167730e6cSSean Christopherson int h;
22267730e6cSSean Christopherson
22367730e6cSSean Christopherson local_irq_disable();
22467730e6cSSean Christopherson
22567730e6cSSean Christopherson for (h = atomic_read(&shared_data.handled); h == atomic_read(&shared_data.handled);) {
22667730e6cSSean Christopherson wfi();
22767730e6cSSean Christopherson local_irq_enable();
22867730e6cSSean Christopherson isb(); /* handle IRQ */
22967730e6cSSean Christopherson local_irq_disable();
23067730e6cSSean Christopherson }
23167730e6cSSean Christopherson }
23267730e6cSSean Christopherson
23367730e6cSSean Christopherson /*
23467730e6cSSean Christopherson * Wait for an non-spurious IRQ by polling in the guest or in
23567730e6cSSean Christopherson * userspace (e.g. userspace_cmd=USERSPACE_SCHED_YIELD).
23667730e6cSSean Christopherson *
23767730e6cSSean Christopherson * Note that this can theoretically hang forever, so we rely on having
23867730e6cSSean Christopherson * a timeout mechanism in the "runner", like:
23967730e6cSSean Christopherson * tools/testing/selftests/kselftest/runner.sh.
24067730e6cSSean Christopherson */
poll_for_non_spurious_irq(enum sync_cmd usp_cmd)24167730e6cSSean Christopherson static void poll_for_non_spurious_irq(enum sync_cmd usp_cmd)
24267730e6cSSean Christopherson {
24367730e6cSSean Christopherson int h;
24467730e6cSSean Christopherson
24567730e6cSSean Christopherson local_irq_disable();
24667730e6cSSean Christopherson
24767730e6cSSean Christopherson h = atomic_read(&shared_data.handled);
24867730e6cSSean Christopherson
24967730e6cSSean Christopherson local_irq_enable();
25067730e6cSSean Christopherson while (h == atomic_read(&shared_data.handled)) {
25167730e6cSSean Christopherson if (usp_cmd == NO_USERSPACE_CMD)
25267730e6cSSean Christopherson cpu_relax();
25367730e6cSSean Christopherson else
25467730e6cSSean Christopherson userspace_cmd(usp_cmd);
25567730e6cSSean Christopherson }
25667730e6cSSean Christopherson local_irq_disable();
25767730e6cSSean Christopherson }
25867730e6cSSean Christopherson
wait_poll_for_irq(void)25967730e6cSSean Christopherson static void wait_poll_for_irq(void)
26067730e6cSSean Christopherson {
26167730e6cSSean Christopherson poll_for_non_spurious_irq(NO_USERSPACE_CMD);
26267730e6cSSean Christopherson }
26367730e6cSSean Christopherson
wait_sched_poll_for_irq(void)26467730e6cSSean Christopherson static void wait_sched_poll_for_irq(void)
26567730e6cSSean Christopherson {
26667730e6cSSean Christopherson poll_for_non_spurious_irq(USERSPACE_SCHED_YIELD);
26767730e6cSSean Christopherson }
26867730e6cSSean Christopherson
wait_migrate_poll_for_irq(void)26967730e6cSSean Christopherson static void wait_migrate_poll_for_irq(void)
27067730e6cSSean Christopherson {
27167730e6cSSean Christopherson poll_for_non_spurious_irq(USERSPACE_MIGRATE_SELF);
27267730e6cSSean Christopherson }
27367730e6cSSean Christopherson
27467730e6cSSean Christopherson /*
27567730e6cSSean Christopherson * Sleep for usec microseconds by polling in the guest or in
27667730e6cSSean Christopherson * userspace (e.g. userspace_cmd=USERSPACE_SCHEDULE).
27767730e6cSSean Christopherson */
guest_poll(enum arch_timer test_timer,uint64_t usec,enum sync_cmd usp_cmd)27867730e6cSSean Christopherson static void guest_poll(enum arch_timer test_timer, uint64_t usec,
27967730e6cSSean Christopherson enum sync_cmd usp_cmd)
28067730e6cSSean Christopherson {
28167730e6cSSean Christopherson uint64_t cycles = usec_to_cycles(usec);
28267730e6cSSean Christopherson /* Whichever timer we are testing with, sleep with the other. */
28367730e6cSSean Christopherson enum arch_timer sleep_timer = 1 - test_timer;
28467730e6cSSean Christopherson uint64_t start = timer_get_cntct(sleep_timer);
28567730e6cSSean Christopherson
28667730e6cSSean Christopherson while ((timer_get_cntct(sleep_timer) - start) < cycles) {
28767730e6cSSean Christopherson if (usp_cmd == NO_USERSPACE_CMD)
28867730e6cSSean Christopherson cpu_relax();
28967730e6cSSean Christopherson else
29067730e6cSSean Christopherson userspace_cmd(usp_cmd);
29167730e6cSSean Christopherson }
29267730e6cSSean Christopherson }
29367730e6cSSean Christopherson
sleep_poll(enum arch_timer timer,uint64_t usec)29467730e6cSSean Christopherson static void sleep_poll(enum arch_timer timer, uint64_t usec)
29567730e6cSSean Christopherson {
29667730e6cSSean Christopherson guest_poll(timer, usec, NO_USERSPACE_CMD);
29767730e6cSSean Christopherson }
29867730e6cSSean Christopherson
sleep_sched_poll(enum arch_timer timer,uint64_t usec)29967730e6cSSean Christopherson static void sleep_sched_poll(enum arch_timer timer, uint64_t usec)
30067730e6cSSean Christopherson {
30167730e6cSSean Christopherson guest_poll(timer, usec, USERSPACE_SCHED_YIELD);
30267730e6cSSean Christopherson }
30367730e6cSSean Christopherson
sleep_migrate(enum arch_timer timer,uint64_t usec)30467730e6cSSean Christopherson static void sleep_migrate(enum arch_timer timer, uint64_t usec)
30567730e6cSSean Christopherson {
30667730e6cSSean Christopherson guest_poll(timer, usec, USERSPACE_MIGRATE_SELF);
30767730e6cSSean Christopherson }
30867730e6cSSean Christopherson
sleep_in_userspace(enum arch_timer timer,uint64_t usec)30967730e6cSSean Christopherson static void sleep_in_userspace(enum arch_timer timer, uint64_t usec)
31067730e6cSSean Christopherson {
31167730e6cSSean Christopherson userspace_sleep(usec);
31267730e6cSSean Christopherson }
31367730e6cSSean Christopherson
31467730e6cSSean Christopherson /*
31567730e6cSSean Christopherson * Reset the timer state to some nice values like the counter not being close
31667730e6cSSean Christopherson * to the edge, and the control register masked and disabled.
31767730e6cSSean Christopherson */
reset_timer_state(enum arch_timer timer,uint64_t cnt)31867730e6cSSean Christopherson static void reset_timer_state(enum arch_timer timer, uint64_t cnt)
31967730e6cSSean Christopherson {
32067730e6cSSean Christopherson set_counter(timer, cnt);
32167730e6cSSean Christopherson timer_set_ctl(timer, CTL_IMASK);
32267730e6cSSean Christopherson }
32367730e6cSSean Christopherson
test_timer_xval(enum arch_timer timer,uint64_t xval,enum timer_view tv,irq_wait_method_t wm,bool reset_state,uint64_t reset_cnt)32467730e6cSSean Christopherson static void test_timer_xval(enum arch_timer timer, uint64_t xval,
32567730e6cSSean Christopherson enum timer_view tv, irq_wait_method_t wm, bool reset_state,
32667730e6cSSean Christopherson uint64_t reset_cnt)
32767730e6cSSean Christopherson {
32867730e6cSSean Christopherson local_irq_disable();
32967730e6cSSean Christopherson
33067730e6cSSean Christopherson if (reset_state)
33167730e6cSSean Christopherson reset_timer_state(timer, reset_cnt);
33267730e6cSSean Christopherson
33367730e6cSSean Christopherson set_xval_irq(timer, xval, CTL_ENABLE, tv);
33467730e6cSSean Christopherson
33567730e6cSSean Christopherson /* This method re-enables IRQs to handle the one we're looking for. */
33667730e6cSSean Christopherson wm();
33767730e6cSSean Christopherson
33867730e6cSSean Christopherson assert_irqs_handled(1);
33967730e6cSSean Christopherson local_irq_enable();
34067730e6cSSean Christopherson }
34167730e6cSSean Christopherson
34267730e6cSSean Christopherson /*
34367730e6cSSean Christopherson * The test_timer_* functions will program the timer, wait for it, and assert
34467730e6cSSean Christopherson * the firing of the correct IRQ.
34567730e6cSSean Christopherson *
34667730e6cSSean Christopherson * These functions don't have a timeout and return as soon as they receive an
34767730e6cSSean Christopherson * IRQ. They can hang (forever), so we rely on having a timeout mechanism in
34867730e6cSSean Christopherson * the "runner", like: tools/testing/selftests/kselftest/runner.sh.
34967730e6cSSean Christopherson */
35067730e6cSSean Christopherson
test_timer_cval(enum arch_timer timer,uint64_t cval,irq_wait_method_t wm,bool reset_state,uint64_t reset_cnt)35167730e6cSSean Christopherson static void test_timer_cval(enum arch_timer timer, uint64_t cval,
35267730e6cSSean Christopherson irq_wait_method_t wm, bool reset_state,
35367730e6cSSean Christopherson uint64_t reset_cnt)
35467730e6cSSean Christopherson {
35567730e6cSSean Christopherson test_timer_xval(timer, cval, TIMER_CVAL, wm, reset_state, reset_cnt);
35667730e6cSSean Christopherson }
35767730e6cSSean Christopherson
test_timer_tval(enum arch_timer timer,int32_t tval,irq_wait_method_t wm,bool reset_state,uint64_t reset_cnt)35867730e6cSSean Christopherson static void test_timer_tval(enum arch_timer timer, int32_t tval,
35967730e6cSSean Christopherson irq_wait_method_t wm, bool reset_state,
36067730e6cSSean Christopherson uint64_t reset_cnt)
36167730e6cSSean Christopherson {
36267730e6cSSean Christopherson test_timer_xval(timer, (uint64_t) tval, TIMER_TVAL, wm, reset_state,
36367730e6cSSean Christopherson reset_cnt);
36467730e6cSSean Christopherson }
36567730e6cSSean Christopherson
test_xval_check_no_irq(enum arch_timer timer,uint64_t xval,uint64_t usec,enum timer_view timer_view,sleep_method_t guest_sleep)36667730e6cSSean Christopherson static void test_xval_check_no_irq(enum arch_timer timer, uint64_t xval,
36767730e6cSSean Christopherson uint64_t usec, enum timer_view timer_view,
36867730e6cSSean Christopherson sleep_method_t guest_sleep)
36967730e6cSSean Christopherson {
37067730e6cSSean Christopherson local_irq_disable();
37167730e6cSSean Christopherson
37267730e6cSSean Christopherson set_xval_irq(timer, xval, CTL_ENABLE | CTL_IMASK, timer_view);
37367730e6cSSean Christopherson guest_sleep(timer, usec);
37467730e6cSSean Christopherson
37567730e6cSSean Christopherson local_irq_enable();
37667730e6cSSean Christopherson isb();
37767730e6cSSean Christopherson
37867730e6cSSean Christopherson /* Assume success (no IRQ) after waiting usec microseconds */
37967730e6cSSean Christopherson assert_irqs_handled(0);
38067730e6cSSean Christopherson }
38167730e6cSSean Christopherson
test_cval_no_irq(enum arch_timer timer,uint64_t cval,uint64_t usec,sleep_method_t wm)38267730e6cSSean Christopherson static void test_cval_no_irq(enum arch_timer timer, uint64_t cval,
38367730e6cSSean Christopherson uint64_t usec, sleep_method_t wm)
38467730e6cSSean Christopherson {
38567730e6cSSean Christopherson test_xval_check_no_irq(timer, cval, usec, TIMER_CVAL, wm);
38667730e6cSSean Christopherson }
38767730e6cSSean Christopherson
test_tval_no_irq(enum arch_timer timer,int32_t tval,uint64_t usec,sleep_method_t wm)38867730e6cSSean Christopherson static void test_tval_no_irq(enum arch_timer timer, int32_t tval, uint64_t usec,
38967730e6cSSean Christopherson sleep_method_t wm)
39067730e6cSSean Christopherson {
39167730e6cSSean Christopherson /* tval will be cast to an int32_t in test_xval_check_no_irq */
39267730e6cSSean Christopherson test_xval_check_no_irq(timer, (uint64_t) tval, usec, TIMER_TVAL, wm);
39367730e6cSSean Christopherson }
39467730e6cSSean Christopherson
39567730e6cSSean Christopherson /* Test masking/unmasking a timer using the timer mask (not the IRQ mask). */
test_timer_control_mask_then_unmask(enum arch_timer timer)39667730e6cSSean Christopherson static void test_timer_control_mask_then_unmask(enum arch_timer timer)
39767730e6cSSean Christopherson {
39867730e6cSSean Christopherson reset_timer_state(timer, DEF_CNT);
39967730e6cSSean Christopherson set_tval_irq(timer, -1, CTL_ENABLE | CTL_IMASK);
40067730e6cSSean Christopherson
40167730e6cSSean Christopherson /* Unmask the timer, and then get an IRQ. */
40267730e6cSSean Christopherson local_irq_disable();
40367730e6cSSean Christopherson timer_set_ctl(timer, CTL_ENABLE);
40467730e6cSSean Christopherson /* This method re-enables IRQs to handle the one we're looking for. */
40567730e6cSSean Christopherson wait_for_non_spurious_irq();
40667730e6cSSean Christopherson
40767730e6cSSean Christopherson assert_irqs_handled(1);
40867730e6cSSean Christopherson local_irq_enable();
40967730e6cSSean Christopherson }
41067730e6cSSean Christopherson
41167730e6cSSean Christopherson /* Check that timer control masks actually mask a timer being fired. */
test_timer_control_masks(enum arch_timer timer)41267730e6cSSean Christopherson static void test_timer_control_masks(enum arch_timer timer)
41367730e6cSSean Christopherson {
41467730e6cSSean Christopherson reset_timer_state(timer, DEF_CNT);
41567730e6cSSean Christopherson
41667730e6cSSean Christopherson /* Local IRQs are not masked at this point. */
41767730e6cSSean Christopherson
41867730e6cSSean Christopherson set_tval_irq(timer, -1, CTL_ENABLE | CTL_IMASK);
41967730e6cSSean Christopherson
42067730e6cSSean Christopherson /* Assume no IRQ after waiting TIMEOUT_NO_IRQ_US microseconds */
42167730e6cSSean Christopherson sleep_poll(timer, TIMEOUT_NO_IRQ_US);
42267730e6cSSean Christopherson
42367730e6cSSean Christopherson assert_irqs_handled(0);
42467730e6cSSean Christopherson timer_set_ctl(timer, CTL_IMASK);
42567730e6cSSean Christopherson }
42667730e6cSSean Christopherson
test_fire_a_timer_multiple_times(enum arch_timer timer,irq_wait_method_t wm,int num)42767730e6cSSean Christopherson static void test_fire_a_timer_multiple_times(enum arch_timer timer,
42867730e6cSSean Christopherson irq_wait_method_t wm, int num)
42967730e6cSSean Christopherson {
43067730e6cSSean Christopherson int i;
43167730e6cSSean Christopherson
43267730e6cSSean Christopherson local_irq_disable();
43367730e6cSSean Christopherson reset_timer_state(timer, DEF_CNT);
43467730e6cSSean Christopherson
43567730e6cSSean Christopherson set_tval_irq(timer, 0, CTL_ENABLE);
43667730e6cSSean Christopherson
43767730e6cSSean Christopherson for (i = 1; i <= num; i++) {
43867730e6cSSean Christopherson /* This method re-enables IRQs to handle the one we're looking for. */
43967730e6cSSean Christopherson wm();
44067730e6cSSean Christopherson
44167730e6cSSean Christopherson /* The IRQ handler masked and disabled the timer.
44267730e6cSSean Christopherson * Enable and unmmask it again.
44367730e6cSSean Christopherson */
44467730e6cSSean Christopherson timer_set_ctl(timer, CTL_ENABLE);
44567730e6cSSean Christopherson
44667730e6cSSean Christopherson assert_irqs_handled(i);
44767730e6cSSean Christopherson }
44867730e6cSSean Christopherson
44967730e6cSSean Christopherson local_irq_enable();
45067730e6cSSean Christopherson }
45167730e6cSSean Christopherson
test_timers_fired_multiple_times(enum arch_timer timer)45267730e6cSSean Christopherson static void test_timers_fired_multiple_times(enum arch_timer timer)
45367730e6cSSean Christopherson {
45467730e6cSSean Christopherson int i;
45567730e6cSSean Christopherson
45667730e6cSSean Christopherson for (i = 0; i < ARRAY_SIZE(irq_wait_method); i++)
45767730e6cSSean Christopherson test_fire_a_timer_multiple_times(timer, irq_wait_method[i], 10);
45867730e6cSSean Christopherson }
45967730e6cSSean Christopherson
46067730e6cSSean Christopherson /*
46167730e6cSSean Christopherson * Set a timer for tval=delta_1_ms then reprogram it to
46267730e6cSSean Christopherson * tval=delta_2_ms. Check that we get the timer fired. There is no
46367730e6cSSean Christopherson * timeout for the wait: we use the wfi instruction.
46467730e6cSSean Christopherson */
test_reprogramming_timer(enum arch_timer timer,irq_wait_method_t wm,int32_t delta_1_ms,int32_t delta_2_ms)46567730e6cSSean Christopherson static void test_reprogramming_timer(enum arch_timer timer, irq_wait_method_t wm,
46667730e6cSSean Christopherson int32_t delta_1_ms, int32_t delta_2_ms)
46767730e6cSSean Christopherson {
46867730e6cSSean Christopherson local_irq_disable();
46967730e6cSSean Christopherson reset_timer_state(timer, DEF_CNT);
47067730e6cSSean Christopherson
47167730e6cSSean Christopherson /* Program the timer to DEF_CNT + delta_1_ms. */
47267730e6cSSean Christopherson set_tval_irq(timer, msec_to_cycles(delta_1_ms), CTL_ENABLE);
47367730e6cSSean Christopherson
47467730e6cSSean Christopherson /* Reprogram the timer to DEF_CNT + delta_2_ms. */
47567730e6cSSean Christopherson timer_set_tval(timer, msec_to_cycles(delta_2_ms));
47667730e6cSSean Christopherson
47767730e6cSSean Christopherson /* This method re-enables IRQs to handle the one we're looking for. */
47867730e6cSSean Christopherson wm();
47967730e6cSSean Christopherson
48067730e6cSSean Christopherson /* The IRQ should arrive at DEF_CNT + delta_2_ms (or after). */
48167730e6cSSean Christopherson GUEST_ASSERT(timer_get_cntct(timer) >=
48267730e6cSSean Christopherson DEF_CNT + msec_to_cycles(delta_2_ms));
48367730e6cSSean Christopherson
48467730e6cSSean Christopherson local_irq_enable();
48567730e6cSSean Christopherson assert_irqs_handled(1);
48667730e6cSSean Christopherson };
48767730e6cSSean Christopherson
test_reprogram_timers(enum arch_timer timer)48867730e6cSSean Christopherson static void test_reprogram_timers(enum arch_timer timer)
48967730e6cSSean Christopherson {
49067730e6cSSean Christopherson int i;
49167730e6cSSean Christopherson uint64_t base_wait = test_args.wait_ms;
49267730e6cSSean Christopherson
49367730e6cSSean Christopherson for (i = 0; i < ARRAY_SIZE(irq_wait_method); i++) {
49467730e6cSSean Christopherson /*
49567730e6cSSean Christopherson * Ensure reprogramming works whether going from a
49667730e6cSSean Christopherson * longer time to a shorter or vice versa.
49767730e6cSSean Christopherson */
49867730e6cSSean Christopherson test_reprogramming_timer(timer, irq_wait_method[i], 2 * base_wait,
49967730e6cSSean Christopherson base_wait);
50067730e6cSSean Christopherson test_reprogramming_timer(timer, irq_wait_method[i], base_wait,
50167730e6cSSean Christopherson 2 * base_wait);
50267730e6cSSean Christopherson }
50367730e6cSSean Christopherson }
50467730e6cSSean Christopherson
test_basic_functionality(enum arch_timer timer)50567730e6cSSean Christopherson static void test_basic_functionality(enum arch_timer timer)
50667730e6cSSean Christopherson {
50767730e6cSSean Christopherson int32_t tval = (int32_t) msec_to_cycles(test_args.wait_ms);
50867730e6cSSean Christopherson uint64_t cval = DEF_CNT + msec_to_cycles(test_args.wait_ms);
50967730e6cSSean Christopherson int i;
51067730e6cSSean Christopherson
51167730e6cSSean Christopherson for (i = 0; i < ARRAY_SIZE(irq_wait_method); i++) {
51267730e6cSSean Christopherson irq_wait_method_t wm = irq_wait_method[i];
51367730e6cSSean Christopherson
51467730e6cSSean Christopherson test_timer_cval(timer, cval, wm, true, DEF_CNT);
51567730e6cSSean Christopherson test_timer_tval(timer, tval, wm, true, DEF_CNT);
51667730e6cSSean Christopherson }
51767730e6cSSean Christopherson }
51867730e6cSSean Christopherson
51967730e6cSSean Christopherson /*
52067730e6cSSean Christopherson * This test checks basic timer behavior without actually firing timers, things
52167730e6cSSean Christopherson * like: the relationship between cval and tval, tval down-counting.
52267730e6cSSean Christopherson */
timers_sanity_checks(enum arch_timer timer,bool use_sched)52367730e6cSSean Christopherson static void timers_sanity_checks(enum arch_timer timer, bool use_sched)
52467730e6cSSean Christopherson {
52567730e6cSSean Christopherson reset_timer_state(timer, DEF_CNT);
52667730e6cSSean Christopherson
52767730e6cSSean Christopherson local_irq_disable();
52867730e6cSSean Christopherson
52967730e6cSSean Christopherson /* cval in the past */
53067730e6cSSean Christopherson timer_set_cval(timer,
53167730e6cSSean Christopherson timer_get_cntct(timer) -
53267730e6cSSean Christopherson msec_to_cycles(test_args.wait_ms));
53367730e6cSSean Christopherson if (use_sched)
53467730e6cSSean Christopherson userspace_migrate_vcpu();
53567730e6cSSean Christopherson GUEST_ASSERT(timer_get_tval(timer) < 0);
53667730e6cSSean Christopherson
53767730e6cSSean Christopherson /* tval in the past */
53867730e6cSSean Christopherson timer_set_tval(timer, -1);
53967730e6cSSean Christopherson if (use_sched)
54067730e6cSSean Christopherson userspace_migrate_vcpu();
54167730e6cSSean Christopherson GUEST_ASSERT(timer_get_cval(timer) < timer_get_cntct(timer));
54267730e6cSSean Christopherson
54367730e6cSSean Christopherson /* tval larger than TVAL_MAX. This requires programming with
54467730e6cSSean Christopherson * timer_set_cval instead so the value is expressible
54567730e6cSSean Christopherson */
54667730e6cSSean Christopherson timer_set_cval(timer,
54767730e6cSSean Christopherson timer_get_cntct(timer) + TVAL_MAX +
54867730e6cSSean Christopherson msec_to_cycles(test_args.wait_ms));
54967730e6cSSean Christopherson if (use_sched)
55067730e6cSSean Christopherson userspace_migrate_vcpu();
55167730e6cSSean Christopherson GUEST_ASSERT(timer_get_tval(timer) <= 0);
55267730e6cSSean Christopherson
55367730e6cSSean Christopherson /*
55467730e6cSSean Christopherson * tval larger than 2 * TVAL_MAX.
55567730e6cSSean Christopherson * Twice the TVAL_MAX completely loops around the TVAL.
55667730e6cSSean Christopherson */
55767730e6cSSean Christopherson timer_set_cval(timer,
55867730e6cSSean Christopherson timer_get_cntct(timer) + 2ULL * TVAL_MAX +
55967730e6cSSean Christopherson msec_to_cycles(test_args.wait_ms));
56067730e6cSSean Christopherson if (use_sched)
56167730e6cSSean Christopherson userspace_migrate_vcpu();
56267730e6cSSean Christopherson GUEST_ASSERT(timer_get_tval(timer) <=
56367730e6cSSean Christopherson msec_to_cycles(test_args.wait_ms));
56467730e6cSSean Christopherson
56567730e6cSSean Christopherson /* negative tval that rollovers from 0. */
56667730e6cSSean Christopherson set_counter(timer, msec_to_cycles(1));
56767730e6cSSean Christopherson timer_set_tval(timer, -1 * msec_to_cycles(test_args.wait_ms));
56867730e6cSSean Christopherson if (use_sched)
56967730e6cSSean Christopherson userspace_migrate_vcpu();
57067730e6cSSean Christopherson GUEST_ASSERT(timer_get_cval(timer) >= (CVAL_MAX - msec_to_cycles(test_args.wait_ms)));
57167730e6cSSean Christopherson
57267730e6cSSean Christopherson /* tval should keep down-counting from 0 to -1. */
57367730e6cSSean Christopherson timer_set_tval(timer, 0);
57467730e6cSSean Christopherson sleep_poll(timer, 1);
57567730e6cSSean Christopherson GUEST_ASSERT(timer_get_tval(timer) < 0);
57667730e6cSSean Christopherson
57767730e6cSSean Christopherson local_irq_enable();
57867730e6cSSean Christopherson
57967730e6cSSean Christopherson /* Mask and disable any pending timer. */
58067730e6cSSean Christopherson timer_set_ctl(timer, CTL_IMASK);
58167730e6cSSean Christopherson }
58267730e6cSSean Christopherson
test_timers_sanity_checks(enum arch_timer timer)58367730e6cSSean Christopherson static void test_timers_sanity_checks(enum arch_timer timer)
58467730e6cSSean Christopherson {
58567730e6cSSean Christopherson timers_sanity_checks(timer, false);
58667730e6cSSean Christopherson /* Check how KVM saves/restores these edge-case values. */
58767730e6cSSean Christopherson timers_sanity_checks(timer, true);
58867730e6cSSean Christopherson }
58967730e6cSSean Christopherson
test_set_cnt_after_tval_max(enum arch_timer timer,irq_wait_method_t wm)59067730e6cSSean Christopherson static void test_set_cnt_after_tval_max(enum arch_timer timer, irq_wait_method_t wm)
59167730e6cSSean Christopherson {
59267730e6cSSean Christopherson local_irq_disable();
59367730e6cSSean Christopherson reset_timer_state(timer, DEF_CNT);
59467730e6cSSean Christopherson
59567730e6cSSean Christopherson set_cval_irq(timer,
59667730e6cSSean Christopherson (uint64_t) TVAL_MAX +
59767730e6cSSean Christopherson msec_to_cycles(test_args.wait_ms) / 2, CTL_ENABLE);
59867730e6cSSean Christopherson
59967730e6cSSean Christopherson set_counter(timer, TVAL_MAX);
60067730e6cSSean Christopherson
60167730e6cSSean Christopherson /* This method re-enables IRQs to handle the one we're looking for. */
60267730e6cSSean Christopherson wm();
60367730e6cSSean Christopherson
60467730e6cSSean Christopherson assert_irqs_handled(1);
60567730e6cSSean Christopherson local_irq_enable();
60667730e6cSSean Christopherson }
60767730e6cSSean Christopherson
60867730e6cSSean Christopherson /* Test timers set for: cval = now + TVAL_MAX + wait_ms / 2 */
test_timers_above_tval_max(enum arch_timer timer)60967730e6cSSean Christopherson static void test_timers_above_tval_max(enum arch_timer timer)
61067730e6cSSean Christopherson {
61167730e6cSSean Christopherson uint64_t cval;
61267730e6cSSean Christopherson int i;
61367730e6cSSean Christopherson
61467730e6cSSean Christopherson /*
61567730e6cSSean Christopherson * Test that the system is not implementing cval in terms of
61667730e6cSSean Christopherson * tval. If that was the case, setting a cval to "cval = now
61767730e6cSSean Christopherson * + TVAL_MAX + wait_ms" would wrap to "cval = now +
61867730e6cSSean Christopherson * wait_ms", and the timer would fire immediately. Test that it
61967730e6cSSean Christopherson * doesn't.
62067730e6cSSean Christopherson */
62167730e6cSSean Christopherson for (i = 0; i < ARRAY_SIZE(sleep_method); i++) {
62267730e6cSSean Christopherson reset_timer_state(timer, DEF_CNT);
62367730e6cSSean Christopherson cval = timer_get_cntct(timer) + TVAL_MAX +
62467730e6cSSean Christopherson msec_to_cycles(test_args.wait_ms);
62567730e6cSSean Christopherson test_cval_no_irq(timer, cval,
62667730e6cSSean Christopherson msecs_to_usecs(test_args.wait_ms) +
62767730e6cSSean Christopherson TIMEOUT_NO_IRQ_US, sleep_method[i]);
62867730e6cSSean Christopherson }
62967730e6cSSean Christopherson
63067730e6cSSean Christopherson for (i = 0; i < ARRAY_SIZE(irq_wait_method); i++) {
63167730e6cSSean Christopherson /* Get the IRQ by moving the counter forward. */
63267730e6cSSean Christopherson test_set_cnt_after_tval_max(timer, irq_wait_method[i]);
63367730e6cSSean Christopherson }
63467730e6cSSean Christopherson }
63567730e6cSSean Christopherson
63667730e6cSSean Christopherson /*
63767730e6cSSean Christopherson * Template function to be used by the test_move_counter_ahead_* tests. It
63867730e6cSSean Christopherson * sets the counter to cnt_1, the [c|t]val, the counter to cnt_2, and
63967730e6cSSean Christopherson * then waits for an IRQ.
64067730e6cSSean Christopherson */
test_set_cnt_after_xval(enum arch_timer timer,uint64_t cnt_1,uint64_t xval,uint64_t cnt_2,irq_wait_method_t wm,enum timer_view tv)64167730e6cSSean Christopherson static void test_set_cnt_after_xval(enum arch_timer timer, uint64_t cnt_1,
64267730e6cSSean Christopherson uint64_t xval, uint64_t cnt_2,
64367730e6cSSean Christopherson irq_wait_method_t wm, enum timer_view tv)
64467730e6cSSean Christopherson {
64567730e6cSSean Christopherson local_irq_disable();
64667730e6cSSean Christopherson
64767730e6cSSean Christopherson set_counter(timer, cnt_1);
64867730e6cSSean Christopherson timer_set_ctl(timer, CTL_IMASK);
64967730e6cSSean Christopherson
65067730e6cSSean Christopherson set_xval_irq(timer, xval, CTL_ENABLE, tv);
65167730e6cSSean Christopherson set_counter(timer, cnt_2);
65267730e6cSSean Christopherson /* This method re-enables IRQs to handle the one we're looking for. */
65367730e6cSSean Christopherson wm();
65467730e6cSSean Christopherson
65567730e6cSSean Christopherson assert_irqs_handled(1);
65667730e6cSSean Christopherson local_irq_enable();
65767730e6cSSean Christopherson }
65867730e6cSSean Christopherson
65967730e6cSSean Christopherson /*
66067730e6cSSean Christopherson * Template function to be used by the test_move_counter_ahead_* tests. It
66167730e6cSSean Christopherson * sets the counter to cnt_1, the [c|t]val, the counter to cnt_2, and
66267730e6cSSean Christopherson * then waits for an IRQ.
66367730e6cSSean Christopherson */
test_set_cnt_after_xval_no_irq(enum arch_timer timer,uint64_t cnt_1,uint64_t xval,uint64_t cnt_2,sleep_method_t guest_sleep,enum timer_view tv)66467730e6cSSean Christopherson static void test_set_cnt_after_xval_no_irq(enum arch_timer timer,
66567730e6cSSean Christopherson uint64_t cnt_1, uint64_t xval,
66667730e6cSSean Christopherson uint64_t cnt_2,
66767730e6cSSean Christopherson sleep_method_t guest_sleep,
66867730e6cSSean Christopherson enum timer_view tv)
66967730e6cSSean Christopherson {
67067730e6cSSean Christopherson local_irq_disable();
67167730e6cSSean Christopherson
67267730e6cSSean Christopherson set_counter(timer, cnt_1);
67367730e6cSSean Christopherson timer_set_ctl(timer, CTL_IMASK);
67467730e6cSSean Christopherson
67567730e6cSSean Christopherson set_xval_irq(timer, xval, CTL_ENABLE, tv);
67667730e6cSSean Christopherson set_counter(timer, cnt_2);
67767730e6cSSean Christopherson guest_sleep(timer, TIMEOUT_NO_IRQ_US);
67867730e6cSSean Christopherson
67967730e6cSSean Christopherson local_irq_enable();
68067730e6cSSean Christopherson isb();
68167730e6cSSean Christopherson
68267730e6cSSean Christopherson /* Assume no IRQ after waiting TIMEOUT_NO_IRQ_US microseconds */
68367730e6cSSean Christopherson assert_irqs_handled(0);
68467730e6cSSean Christopherson timer_set_ctl(timer, CTL_IMASK);
68567730e6cSSean Christopherson }
68667730e6cSSean Christopherson
test_set_cnt_after_tval(enum arch_timer timer,uint64_t cnt_1,int32_t tval,uint64_t cnt_2,irq_wait_method_t wm)68767730e6cSSean Christopherson static void test_set_cnt_after_tval(enum arch_timer timer, uint64_t cnt_1,
68867730e6cSSean Christopherson int32_t tval, uint64_t cnt_2,
68967730e6cSSean Christopherson irq_wait_method_t wm)
69067730e6cSSean Christopherson {
69167730e6cSSean Christopherson test_set_cnt_after_xval(timer, cnt_1, tval, cnt_2, wm, TIMER_TVAL);
69267730e6cSSean Christopherson }
69367730e6cSSean Christopherson
test_set_cnt_after_cval(enum arch_timer timer,uint64_t cnt_1,uint64_t cval,uint64_t cnt_2,irq_wait_method_t wm)69467730e6cSSean Christopherson static void test_set_cnt_after_cval(enum arch_timer timer, uint64_t cnt_1,
69567730e6cSSean Christopherson uint64_t cval, uint64_t cnt_2,
69667730e6cSSean Christopherson irq_wait_method_t wm)
69767730e6cSSean Christopherson {
69867730e6cSSean Christopherson test_set_cnt_after_xval(timer, cnt_1, cval, cnt_2, wm, TIMER_CVAL);
69967730e6cSSean Christopherson }
70067730e6cSSean Christopherson
test_set_cnt_after_tval_no_irq(enum arch_timer timer,uint64_t cnt_1,int32_t tval,uint64_t cnt_2,sleep_method_t wm)70167730e6cSSean Christopherson static void test_set_cnt_after_tval_no_irq(enum arch_timer timer,
70267730e6cSSean Christopherson uint64_t cnt_1, int32_t tval,
70367730e6cSSean Christopherson uint64_t cnt_2, sleep_method_t wm)
70467730e6cSSean Christopherson {
70567730e6cSSean Christopherson test_set_cnt_after_xval_no_irq(timer, cnt_1, tval, cnt_2, wm,
70667730e6cSSean Christopherson TIMER_TVAL);
70767730e6cSSean Christopherson }
70867730e6cSSean Christopherson
test_set_cnt_after_cval_no_irq(enum arch_timer timer,uint64_t cnt_1,uint64_t cval,uint64_t cnt_2,sleep_method_t wm)70967730e6cSSean Christopherson static void test_set_cnt_after_cval_no_irq(enum arch_timer timer,
71067730e6cSSean Christopherson uint64_t cnt_1, uint64_t cval,
71167730e6cSSean Christopherson uint64_t cnt_2, sleep_method_t wm)
71267730e6cSSean Christopherson {
71367730e6cSSean Christopherson test_set_cnt_after_xval_no_irq(timer, cnt_1, cval, cnt_2, wm,
71467730e6cSSean Christopherson TIMER_CVAL);
71567730e6cSSean Christopherson }
71667730e6cSSean Christopherson
71767730e6cSSean Christopherson /* Set a timer and then move the counter ahead of it. */
test_move_counters_ahead_of_timers(enum arch_timer timer)71867730e6cSSean Christopherson static void test_move_counters_ahead_of_timers(enum arch_timer timer)
71967730e6cSSean Christopherson {
72067730e6cSSean Christopherson int i;
72167730e6cSSean Christopherson int32_t tval;
72267730e6cSSean Christopherson
72367730e6cSSean Christopherson for (i = 0; i < ARRAY_SIZE(irq_wait_method); i++) {
72467730e6cSSean Christopherson irq_wait_method_t wm = irq_wait_method[i];
72567730e6cSSean Christopherson
72667730e6cSSean Christopherson test_set_cnt_after_cval(timer, 0, DEF_CNT, DEF_CNT + 1, wm);
72767730e6cSSean Christopherson test_set_cnt_after_cval(timer, CVAL_MAX, 1, 2, wm);
72867730e6cSSean Christopherson
72967730e6cSSean Christopherson /* Move counter ahead of negative tval. */
73067730e6cSSean Christopherson test_set_cnt_after_tval(timer, 0, -1, DEF_CNT + 1, wm);
73167730e6cSSean Christopherson test_set_cnt_after_tval(timer, 0, -1, TVAL_MAX, wm);
73267730e6cSSean Christopherson tval = TVAL_MAX;
73367730e6cSSean Christopherson test_set_cnt_after_tval(timer, 0, tval, (uint64_t) tval + 1,
73467730e6cSSean Christopherson wm);
73567730e6cSSean Christopherson }
73667730e6cSSean Christopherson }
73767730e6cSSean Christopherson
73867730e6cSSean Christopherson /*
73967730e6cSSean Christopherson * Program a timer, mask it, and then change the tval or counter to cancel it.
74067730e6cSSean Christopherson * Unmask it and check that nothing fires.
74167730e6cSSean Christopherson */
test_move_counters_behind_timers(enum arch_timer timer)74267730e6cSSean Christopherson static void test_move_counters_behind_timers(enum arch_timer timer)
74367730e6cSSean Christopherson {
74467730e6cSSean Christopherson int i;
74567730e6cSSean Christopherson
74667730e6cSSean Christopherson for (i = 0; i < ARRAY_SIZE(sleep_method); i++) {
74767730e6cSSean Christopherson sleep_method_t sm = sleep_method[i];
74867730e6cSSean Christopherson
74967730e6cSSean Christopherson test_set_cnt_after_cval_no_irq(timer, DEF_CNT, DEF_CNT - 1, 0,
75067730e6cSSean Christopherson sm);
75167730e6cSSean Christopherson test_set_cnt_after_tval_no_irq(timer, DEF_CNT, -1, 0, sm);
75267730e6cSSean Christopherson }
75367730e6cSSean Christopherson }
75467730e6cSSean Christopherson
test_timers_in_the_past(enum arch_timer timer)75567730e6cSSean Christopherson static void test_timers_in_the_past(enum arch_timer timer)
75667730e6cSSean Christopherson {
75767730e6cSSean Christopherson int32_t tval = -1 * (int32_t) msec_to_cycles(test_args.wait_ms);
75867730e6cSSean Christopherson uint64_t cval;
75967730e6cSSean Christopherson int i;
76067730e6cSSean Christopherson
76167730e6cSSean Christopherson for (i = 0; i < ARRAY_SIZE(irq_wait_method); i++) {
76267730e6cSSean Christopherson irq_wait_method_t wm = irq_wait_method[i];
76367730e6cSSean Christopherson
76467730e6cSSean Christopherson /* set a timer wait_ms the past. */
76567730e6cSSean Christopherson cval = DEF_CNT - msec_to_cycles(test_args.wait_ms);
76667730e6cSSean Christopherson test_timer_cval(timer, cval, wm, true, DEF_CNT);
76767730e6cSSean Christopherson test_timer_tval(timer, tval, wm, true, DEF_CNT);
76867730e6cSSean Christopherson
76967730e6cSSean Christopherson /* Set a timer to counter=0 (in the past) */
77067730e6cSSean Christopherson test_timer_cval(timer, 0, wm, true, DEF_CNT);
77167730e6cSSean Christopherson
77267730e6cSSean Christopherson /* Set a time for tval=0 (now) */
77367730e6cSSean Christopherson test_timer_tval(timer, 0, wm, true, DEF_CNT);
77467730e6cSSean Christopherson
77567730e6cSSean Christopherson /* Set a timer to as far in the past as possible */
77667730e6cSSean Christopherson test_timer_tval(timer, TVAL_MIN, wm, true, DEF_CNT);
77767730e6cSSean Christopherson }
77867730e6cSSean Christopherson
77967730e6cSSean Christopherson /*
78067730e6cSSean Christopherson * Set the counter to wait_ms, and a tval to -wait_ms. There should be no
78167730e6cSSean Christopherson * IRQ as that tval means cval=CVAL_MAX-wait_ms.
78267730e6cSSean Christopherson */
78367730e6cSSean Christopherson for (i = 0; i < ARRAY_SIZE(sleep_method); i++) {
78467730e6cSSean Christopherson sleep_method_t sm = sleep_method[i];
78567730e6cSSean Christopherson
78667730e6cSSean Christopherson set_counter(timer, msec_to_cycles(test_args.wait_ms));
78767730e6cSSean Christopherson test_tval_no_irq(timer, tval, TIMEOUT_NO_IRQ_US, sm);
78867730e6cSSean Christopherson }
78967730e6cSSean Christopherson }
79067730e6cSSean Christopherson
test_long_timer_delays(enum arch_timer timer)79167730e6cSSean Christopherson static void test_long_timer_delays(enum arch_timer timer)
79267730e6cSSean Christopherson {
79367730e6cSSean Christopherson int32_t tval = (int32_t) msec_to_cycles(test_args.long_wait_ms);
79467730e6cSSean Christopherson uint64_t cval = DEF_CNT + msec_to_cycles(test_args.long_wait_ms);
79567730e6cSSean Christopherson int i;
79667730e6cSSean Christopherson
79767730e6cSSean Christopherson for (i = 0; i < ARRAY_SIZE(irq_wait_method); i++) {
79867730e6cSSean Christopherson irq_wait_method_t wm = irq_wait_method[i];
79967730e6cSSean Christopherson
80067730e6cSSean Christopherson test_timer_cval(timer, cval, wm, true, DEF_CNT);
80167730e6cSSean Christopherson test_timer_tval(timer, tval, wm, true, DEF_CNT);
80267730e6cSSean Christopherson }
80367730e6cSSean Christopherson }
80467730e6cSSean Christopherson
guest_run_iteration(enum arch_timer timer)80567730e6cSSean Christopherson static void guest_run_iteration(enum arch_timer timer)
80667730e6cSSean Christopherson {
80767730e6cSSean Christopherson test_basic_functionality(timer);
80867730e6cSSean Christopherson test_timers_sanity_checks(timer);
80967730e6cSSean Christopherson
81067730e6cSSean Christopherson test_timers_above_tval_max(timer);
81167730e6cSSean Christopherson test_timers_in_the_past(timer);
81267730e6cSSean Christopherson
81367730e6cSSean Christopherson test_move_counters_ahead_of_timers(timer);
81467730e6cSSean Christopherson test_move_counters_behind_timers(timer);
81567730e6cSSean Christopherson test_reprogram_timers(timer);
81667730e6cSSean Christopherson
81767730e6cSSean Christopherson test_timers_fired_multiple_times(timer);
81867730e6cSSean Christopherson
81967730e6cSSean Christopherson test_timer_control_mask_then_unmask(timer);
82067730e6cSSean Christopherson test_timer_control_masks(timer);
82167730e6cSSean Christopherson }
82267730e6cSSean Christopherson
guest_code(enum arch_timer timer)82367730e6cSSean Christopherson static void guest_code(enum arch_timer timer)
82467730e6cSSean Christopherson {
82567730e6cSSean Christopherson int i;
82667730e6cSSean Christopherson
82767730e6cSSean Christopherson local_irq_disable();
82867730e6cSSean Christopherson
82967730e6cSSean Christopherson gic_init(GIC_V3, 1);
83067730e6cSSean Christopherson
83167730e6cSSean Christopherson timer_set_ctl(VIRTUAL, CTL_IMASK);
83267730e6cSSean Christopherson timer_set_ctl(PHYSICAL, CTL_IMASK);
83367730e6cSSean Christopherson
83467730e6cSSean Christopherson gic_irq_enable(vtimer_irq);
83567730e6cSSean Christopherson gic_irq_enable(ptimer_irq);
83667730e6cSSean Christopherson local_irq_enable();
83767730e6cSSean Christopherson
83867730e6cSSean Christopherson for (i = 0; i < test_args.iterations; i++) {
83967730e6cSSean Christopherson GUEST_SYNC(i);
84067730e6cSSean Christopherson guest_run_iteration(timer);
84167730e6cSSean Christopherson }
84267730e6cSSean Christopherson
84367730e6cSSean Christopherson test_long_timer_delays(timer);
84467730e6cSSean Christopherson GUEST_DONE();
84567730e6cSSean Christopherson }
84667730e6cSSean Christopherson
847050632aeSSebastian Ott static cpu_set_t default_cpuset;
848050632aeSSebastian Ott
next_pcpu(void)84967730e6cSSean Christopherson static uint32_t next_pcpu(void)
85067730e6cSSean Christopherson {
85167730e6cSSean Christopherson uint32_t max = get_nprocs();
85267730e6cSSean Christopherson uint32_t cur = sched_getcpu();
85367730e6cSSean Christopherson uint32_t next = cur;
854050632aeSSebastian Ott cpu_set_t cpuset = default_cpuset;
85567730e6cSSean Christopherson
85667730e6cSSean Christopherson TEST_ASSERT(max > 1, "Need at least two physical cpus");
85767730e6cSSean Christopherson
85867730e6cSSean Christopherson do {
85967730e6cSSean Christopherson next = (next + 1) % CPU_SETSIZE;
86067730e6cSSean Christopherson } while (!CPU_ISSET(next, &cpuset));
86167730e6cSSean Christopherson
86267730e6cSSean Christopherson return next;
86367730e6cSSean Christopherson }
86467730e6cSSean Christopherson
migrate_self(uint32_t new_pcpu)86567730e6cSSean Christopherson static void migrate_self(uint32_t new_pcpu)
86667730e6cSSean Christopherson {
86767730e6cSSean Christopherson int ret;
86867730e6cSSean Christopherson cpu_set_t cpuset;
86967730e6cSSean Christopherson pthread_t thread;
87067730e6cSSean Christopherson
87167730e6cSSean Christopherson thread = pthread_self();
87267730e6cSSean Christopherson
87367730e6cSSean Christopherson CPU_ZERO(&cpuset);
87467730e6cSSean Christopherson CPU_SET(new_pcpu, &cpuset);
87567730e6cSSean Christopherson
87667730e6cSSean Christopherson pr_debug("Migrating from %u to %u\n", sched_getcpu(), new_pcpu);
87767730e6cSSean Christopherson
87867730e6cSSean Christopherson ret = pthread_setaffinity_np(thread, sizeof(cpuset), &cpuset);
87967730e6cSSean Christopherson
88067730e6cSSean Christopherson TEST_ASSERT(ret == 0, "Failed to migrate to pCPU: %u; ret: %d\n",
88167730e6cSSean Christopherson new_pcpu, ret);
88267730e6cSSean Christopherson }
88367730e6cSSean Christopherson
kvm_set_cntxct(struct kvm_vcpu * vcpu,uint64_t cnt,enum arch_timer timer)88467730e6cSSean Christopherson static void kvm_set_cntxct(struct kvm_vcpu *vcpu, uint64_t cnt,
88567730e6cSSean Christopherson enum arch_timer timer)
88667730e6cSSean Christopherson {
88767730e6cSSean Christopherson if (timer == PHYSICAL)
88867730e6cSSean Christopherson vcpu_set_reg(vcpu, KVM_REG_ARM_PTIMER_CNT, cnt);
88967730e6cSSean Christopherson else
89067730e6cSSean Christopherson vcpu_set_reg(vcpu, KVM_REG_ARM_TIMER_CNT, cnt);
89167730e6cSSean Christopherson }
89267730e6cSSean Christopherson
handle_sync(struct kvm_vcpu * vcpu,struct ucall * uc)89367730e6cSSean Christopherson static void handle_sync(struct kvm_vcpu *vcpu, struct ucall *uc)
89467730e6cSSean Christopherson {
89567730e6cSSean Christopherson enum sync_cmd cmd = uc->args[1];
89667730e6cSSean Christopherson uint64_t val = uc->args[2];
89767730e6cSSean Christopherson enum arch_timer timer = uc->args[3];
89867730e6cSSean Christopherson
89967730e6cSSean Christopherson switch (cmd) {
90067730e6cSSean Christopherson case SET_COUNTER_VALUE:
90167730e6cSSean Christopherson kvm_set_cntxct(vcpu, val, timer);
90267730e6cSSean Christopherson break;
90367730e6cSSean Christopherson case USERSPACE_USLEEP:
90467730e6cSSean Christopherson usleep(val);
90567730e6cSSean Christopherson break;
90667730e6cSSean Christopherson case USERSPACE_SCHED_YIELD:
90767730e6cSSean Christopherson sched_yield();
90867730e6cSSean Christopherson break;
90967730e6cSSean Christopherson case USERSPACE_MIGRATE_SELF:
91067730e6cSSean Christopherson migrate_self(next_pcpu());
91167730e6cSSean Christopherson break;
91267730e6cSSean Christopherson default:
91367730e6cSSean Christopherson break;
91467730e6cSSean Christopherson }
91567730e6cSSean Christopherson }
91667730e6cSSean Christopherson
test_run(struct kvm_vm * vm,struct kvm_vcpu * vcpu)91767730e6cSSean Christopherson static void test_run(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
91867730e6cSSean Christopherson {
91967730e6cSSean Christopherson struct ucall uc;
92067730e6cSSean Christopherson
92167730e6cSSean Christopherson /* Start on CPU 0 */
92267730e6cSSean Christopherson migrate_self(0);
92367730e6cSSean Christopherson
92467730e6cSSean Christopherson while (true) {
92567730e6cSSean Christopherson vcpu_run(vcpu);
92667730e6cSSean Christopherson switch (get_ucall(vcpu, &uc)) {
92767730e6cSSean Christopherson case UCALL_SYNC:
92867730e6cSSean Christopherson handle_sync(vcpu, &uc);
92967730e6cSSean Christopherson break;
93067730e6cSSean Christopherson case UCALL_DONE:
93167730e6cSSean Christopherson goto out;
93267730e6cSSean Christopherson case UCALL_ABORT:
93367730e6cSSean Christopherson REPORT_GUEST_ASSERT(uc);
93467730e6cSSean Christopherson goto out;
93567730e6cSSean Christopherson default:
93667730e6cSSean Christopherson TEST_FAIL("Unexpected guest exit\n");
93767730e6cSSean Christopherson }
93867730e6cSSean Christopherson }
93967730e6cSSean Christopherson
94067730e6cSSean Christopherson out:
94167730e6cSSean Christopherson return;
94267730e6cSSean Christopherson }
94367730e6cSSean Christopherson
test_init_timer_irq(struct kvm_vm * vm,struct kvm_vcpu * vcpu)94467730e6cSSean Christopherson static void test_init_timer_irq(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
94567730e6cSSean Christopherson {
94667730e6cSSean Christopherson vcpu_device_attr_get(vcpu, KVM_ARM_VCPU_TIMER_CTRL,
94767730e6cSSean Christopherson KVM_ARM_VCPU_TIMER_IRQ_PTIMER, &ptimer_irq);
94867730e6cSSean Christopherson vcpu_device_attr_get(vcpu, KVM_ARM_VCPU_TIMER_CTRL,
94967730e6cSSean Christopherson KVM_ARM_VCPU_TIMER_IRQ_VTIMER, &vtimer_irq);
95067730e6cSSean Christopherson
95167730e6cSSean Christopherson sync_global_to_guest(vm, ptimer_irq);
95267730e6cSSean Christopherson sync_global_to_guest(vm, vtimer_irq);
95367730e6cSSean Christopherson
95467730e6cSSean Christopherson pr_debug("ptimer_irq: %d; vtimer_irq: %d\n", ptimer_irq, vtimer_irq);
95567730e6cSSean Christopherson }
95667730e6cSSean Christopherson
957*56a14984SZenghui Yu static int gic_fd;
958*56a14984SZenghui Yu
test_vm_create(struct kvm_vm ** vm,struct kvm_vcpu ** vcpu,enum arch_timer timer)95967730e6cSSean Christopherson static void test_vm_create(struct kvm_vm **vm, struct kvm_vcpu **vcpu,
96067730e6cSSean Christopherson enum arch_timer timer)
96167730e6cSSean Christopherson {
96267730e6cSSean Christopherson *vm = vm_create_with_one_vcpu(vcpu, guest_code);
96367730e6cSSean Christopherson TEST_ASSERT(*vm, "Failed to create the test VM\n");
96467730e6cSSean Christopherson
96567730e6cSSean Christopherson vm_init_descriptor_tables(*vm);
96667730e6cSSean Christopherson vm_install_exception_handler(*vm, VECTOR_IRQ_CURRENT,
96767730e6cSSean Christopherson guest_irq_handler);
96867730e6cSSean Christopherson
96967730e6cSSean Christopherson vcpu_init_descriptor_tables(*vcpu);
97067730e6cSSean Christopherson vcpu_args_set(*vcpu, 1, timer);
97167730e6cSSean Christopherson
97267730e6cSSean Christopherson test_init_timer_irq(*vm, *vcpu);
973*56a14984SZenghui Yu gic_fd = vgic_v3_setup(*vm, 1, 64);
974*56a14984SZenghui Yu __TEST_REQUIRE(gic_fd >= 0, "Failed to create vgic-v3");
975*56a14984SZenghui Yu
97667730e6cSSean Christopherson sync_global_to_guest(*vm, test_args);
977fad4cf94SSebastian Ott sync_global_to_guest(*vm, CVAL_MAX);
978fad4cf94SSebastian Ott sync_global_to_guest(*vm, DEF_CNT);
97967730e6cSSean Christopherson }
98067730e6cSSean Christopherson
test_vm_cleanup(struct kvm_vm * vm)981*56a14984SZenghui Yu static void test_vm_cleanup(struct kvm_vm *vm)
982*56a14984SZenghui Yu {
983*56a14984SZenghui Yu close(gic_fd);
984*56a14984SZenghui Yu kvm_vm_free(vm);
985*56a14984SZenghui Yu }
986*56a14984SZenghui Yu
test_print_help(char * name)98767730e6cSSean Christopherson static void test_print_help(char *name)
98867730e6cSSean Christopherson {
98967730e6cSSean Christopherson pr_info("Usage: %s [-h] [-b] [-i iterations] [-l long_wait_ms] [-p] [-v]\n"
99067730e6cSSean Christopherson , name);
99167730e6cSSean Christopherson pr_info("\t-i: Number of iterations (default: %u)\n",
99267730e6cSSean Christopherson NR_TEST_ITERS_DEF);
99367730e6cSSean Christopherson pr_info("\t-b: Test both physical and virtual timers (default: true)\n");
99467730e6cSSean Christopherson pr_info("\t-l: Delta (in ms) used for long wait time test (default: %u)\n",
99567730e6cSSean Christopherson LONG_WAIT_TEST_MS);
9969a9864fdSSebastian Ott pr_info("\t-w: Delta (in ms) used for wait times (default: %u)\n",
99767730e6cSSean Christopherson WAIT_TEST_MS);
99867730e6cSSean Christopherson pr_info("\t-p: Test physical timer (default: true)\n");
99967730e6cSSean Christopherson pr_info("\t-v: Test virtual timer (default: true)\n");
100067730e6cSSean Christopherson pr_info("\t-h: Print this help message\n");
100167730e6cSSean Christopherson }
100267730e6cSSean Christopherson
parse_args(int argc,char * argv[])100367730e6cSSean Christopherson static bool parse_args(int argc, char *argv[])
100467730e6cSSean Christopherson {
100567730e6cSSean Christopherson int opt;
100667730e6cSSean Christopherson
100767730e6cSSean Christopherson while ((opt = getopt(argc, argv, "bhi:l:pvw:")) != -1) {
100867730e6cSSean Christopherson switch (opt) {
100967730e6cSSean Christopherson case 'b':
101067730e6cSSean Christopherson test_args.test_physical = true;
101167730e6cSSean Christopherson test_args.test_virtual = true;
101267730e6cSSean Christopherson break;
101367730e6cSSean Christopherson case 'i':
101467730e6cSSean Christopherson test_args.iterations =
101567730e6cSSean Christopherson atoi_positive("Number of iterations", optarg);
101667730e6cSSean Christopherson break;
101767730e6cSSean Christopherson case 'l':
101867730e6cSSean Christopherson test_args.long_wait_ms =
101967730e6cSSean Christopherson atoi_positive("Long wait time", optarg);
102067730e6cSSean Christopherson break;
102167730e6cSSean Christopherson case 'p':
102267730e6cSSean Christopherson test_args.test_physical = true;
102367730e6cSSean Christopherson test_args.test_virtual = false;
102467730e6cSSean Christopherson break;
102567730e6cSSean Christopherson case 'v':
102667730e6cSSean Christopherson test_args.test_virtual = true;
102767730e6cSSean Christopherson test_args.test_physical = false;
102867730e6cSSean Christopherson break;
102967730e6cSSean Christopherson case 'w':
103067730e6cSSean Christopherson test_args.wait_ms = atoi_positive("Wait time", optarg);
103167730e6cSSean Christopherson break;
103267730e6cSSean Christopherson case 'h':
103367730e6cSSean Christopherson default:
103467730e6cSSean Christopherson goto err;
103567730e6cSSean Christopherson }
103667730e6cSSean Christopherson }
103767730e6cSSean Christopherson
103867730e6cSSean Christopherson return true;
103967730e6cSSean Christopherson
104067730e6cSSean Christopherson err:
104167730e6cSSean Christopherson test_print_help(argv[0]);
104267730e6cSSean Christopherson return false;
104367730e6cSSean Christopherson }
104467730e6cSSean Christopherson
set_counter_defaults(void)1045fad4cf94SSebastian Ott static void set_counter_defaults(void)
1046fad4cf94SSebastian Ott {
1047fad4cf94SSebastian Ott const uint64_t MIN_ROLLOVER_SECS = 40ULL * 365 * 24 * 3600;
1048fad4cf94SSebastian Ott uint64_t freq = read_sysreg(CNTFRQ_EL0);
1049fad4cf94SSebastian Ott uint64_t width = ilog2(MIN_ROLLOVER_SECS * freq);
1050fad4cf94SSebastian Ott
1051fad4cf94SSebastian Ott width = clamp(width, 56, 64);
1052fad4cf94SSebastian Ott CVAL_MAX = GENMASK_ULL(width - 1, 0);
1053fad4cf94SSebastian Ott DEF_CNT = CVAL_MAX / 2;
1054fad4cf94SSebastian Ott }
1055fad4cf94SSebastian Ott
main(int argc,char * argv[])105667730e6cSSean Christopherson int main(int argc, char *argv[])
105767730e6cSSean Christopherson {
105867730e6cSSean Christopherson struct kvm_vcpu *vcpu;
105967730e6cSSean Christopherson struct kvm_vm *vm;
106067730e6cSSean Christopherson
106167730e6cSSean Christopherson /* Tell stdout not to buffer its content */
106267730e6cSSean Christopherson setbuf(stdout, NULL);
106367730e6cSSean Christopherson
106467730e6cSSean Christopherson if (!parse_args(argc, argv))
106567730e6cSSean Christopherson exit(KSFT_SKIP);
106667730e6cSSean Christopherson
1067050632aeSSebastian Ott sched_getaffinity(0, sizeof(default_cpuset), &default_cpuset);
1068fad4cf94SSebastian Ott set_counter_defaults();
1069050632aeSSebastian Ott
107067730e6cSSean Christopherson if (test_args.test_virtual) {
107167730e6cSSean Christopherson test_vm_create(&vm, &vcpu, VIRTUAL);
107267730e6cSSean Christopherson test_run(vm, vcpu);
1073*56a14984SZenghui Yu test_vm_cleanup(vm);
107467730e6cSSean Christopherson }
107567730e6cSSean Christopherson
107667730e6cSSean Christopherson if (test_args.test_physical) {
107767730e6cSSean Christopherson test_vm_create(&vm, &vcpu, PHYSICAL);
107867730e6cSSean Christopherson test_run(vm, vcpu);
1079*56a14984SZenghui Yu test_vm_cleanup(vm);
108067730e6cSSean Christopherson }
108167730e6cSSean Christopherson
108267730e6cSSean Christopherson return 0;
108367730e6cSSean Christopherson }
1084