summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjkim <jkim@FreeBSD.org>2010-12-14 20:07:51 +0000
committerjkim <jkim@FreeBSD.org>2010-12-14 20:07:51 +0000
commit879b3da6b59546ff4f89076a858a746027da0a05 (patch)
tree097eb45b509a90553e05cf7a887104084d416a9d /sys
parentb683a398af3500a579e31d0fc2e293dd936b2e8e (diff)
downloadFreeBSD-src-879b3da6b59546ff4f89076a858a746027da0a05.zip
FreeBSD-src-879b3da6b59546ff4f89076a858a746027da0a05.tar.gz
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.
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/legacy.c17
-rw-r--r--sys/amd64/amd64/machdep.c4
-rw-r--r--sys/dev/acpica/acpi_cpu.c11
-rw-r--r--sys/i386/i386/legacy.c17
-rw-r--r--sys/i386/i386/machdep.c4
5 files changed, 47 insertions, 6 deletions
diff --git a/sys/amd64/amd64/legacy.c b/sys/amd64/amd64/legacy.c
index 4123f84..0e7bac1 100644
--- a/sys/amd64/amd64/legacy.c
+++ b/sys/amd64/amd64/legacy.c
@@ -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 child, int index, uintptr_t *result)
{
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);
}
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 55b1ea3..5661a84 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -537,6 +537,10 @@ cpu_est_clockrate(int cpu_id, uint64_t *rate)
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;
diff --git a/sys/dev/acpica/acpi_cpu.c b/sys/dev/acpica/acpi_cpu.c
index eb34753..85a706f 100644
--- a/sys/dev/acpica/acpi_cpu.c
+++ b/sys/dev/acpica/acpi_cpu.c
@@ -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_t child, int index, uintptr_t *result)
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);
}
diff --git a/sys/i386/i386/legacy.c b/sys/i386/i386/legacy.c
index fe9b403..4d342f5 100644
--- a/sys/i386/i386/legacy.c
+++ b/sys/i386/i386/legacy.c
@@ -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 child, int index, uintptr_t *result)
{
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);
}
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index a04e578..a24fb11 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -1131,6 +1131,10 @@ cpu_est_clockrate(int cpu_id, uint64_t *rate)
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;
OpenPOWER on IntegriCloud