Index: sys/x86/x86/identcpu.c =================================================================== --- sys/x86/x86/identcpu.c +++ sys/x86/x86/identcpu.c @@ -65,6 +65,7 @@ #include #include #include +#include #ifdef __i386__ #if !defined(CPU_DISABLE_SSE) && defined(I686_CPU) @@ -1268,6 +1269,22 @@ NULL }; +#define HV_X64_MSR_TIME_REF_COUNT 0x40000020 + +/* Wait "n" microseconds. */ +static void +hyperv_delay(int n) +{ + uint64_t now, end; + + /* The time counter has a fixed frequency of 10MHz */ + now = rdmsr(HV_X64_MSR_TIME_REF_COUNT); + end = now + n * 10; + + while (now < end) + now = rdmsr(HV_X64_MSR_TIME_REF_COUNT); +} + static void identify_hypervisor(void) { @@ -1294,8 +1311,12 @@ hv_vendor[12] = '\0'; if (strcmp(hv_vendor, "VMwareVMware") == 0) vm_guest = VM_GUEST_VMWARE; - else if (strcmp(hv_vendor, "Microsoft Hv") == 0) + else if (strcmp(hv_vendor, "Microsoft Hv") == 0) { vm_guest = VM_GUEST_HV; + + /* Hyper-V's i8254 emulation is unreliable */ + init_ops.early_delay = hyperv_delay; + } } return; }