summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2003-04-10 23:07:24 +0000
committerdes <des@FreeBSD.org>2003-04-10 23:07:24 +0000
commit6366f8a79628b89a774e412272088d4b9d6bb701 (patch)
tree19d966fd201d46f2ef2673a4481767d664ba8249
parentea793948f7e836abfe00c166d6989e6d17d31e99 (diff)
downloadFreeBSD-src-6366f8a79628b89a774e412272088d4b9d6bb701.zip
FreeBSD-src-6366f8a79628b89a774e412272088d4b9d6bb701.tar.gz
Convert the SMP_TSC kernel option into a loader tunable. Also enable
the TSC timecounter on single-CPU systems even when they are running an SMP kernel.
-rw-r--r--sys/amd64/amd64/tsc.c25
-rw-r--r--sys/conf/options.i3861
-rw-r--r--sys/i386/conf/NOTES5
-rw-r--r--sys/i386/i386/tsc.c25
-rw-r--r--sys/sys/timetc.h4
5 files changed, 40 insertions, 20 deletions
diff --git a/sys/amd64/amd64/tsc.c b/sys/amd64/amd64/tsc.c
index abc6a93..36ae1b9 100644
--- a/sys/amd64/amd64/tsc.c
+++ b/sys/amd64/amd64/tsc.c
@@ -30,11 +30,12 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/sysctl.h>
#include <sys/time.h>
#include <sys/timetc.h>
#include <sys/kernel.h>
-#include <sys/sysctl.h>
#include <sys/power.h>
+#include <sys/smp.h>
#include <machine/clock.h>
#include <machine/md_var.h>
#include <machine/specialreg.h>
@@ -43,6 +44,13 @@ uint64_t tsc_freq;
int tsc_is_broken;
u_int tsc_present;
+#ifdef SMP
+static int smp_tsc;
+SYSCTL_INT(_kern_timecounter, OID_AUTO, smp_tsc, CTLFLAG_RD, &smp_tsc, 0,
+ "Indicates whether the TSC is safe to use in SMP mode");
+TUNABLE_INT("kern.timecounter.smp_tsc", &smp_tsc);
+#endif
+
static unsigned tsc_get_timecount(struct timecounter *tc);
static struct timecounter tsc_timecounter = {
@@ -77,14 +85,17 @@ init_TSC(void)
if (bootverbose)
printf("TSC clock: %ju Hz\n", (intmax_t)tsc_freq);
-#if defined(SMP) && !defined(SMP_TSC)
+#ifdef SMP
/*
- * We can not use the TSC in SMP mode, until we figure out a
- * cheap (impossible), reliable and precise (yeah right!) way
- * to synchronize the TSCs of all the CPUs.
- * Modern SMP hardware has the ACPI timer and we use that.
+ * We can not use the TSC in SMP mode unless the TSCs on all CPUs
+ * are somehow synchronized. Some hardware configurations do
+ * this, but we have no way of determining whether this is the
+ * case, so we do not use the TSC in multi-processor systems
+ * unless the user indicated (by setting kern.timecounter.smp_tsc
+ * to 1) that he believes that his TSCs are synchronized.
*/
- return;
+ if (mp_ncpus > 1 && !smp_tsc)
+ return;
#endif
/*
diff --git a/sys/conf/options.i386 b/sys/conf/options.i386
index d60b57e..de784be 100644
--- a/sys/conf/options.i386
+++ b/sys/conf/options.i386
@@ -41,7 +41,6 @@ PAE opt_global.h
CLK_CALIBRATION_LOOP opt_clock.h
CLK_USE_I8254_CALIBRATION opt_clock.h
CLK_USE_TSC_CALIBRATION opt_clock.h
-SMP_TSC opt_clock.h
TIMER_FREQ opt_clock.h
NO_F00F_HACK opt_cpu.h
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index 6b0fb42..46bebdd 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -247,11 +247,6 @@ options CLK_CALIBRATION_LOOP
options CLK_USE_I8254_CALIBRATION
options CLK_USE_TSC_CALIBRATION
-# One some SMP mainboards, the TSCs can be used in SMP mode due to
-# them being synchronized. This can significantly reduce the context
-# switch cost.
-options SMP_TSC
-
#####################################################################
# MISCELLANEOUS DEVICES AND OPTIONS
diff --git a/sys/i386/i386/tsc.c b/sys/i386/i386/tsc.c
index abc6a93..36ae1b9 100644
--- a/sys/i386/i386/tsc.c
+++ b/sys/i386/i386/tsc.c
@@ -30,11 +30,12 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/sysctl.h>
#include <sys/time.h>
#include <sys/timetc.h>
#include <sys/kernel.h>
-#include <sys/sysctl.h>
#include <sys/power.h>
+#include <sys/smp.h>
#include <machine/clock.h>
#include <machine/md_var.h>
#include <machine/specialreg.h>
@@ -43,6 +44,13 @@ uint64_t tsc_freq;
int tsc_is_broken;
u_int tsc_present;
+#ifdef SMP
+static int smp_tsc;
+SYSCTL_INT(_kern_timecounter, OID_AUTO, smp_tsc, CTLFLAG_RD, &smp_tsc, 0,
+ "Indicates whether the TSC is safe to use in SMP mode");
+TUNABLE_INT("kern.timecounter.smp_tsc", &smp_tsc);
+#endif
+
static unsigned tsc_get_timecount(struct timecounter *tc);
static struct timecounter tsc_timecounter = {
@@ -77,14 +85,17 @@ init_TSC(void)
if (bootverbose)
printf("TSC clock: %ju Hz\n", (intmax_t)tsc_freq);
-#if defined(SMP) && !defined(SMP_TSC)
+#ifdef SMP
/*
- * We can not use the TSC in SMP mode, until we figure out a
- * cheap (impossible), reliable and precise (yeah right!) way
- * to synchronize the TSCs of all the CPUs.
- * Modern SMP hardware has the ACPI timer and we use that.
+ * We can not use the TSC in SMP mode unless the TSCs on all CPUs
+ * are somehow synchronized. Some hardware configurations do
+ * this, but we have no way of determining whether this is the
+ * case, so we do not use the TSC in multi-processor systems
+ * unless the user indicated (by setting kern.timecounter.smp_tsc
+ * to 1) that he believes that his TSCs are synchronized.
*/
- return;
+ if (mp_ncpus > 1 && !smp_tsc)
+ return;
#endif
/*
diff --git a/sys/sys/timetc.h b/sys/sys/timetc.h
index bc6a472..81bad80 100644
--- a/sys/sys/timetc.h
+++ b/sys/sys/timetc.h
@@ -64,4 +64,8 @@ void tc_init(struct timecounter *tc);
void tc_setclock(struct timespec *ts);
void tc_ticktock(void);
+#ifdef SYSCTL_DECL
+SYSCTL_DECL(_kern_timecounter);
+#endif
+
#endif /* !_SYS_TIMETC_H_ */
OpenPOWER on IntegriCloud