summaryrefslogtreecommitdiff
path: root/src/cpu
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2013-05-01 15:55:14 -0500
committerRonald G. Minnich <rminnich@gmail.com>2013-05-07 22:53:08 +0200
commit703aa978aa6db915fbc7fa42e5ca79cf31f57505 (patch)
tree918d776ed5f07f7893acc44548e7e84e8e0778df /src/cpu
parentddddf15ca359e932ed2e61e9a6dcec77ed2d4411 (diff)
x86: harden tsc udelay() function
Since the TSC udelay() function can be used in SMM that means the TSC can count up to whatever value. The current loop was not handling TSC rollover properly. In most cases this should not matter as the TSC typically starts ticking at value 0, and it would take a very long time to roll it over. However, it is my understanding that this behavior is not guaranteed. Theoretically the TSC could start or be be written to with a large value that would cause the rollover. Change-Id: I2f11a5bc4f27d5543e74f8224811fa91e4a55484 Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/3171 Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org> Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Diffstat (limited to 'src/cpu')
-rw-r--r--src/cpu/x86/tsc/delay_tsc.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/src/cpu/x86/tsc/delay_tsc.c b/src/cpu/x86/tsc/delay_tsc.c
index 0540496f5e..0e2a9c0faf 100644
--- a/src/cpu/x86/tsc/delay_tsc.c
+++ b/src/cpu/x86/tsc/delay_tsc.c
@@ -172,18 +172,18 @@ static inline unsigned long get_clocks_per_usec(void)
void udelay(unsigned us)
{
- unsigned long long count;
- unsigned long long stop;
- unsigned long long clocks;
+ unsigned long long start;
+ unsigned long long current;
+ unsigned long long clocks;
+ start = rdtscll();
clocks = us;
clocks *= get_clocks_per_usec();
- count = rdtscll();
- stop = clocks + count;
- while(stop > count) {
+ current = rdtscll();
+ while((current - start) < clocks) {
cpu_relax();
- count = rdtscll();
- }
+ current = rdtscll();
+ }
}
#if CONFIG_TSC_MONOTONIC_TIMER && !defined(__PRE_RAM__) && !defined(__SMM__)