xref: /kvm-unit-tests/x86/hyperv_stimer.c (revision 5c3582f05f30f30fee86b73efa2131540c7a2255)
169d4bf75SAndrey Smetanin #include "libcflat.h"
269d4bf75SAndrey Smetanin #include "processor.h"
369d4bf75SAndrey Smetanin #include "msr.h"
469d4bf75SAndrey Smetanin #include "isr.h"
569d4bf75SAndrey Smetanin #include "vm.h"
669d4bf75SAndrey Smetanin #include "apic.h"
769d4bf75SAndrey Smetanin #include "desc.h"
869d4bf75SAndrey Smetanin #include "smp.h"
969d4bf75SAndrey Smetanin #include "atomic.h"
1069d4bf75SAndrey Smetanin #include "hyperv.h"
118226c540SAlexander Gordeev #include "asm/barrier.h"
125aca024eSPaolo Bonzini #include "alloc_page.h"
1369d4bf75SAndrey Smetanin 
1469d4bf75SAndrey Smetanin #define MAX_CPUS 4
1569d4bf75SAndrey Smetanin 
1669d4bf75SAndrey Smetanin #define SINT1_VEC 0xF1
1769d4bf75SAndrey Smetanin #define SINT2_VEC 0xF2
1869d4bf75SAndrey Smetanin 
1969d4bf75SAndrey Smetanin #define SINT1_NUM 2
2069d4bf75SAndrey Smetanin #define SINT2_NUM 3
2169d4bf75SAndrey Smetanin #define ONE_MS_IN_100NS 10000
2269d4bf75SAndrey Smetanin 
2369d4bf75SAndrey Smetanin static struct spinlock g_synic_alloc_lock;
2469d4bf75SAndrey Smetanin 
2569d4bf75SAndrey Smetanin struct stimer {
2669d4bf75SAndrey Smetanin     int sint;
2769d4bf75SAndrey Smetanin     int index;
2869d4bf75SAndrey Smetanin     atomic_t fire_count;
2969d4bf75SAndrey Smetanin };
3069d4bf75SAndrey Smetanin 
3169d4bf75SAndrey Smetanin struct svcpu {
3269d4bf75SAndrey Smetanin     int vcpu;
3369d4bf75SAndrey Smetanin     void *msg_page;
3469d4bf75SAndrey Smetanin     void *evt_page;
3569d4bf75SAndrey Smetanin     struct stimer timer[HV_SYNIC_STIMER_COUNT];
3669d4bf75SAndrey Smetanin };
3769d4bf75SAndrey Smetanin 
3869d4bf75SAndrey Smetanin static struct svcpu g_synic_vcpu[MAX_CPUS];
3969d4bf75SAndrey Smetanin 
4069d4bf75SAndrey Smetanin static void *synic_alloc_page(void)
4169d4bf75SAndrey Smetanin {
4269d4bf75SAndrey Smetanin     void *page;
4369d4bf75SAndrey Smetanin 
4469d4bf75SAndrey Smetanin     spin_lock(&g_synic_alloc_lock);
4569d4bf75SAndrey Smetanin     page = alloc_page();
4669d4bf75SAndrey Smetanin     spin_unlock(&g_synic_alloc_lock);
4769d4bf75SAndrey Smetanin     return page;
4869d4bf75SAndrey Smetanin }
4969d4bf75SAndrey Smetanin 
5069d4bf75SAndrey Smetanin static void synic_free_page(void *page)
5169d4bf75SAndrey Smetanin {
5269d4bf75SAndrey Smetanin     spin_lock(&g_synic_alloc_lock);
5369d4bf75SAndrey Smetanin     free_page(page);
5469d4bf75SAndrey Smetanin     spin_unlock(&g_synic_alloc_lock);
5569d4bf75SAndrey Smetanin }
5669d4bf75SAndrey Smetanin 
5769d4bf75SAndrey Smetanin static void stimer_init(struct stimer *timer, int index)
5869d4bf75SAndrey Smetanin {
5969d4bf75SAndrey Smetanin     memset(timer, 0, sizeof(*timer));
6069d4bf75SAndrey Smetanin     timer->index = index;
6169d4bf75SAndrey Smetanin }
6269d4bf75SAndrey Smetanin 
6369d4bf75SAndrey Smetanin static void synic_enable(void)
6469d4bf75SAndrey Smetanin {
6569d4bf75SAndrey Smetanin     int vcpu = smp_id(), i;
6669d4bf75SAndrey Smetanin     struct svcpu *svcpu = &g_synic_vcpu[vcpu];
6769d4bf75SAndrey Smetanin 
6869d4bf75SAndrey Smetanin     memset(svcpu, 0, sizeof(*svcpu));
6969d4bf75SAndrey Smetanin     svcpu->vcpu = vcpu;
7069d4bf75SAndrey Smetanin     svcpu->msg_page = synic_alloc_page();
7169d4bf75SAndrey Smetanin     for (i = 0; i < ARRAY_SIZE(svcpu->timer); i++) {
7269d4bf75SAndrey Smetanin         stimer_init(&svcpu->timer[i], i);
7369d4bf75SAndrey Smetanin     }
7469d4bf75SAndrey Smetanin     wrmsr(HV_X64_MSR_SIMP, (u64)virt_to_phys(svcpu->msg_page) |
7569d4bf75SAndrey Smetanin             HV_SYNIC_SIMP_ENABLE);
7669d4bf75SAndrey Smetanin     wrmsr(HV_X64_MSR_SCONTROL, HV_SYNIC_CONTROL_ENABLE);
7769d4bf75SAndrey Smetanin }
7869d4bf75SAndrey Smetanin 
7969d4bf75SAndrey Smetanin static void stimer_shutdown(struct stimer *timer)
8069d4bf75SAndrey Smetanin {
8169d4bf75SAndrey Smetanin     wrmsr(HV_X64_MSR_STIMER0_CONFIG + 2*timer->index, 0);
8269d4bf75SAndrey Smetanin }
8369d4bf75SAndrey Smetanin 
8469d4bf75SAndrey Smetanin static void process_stimer_expired(struct svcpu *svcpu, struct stimer *timer,
8569d4bf75SAndrey Smetanin                                    u64 expiration_time, u64 delivery_time)
8669d4bf75SAndrey Smetanin {
8769d4bf75SAndrey Smetanin     atomic_inc(&timer->fire_count);
8869d4bf75SAndrey Smetanin }
8969d4bf75SAndrey Smetanin 
9069d4bf75SAndrey Smetanin static void process_stimer_msg(struct svcpu *svcpu,
9169d4bf75SAndrey Smetanin                               struct hv_message *msg, int sint)
9269d4bf75SAndrey Smetanin {
9369d4bf75SAndrey Smetanin     struct hv_timer_message_payload *payload =
9469d4bf75SAndrey Smetanin                         (struct hv_timer_message_payload *)msg->u.payload;
9569d4bf75SAndrey Smetanin     struct stimer *timer;
9669d4bf75SAndrey Smetanin 
9769d4bf75SAndrey Smetanin     if (msg->header.message_type != HVMSG_TIMER_EXPIRED &&
9869d4bf75SAndrey Smetanin         msg->header.message_type != HVMSG_NONE) {
99198dfd0eSJanis Schoetterl-Glausch         report_fail("invalid Hyper-V SynIC msg type");
10069d4bf75SAndrey Smetanin         report_summary();
101a2b7c499SAndrew Jones         abort();
10269d4bf75SAndrey Smetanin     }
10369d4bf75SAndrey Smetanin 
10469d4bf75SAndrey Smetanin     if (msg->header.message_type == HVMSG_NONE) {
10569d4bf75SAndrey Smetanin         return;
10669d4bf75SAndrey Smetanin     }
10769d4bf75SAndrey Smetanin 
10869d4bf75SAndrey Smetanin     if (msg->header.payload_size < sizeof(*payload)) {
109198dfd0eSJanis Schoetterl-Glausch         report_fail("invalid Hyper-V SynIC msg payload size");
11069d4bf75SAndrey Smetanin         report_summary();
111a2b7c499SAndrew Jones         abort();
11269d4bf75SAndrey Smetanin     }
11369d4bf75SAndrey Smetanin 
11469d4bf75SAndrey Smetanin     /* Now process timer expiration message */
11569d4bf75SAndrey Smetanin 
11669d4bf75SAndrey Smetanin     if (payload->timer_index >= ARRAY_SIZE(svcpu->timer)) {
117198dfd0eSJanis Schoetterl-Glausch         report_fail("invalid Hyper-V SynIC timer index");
11869d4bf75SAndrey Smetanin         report_summary();
119a2b7c499SAndrew Jones         abort();
12069d4bf75SAndrey Smetanin     }
12169d4bf75SAndrey Smetanin     timer = &svcpu->timer[payload->timer_index];
12269d4bf75SAndrey Smetanin     process_stimer_expired(svcpu, timer, payload->expiration_time,
12369d4bf75SAndrey Smetanin                           payload->delivery_time);
12469d4bf75SAndrey Smetanin 
12569d4bf75SAndrey Smetanin     msg->header.message_type = HVMSG_NONE;
12669d4bf75SAndrey Smetanin     mb();
12769d4bf75SAndrey Smetanin     if (msg->header.message_flags.msg_pending) {
12869d4bf75SAndrey Smetanin         wrmsr(HV_X64_MSR_EOM, 0);
12969d4bf75SAndrey Smetanin     }
13069d4bf75SAndrey Smetanin }
13169d4bf75SAndrey Smetanin 
13269d4bf75SAndrey Smetanin static void __stimer_isr(int vcpu)
13369d4bf75SAndrey Smetanin {
13469d4bf75SAndrey Smetanin     struct svcpu *svcpu = &g_synic_vcpu[vcpu];
13569d4bf75SAndrey Smetanin     struct hv_message_page *msg_page;
13669d4bf75SAndrey Smetanin     struct hv_message *msg;
13769d4bf75SAndrey Smetanin     int i;
13869d4bf75SAndrey Smetanin 
13969d4bf75SAndrey Smetanin 
14069d4bf75SAndrey Smetanin     msg_page = (struct hv_message_page *)svcpu->msg_page;
14169d4bf75SAndrey Smetanin     for (i = 0; i < ARRAY_SIZE(msg_page->sint_message); i++) {
14269d4bf75SAndrey Smetanin         msg = &msg_page->sint_message[i];
14369d4bf75SAndrey Smetanin         process_stimer_msg(svcpu, msg, i);
14469d4bf75SAndrey Smetanin     }
14569d4bf75SAndrey Smetanin }
14669d4bf75SAndrey Smetanin 
14769d4bf75SAndrey Smetanin static void stimer_isr(isr_regs_t *regs)
14869d4bf75SAndrey Smetanin {
14969d4bf75SAndrey Smetanin     int vcpu = smp_id();
15069d4bf75SAndrey Smetanin 
15169d4bf75SAndrey Smetanin     __stimer_isr(vcpu);
15269d4bf75SAndrey Smetanin     eoi();
15369d4bf75SAndrey Smetanin }
15469d4bf75SAndrey Smetanin 
15569d4bf75SAndrey Smetanin static void stimer_isr_auto_eoi(isr_regs_t *regs)
15669d4bf75SAndrey Smetanin {
15769d4bf75SAndrey Smetanin     int vcpu = smp_id();
15869d4bf75SAndrey Smetanin 
15969d4bf75SAndrey Smetanin     __stimer_isr(vcpu);
16069d4bf75SAndrey Smetanin }
16169d4bf75SAndrey Smetanin 
16269d4bf75SAndrey Smetanin static void stimer_start(struct stimer *timer,
16369d4bf75SAndrey Smetanin                          bool auto_enable, bool periodic,
16469d4bf75SAndrey Smetanin                          u64 tick_100ns, int sint)
16569d4bf75SAndrey Smetanin {
16669d4bf75SAndrey Smetanin     u64 config, count;
16769d4bf75SAndrey Smetanin 
16869d4bf75SAndrey Smetanin     timer->sint = sint;
16969d4bf75SAndrey Smetanin     atomic_set(&timer->fire_count, 0);
17069d4bf75SAndrey Smetanin 
17169d4bf75SAndrey Smetanin     config = 0;
17269d4bf75SAndrey Smetanin     if (periodic) {
17369d4bf75SAndrey Smetanin         config |= HV_STIMER_PERIODIC;
17469d4bf75SAndrey Smetanin     }
17569d4bf75SAndrey Smetanin 
17669d4bf75SAndrey Smetanin     config |= ((u8)(sint & 0xFF)) << 16;
17769d4bf75SAndrey Smetanin     config |= HV_STIMER_ENABLE;
17869d4bf75SAndrey Smetanin     if (auto_enable) {
17969d4bf75SAndrey Smetanin         config |= HV_STIMER_AUTOENABLE;
18069d4bf75SAndrey Smetanin     }
18169d4bf75SAndrey Smetanin 
18269d4bf75SAndrey Smetanin     if (periodic) {
18369d4bf75SAndrey Smetanin         count = tick_100ns;
18469d4bf75SAndrey Smetanin     } else {
18569d4bf75SAndrey Smetanin         count = rdmsr(HV_X64_MSR_TIME_REF_COUNT) + tick_100ns;
18669d4bf75SAndrey Smetanin     }
18769d4bf75SAndrey Smetanin 
18869d4bf75SAndrey Smetanin     if (!auto_enable) {
18969d4bf75SAndrey Smetanin         wrmsr(HV_X64_MSR_STIMER0_COUNT + timer->index*2, count);
19069d4bf75SAndrey Smetanin         wrmsr(HV_X64_MSR_STIMER0_CONFIG + timer->index*2, config);
19169d4bf75SAndrey Smetanin     } else {
19269d4bf75SAndrey Smetanin         wrmsr(HV_X64_MSR_STIMER0_CONFIG + timer->index*2, config);
19369d4bf75SAndrey Smetanin         wrmsr(HV_X64_MSR_STIMER0_COUNT + timer->index*2, count);
19469d4bf75SAndrey Smetanin     }
19569d4bf75SAndrey Smetanin }
19669d4bf75SAndrey Smetanin 
19769d4bf75SAndrey Smetanin static void stimers_shutdown(void)
19869d4bf75SAndrey Smetanin {
19969d4bf75SAndrey Smetanin     int vcpu = smp_id(), i;
20069d4bf75SAndrey Smetanin     struct svcpu *svcpu = &g_synic_vcpu[vcpu];
20169d4bf75SAndrey Smetanin 
20269d4bf75SAndrey Smetanin     for (i = 0; i < ARRAY_SIZE(svcpu->timer); i++) {
20369d4bf75SAndrey Smetanin         stimer_shutdown(&svcpu->timer[i]);
20469d4bf75SAndrey Smetanin     }
20569d4bf75SAndrey Smetanin }
20669d4bf75SAndrey Smetanin 
20769d4bf75SAndrey Smetanin static void synic_disable(void)
20869d4bf75SAndrey Smetanin {
20969d4bf75SAndrey Smetanin     int vcpu = smp_id();
21069d4bf75SAndrey Smetanin     struct svcpu *svcpu = &g_synic_vcpu[vcpu];
21169d4bf75SAndrey Smetanin 
21269d4bf75SAndrey Smetanin     wrmsr(HV_X64_MSR_SCONTROL, 0);
21369d4bf75SAndrey Smetanin     wrmsr(HV_X64_MSR_SIMP, 0);
21469d4bf75SAndrey Smetanin     wrmsr(HV_X64_MSR_SIEFP, 0);
21569d4bf75SAndrey Smetanin     synic_free_page(svcpu->msg_page);
21669d4bf75SAndrey Smetanin }
21769d4bf75SAndrey Smetanin 
21869d4bf75SAndrey Smetanin 
21969d4bf75SAndrey Smetanin static void stimer_test_prepare(void *ctx)
22069d4bf75SAndrey Smetanin {
22169d4bf75SAndrey Smetanin     write_cr3((ulong)ctx);
22269d4bf75SAndrey Smetanin     synic_enable();
223d2c248afSRoman Kagan     synic_sint_create(SINT1_NUM, SINT1_VEC, false);
224d2c248afSRoman Kagan     synic_sint_create(SINT2_NUM, SINT2_VEC, true);
22569d4bf75SAndrey Smetanin }
22669d4bf75SAndrey Smetanin 
22769d4bf75SAndrey Smetanin static void stimer_test_periodic(int vcpu, struct stimer *timer1,
22869d4bf75SAndrey Smetanin                                  struct stimer *timer2)
22969d4bf75SAndrey Smetanin {
23069d4bf75SAndrey Smetanin     /* Check periodic timers */
23169d4bf75SAndrey Smetanin     stimer_start(timer1, false, true, ONE_MS_IN_100NS, SINT1_NUM);
23269d4bf75SAndrey Smetanin     stimer_start(timer2, false, true, ONE_MS_IN_100NS, SINT2_NUM);
23369d4bf75SAndrey Smetanin     while ((atomic_read(&timer1->fire_count) < 1000) ||
23469d4bf75SAndrey Smetanin            (atomic_read(&timer2->fire_count) < 1000)) {
23569d4bf75SAndrey Smetanin         pause();
23669d4bf75SAndrey Smetanin     }
237*5c3582f0SJanis Schoetterl-Glausch     report_pass("Hyper-V SynIC periodic timers test vcpu %d", vcpu);
23869d4bf75SAndrey Smetanin     stimer_shutdown(timer1);
23969d4bf75SAndrey Smetanin     stimer_shutdown(timer2);
24069d4bf75SAndrey Smetanin }
24169d4bf75SAndrey Smetanin 
24269d4bf75SAndrey Smetanin static void stimer_test_one_shot(int vcpu, struct stimer *timer)
24369d4bf75SAndrey Smetanin {
24469d4bf75SAndrey Smetanin     /* Check one-shot timer */
24569d4bf75SAndrey Smetanin     stimer_start(timer, false, false, ONE_MS_IN_100NS, SINT1_NUM);
24669d4bf75SAndrey Smetanin     while (atomic_read(&timer->fire_count) < 1) {
24769d4bf75SAndrey Smetanin         pause();
24869d4bf75SAndrey Smetanin     }
249*5c3582f0SJanis Schoetterl-Glausch     report_pass("Hyper-V SynIC one-shot test vcpu %d", vcpu);
25069d4bf75SAndrey Smetanin     stimer_shutdown(timer);
25169d4bf75SAndrey Smetanin }
25269d4bf75SAndrey Smetanin 
25369d4bf75SAndrey Smetanin static void stimer_test_auto_enable_one_shot(int vcpu, struct stimer *timer)
25469d4bf75SAndrey Smetanin {
25569d4bf75SAndrey Smetanin     /* Check auto-enable one-shot timer */
25669d4bf75SAndrey Smetanin     stimer_start(timer, true, false, ONE_MS_IN_100NS, SINT1_NUM);
25769d4bf75SAndrey Smetanin     while (atomic_read(&timer->fire_count) < 1) {
25869d4bf75SAndrey Smetanin         pause();
25969d4bf75SAndrey Smetanin     }
260*5c3582f0SJanis Schoetterl-Glausch     report_pass("Hyper-V SynIC auto-enable one-shot timer test vcpu %d", vcpu);
26169d4bf75SAndrey Smetanin     stimer_shutdown(timer);
26269d4bf75SAndrey Smetanin }
26369d4bf75SAndrey Smetanin 
26469d4bf75SAndrey Smetanin static void stimer_test_auto_enable_periodic(int vcpu, struct stimer *timer)
26569d4bf75SAndrey Smetanin {
26669d4bf75SAndrey Smetanin     /* Check auto-enable periodic timer */
26769d4bf75SAndrey Smetanin     stimer_start(timer, true, true, ONE_MS_IN_100NS, SINT1_NUM);
26869d4bf75SAndrey Smetanin     while (atomic_read(&timer->fire_count) < 1000) {
26969d4bf75SAndrey Smetanin         pause();
27069d4bf75SAndrey Smetanin     }
271*5c3582f0SJanis Schoetterl-Glausch     report_pass("Hyper-V SynIC auto-enable periodic timer test vcpu %d", vcpu);
27269d4bf75SAndrey Smetanin     stimer_shutdown(timer);
27369d4bf75SAndrey Smetanin }
27469d4bf75SAndrey Smetanin 
275cf12f77aSRoman Kagan static void stimer_test_one_shot_busy(int vcpu, struct stimer *timer)
276cf12f77aSRoman Kagan {
277cf12f77aSRoman Kagan     struct hv_message_page *msg_page = g_synic_vcpu[vcpu].msg_page;
278cf12f77aSRoman Kagan     struct hv_message *msg = &msg_page->sint_message[timer->sint];
279cf12f77aSRoman Kagan 
280cf12f77aSRoman Kagan     msg->header.message_type = HVMSG_TIMER_EXPIRED;
281cf12f77aSRoman Kagan     wmb();
282cf12f77aSRoman Kagan 
283cf12f77aSRoman Kagan     stimer_start(timer, false, false, ONE_MS_IN_100NS, SINT1_NUM);
284cf12f77aSRoman Kagan 
285cf12f77aSRoman Kagan     do
286cf12f77aSRoman Kagan         rmb();
287cf12f77aSRoman Kagan     while (!msg->header.message_flags.msg_pending);
288cf12f77aSRoman Kagan 
289a299895bSThomas Huth     report(!atomic_read(&timer->fire_count),
290a299895bSThomas Huth            "no timer fired while msg slot busy: vcpu %d", vcpu);
291cf12f77aSRoman Kagan 
292cf12f77aSRoman Kagan     msg->header.message_type = HVMSG_NONE;
293cf12f77aSRoman Kagan     wmb();
294cf12f77aSRoman Kagan     wrmsr(HV_X64_MSR_EOM, 0);
295cf12f77aSRoman Kagan 
296cf12f77aSRoman Kagan     while (atomic_read(&timer->fire_count) < 1) {
297cf12f77aSRoman Kagan         pause();
298cf12f77aSRoman Kagan     }
299*5c3582f0SJanis Schoetterl-Glausch     report_pass("timer resumed when msg slot released: vcpu %d", vcpu);
300cf12f77aSRoman Kagan 
301cf12f77aSRoman Kagan     stimer_shutdown(timer);
302cf12f77aSRoman Kagan }
303cf12f77aSRoman Kagan 
30469d4bf75SAndrey Smetanin static void stimer_test(void *ctx)
30569d4bf75SAndrey Smetanin {
30669d4bf75SAndrey Smetanin     int vcpu = smp_id();
30769d4bf75SAndrey Smetanin     struct svcpu *svcpu = &g_synic_vcpu[vcpu];
30869d4bf75SAndrey Smetanin     struct stimer *timer1, *timer2;
30969d4bf75SAndrey Smetanin 
31069d4bf75SAndrey Smetanin     irq_enable();
31169d4bf75SAndrey Smetanin 
31269d4bf75SAndrey Smetanin     timer1 = &svcpu->timer[0];
31369d4bf75SAndrey Smetanin     timer2 = &svcpu->timer[1];
31469d4bf75SAndrey Smetanin 
31569d4bf75SAndrey Smetanin     stimer_test_periodic(vcpu, timer1, timer2);
31669d4bf75SAndrey Smetanin     stimer_test_one_shot(vcpu, timer1);
31769d4bf75SAndrey Smetanin     stimer_test_auto_enable_one_shot(vcpu, timer2);
31869d4bf75SAndrey Smetanin     stimer_test_auto_enable_periodic(vcpu, timer1);
319cf12f77aSRoman Kagan     stimer_test_one_shot_busy(vcpu, timer1);
32069d4bf75SAndrey Smetanin 
32169d4bf75SAndrey Smetanin     irq_disable();
32269d4bf75SAndrey Smetanin }
32369d4bf75SAndrey Smetanin 
32469d4bf75SAndrey Smetanin static void stimer_test_cleanup(void *ctx)
32569d4bf75SAndrey Smetanin {
32669d4bf75SAndrey Smetanin     stimers_shutdown();
327d2c248afSRoman Kagan     synic_sint_destroy(SINT1_NUM);
328d2c248afSRoman Kagan     synic_sint_destroy(SINT2_NUM);
32969d4bf75SAndrey Smetanin     synic_disable();
33069d4bf75SAndrey Smetanin }
33169d4bf75SAndrey Smetanin 
33269d4bf75SAndrey Smetanin static void stimer_test_all(void)
33369d4bf75SAndrey Smetanin {
33469d4bf75SAndrey Smetanin     int ncpus;
33569d4bf75SAndrey Smetanin 
33669d4bf75SAndrey Smetanin     setup_vm();
33769d4bf75SAndrey Smetanin     enable_apic();
33869d4bf75SAndrey Smetanin 
3399b910f27SAndrew Jones     ncpus = cpu_count();
3409b910f27SAndrew Jones     if (ncpus > MAX_CPUS)
3419b910f27SAndrew Jones         report_abort("number cpus exceeds %d", MAX_CPUS);
3429b910f27SAndrew Jones     printf("cpus = %d\n", ncpus);
3439b910f27SAndrew Jones 
34469d4bf75SAndrey Smetanin     handle_irq(SINT1_VEC, stimer_isr);
34569d4bf75SAndrey Smetanin     handle_irq(SINT2_VEC, stimer_isr_auto_eoi);
34669d4bf75SAndrey Smetanin 
3479b910f27SAndrew Jones     on_cpus(stimer_test_prepare, (void *)read_cr3());
3489b910f27SAndrew Jones     on_cpus(stimer_test, NULL);
3499b910f27SAndrew Jones     on_cpus(stimer_test_cleanup, NULL);
35069d4bf75SAndrey Smetanin }
35169d4bf75SAndrey Smetanin 
35269d4bf75SAndrey Smetanin int main(int ac, char **av)
35369d4bf75SAndrey Smetanin {
35469d4bf75SAndrey Smetanin 
35569d4bf75SAndrey Smetanin     if (!synic_supported()) {
356*5c3582f0SJanis Schoetterl-Glausch         report_pass("Hyper-V SynIC is not supported");
35769d4bf75SAndrey Smetanin         goto done;
35869d4bf75SAndrey Smetanin     }
35969d4bf75SAndrey Smetanin 
36069d4bf75SAndrey Smetanin     if (!stimer_supported()) {
361*5c3582f0SJanis Schoetterl-Glausch         report_pass("Hyper-V SynIC timers are not supported");
36269d4bf75SAndrey Smetanin         goto done;
36369d4bf75SAndrey Smetanin     }
36469d4bf75SAndrey Smetanin 
36569d4bf75SAndrey Smetanin     if (!hv_time_ref_counter_supported()) {
366*5c3582f0SJanis Schoetterl-Glausch         report_pass("Hyper-V time reference counter is not supported");
36769d4bf75SAndrey Smetanin         goto done;
36869d4bf75SAndrey Smetanin     }
36969d4bf75SAndrey Smetanin 
37069d4bf75SAndrey Smetanin     stimer_test_all();
37169d4bf75SAndrey Smetanin done:
37269d4bf75SAndrey Smetanin     return report_summary();
37369d4bf75SAndrey Smetanin }
374