aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2017-12-22 04:20:13 -0500
committerThomas Gleixner <tglx@linutronix.de>2018-01-14 14:18:23 -0500
commitaa83c45762a242acce9b35020363225a7b59d7c9 (patch)
tree99a6433c1604f83084702f9486aeb2313956e4bd
parent6d671e1b85c63e7a337ba76c1a154c091545cff8 (diff)
x86/tsc: Introduce early tsc clocksource
Without TSC_KNOWN_FREQ the TSC clocksource is registered so late that the kernel first switches to the HPET. Using HPET on large CPU count machines is undesirable. Therefore register a tsc-early clocksource using the preliminary tsc_khz from quick calibration. Then when the final TSC calibration is done, it can switch to the tuned frequency. The only notably problem is that the real tsc clocksource must be marked with CLOCK_SOURCE_VALID_FOR_HRES, otherwise it will not be selected when unregistering tsc-early. tsc-early cannot be left registered, because then the clocksource code would fall back to it when we tsc clocksource is marked unstable later. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: len.brown@intel.com Cc: rui.zhang@intel.com Cc: Len Brown <lenb@kernel.org> Link: https://lkml.kernel.org/r/20171222092243.431585460@infradead.org
-rw-r--r--arch/x86/kernel/tsc.c43
1 files changed, 33 insertions, 10 deletions
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index a2c9dd8bfc6f..fb4302738410 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -1006,8 +1006,6 @@ static void __init detect_art(void)
1006 1006
1007/* clocksource code */ 1007/* clocksource code */
1008 1008
1009static struct clocksource clocksource_tsc;
1010
1011static void tsc_resume(struct clocksource *cs) 1009static void tsc_resume(struct clocksource *cs)
1012{ 1010{
1013 tsc_verify_tsc_adjust(true); 1011 tsc_verify_tsc_adjust(true);
@@ -1058,12 +1056,31 @@ static void tsc_cs_tick_stable(struct clocksource *cs)
1058/* 1056/*
1059 * .mask MUST be CLOCKSOURCE_MASK(64). See comment above read_tsc() 1057 * .mask MUST be CLOCKSOURCE_MASK(64). See comment above read_tsc()
1060 */ 1058 */
1059static struct clocksource clocksource_tsc_early = {
1060 .name = "tsc-early",
1061 .rating = 299,
1062 .read = read_tsc,
1063 .mask = CLOCKSOURCE_MASK(64),
1064 .flags = CLOCK_SOURCE_IS_CONTINUOUS |
1065 CLOCK_SOURCE_MUST_VERIFY,
1066 .archdata = { .vclock_mode = VCLOCK_TSC },
1067 .resume = tsc_resume,
1068 .mark_unstable = tsc_cs_mark_unstable,
1069 .tick_stable = tsc_cs_tick_stable,
1070};
1071
1072/*
1073 * Must mark VALID_FOR_HRES early such that when we unregister tsc_early
1074 * this one will immediately take over. We will only register if TSC has
1075 * been found good.
1076 */
1061static struct clocksource clocksource_tsc = { 1077static struct clocksource clocksource_tsc = {
1062 .name = "tsc", 1078 .name = "tsc",
1063 .rating = 300, 1079 .rating = 300,
1064 .read = read_tsc, 1080 .read = read_tsc,
1065 .mask = CLOCKSOURCE_MASK(64), 1081 .mask = CLOCKSOURCE_MASK(64),
1066 .flags = CLOCK_SOURCE_IS_CONTINUOUS | 1082 .flags = CLOCK_SOURCE_IS_CONTINUOUS |
1083 CLOCK_SOURCE_VALID_FOR_HRES |
1067 CLOCK_SOURCE_MUST_VERIFY, 1084 CLOCK_SOURCE_MUST_VERIFY,
1068 .archdata = { .vclock_mode = VCLOCK_TSC }, 1085 .archdata = { .vclock_mode = VCLOCK_TSC },
1069 .resume = tsc_resume, 1086 .resume = tsc_resume,
@@ -1187,8 +1204,8 @@ static void tsc_refine_calibration_work(struct work_struct *work)
1187 int cpu; 1204 int cpu;
1188 1205
1189 /* Don't bother refining TSC on unstable systems */ 1206 /* Don't bother refining TSC on unstable systems */
1190 if (check_tsc_unstable()) 1207 if (tsc_unstable)
1191 goto out; 1208 return;
1192 1209
1193 /* 1210 /*
1194 * Since the work is started early in boot, we may be 1211 * Since the work is started early in boot, we may be
@@ -1240,9 +1257,13 @@ static void tsc_refine_calibration_work(struct work_struct *work)
1240 set_cyc2ns_scale(tsc_khz, cpu, tsc_stop); 1257 set_cyc2ns_scale(tsc_khz, cpu, tsc_stop);
1241 1258
1242out: 1259out:
1260 if (tsc_unstable)
1261 return;
1262
1243 if (boot_cpu_has(X86_FEATURE_ART)) 1263 if (boot_cpu_has(X86_FEATURE_ART))
1244 art_related_clocksource = &clocksource_tsc; 1264 art_related_clocksource = &clocksource_tsc;
1245 clocksource_register_khz(&clocksource_tsc, tsc_khz); 1265 clocksource_register_khz(&clocksource_tsc, tsc_khz);
1266 clocksource_unregister(&clocksource_tsc_early);
1246} 1267}
1247 1268
1248 1269
@@ -1251,13 +1272,11 @@ static int __init init_tsc_clocksource(void)
1251 if (!boot_cpu_has(X86_FEATURE_TSC) || tsc_disabled > 0 || !tsc_khz) 1272 if (!boot_cpu_has(X86_FEATURE_TSC) || tsc_disabled > 0 || !tsc_khz)
1252 return 0; 1273 return 0;
1253 1274
1275 if (check_tsc_unstable())
1276 return 0;
1277
1254 if (tsc_clocksource_reliable) 1278 if (tsc_clocksource_reliable)
1255 clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY; 1279 clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY;
1256 /* lower the rating if we already know its unstable: */
1257 if (check_tsc_unstable()) {
1258 clocksource_tsc.rating = 0;
1259 clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
1260 }
1261 1280
1262 if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC_S3)) 1281 if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC_S3))
1263 clocksource_tsc.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP; 1282 clocksource_tsc.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
@@ -1270,6 +1289,7 @@ static int __init init_tsc_clocksource(void)
1270 if (boot_cpu_has(X86_FEATURE_ART)) 1289 if (boot_cpu_has(X86_FEATURE_ART))
1271 art_related_clocksource = &clocksource_tsc; 1290 art_related_clocksource = &clocksource_tsc;
1272 clocksource_register_khz(&clocksource_tsc, tsc_khz); 1291 clocksource_register_khz(&clocksource_tsc, tsc_khz);
1292 clocksource_unregister(&clocksource_tsc_early);
1273 return 0; 1293 return 0;
1274 } 1294 }
1275 1295
@@ -1374,9 +1394,12 @@ void __init tsc_init(void)
1374 1394
1375 check_system_tsc_reliable(); 1395 check_system_tsc_reliable();
1376 1396
1377 if (unsynchronized_tsc()) 1397 if (unsynchronized_tsc()) {
1378 mark_tsc_unstable("TSCs unsynchronized"); 1398 mark_tsc_unstable("TSCs unsynchronized");
1399 return;
1400 }
1379 1401
1402 clocksource_register_khz(&clocksource_tsc_early, tsc_khz);
1380 detect_art(); 1403 detect_art();
1381} 1404}
1382 1405