# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1274949587 -3600
# Node ID 26c2922da53cb2b36ef9484bbd6d74ea74b1c354
# Parent 26a0942a9c180c38a91aa223cfd3e6766a93c1fa
x86: Synchronize slave TSC to master if necessary, during cpu bringup
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
xen/arch/x86/smpboot.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 49 insertions(+)
diff -r 26a0942a9c18 -r 26c2922da53c xen/arch/x86/smpboot.c
--- a/xen/arch/x86/smpboot.c Thu May 27 09:04:46 2010 +0100
+++ b/xen/arch/x86/smpboot.c Thu May 27 09:39:47 2010 +0100
@@ -132,6 +132,49 @@ static void smp_store_cpu_info(int id)
;
}
+static atomic_t tsc_count;
+static uint64_t tsc_value;
+static cpumask_t tsc_sync_cpu_mask;
+
+static void synchronize_tsc_master(unsigned int slave)
+{
+ unsigned int i;
+
+ if ( boot_cpu_has(X86_FEATURE_TSC_RELIABLE) &&
+ !cpu_isset(slave, tsc_sync_cpu_mask) )
+ return;
+
+ for ( i = 1; i <= 5; i++ )
+ {
+ rdtscll(tsc_value);
+ wmb();
+ atomic_inc(&tsc_count);
+ while ( atomic_read(&tsc_count) != (i<<1) )
+ cpu_relax();
+ }
+
+ atomic_set(&tsc_count, 0);
+ cpu_clear(slave, tsc_sync_cpu_mask);
+}
+
+static void synchronize_tsc_slave(unsigned int slave)
+{
+ unsigned int i;
+
+ if ( boot_cpu_has(X86_FEATURE_TSC_RELIABLE) &&
+ !cpu_isset(slave, tsc_sync_cpu_mask) )
+ return;
+
+ for ( i = 1; i <= 5; i++ )
+ {
+ while ( atomic_read(&tsc_count) != ((i<<1)-1) )
+ cpu_relax();
+ rmb();
+ write_tsc(tsc_value);
+ atomic_inc(&tsc_count);
+ }
+}
+
void smp_callin(void)
{
unsigned int cpu = smp_processor_id();
@@ -172,6 +215,8 @@ void smp_callin(void)
/* Allow the master to continue. */
set_cpu_state(CPU_STATE_CALLIN);
+
+ synchronize_tsc_slave(cpu);
/* And wait for our final Ack. */
while ( cpu_state != CPU_STATE_ONLINE )
@@ -532,6 +577,7 @@ static int do_boot_cpu(int apicid, int c
/* number CPUs logically, starting from 1 (BSP is 0) */
Dprintk("OK.\n");
print_cpu_info(cpu);
+ synchronize_tsc_master(cpu);
Dprintk("CPU has booted.\n");
}
else if ( cpu_state == CPU_STATE_DEAD )
@@ -876,6 +922,9 @@ int cpu_add(uint32_t apic_id, uint32_t a
apicid_to_node[apic_id] = node;
}
+ /* Physically added CPUs do not have synchronised TSC. */
+ cpu_set(cpu, tsc_sync_cpu_mask);
+
srat_detect_node(cpu);
numa_add_cpu(cpu);
dprintk(XENLOG_INFO, "Add CPU %x with index %x\n", apic_id, cpu);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|