summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/include/clock.h3
-rw-r--r--sys/amd64/vmm/x86.c19
-rw-r--r--sys/x86/x86/tsc.c2
3 files changed, 22 insertions, 2 deletions
diff --git a/sys/amd64/include/clock.h b/sys/amd64/include/clock.h
index d2602d8..d7f7d82 100644
--- a/sys/amd64/include/clock.h
+++ b/sys/amd64/include/clock.h
@@ -20,6 +20,9 @@ extern int i8254_max_count;
extern uint64_t tsc_freq;
extern int tsc_is_invariant;
extern int tsc_perf_stat;
+#ifdef SMP
+extern int smp_tsc;
+#endif
void i8254_init(void);
diff --git a/sys/amd64/vmm/x86.c b/sys/amd64/vmm/x86.c
index 13eaaad..fa2eabc 100644
--- a/sys/amd64/vmm/x86.c
+++ b/sys/amd64/vmm/x86.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/cpuset.h>
+#include <machine/clock.h>
#include <machine/cpufunc.h>
#include <machine/md_var.h>
#include <machine/specialreg.h>
@@ -89,11 +90,27 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id,
case CPUID_8000_0003:
case CPUID_8000_0004:
case CPUID_8000_0006:
- case CPUID_8000_0007:
case CPUID_8000_0008:
cpuid_count(*eax, *ecx, regs);
break;
+ case CPUID_8000_0007:
+ cpuid_count(*eax, *ecx, regs);
+ /*
+ * If the host TSCs are not synchronized across
+ * physical cpus then we cannot advertise an
+ * invariant tsc to a vcpu.
+ *
+ * XXX This still falls short because the vcpu
+ * can observe the TSC moving backwards as it
+ * migrates across physical cpus. But at least
+ * it should discourage the guest from using the
+ * TSC to keep track of time.
+ */
+ if (!smp_tsc)
+ regs[3] &= ~AMDPM_TSC_INVARIANT;
+ break;
+
case CPUID_0000_0001:
do_cpuid(1, regs);
diff --git a/sys/x86/x86/tsc.c b/sys/x86/x86/tsc.c
index 4f67818..0994e9c 100644
--- a/sys/x86/x86/tsc.c
+++ b/sys/x86/x86/tsc.c
@@ -61,7 +61,7 @@ SYSCTL_INT(_kern_timecounter, OID_AUTO, invariant_tsc, CTLFLAG_RDTUN,
TUNABLE_INT("kern.timecounter.invariant_tsc", &tsc_is_invariant);
#ifdef SMP
-static int smp_tsc;
+int smp_tsc;
SYSCTL_INT(_kern_timecounter, OID_AUTO, smp_tsc, CTLFLAG_RDTUN, &smp_tsc, 0,
"Indicates whether the TSC is safe to use in SMP mode");
TUNABLE_INT("kern.timecounter.smp_tsc", &smp_tsc);
OpenPOWER on IntegriCloud