svn commit: r216443 - in head/sys: amd64/amd64 dev/acpica i386/i386

Jung-uk Kim jkim at FreeBSD.org
Tue Dec 14 20:07:51 UTC 2010


Author: jkim
Date: Tue Dec 14 20:07:51 2010
New Revision: 216443
URL: http://svn.freebsd.org/changeset/base/216443

Log:
  Stop lying about supporting cpu_est_clockrate() when TSC is invariant.  This
  function always returned the nominal frequency instead of current frequency
  because we use RDTSC instruction to calculate difference in CPU ticks, which
  is supposedly constant for the case.  Now we support cpu_get_nominal_mhz()
  for the case, instead.  Note it should be just enough for most usage cases
  because cpu_est_clockrate() is often times abused to find maximum frequency
  of the processor.

Modified:
  head/sys/amd64/amd64/legacy.c
  head/sys/amd64/amd64/machdep.c
  head/sys/dev/acpica/acpi_cpu.c
  head/sys/i386/i386/legacy.c
  head/sys/i386/i386/machdep.c

Modified: head/sys/amd64/amd64/legacy.c
==============================================================================
--- head/sys/amd64/amd64/legacy.c	Tue Dec 14 20:06:55 2010	(r216442)
+++ head/sys/amd64/amd64/legacy.c	Tue Dec 14 20:07:51 2010	(r216443)
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/rman.h>
 #include <sys/smp.h>
 
+#include <machine/clock.h>
 #include <machine/legacyvar.h>
 #include <machine/resource.h>
 
@@ -313,9 +314,19 @@ cpu_read_ivar(device_t dev, device_t chi
 {
 	struct cpu_device *cpdev;
 
-	if (index != CPU_IVAR_PCPU)
+	switch (index) {
+	case CPU_IVAR_PCPU:
+		cpdev = device_get_ivars(child);
+		*result = (uintptr_t)cpdev->cd_pcpu;
+		break;
+	case CPU_IVAR_NOMINAL_MHZ:
+		if (tsc_is_invariant) {
+			*result = (uintptr_t)(tsc_freq / 1000000);
+			break;
+		}
+		/* FALLTHROUGH */
+	default:
 		return (ENOENT);
-	cpdev = device_get_ivars(child);
-	*result = (uintptr_t)cpdev->cd_pcpu;
+	}
 	return (0);
 }

Modified: head/sys/amd64/amd64/machdep.c
==============================================================================
--- head/sys/amd64/amd64/machdep.c	Tue Dec 14 20:06:55 2010	(r216442)
+++ head/sys/amd64/amd64/machdep.c	Tue Dec 14 20:07:51 2010	(r216443)
@@ -537,6 +537,10 @@ cpu_est_clockrate(int cpu_id, uint64_t *
 	if (pcpu_find(cpu_id) == NULL || rate == NULL)
 		return (EINVAL);
 
+	/* If TSC is P-state invariant, DELAY(9) based logic fails. */
+	if (tsc_is_invariant)
+		return (EOPNOTSUPP);
+
 	/* If we're booting, trust the rate calibrated moments ago. */
 	if (cold) {
 		*rate = tsc_freq;

Modified: head/sys/dev/acpica/acpi_cpu.c
==============================================================================
--- head/sys/dev/acpica/acpi_cpu.c	Tue Dec 14 20:06:55 2010	(r216442)
+++ head/sys/dev/acpica/acpi_cpu.c	Tue Dec 14 20:07:51 2010	(r216443)
@@ -44,6 +44,9 @@ __FBSDID("$FreeBSD$");
 #include <dev/pci/pcivar.h>
 #include <machine/atomic.h>
 #include <machine/bus.h>
+#if defined(__amd64__) || defined(__i386__)
+#include <machine/clock.h>
+#endif
 #include <sys/rman.h>
 
 #include <contrib/dev/acpica/include/acpi.h>
@@ -510,6 +513,14 @@ acpi_cpu_read_ivar(device_t dev, device_
     case CPU_IVAR_PCPU:
 	*result = (uintptr_t)sc->cpu_pcpu;
 	break;
+#if defined(__amd64__) || defined(__i386__)
+    case CPU_IVAR_NOMINAL_MHZ:
+	if (tsc_is_invariant) {
+	    *result = (uintptr_t)(tsc_freq / 1000000);
+	    break;
+	}
+	/* FALLTHROUGH */
+#endif
     default:
 	return (ENOENT);
     }

Modified: head/sys/i386/i386/legacy.c
==============================================================================
--- head/sys/i386/i386/legacy.c	Tue Dec 14 20:06:55 2010	(r216442)
+++ head/sys/i386/i386/legacy.c	Tue Dec 14 20:07:51 2010	(r216443)
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
 #include <i386/bios/mca_machdep.h>
 #endif
 
+#include <machine/clock.h>
 #include <machine/legacyvar.h>
 #include <machine/resource.h>
 
@@ -334,9 +335,19 @@ cpu_read_ivar(device_t dev, device_t chi
 {
 	struct cpu_device *cpdev;
 
-	if (index != CPU_IVAR_PCPU)
+	switch (index) {
+	case CPU_IVAR_PCPU:
+		cpdev = device_get_ivars(child);
+		*result = (uintptr_t)cpdev->cd_pcpu;
+		break;
+	case CPU_IVAR_NOMINAL_MHZ:
+		if (tsc_is_invariant) {
+			*result = (uintptr_t)(tsc_freq / 1000000);
+			break;
+		}
+		/* FALLTHROUGH */
+	default:
 		return (ENOENT);
-	cpdev = device_get_ivars(child);
-	*result = (uintptr_t)cpdev->cd_pcpu;
+	}
 	return (0);
 }

Modified: head/sys/i386/i386/machdep.c
==============================================================================
--- head/sys/i386/i386/machdep.c	Tue Dec 14 20:06:55 2010	(r216442)
+++ head/sys/i386/i386/machdep.c	Tue Dec 14 20:07:51 2010	(r216443)
@@ -1131,6 +1131,10 @@ cpu_est_clockrate(int cpu_id, uint64_t *
 	if (!tsc_present)
 		return (EOPNOTSUPP);
 
+	/* If TSC is P-state invariant, DELAY(9) based logic fails. */
+	if (tsc_is_invariant)
+		return (EOPNOTSUPP);
+
 	/* If we're booting, trust the rate calibrated moments ago. */
 	if (cold) {
 		*rate = tsc_freq;


More information about the svn-src-all mailing list