From 7f20f4cae9ba9f30fb1b917499af8729134e8a9a Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Wed, 1 May 2013 15:55:14 -0500 Subject: [PATCH] BACKPORT: 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. BUG=None BRANCH=None TEST=Compiled and booted Change-Id: I0f86672e0951b51c791c63bb1173eb371b347f40 Signed-off-by: Aaron Durbin Reviewed-on: https://gerrit.chromium.org/gerrit/50457 Reviewed-by: Stefan Reinauer --- 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 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__)