Mon Dec 15 12:46:28 2008 UTC ()
More paranoia.


(ad)
diff -r1.21 -r1.22 src/sys/arch/x86/x86/tsc.c

cvs diff -r1.21 -r1.22 src/sys/arch/x86/x86/tsc.c (expand / switch to unified diff)

--- src/sys/arch/x86/x86/tsc.c 2008/11/25 15:40:30 1.21
+++ src/sys/arch/x86/x86/tsc.c 2008/12/15 12:46:28 1.22
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: tsc.c,v 1.21 2008/11/25 15:40:30 ad Exp $ */ 1/* $NetBSD: tsc.c,v 1.22 2008/12/15 12:46:28 ad Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -17,51 +17,54 @@ @@ -17,51 +17,54 @@
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.21 2008/11/25 15:40:30 ad Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.22 2008/12/15 12:46:28 ad Exp $");
31 31
32#include <sys/param.h> 32#include <sys/param.h>
33#include <sys/systm.h> 33#include <sys/systm.h>
34#include <sys/time.h> 34#include <sys/time.h>
35#include <sys/timetc.h> 35#include <sys/timetc.h>
36#include <sys/lwp.h> 36#include <sys/lwp.h>
37#include <sys/atomic.h> 37#include <sys/atomic.h>
38#include <sys/kernel.h> 38#include <sys/kernel.h>
39#include <sys/cpu.h> 39#include <sys/cpu.h>
40 40
41#include <machine/cpu_counter.h> 41#include <machine/cpu_counter.h>
42#include <machine/cpuvar.h> 42#include <machine/cpuvar.h>
43#include <machine/cpufunc.h> 43#include <machine/cpufunc.h>
44#include <machine/specialreg.h> 44#include <machine/specialreg.h>
45#include <machine/cputypes.h> 45#include <machine/cputypes.h>
46 46
47#include "tsc.h" 47#include "tsc.h"
48 48
49u_int tsc_get_timecount(struct timecounter *); 49u_int tsc_get_timecount(struct timecounter *);
50 50
51uint64_t tsc_freq; 51uint64_t tsc_freq;
52int64_t tsc_drift_max = 250; /* max cycles */ 52int64_t tsc_drift_max = 250; /* max cycles */
53int64_t tsc_drift_observed; 53int64_t tsc_drift_observed;
54 54
 55static volatile int64_t tsc_sync_val;
 56static volatile struct cpu_info *tsc_sync_cpu;
 57
