diff --git a/sys/arch/x86/x86/tsc.c b/sys/arch/x86/x86/tsc.c index 994e6b8e4361..350025376e80 100644 --- a/sys/arch/x86/x86/tsc.c +++ b/sys/arch/x86/x86/tsc.c @@ -1,4 +1,4 @@ -/* $NetBSD: tsc.c,v 1.23 2008/12/19 11:11:55 ad Exp $ */ +/* $NetBSD: tsc.c,v 1.24 2008/12/19 11:21:52 ad Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -27,7 +27,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.23 2008/12/19 11:11:55 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.24 2008/12/19 11:21:52 ad Exp $"); #include #include @@ -52,6 +52,9 @@ uint64_t tsc_freq; int64_t tsc_drift_max = 250; /* max cycles */ int64_t tsc_drift_observed; +static volatile int64_t tsc_sync_val; +static volatile struct cpu_info *tsc_sync_cpu; + static struct timecounter tsc_timecounter = { .tc_get_timecount = tsc_get_timecount, .tc_counter_mask = ~0U, @@ -168,8 +171,9 @@ tsc_sync_bp(struct cpu_info *ci) { uint64_t tsc; - /* Clear remote result, pending later update. */ - ci->ci_data.cpu_cc_skew = 0x7fffffffffffffffLL; + if (atomic_swap_ptr(&tsc_sync_cpu, ci) != NULL) { + panic("tsc_sync_bp: 1"); + } /* Flag it and read our TSC. */ atomic_or_uint(&ci->ci_flags, CPUF_SYNCTSC); @@ -182,12 +186,15 @@ tsc_sync_bp(struct cpu_info *ci) tsc += (rdmsr(MSR_TSC) >> 1); /* Wait for the results to come in. */ - while (ci->ci_data.cpu_cc_skew == 0x7fffffffffffffffLL) { + while (tsc_sync_cpu == ci) { x86_pause(); } + if (tsc_sync_cpu != NULL) { + panic("tsc_sync_bp: 2"); + } /* Compute final value to adjust for skew. */ - ci->ci_data.cpu_cc_skew = tsc - ci->ci_data.cpu_cc_skew; + ci->ci_data.cpu_cc_skew = tsc - tsc_sync_val; } /* @@ -210,7 +217,11 @@ tsc_sync_ap(struct cpu_info *ci) tsc += (rdmsr(MSR_TSC) >> 1); /* Post result. Ensure the whole value goes out atomically. */ - (void)atomic_swap_64(&ci->ci_data.cpu_cc_skew, tsc); + (void)atomic_swap_64(&tsc_sync_val, tsc); + + if (atomic_swap_ptr(&tsc_sync_cpu, NULL) != ci) { + panic("tsc_sync_ap"); + } } uint64_t