1*69d4bf75SAndrey Smetanin #include "libcflat.h" 2*69d4bf75SAndrey Smetanin #include "processor.h" 3*69d4bf75SAndrey Smetanin #include "msr.h" 4*69d4bf75SAndrey Smetanin #include "isr.h" 5*69d4bf75SAndrey Smetanin #include "vm.h" 6*69d4bf75SAndrey Smetanin #include "apic.h" 7*69d4bf75SAndrey Smetanin #include "desc.h" 8*69d4bf75SAndrey Smetanin #include "io.h" 9*69d4bf75SAndrey Smetanin #include "smp.h" 10*69d4bf75SAndrey Smetanin #include "atomic.h" 11*69d4bf75SAndrey Smetanin #include "hyperv.h" 12*69d4bf75SAndrey Smetanin 13*69d4bf75SAndrey Smetanin #define MAX_CPUS 4 14*69d4bf75SAndrey Smetanin 15*69d4bf75SAndrey Smetanin #define SINT1_VEC 0xF1 16*69d4bf75SAndrey Smetanin #define SINT2_VEC 0xF2 17*69d4bf75SAndrey Smetanin 18*69d4bf75SAndrey Smetanin #define SINT1_NUM 2 19*69d4bf75SAndrey Smetanin #define SINT2_NUM 3 20*69d4bf75SAndrey Smetanin #define ONE_MS_IN_100NS 10000 21*69d4bf75SAndrey Smetanin 22*69d4bf75SAndrey Smetanin static atomic_t g_cpus_comp_count; 23*69d4bf75SAndrey Smetanin static int g_cpus_count; 24*69d4bf75SAndrey Smetanin static struct spinlock g_synic_alloc_lock; 25*69d4bf75SAndrey Smetanin 26*69d4bf75SAndrey Smetanin struct stimer { 27*69d4bf75SAndrey Smetanin int sint; 28*69d4bf75SAndrey Smetanin int index; 29*69d4bf75SAndrey Smetanin atomic_t fire_count; 30*69d4bf75SAndrey Smetanin }; 31*69d4bf75SAndrey Smetanin 32*69d4bf75SAndrey Smetanin struct svcpu { 33*69d4bf75SAndrey Smetanin int vcpu; 34*69d4bf75SAndrey Smetanin void *msg_page; 35*69d4bf75SAndrey Smetanin void *evt_page; 36*69d4bf75SAndrey Smetanin struct stimer timer[HV_SYNIC_STIMER_COUNT]; 37*69d4bf75SAndrey Smetanin }; 38*69d4bf75SAndrey Smetanin 39*69d4bf75SAndrey Smetanin static struct svcpu g_synic_vcpu[MAX_CPUS]; 40*69d4bf75SAndrey Smetanin 41*69d4bf75SAndrey Smetanin static void *synic_alloc_page(void) 42*69d4bf75SAndrey Smetanin { 43*69d4bf75SAndrey Smetanin void *page; 44*69d4bf75SAndrey Smetanin 45*69d4bf75SAndrey Smetanin spin_lock(&g_synic_alloc_lock); 46*69d4bf75SAndrey Smetanin page = alloc_page(); 47*69d4bf75SAndrey Smetanin spin_unlock(&g_synic_alloc_lock); 48*69d4bf75SAndrey Smetanin return page; 49*69d4bf75SAndrey Smetanin } 50*69d4bf75SAndrey Smetanin 51*69d4bf75SAndrey Smetanin static void synic_free_page(void *page) 52*69d4bf75SAndrey Smetanin { 53*69d4bf75SAndrey Smetanin spin_lock(&g_synic_alloc_lock); 54*69d4bf75SAndrey Smetanin free_page(page); 55*69d4bf75SAndrey Smetanin spin_unlock(&g_synic_alloc_lock); 56*69d4bf75SAndrey Smetanin } 57*69d4bf75SAndrey Smetanin 58*69d4bf75SAndrey Smetanin static void stimer_init(struct stimer *timer, int index) 59*69d4bf75SAndrey Smetanin { 60*69d4bf75SAndrey Smetanin memset(timer, 0, sizeof(*timer)); 61*69d4bf75SAndrey Smetanin timer->index = index; 62*69d4bf75SAndrey Smetanin } 63*69d4bf75SAndrey Smetanin 64*69d4bf75SAndrey Smetanin static void synic_enable(void) 65*69d4bf75SAndrey Smetanin { 66*69d4bf75SAndrey Smetanin int vcpu = smp_id(), i; 67*69d4bf75SAndrey Smetanin struct svcpu *svcpu = &g_synic_vcpu[vcpu]; 68*69d4bf75SAndrey Smetanin 69*69d4bf75SAndrey Smetanin memset(svcpu, 0, sizeof(*svcpu)); 70*69d4bf75SAndrey Smetanin svcpu->vcpu = vcpu; 71*69d4bf75SAndrey Smetanin svcpu->msg_page = synic_alloc_page(); 72*69d4bf75SAndrey Smetanin for (i = 0; i < ARRAY_SIZE(svcpu->timer); i++) { 73*69d4bf75SAndrey Smetanin stimer_init(&svcpu->timer[i], i); 74*69d4bf75SAndrey Smetanin } 75*69d4bf75SAndrey Smetanin wrmsr(HV_X64_MSR_SIMP, (u64)virt_to_phys(svcpu->msg_page) | 76*69d4bf75SAndrey Smetanin HV_SYNIC_SIMP_ENABLE); 77*69d4bf75SAndrey Smetanin wrmsr(HV_X64_MSR_SCONTROL, HV_SYNIC_CONTROL_ENABLE); 78*69d4bf75SAndrey Smetanin } 79*69d4bf75SAndrey Smetanin 80*69d4bf75SAndrey Smetanin static void stimer_shutdown(struct stimer *timer) 81*69d4bf75SAndrey Smetanin { 82*69d4bf75SAndrey Smetanin wrmsr(HV_X64_MSR_STIMER0_CONFIG + 2*timer->index, 0); 83*69d4bf75SAndrey Smetanin } 84*69d4bf75SAndrey Smetanin 85*69d4bf75SAndrey Smetanin static void process_stimer_expired(struct svcpu *svcpu, struct stimer *timer, 86*69d4bf75SAndrey Smetanin u64 expiration_time, u64 delivery_time) 87*69d4bf75SAndrey Smetanin { 88*69d4bf75SAndrey Smetanin atomic_inc(&timer->fire_count); 89*69d4bf75SAndrey Smetanin } 90*69d4bf75SAndrey Smetanin 91*69d4bf75SAndrey Smetanin static void process_stimer_msg(struct svcpu *svcpu, 92*69d4bf75SAndrey Smetanin struct hv_message *msg, int sint) 93*69d4bf75SAndrey Smetanin { 94*69d4bf75SAndrey Smetanin struct hv_timer_message_payload *payload = 95*69d4bf75SAndrey Smetanin (struct hv_timer_message_payload *)msg->u.payload; 96*69d4bf75SAndrey Smetanin struct stimer *timer; 97*69d4bf75SAndrey Smetanin 98*69d4bf75SAndrey Smetanin if (msg->header.message_type != HVMSG_TIMER_EXPIRED && 99*69d4bf75SAndrey Smetanin msg->header.message_type != HVMSG_NONE) { 100*69d4bf75SAndrey Smetanin report("invalid Hyper-V SynIC msg type", false); 101*69d4bf75SAndrey Smetanin report_summary(); 102*69d4bf75SAndrey Smetanin exit(-1); 103*69d4bf75SAndrey Smetanin return; 104*69d4bf75SAndrey Smetanin } 105*69d4bf75SAndrey Smetanin 106*69d4bf75SAndrey Smetanin if (msg->header.message_type == HVMSG_NONE) { 107*69d4bf75SAndrey Smetanin return; 108*69d4bf75SAndrey Smetanin } 109*69d4bf75SAndrey Smetanin 110*69d4bf75SAndrey Smetanin if (msg->header.payload_size < sizeof(*payload)) { 111*69d4bf75SAndrey Smetanin report("invalid Hyper-V SynIC msg payload size", false); 112*69d4bf75SAndrey Smetanin report_summary(); 113*69d4bf75SAndrey Smetanin exit(-1); 114*69d4bf75SAndrey Smetanin return; 115*69d4bf75SAndrey Smetanin } 116*69d4bf75SAndrey Smetanin 117*69d4bf75SAndrey Smetanin /* Now process timer expiration message */ 118*69d4bf75SAndrey Smetanin 119*69d4bf75SAndrey Smetanin if (payload->timer_index >= ARRAY_SIZE(svcpu->timer)) { 120*69d4bf75SAndrey Smetanin report("invalid Hyper-V SynIC timer index", false); 121*69d4bf75SAndrey Smetanin report_summary(); 122*69d4bf75SAndrey Smetanin exit(-1); 123*69d4bf75SAndrey Smetanin return; 124*69d4bf75SAndrey Smetanin } 125*69d4bf75SAndrey Smetanin timer = &svcpu->timer[payload->timer_index]; 126*69d4bf75SAndrey Smetanin process_stimer_expired(svcpu, timer, payload->expiration_time, 127*69d4bf75SAndrey Smetanin payload->delivery_time); 128*69d4bf75SAndrey Smetanin 129*69d4bf75SAndrey Smetanin msg->header.message_type = HVMSG_NONE; 130*69d4bf75SAndrey Smetanin mb(); 131*69d4bf75SAndrey Smetanin if (msg->header.message_flags.msg_pending) { 132*69d4bf75SAndrey Smetanin wrmsr(HV_X64_MSR_EOM, 0); 133*69d4bf75SAndrey Smetanin } 134*69d4bf75SAndrey Smetanin } 135*69d4bf75SAndrey Smetanin 136*69d4bf75SAndrey Smetanin static void __stimer_isr(int vcpu) 137*69d4bf75SAndrey Smetanin { 138*69d4bf75SAndrey Smetanin struct svcpu *svcpu = &g_synic_vcpu[vcpu]; 139*69d4bf75SAndrey Smetanin struct hv_message_page *msg_page; 140*69d4bf75SAndrey Smetanin struct hv_message *msg; 141*69d4bf75SAndrey Smetanin int i; 142*69d4bf75SAndrey Smetanin 143*69d4bf75SAndrey Smetanin 144*69d4bf75SAndrey Smetanin msg_page = (struct hv_message_page *)svcpu->msg_page; 145*69d4bf75SAndrey Smetanin for (i = 0; i < ARRAY_SIZE(msg_page->sint_message); i++) { 146*69d4bf75SAndrey Smetanin msg = &msg_page->sint_message[i]; 147*69d4bf75SAndrey Smetanin process_stimer_msg(svcpu, msg, i); 148*69d4bf75SAndrey Smetanin } 149*69d4bf75SAndrey Smetanin } 150*69d4bf75SAndrey Smetanin 151*69d4bf75SAndrey Smetanin static void stimer_isr(isr_regs_t *regs) 152*69d4bf75SAndrey Smetanin { 153*69d4bf75SAndrey Smetanin int vcpu = smp_id(); 154*69d4bf75SAndrey Smetanin 155*69d4bf75SAndrey Smetanin __stimer_isr(vcpu); 156*69d4bf75SAndrey Smetanin eoi(); 157*69d4bf75SAndrey Smetanin } 158*69d4bf75SAndrey Smetanin 159*69d4bf75SAndrey Smetanin static void stimer_isr_auto_eoi(isr_regs_t *regs) 160*69d4bf75SAndrey Smetanin { 161*69d4bf75SAndrey Smetanin int vcpu = smp_id(); 162*69d4bf75SAndrey Smetanin 163*69d4bf75SAndrey Smetanin __stimer_isr(vcpu); 164*69d4bf75SAndrey Smetanin } 165*69d4bf75SAndrey Smetanin 166*69d4bf75SAndrey Smetanin static void stimer_start(struct stimer *timer, 167*69d4bf75SAndrey Smetanin bool auto_enable, bool periodic, 168*69d4bf75SAndrey Smetanin u64 tick_100ns, int sint) 169*69d4bf75SAndrey Smetanin { 170*69d4bf75SAndrey Smetanin u64 config, count; 171*69d4bf75SAndrey Smetanin 172*69d4bf75SAndrey Smetanin timer->sint = sint; 173*69d4bf75SAndrey Smetanin atomic_set(&timer->fire_count, 0); 174*69d4bf75SAndrey Smetanin 175*69d4bf75SAndrey Smetanin config = 0; 176*69d4bf75SAndrey Smetanin if (periodic) { 177*69d4bf75SAndrey Smetanin config |= HV_STIMER_PERIODIC; 178*69d4bf75SAndrey Smetanin } 179*69d4bf75SAndrey Smetanin 180*69d4bf75SAndrey Smetanin config |= ((u8)(sint & 0xFF)) << 16; 181*69d4bf75SAndrey Smetanin config |= HV_STIMER_ENABLE; 182*69d4bf75SAndrey Smetanin if (auto_enable) { 183*69d4bf75SAndrey Smetanin config |= HV_STIMER_AUTOENABLE; 184*69d4bf75SAndrey Smetanin } 185*69d4bf75SAndrey Smetanin 186*69d4bf75SAndrey Smetanin if (periodic) { 187*69d4bf75SAndrey Smetanin count = tick_100ns; 188*69d4bf75SAndrey Smetanin } else { 189*69d4bf75SAndrey Smetanin count = rdmsr(HV_X64_MSR_TIME_REF_COUNT) + tick_100ns; 190*69d4bf75SAndrey Smetanin } 191*69d4bf75SAndrey Smetanin 192*69d4bf75SAndrey Smetanin if (!auto_enable) { 193*69d4bf75SAndrey Smetanin wrmsr(HV_X64_MSR_STIMER0_COUNT + timer->index*2, count); 194*69d4bf75SAndrey Smetanin wrmsr(HV_X64_MSR_STIMER0_CONFIG + timer->index*2, config); 195*69d4bf75SAndrey Smetanin } else { 196*69d4bf75SAndrey Smetanin wrmsr(HV_X64_MSR_STIMER0_CONFIG + timer->index*2, config); 197*69d4bf75SAndrey Smetanin wrmsr(HV_X64_MSR_STIMER0_COUNT + timer->index*2, count); 198*69d4bf75SAndrey Smetanin } 199*69d4bf75SAndrey Smetanin } 200*69d4bf75SAndrey Smetanin 201*69d4bf75SAndrey Smetanin static void stimers_shutdown(void) 202*69d4bf75SAndrey Smetanin { 203*69d4bf75SAndrey Smetanin int vcpu = smp_id(), i; 204*69d4bf75SAndrey Smetanin struct svcpu *svcpu = &g_synic_vcpu[vcpu]; 205*69d4bf75SAndrey Smetanin 206*69d4bf75SAndrey Smetanin for (i = 0; i < ARRAY_SIZE(svcpu->timer); i++) { 207*69d4bf75SAndrey Smetanin stimer_shutdown(&svcpu->timer[i]); 208*69d4bf75SAndrey Smetanin } 209*69d4bf75SAndrey Smetanin } 210*69d4bf75SAndrey Smetanin 211*69d4bf75SAndrey Smetanin static void synic_disable(void) 212*69d4bf75SAndrey Smetanin { 213*69d4bf75SAndrey Smetanin int vcpu = smp_id(); 214*69d4bf75SAndrey Smetanin struct svcpu *svcpu = &g_synic_vcpu[vcpu]; 215*69d4bf75SAndrey Smetanin 216*69d4bf75SAndrey Smetanin wrmsr(HV_X64_MSR_SCONTROL, 0); 217*69d4bf75SAndrey Smetanin wrmsr(HV_X64_MSR_SIMP, 0); 218*69d4bf75SAndrey Smetanin wrmsr(HV_X64_MSR_SIEFP, 0); 219*69d4bf75SAndrey Smetanin synic_free_page(svcpu->msg_page); 220*69d4bf75SAndrey Smetanin } 221*69d4bf75SAndrey Smetanin 222*69d4bf75SAndrey Smetanin static void cpu_comp(void) 223*69d4bf75SAndrey Smetanin { 224*69d4bf75SAndrey Smetanin atomic_inc(&g_cpus_comp_count); 225*69d4bf75SAndrey Smetanin } 226*69d4bf75SAndrey Smetanin 227*69d4bf75SAndrey Smetanin static void stimer_test_prepare(void *ctx) 228*69d4bf75SAndrey Smetanin { 229*69d4bf75SAndrey Smetanin int vcpu = smp_id(); 230*69d4bf75SAndrey Smetanin 231*69d4bf75SAndrey Smetanin write_cr3((ulong)ctx); 232*69d4bf75SAndrey Smetanin synic_enable(); 233*69d4bf75SAndrey Smetanin synic_sint_create(vcpu, SINT1_NUM, SINT1_VEC, false); 234*69d4bf75SAndrey Smetanin synic_sint_create(vcpu, SINT2_NUM, SINT2_VEC, true); 235*69d4bf75SAndrey Smetanin cpu_comp(); 236*69d4bf75SAndrey Smetanin } 237*69d4bf75SAndrey Smetanin 238*69d4bf75SAndrey Smetanin static void stimer_test_periodic(int vcpu, struct stimer *timer1, 239*69d4bf75SAndrey Smetanin struct stimer *timer2) 240*69d4bf75SAndrey Smetanin { 241*69d4bf75SAndrey Smetanin /* Check periodic timers */ 242*69d4bf75SAndrey Smetanin stimer_start(timer1, false, true, ONE_MS_IN_100NS, SINT1_NUM); 243*69d4bf75SAndrey Smetanin stimer_start(timer2, false, true, ONE_MS_IN_100NS, SINT2_NUM); 244*69d4bf75SAndrey Smetanin while ((atomic_read(&timer1->fire_count) < 1000) || 245*69d4bf75SAndrey Smetanin (atomic_read(&timer2->fire_count) < 1000)) { 246*69d4bf75SAndrey Smetanin pause(); 247*69d4bf75SAndrey Smetanin } 248*69d4bf75SAndrey Smetanin report("Hyper-V SynIC periodic timers test vcpu %d", true, vcpu); 249*69d4bf75SAndrey Smetanin stimer_shutdown(timer1); 250*69d4bf75SAndrey Smetanin stimer_shutdown(timer2); 251*69d4bf75SAndrey Smetanin } 252*69d4bf75SAndrey Smetanin 253*69d4bf75SAndrey Smetanin static void stimer_test_one_shot(int vcpu, struct stimer *timer) 254*69d4bf75SAndrey Smetanin { 255*69d4bf75SAndrey Smetanin /* Check one-shot timer */ 256*69d4bf75SAndrey Smetanin stimer_start(timer, false, false, ONE_MS_IN_100NS, SINT1_NUM); 257*69d4bf75SAndrey Smetanin while (atomic_read(&timer->fire_count) < 1) { 258*69d4bf75SAndrey Smetanin pause(); 259*69d4bf75SAndrey Smetanin } 260*69d4bf75SAndrey Smetanin report("Hyper-V SynIC one-shot test vcpu %d", true, vcpu); 261*69d4bf75SAndrey Smetanin stimer_shutdown(timer); 262*69d4bf75SAndrey Smetanin } 263*69d4bf75SAndrey Smetanin 264*69d4bf75SAndrey Smetanin static void stimer_test_auto_enable_one_shot(int vcpu, struct stimer *timer) 265*69d4bf75SAndrey Smetanin { 266*69d4bf75SAndrey Smetanin /* Check auto-enable one-shot timer */ 267*69d4bf75SAndrey Smetanin stimer_start(timer, true, false, ONE_MS_IN_100NS, SINT1_NUM); 268*69d4bf75SAndrey Smetanin while (atomic_read(&timer->fire_count) < 1) { 269*69d4bf75SAndrey Smetanin pause(); 270*69d4bf75SAndrey Smetanin } 271*69d4bf75SAndrey Smetanin report("Hyper-V SynIC auto-enable one-shot timer test vcpu %d", true, vcpu); 272*69d4bf75SAndrey Smetanin stimer_shutdown(timer); 273*69d4bf75SAndrey Smetanin } 274*69d4bf75SAndrey Smetanin 275*69d4bf75SAndrey Smetanin static void stimer_test_auto_enable_periodic(int vcpu, struct stimer *timer) 276*69d4bf75SAndrey Smetanin { 277*69d4bf75SAndrey Smetanin /* Check auto-enable periodic timer */ 278*69d4bf75SAndrey Smetanin stimer_start(timer, true, true, ONE_MS_IN_100NS, SINT1_NUM); 279*69d4bf75SAndrey Smetanin while (atomic_read(&timer->fire_count) < 1000) { 280*69d4bf75SAndrey Smetanin pause(); 281*69d4bf75SAndrey Smetanin } 282*69d4bf75SAndrey Smetanin report("Hyper-V SynIC auto-enable periodic timer test vcpu %d", true, vcpu); 283*69d4bf75SAndrey Smetanin stimer_shutdown(timer); 284*69d4bf75SAndrey Smetanin } 285*69d4bf75SAndrey Smetanin 286*69d4bf75SAndrey Smetanin static void stimer_test(void *ctx) 287*69d4bf75SAndrey Smetanin { 288*69d4bf75SAndrey Smetanin int vcpu = smp_id(); 289*69d4bf75SAndrey Smetanin struct svcpu *svcpu = &g_synic_vcpu[vcpu]; 290*69d4bf75SAndrey Smetanin struct stimer *timer1, *timer2; 291*69d4bf75SAndrey Smetanin 292*69d4bf75SAndrey Smetanin irq_enable(); 293*69d4bf75SAndrey Smetanin 294*69d4bf75SAndrey Smetanin timer1 = &svcpu->timer[0]; 295*69d4bf75SAndrey Smetanin timer2 = &svcpu->timer[1]; 296*69d4bf75SAndrey Smetanin 297*69d4bf75SAndrey Smetanin stimer_test_periodic(vcpu, timer1, timer2); 298*69d4bf75SAndrey Smetanin stimer_test_one_shot(vcpu, timer1); 299*69d4bf75SAndrey Smetanin stimer_test_auto_enable_one_shot(vcpu, timer2); 300*69d4bf75SAndrey Smetanin stimer_test_auto_enable_periodic(vcpu, timer1); 301*69d4bf75SAndrey Smetanin 302*69d4bf75SAndrey Smetanin irq_disable(); 303*69d4bf75SAndrey Smetanin cpu_comp(); 304*69d4bf75SAndrey Smetanin } 305*69d4bf75SAndrey Smetanin 306*69d4bf75SAndrey Smetanin static void stimer_test_cleanup(void *ctx) 307*69d4bf75SAndrey Smetanin { 308*69d4bf75SAndrey Smetanin int vcpu = smp_id(); 309*69d4bf75SAndrey Smetanin 310*69d4bf75SAndrey Smetanin stimers_shutdown(); 311*69d4bf75SAndrey Smetanin synic_sint_destroy(vcpu, SINT1_NUM); 312*69d4bf75SAndrey Smetanin synic_sint_destroy(vcpu, SINT2_NUM); 313*69d4bf75SAndrey Smetanin synic_disable(); 314*69d4bf75SAndrey Smetanin cpu_comp(); 315*69d4bf75SAndrey Smetanin } 316*69d4bf75SAndrey Smetanin 317*69d4bf75SAndrey Smetanin static void on_each_cpu_async_wait(void (*func)(void *ctx), void *ctx) 318*69d4bf75SAndrey Smetanin { 319*69d4bf75SAndrey Smetanin int i; 320*69d4bf75SAndrey Smetanin 321*69d4bf75SAndrey Smetanin atomic_set(&g_cpus_comp_count, 0); 322*69d4bf75SAndrey Smetanin for (i = 0; i < g_cpus_count; i++) { 323*69d4bf75SAndrey Smetanin on_cpu_async(i, func, ctx); 324*69d4bf75SAndrey Smetanin } 325*69d4bf75SAndrey Smetanin while (atomic_read(&g_cpus_comp_count) != g_cpus_count) { 326*69d4bf75SAndrey Smetanin pause(); 327*69d4bf75SAndrey Smetanin } 328*69d4bf75SAndrey Smetanin } 329*69d4bf75SAndrey Smetanin 330*69d4bf75SAndrey Smetanin static void stimer_test_all(void) 331*69d4bf75SAndrey Smetanin { 332*69d4bf75SAndrey Smetanin int ncpus; 333*69d4bf75SAndrey Smetanin 334*69d4bf75SAndrey Smetanin setup_vm(); 335*69d4bf75SAndrey Smetanin smp_init(); 336*69d4bf75SAndrey Smetanin setup_idt(); 337*69d4bf75SAndrey Smetanin enable_apic(); 338*69d4bf75SAndrey Smetanin 339*69d4bf75SAndrey Smetanin handle_irq(SINT1_VEC, stimer_isr); 340*69d4bf75SAndrey Smetanin handle_irq(SINT2_VEC, stimer_isr_auto_eoi); 341*69d4bf75SAndrey Smetanin 342*69d4bf75SAndrey Smetanin ncpus = cpu_count(); 343*69d4bf75SAndrey Smetanin if (ncpus > MAX_CPUS) { 344*69d4bf75SAndrey Smetanin ncpus = MAX_CPUS; 345*69d4bf75SAndrey Smetanin } 346*69d4bf75SAndrey Smetanin 347*69d4bf75SAndrey Smetanin printf("cpus = %d\n", ncpus); 348*69d4bf75SAndrey Smetanin g_cpus_count = ncpus; 349*69d4bf75SAndrey Smetanin 350*69d4bf75SAndrey Smetanin on_each_cpu_async_wait(stimer_test_prepare, (void *)read_cr3()); 351*69d4bf75SAndrey Smetanin on_each_cpu_async_wait(stimer_test, NULL); 352*69d4bf75SAndrey Smetanin on_each_cpu_async_wait(stimer_test_cleanup, NULL); 353*69d4bf75SAndrey Smetanin } 354*69d4bf75SAndrey Smetanin 355*69d4bf75SAndrey Smetanin int main(int ac, char **av) 356*69d4bf75SAndrey Smetanin { 357*69d4bf75SAndrey Smetanin 358*69d4bf75SAndrey Smetanin if (!synic_supported()) { 359*69d4bf75SAndrey Smetanin report("Hyper-V SynIC is not supported", true); 360*69d4bf75SAndrey Smetanin goto done; 361*69d4bf75SAndrey Smetanin } 362*69d4bf75SAndrey Smetanin 363*69d4bf75SAndrey Smetanin if (!stimer_supported()) { 364*69d4bf75SAndrey Smetanin report("Hyper-V SynIC timers are not supported", true); 365*69d4bf75SAndrey Smetanin goto done; 366*69d4bf75SAndrey Smetanin } 367*69d4bf75SAndrey Smetanin 368*69d4bf75SAndrey Smetanin if (!hv_time_ref_counter_supported()) { 369*69d4bf75SAndrey Smetanin report("Hyper-V time reference counter is not supported", true); 370*69d4bf75SAndrey Smetanin goto done; 371*69d4bf75SAndrey Smetanin } 372*69d4bf75SAndrey Smetanin 373*69d4bf75SAndrey Smetanin stimer_test_all(); 374*69d4bf75SAndrey Smetanin done: 375*69d4bf75SAndrey Smetanin return report_summary(); 376*69d4bf75SAndrey Smetanin } 377