diff options
author | jkim <jkim@FreeBSD.org> | 2010-12-14 20:07:51 +0000 |
---|---|---|
committer | jkim <jkim@FreeBSD.org> | 2010-12-14 20:07:51 +0000 |
commit | 879b3da6b59546ff4f89076a858a746027da0a05 (patch) | |
tree | 097eb45b509a90553e05cf7a887104084d416a9d | |
parent | b683a398af3500a579e31d0fc2e293dd936b2e8e (diff) | |
download | FreeBSD-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.
-rw-r--r-- | sys/amd64/amd64/legacy.c | 17 | ||||
-rw-r--r-- | sys/amd64/amd64/machdep.c | 4 | ||||
-rw-r--r-- | sys/dev/acpica/acpi_cpu.c | 11 | ||||
-rw-r--r-- | sys/i386/i386/legacy.c | 17 | ||||
-rw-r--r-- | sys/i386/i386/machdep.c | 4 |
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; |