diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2013-01-21 15:58:24 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2013-01-21 18:07:31 +0000 |
commit | e458c6ad06318d5f6f41cec13f1b48488cf371a5 (patch) | |
tree | 8c75a8c7b1a91c17d87b9501c824b9658d2edb27 | |
parent | d8fa754c70674815c5f089d43cdaa25a2dbba1f6 (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.h | 29 |
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__) |