#include <asm/flushtlb.h>
#include <asm/msr.h>
#include <asm/mtrr.h>
+#include <asm/time.h>
#include <mach_apic.h>
#include <mach_wakecpu.h>
#include <smpboot_hooks.h>
;
}
+/*
+ * TSC's upper 32 bits can't be written in earlier CPUs (before
+ * Prescott), there is no way to resync one AP against BP.
+ */
+bool_t disable_tsc_sync;
+
static atomic_t tsc_count;
static uint64_t tsc_value;
static cpumask_t tsc_sync_cpu_mask;
{
unsigned int i;
+ if ( disable_tsc_sync )
+ return;
+
if ( boot_cpu_has(X86_FEATURE_TSC_RELIABLE) &&
!cpu_isset(slave, tsc_sync_cpu_mask) )
return;
{
unsigned int i;
+ if ( disable_tsc_sync )
+ return;
+
if ( boot_cpu_has(X86_FEATURE_TSC_RELIABLE) &&
!cpu_isset(slave, tsc_sync_cpu_mask) )
return;
#include <xen/smp.h>
#include <xen/irq.h>
#include <xen/softirq.h>
+#include <xen/cpuidle.h>
#include <xen/symbols.h>
#include <xen/keyhandler.h>
#include <xen/guest_access.h>
if ( boot_cpu_has(X86_FEATURE_NONSTOP_TSC) )
return;
+ ASSERT(boot_cpu_has(X86_FEATURE_TSC_RELIABLE));
+
write_tsc(stime2tsc(read_platform_stime()));
}
}
}
+/*
+ * On certain older Intel CPUs writing the TSC MSR clears the upper 32 bits.
+ * Obviously we must not use write_tsc() on such CPUs.
+ *
+ * Additionally, AMD specifies that being able to write the TSC MSR is not an
+ * architectural feature (but, other than their manual says, also cannot be
+ * determined from CPUID bits).
+ */
+static void __init tsc_check_writability(void)
+{
+ const char *what = NULL;
+ uint64_t tsc;
+
+ /*
+ * If all CPUs are reported as synchronised and in sync, we never write
+ * the TSCs (except unavoidably, when a CPU is physically hot-plugged).
+ * Hence testing for writability is pointless and even harmful.
+ */
+ if ( boot_cpu_has(X86_FEATURE_TSC_RELIABLE) )
+ return;
+
+ rdtscll(tsc);
+ if ( wrmsr_safe(MSR_IA32_TSC, 0) == 0 )
+ {
+ uint64_t tmp, tmp2;
+ rdtscll(tmp2);
+ write_tsc(tsc | (1ULL << 32));
+ rdtscll(tmp);
+ if ( ABS((s64)tmp - (s64)tmp2) < (1LL << 31) )
+ what = "only partially";
+ }
+ else
+ {
+ what = "not";
+ }
+
+ /* Nothing to do if the TSC is fully writable. */
+ if ( !what )
+ {
+ /*
+ * Paranoia - write back original TSC value. However, APs get synced
+ * with BSP as they are brought up, so this doesn't much matter.
+ */
+ write_tsc(tsc);
+ return;
+ }
+
+ printk(XENLOG_WARNING "TSC %s writable\n", what);
+
+ /* time_calibration_tsc_rendezvous() must not be used */
+ setup_clear_cpu_cap(X86_FEATURE_CONSTANT_TSC);
+
+ /* cstate_restore_tsc() must not be used (or do nothing) */
+ if ( !boot_cpu_has(X86_FEATURE_NONSTOP_TSC) )
+ cpuidle_disable_deep_cstate();
+
+ /* synchronize_tsc_slave() must do nothing */
+ disable_tsc_sync = 1;
+}
+
/* Late init function (after all CPUs are booted). */
int __init init_xen_time(void)
{
setup_clear_cpu_cap(X86_FEATURE_TSC_RELIABLE);
}
+ tsc_check_writability();
+
/* If we have constant-rate TSCs then scale factor can be shared. */
if ( boot_cpu_has(X86_FEATURE_CONSTANT_TSC) )
{
* XXX dom0 may rely on RTC interrupt delivery, so only enable
* hpet_broadcast if FSB mode available or if force_hpet_broadcast.
*/
- if ( xen_cpuidle && !boot_cpu_has(X86_FEATURE_ARAT) )
+ if ( cpuidle_using_deep_cstate() && !boot_cpu_has(X86_FEATURE_ARAT) )
{
hpet_broadcast_setup();
if ( !hpet_broadcast_is_available() )