aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2013-01-21 15:58:24 +0000
committerPeter Maydell <peter.maydell@linaro.org>2013-01-21 18:07:31 +0000
commite458c6ad06318d5f6f41cec13f1b48488cf371a5 (patch)
tree8c75a8c7b1a91c17d87b9501c824b9658d2edb27
parentd8fa754c70674815c5f089d43cdaa25a2dbba1f6 (diff)
qemu-timer: Don't use RDTSC on 386s and 486sx86-rdtsc
Adjust the conditional which guards the implementation of cpu_get_real_ticks() via RDTSC, so that we don't try to use it on x86 CPUs which don't implement RDTSC. Instead we will fall back to the no-cycle-counter-available default implementation. Reported-by: Yurij Popov <oss@djphoenix.ru> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--include/qemu/timer.h29
1 files changed, 26 insertions, 3 deletions
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 1766b2d6c7..f67e731f9b 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -171,11 +171,34 @@ static inline int64_t cpu_get_real_ticks(void)
#elif defined(__i386__)
+#include "qemu/cpuid.h"
+
static inline int64_t cpu_get_real_ticks(void)
{
- int64_t val;
- asm volatile ("rdtsc" : "=A" (val));
- return val;
+ /* There is no convenient GCC define to let us find out whether
+ * the target CPU has 'rdtsc', so we must do an initial runtime
+ * check. Our fallback is the same kind of simple monotonic count
+ * as the default cpu_get_real_ticks implementation.
+ */
+ static int64_t ticks = 0;
+
+#if defined(CONFIG_CPUID_H)
+ static bool checked_rdtsc;
+ static bool have_rdtsc;
+
+ if (!checked_rdtsc) {
+ unsigned int a, b, c, d;
+ have_rdtsc = (__get_cpuid(1, &a, &b, &c, &d) && (d & (1 << 4)));
+ checked_rdtsc = true;
+ }
+ if (have_rdtsc) {
+ int64_t val;
+ asm volatile ("rdtsc" : "=A" (val));
+ return val;
+ }
+ /* Otherwise fall through into no-rdtsc code */
+#endif
+ return ticks++;
}
#elif defined(__x86_64__)