~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/kvm/riscv/arch_timer.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * arch_timer.c - Tests the riscv64 sstc timer IRQ functionality
  4  *
  5  * The test validates the sstc timer IRQs using vstimecmp registers.
  6  * It's ported from the aarch64 arch_timer test.
  7  *
  8  * Copyright (c) 2024, Intel Corporation.
  9  */
 10 #include "arch_timer.h"
 11 #include "kvm_util.h"
 12 #include "processor.h"
 13 #include "timer_test.h"
 14 #include "ucall_common.h"
 15 
 16 static int timer_irq = IRQ_S_TIMER;
 17 
 18 static void guest_irq_handler(struct ex_regs *regs)
 19 {
 20         uint64_t xcnt, xcnt_diff_us, cmp;
 21         unsigned int intid = regs->cause & ~CAUSE_IRQ_FLAG;
 22         uint32_t cpu = guest_get_vcpuid();
 23         struct test_vcpu_shared_data *shared_data = &vcpu_shared_data[cpu];
 24 
 25         timer_irq_disable();
 26 
 27         xcnt = timer_get_cycles();
 28         cmp = timer_get_cmp();
 29         xcnt_diff_us = cycles_to_usec(xcnt - shared_data->xcnt);
 30 
 31         /* Make sure we are dealing with the correct timer IRQ */
 32         GUEST_ASSERT_EQ(intid, timer_irq);
 33 
 34         __GUEST_ASSERT(xcnt >= cmp,
 35                         "xcnt = 0x%"PRIx64", cmp = 0x%"PRIx64", xcnt_diff_us = 0x%" PRIx64,
 36                         xcnt, cmp, xcnt_diff_us);
 37 
 38         WRITE_ONCE(shared_data->nr_iter, shared_data->nr_iter + 1);
 39 }
 40 
 41 static void guest_run(struct test_vcpu_shared_data *shared_data)
 42 {
 43         uint32_t irq_iter, config_iter;
 44 
 45         shared_data->nr_iter = 0;
 46         shared_data->guest_stage = 0;
 47 
 48         for (config_iter = 0; config_iter < test_args.nr_iter; config_iter++) {
 49                 /* Setup the next interrupt */
 50                 timer_set_next_cmp_ms(test_args.timer_period_ms);
 51                 shared_data->xcnt = timer_get_cycles();
 52                 timer_irq_enable();
 53 
 54                 /* Setup a timeout for the interrupt to arrive */
 55                 udelay(msecs_to_usecs(test_args.timer_period_ms) +
 56                         test_args.timer_err_margin_us);
 57 
 58                 irq_iter = READ_ONCE(shared_data->nr_iter);
 59                 __GUEST_ASSERT(config_iter + 1 == irq_iter,
 60                                 "config_iter + 1 = 0x%x, irq_iter = 0x%x.\n"
 61                                 "  Guest timer interrupt was not triggered within the specified\n"
 62                                 "  interval, try to increase the error margin by [-e] option.\n",
 63                                 config_iter + 1, irq_iter);
 64         }
 65 }
 66 
 67 static void guest_code(void)
 68 {
 69         uint32_t cpu = guest_get_vcpuid();
 70         struct test_vcpu_shared_data *shared_data = &vcpu_shared_data[cpu];
 71 
 72         timer_irq_disable();
 73         local_irq_enable();
 74 
 75         guest_run(shared_data);
 76 
 77         GUEST_DONE();
 78 }
 79 
 80 struct kvm_vm *test_vm_create(void)
 81 {
 82         struct kvm_vm *vm;
 83         int nr_vcpus = test_args.nr_vcpus;
 84 
 85         vm = vm_create_with_vcpus(nr_vcpus, guest_code, vcpus);
 86         __TEST_REQUIRE(__vcpu_has_isa_ext(vcpus[0], KVM_RISCV_ISA_EXT_SSTC),
 87                                    "SSTC not available, skipping test\n");
 88 
 89         vm_init_vector_tables(vm);
 90         vm_install_interrupt_handler(vm, guest_irq_handler);
 91 
 92         for (int i = 0; i < nr_vcpus; i++)
 93                 vcpu_init_vector_tables(vcpus[i]);
 94 
 95         /* Initialize guest timer frequency. */
 96         vcpu_get_reg(vcpus[0], RISCV_TIMER_REG(frequency), &timer_freq);
 97         sync_global_to_guest(vm, timer_freq);
 98         pr_debug("timer_freq: %lu\n", timer_freq);
 99 
100         /* Make all the test's cmdline args visible to the guest */
101         sync_global_to_guest(vm, test_args);
102 
103         return vm;
104 }
105 
106 void test_vm_cleanup(struct kvm_vm *vm)
107 {
108         kvm_vm_free(vm);
109 }
110 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php