Index: sys/x86/x86/tsc.c =================================================================== --- sys/x86/x86/tsc.c +++ sys/x86/x86/tsc.c @@ -57,6 +57,7 @@ uint64_t tsc_freq; int tsc_is_invariant; int tsc_perf_stat; +static int tsc_vm_enable = 0; static eventhandler_tag tsc_levels_tag, tsc_pre_tag, tsc_post_tag; @@ -86,6 +87,8 @@ CTLFLAG_NOFETCH, &tsc_skip_calibration, 0, "Disable TSC frequency calibration"); +SYSCTL_INT(_machdep, OID_AUTO, tsc_vm_enable, CTLFLAG_RDTUN, &tsc_vm_enable, 0, "Allow to use tsc in guest-mode"); + static void tsc_freq_changed(void *arg, const struct cf_level *level, int status); static void tsc_freq_changing(void *arg, const struct cf_level *level, @@ -115,6 +118,12 @@ #endif }; +static inline bool +tsc_vm_guest_allowed(void) +{ + return vm_guest == VM_GUEST_NO || tsc_vm_enable; +} + static void tsc_freq_vmware(void) { @@ -241,7 +250,7 @@ switch (cpu_vendor_id) { case CPU_VENDOR_AMD: if ((amd_pminfo & AMDPM_TSC_INVARIANT) != 0 || - (vm_guest == VM_GUEST_NO && + (tsc_vm_guest_allowed() && CPUID_TO_FAMILY(cpu_id) >= 0x10)) tsc_is_invariant = 1; if (cpu_feature & CPUID_SSE2) { @@ -251,7 +260,7 @@ break; case CPU_VENDOR_INTEL: if ((amd_pminfo & AMDPM_TSC_INVARIANT) != 0 || - (vm_guest == VM_GUEST_NO && + (tsc_vm_guest_allowed() && ((CPUID_TO_FAMILY(cpu_id) == 0x6 && CPUID_TO_MODEL(cpu_id) >= 0xe) || (CPUID_TO_FAMILY(cpu_id) == 0xf && @@ -263,7 +272,7 @@ } break; case CPU_VENDOR_CENTAUR: - if (vm_guest == VM_GUEST_NO && + if (tsc_vm_guest_allowed() && CPUID_TO_FAMILY(cpu_id) == 0x6 && CPUID_TO_MODEL(cpu_id) >= 0xf && (rdmsr(0x1203) & 0x100000000ULL) == 0) @@ -478,7 +487,7 @@ uint64_t *data, *tsc; u_int i, size, adj; - if ((!smp_tsc && !tsc_is_invariant) || vm_guest) + if ((!smp_tsc && !tsc_is_invariant) || !tsc_vm_guest_allowed()) return (-100); size = (mp_maxid + 1) * 3; data = malloc(sizeof(*data) * size * N, M_TEMP, M_WAITOK);