summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjkim <jkim@FreeBSD.org>2011-03-11 00:44:32 +0000
committerjkim <jkim@FreeBSD.org>2011-03-11 00:44:32 +0000
commit7df55dcdeb4359716cc7b6a3381d2772e1187d62 (patch)
treec5a4a6ac9d73738d09f204667eb641e541525a80 /sys
parent8c8d7206ece7a4dc88c61d5910c6724b0137b26a (diff)
downloadFreeBSD-src-7df55dcdeb4359716cc7b6a3381d2772e1187d62.zip
FreeBSD-src-7df55dcdeb4359716cc7b6a3381d2772e1187d62.tar.gz
Add a tunable "machdep.disable_tsc" to turn off TSC. Specifically, it turns
off boot-time CPU frequency calibration, DELAY(9) with TSC, and using TSC as a CPU ticker. Note tsc_present does not change by this tunable.
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/machdep.c37
-rw-r--r--sys/contrib/altq/altq/altq_subr.c4
-rw-r--r--sys/i386/i386/machdep.c25
-rw-r--r--sys/pc98/pc98/machdep.c23
-rw-r--r--sys/x86/x86/tsc.c18
5 files changed, 71 insertions, 36 deletions
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 0bb552c..808dc08 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -80,6 +80,9 @@ __FBSDID("$FreeBSD$");
#include <sys/reboot.h>
#include <sys/sched.h>
#include <sys/signalvar.h>
+#ifdef SMP
+#include <sys/smp.h>
+#endif
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/sysent.h>
@@ -544,20 +547,22 @@ cpu_est_clockrate(int cpu_id, uint64_t *rate)
return (EINVAL);
/* If TSC is P-state invariant, DELAY(9) based logic fails. */
- if (tsc_is_invariant)
+ if (tsc_is_invariant && tsc_freq != 0)
return (EOPNOTSUPP);
/* If we're booting, trust the rate calibrated moments ago. */
- if (cold) {
+ if (cold && tsc_freq != 0) {
*rate = tsc_freq;
return (0);
}
#ifdef SMP
- /* Schedule ourselves on the indicated cpu. */
- thread_lock(curthread);
- sched_bind(curthread, cpu_id);
- thread_unlock(curthread);
+ if (smp_cpus > 1) {
+ /* Schedule ourselves on the indicated cpu. */
+ thread_lock(curthread);
+ sched_bind(curthread, cpu_id);
+ thread_unlock(curthread);
+ }
#endif
/* Calibrate by measuring a short delay. */
@@ -568,12 +573,24 @@ cpu_est_clockrate(int cpu_id, uint64_t *rate)
intr_restore(reg);
#ifdef SMP
- thread_lock(curthread);
- sched_unbind(curthread);
- thread_unlock(curthread);
+ if (smp_cpus > 1) {
+ thread_lock(curthread);
+ sched_unbind(curthread);
+ thread_unlock(curthread);
+ }
#endif
- *rate = (tsc2 - tsc1) * 1000;
+ tsc2 -= tsc1;
+ if (tsc_freq != 0) {
+ *rate = tsc2 * 1000;
+ return (0);
+ }
+
+ /*
+ * Subtract 0.5% of the total. Empirical testing has shown that
+ * overhead in DELAY() works out to approximately this value.
+ */
+ *rate = tsc2 * 1000 - tsc2 * 5;
return (0);
}
diff --git a/sys/contrib/altq/altq/altq_subr.c b/sys/contrib/altq/altq/altq_subr.c
index 7d2fc77..a58747d 100644
--- a/sys/contrib/altq/altq/altq_subr.c
+++ b/sys/contrib/altq/altq/altq_subr.c
@@ -78,10 +78,10 @@
#include <machine/clock.h>
#endif
#if defined(__amd64__) || defined(__i386__)
+#include <machine/cpu.h> /* for cpu_feature or tsc_present */
#include <machine/cpufunc.h> /* for pentium tsc */
#if defined(__NetBSD__) || defined(__OpenBSD__)
#include <machine/specialreg.h> /* for CPUID_TSC */
-#include <machine/cpu.h> /* for cpu_feature */
#endif
#endif /* __amd64 || __i386__ */
@@ -927,7 +927,7 @@ init_machclk_setup(void)
#if defined(__amd64__) || defined(__i386__)
/* check if TSC is available */
#ifdef __FreeBSD__
- if (tsc_freq == 0)
+ if (!tsc_present || tsc_freq == 0)
#else
if ((cpu_feature & CPUID_TSC) == 0)
#endif
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index c5c0dfc..a87095f 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -79,6 +79,9 @@ __FBSDID("$FreeBSD$");
#include <sys/reboot.h>
#include <sys/sched.h>
#include <sys/signalvar.h>
+#ifdef SMP
+#include <sys/smp.h>
+#endif
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/sysent.h>
@@ -1142,20 +1145,22 @@ cpu_est_clockrate(int cpu_id, uint64_t *rate)
return (EOPNOTSUPP);
/* If TSC is P-state invariant, DELAY(9) based logic fails. */
- if (tsc_is_invariant)
+ if (tsc_is_invariant && tsc_freq != 0)
return (EOPNOTSUPP);
/* If we're booting, trust the rate calibrated moments ago. */
- if (cold) {
+ if (cold && tsc_freq != 0) {
*rate = tsc_freq;
return (0);
}
#ifdef SMP
- /* Schedule ourselves on the indicated cpu. */
- thread_lock(curthread);
- sched_bind(curthread, cpu_id);
- thread_unlock(curthread);
+ if (smp_cpus > 1) {
+ /* Schedule ourselves on the indicated cpu. */
+ thread_lock(curthread);
+ sched_bind(curthread, cpu_id);
+ thread_unlock(curthread);
+ }
#endif
/* Calibrate by measuring a short delay. */
@@ -1166,9 +1171,11 @@ cpu_est_clockrate(int cpu_id, uint64_t *rate)
intr_restore(reg);
#ifdef SMP
- thread_lock(curthread);
- sched_unbind(curthread);
- thread_unlock(curthread);
+ if (smp_cpus > 1) {
+ thread_lock(curthread);
+ sched_unbind(curthread);
+ thread_unlock(curthread);
+ }
#endif
tsc2 -= tsc1;
diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c
index 07b3b84..c1d065c 100644
--- a/sys/pc98/pc98/machdep.c
+++ b/sys/pc98/pc98/machdep.c
@@ -77,6 +77,9 @@ __FBSDID("$FreeBSD$");
#include <sys/reboot.h>
#include <sys/sched.h>
#include <sys/signalvar.h>
+#ifdef SMP
+#include <sys/smp.h>
+#endif
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/sysent.h>
@@ -1077,16 +1080,18 @@ cpu_est_clockrate(int cpu_id, uint64_t *rate)
return (EOPNOTSUPP);
/* If we're booting, trust the rate calibrated moments ago. */
- if (cold) {
+ if (cold && tsc_freq != 0) {
*rate = tsc_freq;
return (0);
}
#ifdef SMP
- /* Schedule ourselves on the indicated cpu. */
- thread_lock(curthread);
- sched_bind(curthread, cpu_id);
- thread_unlock(curthread);
+ if (smp_cpus > 1) {
+ /* Schedule ourselves on the indicated cpu. */
+ thread_lock(curthread);
+ sched_bind(curthread, cpu_id);
+ thread_unlock(curthread);
+ }
#endif
/* Calibrate by measuring a short delay. */
@@ -1097,9 +1102,11 @@ cpu_est_clockrate(int cpu_id, uint64_t *rate)
intr_restore(reg);
#ifdef SMP
- thread_lock(curthread);
- sched_unbind(curthread);
- thread_unlock(curthread);
+ if (smp_cpus > 1) {
+ thread_lock(curthread);
+ sched_unbind(curthread);
+ thread_unlock(curthread);
+ }
#endif
tsc2 -= tsc1;
diff --git a/sys/x86/x86/tsc.c b/sys/x86/x86/tsc.c
index 3e0300b..40d5f3c 100644
--- a/sys/x86/x86/tsc.c
+++ b/sys/x86/x86/tsc.c
@@ -63,6 +63,11 @@ SYSCTL_INT(_kern_timecounter, OID_AUTO, smp_tsc, CTLFLAG_RDTUN, &smp_tsc, 0,
TUNABLE_INT("kern.timecounter.smp_tsc", &smp_tsc);
#endif
+static int tsc_disabled;
+SYSCTL_INT(_machdep, OID_AUTO, disable_tsc, CTLFLAG_RDTUN, &tsc_disabled, 0,
+ "Disable x86 Time Stamp Counter");
+TUNABLE_INT("machdep.disable_tsc", &tsc_disabled);
+
static void tsc_freq_changed(void *arg, const struct cf_level *level,
int status);
static void tsc_freq_changing(void *arg, const struct cf_level *level,
@@ -84,12 +89,11 @@ init_TSC(void)
{
u_int64_t tscval[2];
- if (cpu_feature & CPUID_TSC)
- tsc_present = 1;
- else
- tsc_present = 0;
+ if ((cpu_feature & CPUID_TSC) == 0)
+ return;
+ tsc_present = 1;
- if (!tsc_present)
+ if (tsc_disabled)
return;
if (bootverbose)
@@ -151,7 +155,7 @@ void
init_TSC_tc(void)
{
- if (!tsc_present)
+ if (!tsc_present || tsc_disabled)
return;
/*
@@ -248,7 +252,7 @@ tsc_freq_changed(void *arg, const struct cf_level *level, int status)
{
/* If there was an error during the transition, don't do anything. */
- if (status != 0)
+ if (tsc_disabled || status != 0)
return;
/* Total setting for this level gives the new frequency in MHz. */
OpenPOWER on IntegriCloud