55static struct timecounter tsc_timecounter = { 58static struct timecounter tsc_timecounter = {
56 .tc_get_timecount = tsc_get_timecount, 59 .tc_get_timecount = tsc_get_timecount,
57 .tc_counter_mask = ~0U, 60 .tc_counter_mask = ~0U,
58 .tc_name = "TSC", 61 .tc_name = "TSC",
59 .tc_quality = 3000, 62 .tc_quality = 3000,
60}; 63};
61 64
62void 65void
63tsc_tc_init(void) 66tsc_tc_init(void)
64{ 67{
65 struct cpu_info *ci; 68 struct cpu_info *ci;
66 uint32_t descs[4]; 69 uint32_t descs[4];
67 bool safe; 70 bool safe;
@@ -158,69 +161,77 @@ tsc_sync_drift(int64_t drift) @@ -158,69 +161,77 @@ tsc_sync_drift(int64_t drift)
158 if (drift > tsc_drift_observed) 161 if (drift > tsc_drift_observed)
159 tsc_drift_observed = drift; 162 tsc_drift_observed = drift;
160} 163}
161 164
162/* 165/*
163 * Called during startup of APs, by the boot processor. Interrupts 166 * Called during startup of APs, by the boot processor. Interrupts
164 * are disabled on entry. 167 * are disabled on entry.
165 */ 168 */
166void 169void
167tsc_sync_bp(struct cpu_info *ci) 170tsc_sync_bp(struct cpu_info *ci)
168{ 171{
169 uint64_t tsc; 172 uint64_t tsc;
170 173
171 /* Clear remote result, pending later update. */ 174 if (atomic_swap_ptr(&tsc_sync_cpu, ci) != NULL) {
172 ci->ci_data.cpu_cc_skew = 0x7fffffffffffffffLL; 175 panic("tsc_sync_bp: 1");
 176 }
173 177
174 /* Flag it and read our TSC. */ 178 /* Flag it and read our TSC. */
175 atomic_or_uint(&ci->ci_flags, CPUF_SYNCTSC); 179 atomic_or_uint(&ci->ci_flags, CPUF_SYNCTSC);
176 tsc = rdmsr(MSR_TSC) >> 1; 180 tsc = rdmsr(MSR_TSC) >> 1;
177 181
178 /* Wait for remote to complete, and read ours again. */ 182 /* Wait for remote to complete, and read ours again. */
179 while ((ci->ci_flags & CPUF_SYNCTSC) != 0) { 183 while ((ci->ci_flags & CPUF_SYNCTSC) != 0) {
180 __insn_barrier(); 184 __insn_barrier();
181 } 185 }
182 tsc += (rdmsr(MSR_TSC) >> 1); 186 tsc += (rdmsr(MSR_TSC) >> 1);
183 187
184 /* Wait for the results to come in. */ 188 /* Wait for the results to come in. */
185 while (ci->ci_data.cpu_cc_skew == 0x7fffffffffffffffLL) { 189 while (tsc_sync_cpu == ci) {
186 x86_pause(); 190 x86_pause();
187 } 191 }
 192 if (tsc_sync_cpu != NULL) {
 193 panic("tsc_sync_bp: 2");
 194 }
188 195
189 /* Compute final value to adjust for skew. */ 196 /* Compute final value to adjust for skew. */
190 ci->ci_data.cpu_cc_skew = tsc - ci->ci_data.cpu_cc_skew; 197 ci->ci_data.cpu_cc_skew = tsc - tsc_sync_val;
191} 198}
192 199
193/* 200/*
194 * Called during startup of AP, by the AP itself. Interrupts are 201 * Called during startup of AP, by the AP itself. Interrupts are
195 * disabled on entry. 202 * disabled on entry.
196 */ 203 */
197void 204void
198tsc_sync_ap(struct cpu_info *ci) 205tsc_sync_ap(struct cpu_info *ci)
199{ 206{
200 uint64_t tsc; 207 uint64_t tsc;
201 208
202 /* Wait for go-ahead from primary. */ 209 /* Wait for go-ahead from primary. */
203 while ((ci->ci_flags & CPUF_SYNCTSC) == 0) { 210 while ((ci->ci_flags & CPUF_SYNCTSC) == 0) {
204 __insn_barrier(); 211 __insn_barrier();
205 } 212 }
206 tsc = (rdmsr(MSR_TSC) >> 1); 213 tsc = (rdmsr(MSR_TSC) >> 1);
207 214
208 /* Instruct primary to read its counter. */ 215 /* Instruct primary to read its counter. */
209 atomic_and_uint(&ci->ci_flags, ~CPUF_SYNCTSC); 216 atomic_and_uint(&ci->ci_flags, ~CPUF_SYNCTSC);
210 tsc += (rdmsr(MSR_TSC) >> 1); 217 tsc += (rdmsr(MSR_TSC) >> 1);
211 218
212 /* Post result. Ensure the whole value goes out atomically. */ 219 /* Post result. Ensure the whole value goes out atomically. */
213 (void)atomic_swap_64(&ci->ci_data.cpu_cc_skew, tsc); 220 (void)atomic_swap_64(&tsc_sync_val, tsc);
 221
 222 if (atomic_swap_ptr(&tsc_sync_cpu, NULL) != ci) {
 223 panic("tsc_sync_ap");
 224 }
214} 225}
215 226
216uint64_t 227uint64_t
217cpu_frequency(struct cpu_info *ci) 228cpu_frequency(struct cpu_info *ci)
218{ 229{
219 230
220 return ci->ci_data.cpu_cc_freq; 231 return ci->ci_data.cpu_cc_freq;
221} 232}
222 233
223int 234int
224cpu_hascounter(void) 235cpu_hascounter(void)
225{ 236{
226 237