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