Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Detect whether TSC is invariant, which may be the case o...



details:   https://anonhg.NetBSD.org/src/rev/404d918a80c9
branches:  trunk
changeset: 757234:404d918a80c9
user:      jruoho <jruoho%NetBSD.org@localhost>
date:      Sat Aug 21 03:55:24 2010 +0000

description:
Detect whether TSC is invariant, which may be the case on both new AMD and
Intel processors. The invariance means that TSC runs at a constant rate
during all ACPI state changes. If it is variant, skew may occur and TSC is
generally unsuitable for wall clock services. This is especially relevant
with C-states; with variant TSC, the whole counter may be stopped with states
larger than C1. All x86 CPUs before circa mid-2000s can be assumed to have a
variant time stamp counter.

diffstat:

 sys/arch/x86/acpi/acpi_cpu_md.c |  42 ++++++++++++++++++++++++++++++++++++++--
 sys/dev/acpi/acpi_cpu.h         |  17 ++++++++-------
 2 files changed, 48 insertions(+), 11 deletions(-)

diffs (126 lines):

diff -r c8346be75d4d -r 404d918a80c9 sys/arch/x86/acpi/acpi_cpu_md.c
--- a/sys/arch/x86/acpi/acpi_cpu_md.c   Sat Aug 21 03:06:37 2010 +0000
+++ b/sys/arch/x86/acpi/acpi_cpu_md.c   Sat Aug 21 03:55:24 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_cpu_md.c,v 1.21 2010/08/21 02:47:37 jruoho Exp $ */
+/* $NetBSD: acpi_cpu_md.c,v 1.22 2010/08/21 03:55:24 jruoho Exp $ */
 
 /*-
  * Copyright (c) 2010 Jukka Ruohonen <jruohonen%iki.fi@localhost>
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.21 2010/08/21 02:47:37 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.22 2010/08/21 03:55:24 jruoho Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -48,6 +48,8 @@
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcidevs.h>
 
+#define CPUID_INTEL_TSC                __BIT(8)
+
 #define MSR_0FH_CONTROL                0xc0010041 /* Family 0Fh (and K7).  */
 #define MSR_0FH_STATUS         0xc0010042
 
@@ -119,10 +121,11 @@
        if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0)
                val |= ACPICPU_FLAG_C_FFH;
 
+       val |= ACPICPU_FLAG_C_TSC;
+
        switch (cpu_vendor) {
 
        case CPUVENDOR_IDT:
-       case CPUVENDOR_INTEL:
 
                if ((ci->ci_feat_val[1] & CPUID2_EST) != 0)
                        val |= ACPICPU_FLAG_P_FFH;
@@ -130,7 +133,36 @@
                if ((ci->ci_feat_val[0] & CPUID_ACPI) != 0)
                        val |= ACPICPU_FLAG_T_FFH;
 
+               break;
+
+       case CPUVENDOR_INTEL:
+
                val |= ACPICPU_FLAG_C_BM | ACPICPU_FLAG_C_ARB;
+
+               if ((ci->ci_feat_val[1] & CPUID2_EST) != 0)
+                       val |= ACPICPU_FLAG_P_FFH;
+
+               if ((ci->ci_feat_val[0] & CPUID_ACPI) != 0)
+                       val |= ACPICPU_FLAG_T_FFH;
+
+               /*
+                * Detect whether TSC is invariant. If it is not,
+                * we keep the flag to note that TSC will not run
+                * at constant rate. Depending on the CPU, this may
+                * affect P- and T-state changes, but especially
+                * relevant are C-states; with variant TSC, states
+                * larger than C1 will completely stop the timer.
+                */
+               x86_cpuid(0x80000000, regs);
+
+               if (regs[0] >= 0x80000007) {
+
+                       x86_cpuid(0x80000007, regs);
+
+                       if ((regs[3] & CPUID_INTEL_TSC) != 0)
+                               val &= ~ACPICPU_FLAG_C_TSC;
+               }
+
                break;
 
        case CPUVENDOR_AMD:
@@ -142,11 +174,15 @@
 
                switch (family) {
 
+               case 0x0f:
                case 0x10:
                case 0x11:
 
                        x86_cpuid(0x80000007, regs);
 
+                       if ((regs[3] & CPUID_APM_TSC) != 0)
+                               val &= ~ACPICPU_FLAG_C_TSC;
+
                        if ((regs[3] & CPUID_APM_HWP) != 0)
                                val |= ACPICPU_FLAG_P_FFH;
 
diff -r c8346be75d4d -r 404d918a80c9 sys/dev/acpi/acpi_cpu.h
--- a/sys/dev/acpi/acpi_cpu.h   Sat Aug 21 03:06:37 2010 +0000
+++ b/sys/dev/acpi/acpi_cpu.h   Sat Aug 21 03:55:24 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_cpu.h,v 1.20 2010/08/20 12:20:23 jruoho Exp $ */
+/* $NetBSD: acpi_cpu.h,v 1.21 2010/08/21 03:55:24 jruoho Exp $ */
 
 /*-
  * Copyright (c) 2010 Jukka Ruohonen <jruohonen%iki.fi@localhost>
@@ -100,15 +100,16 @@
 #define ACPICPU_FLAG_C_BM       __BIT(6)       /* Bus master control        */
 #define ACPICPU_FLAG_C_BM_STS   __BIT(7)       /* Bus master check required */
 #define ACPICPU_FLAG_C_ARB      __BIT(8)       /* Bus master arbitration    */
-#define ACPICPU_FLAG_C_C1E      __BIT(9)       /* AMD C1E detected          */
+#define ACPICPU_FLAG_C_TSC      __BIT(9)       /* TSC broken with > C1      */
+#define ACPICPU_FLAG_C_C1E      __BIT(10)      /* AMD C1E detected          */
 
-#define ACPICPU_FLAG_P_FFH      __BIT(10)      /* Native P-states           */
-#define ACPICPU_FLAG_P_HW       __BIT(11)      /* HW coordination supported */
-#define ACPICPU_FLAG_P_XPSS     __BIT(12)      /* Microsoft XPSS in use     */
-#define ACPICPU_FLAG_P_TURBO    __BIT(13)      /* Turbo Boost / Turbo Core  */
+#define ACPICPU_FLAG_P_FFH      __BIT(11)      /* Native P-states           */
+#define ACPICPU_FLAG_P_HW       __BIT(12)      /* HW coordination supported */
+#define ACPICPU_FLAG_P_XPSS     __BIT(13)      /* Microsoft XPSS in use     */
+#define ACPICPU_FLAG_P_TURBO    __BIT(14)      /* Turbo Boost / Turbo Core  */
 
-#define ACPICPU_FLAG_T_FFH      __BIT(14)      /* Native throttling         */
-#define ACPICPU_FLAG_T_FADT     __BIT(15)      /* Throttling with FADT      */
+#define ACPICPU_FLAG_T_FFH      __BIT(15)      /* Native throttling         */
+#define ACPICPU_FLAG_T_FADT     __BIT(16)      /* Throttling with FADT      */
 
 /*
  * This is AML_RESOURCE_GENERIC_REGISTER,



Home | Main Index | Thread Index | Old Index