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>
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 @@
 
 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__)