[coreboot-gerrit] New patch to review for coreboot: 0aa640b Intel 5000: udelay.c: Work around 32-bit overflow

Paul Menzel (paulepanter@users.sourceforge.net) gerrit at coreboot.org
Wed May 8 17:15:41 CEST 2013


Paul Menzel (paulepanter at users.sourceforge.net) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3219

-gerrit

commit 0aa640b9220fd51e6b48d39ee9d6a08bde5c8bb2
Author: Paul Menzel <paulepanter at users.sourceforge.net>
Date:   Wed May 8 16:24:38 2013 +0200

    Intel 5000: udelay.c: Work around 32-bit overflow
    
    Port the following commit over to the Intel 5000.
    
        commit 8bacc40fc7bd07365c2992b260ddbd45cd6e4518
        Author: Nico Huber <nico.huber at secunet.com>
        Date:   Thu Jul 19 16:16:59 2012 +0200
    
            Fix udelay() implementation for i945 romstage
    
            Reviewed-on: http://review.coreboot.org/1254
    
    Change-Id: I5c113bb0b2fed7b93feb3dcb1b5d962e1442963a
    Signed-off-by: Paul Menzel <paulepanter at users.sourceforge.net>
---
 src/northbridge/intel/i5000/udelay.c | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/src/northbridge/intel/i5000/udelay.c b/src/northbridge/intel/i5000/udelay.c
index ce4c7b3..699e0d4 100644
--- a/src/northbridge/intel/i5000/udelay.c
+++ b/src/northbridge/intel/i5000/udelay.c
@@ -2,6 +2,7 @@
  * This file is part of the coreboot project.
  *
  * Copyright (C) 2007-2008 coresystems GmbH
+ *               2012 secunet Security Networks AG
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -23,6 +24,17 @@
 #include <cpu/x86/msr.h>
 #include <cpu/intel/speedstep.h>
 
+/* Simple 32- to 64-bit multiplication. Uses 16-bit words to avoid overflow. */
+static inline void multiply_to_tsc(tsc_t * const tsc, const u32 a, const u32 b)
+{
+	tsc->lo = (a & 0xffff) * (b & 0xffff);
+	tsc->hi = ((tsc->lo >> 16)
+		   + ((a & 0xffff) * (b >> 16))
+		   + ((b & 0xffff) * (a >> 16)));
+	tsc->lo = ((tsc->hi & 0xffff) << 16) | (tsc->lo & 0xffff);
+	tsc->hi = ((a >> 16) * (b >> 16)) + (tsc->hi >> 16);
+}
+
 /**
  * Intel Core(tm) cpus always run the TSC at the maximum possible CPU clock
  */
@@ -34,7 +46,6 @@ void udelay(u32 us)
 	msr_t msr;
 	u32 fsb = 0, divisor;
 	u32 d;			/* ticks per us */
-	u32 dn = 0x1000000 / 2;	/* how many us before we need to use hi */
 
 	msr = rdmsr(MSR_FSB_FREQ);
 	switch (msr.lo & 0x07) {
@@ -64,10 +75,9 @@ void udelay(u32 us)
 	msr = rdmsr(0x198);
 	divisor = (msr.hi >> 8) & 0x1f;
 
-	d = fsb * divisor;
+	d = (fsb * divisor) / 4; /* CPU clock is always a quarter. */
 
-	tscd.hi = us / dn;
-	tscd.lo = (us - tscd.hi * dn) * d;
+	multiply_to_tsc(&tscd, us, d);
 
 	tsc1 = rdtsc();
 	dword = tsc1.lo + tscd.lo;
@@ -81,5 +91,6 @@ void udelay(u32 us)
 
 	do {
 		tsc = rdtsc();
-	} while ((tsc.hi < tsc1.hi) || ((tsc.hi == tsc1.hi) && (tsc.lo < tsc1.lo)));
+	} while ((tsc.hi < tsc1.hi)
+		 || ((tsc.hi == tsc1.hi) && (tsc.lo < tsc1.lo)));
 }



More information about the coreboot-gerrit mailing list