Module Name:    src
Committed By:   jruoho
Date:           Sat Aug 21 03:55:24 UTC 2010

Modified Files:
        src/sys/arch/x86/acpi: acpi_cpu_md.c
        src/sys/dev/acpi: acpi_cpu.h

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.21 -r1.22 src/sys/arch/x86/acpi/acpi_cpu_md.c
cvs rdiff -u -r1.20 -r1.21 src/sys/dev/acpi/acpi_cpu.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/x86/acpi/acpi_cpu_md.c
diff -u src/sys/arch/x86/acpi/acpi_cpu_md.c:1.21 src/sys/arch/x86/acpi/acpi_cpu_md.c:1.22
--- src/sys/arch/x86/acpi/acpi_cpu_md.c:1.21	Sat Aug 21 02:47:37 2010
+++ src/sys/arch/x86/acpi/acpi_cpu_md.c	Sat Aug 21 03:55:24 2010
@@ -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 <jruoho...@iki.fi>
@@ -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;
 

Index: src/sys/dev/acpi/acpi_cpu.h
diff -u src/sys/dev/acpi/acpi_cpu.h:1.20 src/sys/dev/acpi/acpi_cpu.h:1.21
--- src/sys/dev/acpi/acpi_cpu.h:1.20	Fri Aug 20 12:20:23 2010
+++ src/sys/dev/acpi/acpi_cpu.h	Sat Aug 21 03:55:24 2010
@@ -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 <jruoho...@iki.fi>
@@ -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,

Reply via email to