Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/x86/x86 Update invariant TSC detect code from both ...
details: https://anonhg.NetBSD.org/src/rev/9f66f1d5a9b4
branches: trunk
changeset: 325130:9f66f1d5a9b4
user: msaitoh <msaitoh%NetBSD.org@localhost>
date: Sun Dec 08 04:07:38 2013 +0000
description:
Update invariant TSC detect code from both Intel and AMD documents.
The best way to check whether the TSC counter is invariant or not is to check
CPUID 80000007.
diffstat:
sys/arch/x86/x86/tsc.c | 64 ++++++++++++++++++++++++++-----------------------
1 files changed, 34 insertions(+), 30 deletions(-)
diffs (131 lines):
diff -r c7a75a3941e2 -r 9f66f1d5a9b4 sys/arch/x86/x86/tsc.c
--- a/sys/arch/x86/x86/tsc.c Sat Dec 07 20:40:42 2013 +0000
+++ b/sys/arch/x86/x86/tsc.c Sun Dec 08 04:07:38 2013 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tsc.c,v 1.33 2013/11/15 08:47:55 msaitoh Exp $ */
+/* $NetBSD: tsc.c,v 1.34 2013/12/08 04:07:38 msaitoh Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.33 2013/11/15 08:47:55 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.34 2013/12/08 04:07:38 msaitoh Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -68,14 +68,15 @@
{
struct cpu_info *ci;
uint32_t descs[4];
- bool safe;
+ uint32_t family;
+ bool invariant;
if (!cpu_hascounter()) {
return;
}
ci = curcpu();
- safe = false;
+ invariant = false;
tsc_freq = ci->ci_data.cpu_cc_freq;
tsc_good = (cpu_feature[0] & CPUID_MSR) != 0 &&
(rdmsr(MSR_TSC) != 0 || rdmsr(MSR_TSC) != 0);
@@ -84,28 +85,32 @@
/*
* From Intel(tm) 64 and IA-32 Architectures Software
* Developer's Manual Volume 3A: System Programming Guide,
- * Part 1 Order Number: 253668-026US February 2008, these
- * are the processors where the TSC is known safe:
+ * Part 1, 17.13 TIME_STAMP COUNTER, these are the processors
+ * where the TSC is known invariant:
*
* Pentium 4, Intel Xeon (family 0f, models 03 and higher)
* Core Solo and Core Duo processors (family 06, model 0e)
* Xeon 5100 series and Core 2 Duo (family 06, model 0f)
+ * Core 2 and Xeon (family 06, model 17)
+ * Atom (family 06, model 1c)
*
* We'll also assume that it's safe on the Pentium, and
* that it's safe on P-II and P-III Xeons due to the
* typical configuration of those systems.
+ *
*/
switch (CPUID_TO_BASEFAMILY(ci->ci_signature)) {
case 0x05:
- safe = true;
+ invariant = true;
break;
case 0x06:
- safe = CPUID_TO_MODEL(ci->ci_signature) == 0x0e ||
+ invariant = CPUID_TO_MODEL(ci->ci_signature) == 0x0e ||
CPUID_TO_MODEL(ci->ci_signature) == 0x0f ||
- CPUID_TO_MODEL(ci->ci_signature) == 0x0a;
+ CPUID_TO_MODEL(ci->ci_signature) == 0x17 ||
+ CPUID_TO_MODEL(ci->ci_signature) == 0x1c;
break;
case 0x0f:
- safe = CPUID_TO_MODEL(ci->ci_signature) >= 0x03;
+ invariant = CPUID_TO_MODEL(ci->ci_signature) >= 0x03;
break;
}
} else if (cpu_vendor == CPUVENDOR_AMD) {
@@ -114,36 +119,35 @@
* Nov 2, 2005 Rich Brunner, AMD Fellow
* http://lkml.org/lkml/2005/11/4/173
*
- * There are a lot of recommendations in this note.
- * We're only going to follow the simple, reliable
- * ones.
+ * See Appendix E.4.7 CPUID Fn8000_0007_EDX Advanced Power
+ * Management Features, AMD64 Architecture ProgrammerVolume 3:
+ * General-Purpose and System Instructions. The check is
+ * done below.
*/
- switch (CPUID_TO_BASEFAMILY(ci->ci_signature)) {
- case 0x06:
- case 0x07:
- /*
- * TSC is fine, apart from P-state changes.
- * The PowerNow code need hooks to disable
- * the TSC if the user modifies operating
- * parameters. For now, punt. XXX
- */
- break;
- case 0x0f:
- /* Check for "invariant TSC", bit 8 of %edx. */
+ }
+
+ /*
+ * The best way to check whether the TSC counter is invariant or not
+ * is to check CPUID 80000007.
+ */
+ family = CPUID_TO_BASEFAMILY(ci->ci_signature);
+ if (((cpu_vendor == CPUVENDOR_INTEL) || (cpu_vendor == CPUVENDOR_AMD))
+ && ((family == 0x06) || (family == 0x0f))) {
+ x86_cpuid(0x80000000, descs);
+ if (descs[0] >= 0x80000007) {
x86_cpuid(0x80000007, descs);
- safe = (descs[3] & CPUID_APM_TSC) != 0;
- break;
+ invariant = (descs[3] & CPUID_APM_TSC) != 0;
}
}
- if (!safe) {
- aprint_debug("TSC not known safe on this CPU\n");
+ if (!invariant) {
+ aprint_debug("TSC not known invariant on this CPU\n");
tsc_timecounter.tc_quality = -100;
} else if (tsc_drift_observed > tsc_drift_max) {
aprint_error("ERROR: %lld cycle TSC drift observed\n",
(long long)tsc_drift_observed);
tsc_timecounter.tc_quality = -100;
- safe = false;
+ invariant = false;
}
if (tsc_freq != 0) {
Home |
Main Index |
Thread Index |
Old Index