Aaron Durbin (adurbin@google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3171
-gerrit
commit 54c54297f582c3187a1f5f6c357b817901996ed0 Author: Aaron Durbin adurbin@chromium.org Date: Wed May 1 15:55:14 2013 -0500
x86: harden tsc udelay() function
Since the TSC udelay() fucntion 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 --- src/cpu/x86/tsc/delay_tsc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/cpu/x86/tsc/delay_tsc.c b/src/cpu/x86/tsc/delay_tsc.c index 0540496..0e2a9c0 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__)