From: Chris Wright Date: Tue, 24 Jan 2006 18:45:32 +0000 (-0800) Subject: Fix timekeeping on sparc64 ultra-IIe machines, from DaveM X-Git-Tag: v2.6.14.7~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=42fd0b1b844416769079b448187279d524c475ce;p=thirdparty%2Fkernel%2Fstable-queue.git Fix timekeeping on sparc64 ultra-IIe machines, from DaveM --- diff --git a/queue/series b/queue/series index 35c626b95fa..a55dc214f65 100644 --- a/queue/series +++ b/queue/series @@ -4,3 +4,4 @@ input-hid-fix-an-oops-in-pid-initialization-code.patch fix-double-decrement-of-mqueue_mnt-mnt_count-in-sys_mq_open.patch fix-oops-in-ufs_fill_super-at-mount-time.patch elevator-as-back-compatibility.patch +sparc64-fix-timekeeping-on-ultra-IIe-machines.patch diff --git a/queue/sparc64-fix-timekeeping-on-ultra-IIe-machines.patch b/queue/sparc64-fix-timekeeping-on-ultra-IIe-machines.patch new file mode 100644 index 00000000000..36f76931280 --- /dev/null +++ b/queue/sparc64-fix-timekeeping-on-ultra-IIe-machines.patch @@ -0,0 +1,82 @@ +From stable-bounces@linux.kernel.org Tue Jan 17 15:27:59 2006 +Date: Tue, 17 Jan 2006 15:23:00 -0800 (PST) +Message-Id: <20060117.152300.10006770.davem@davemloft.net> +To: stable@kernel.org +From: "David S. Miller" +Subject: [PATCH] Fix timekeeping on sparc64 ultra-IIe machines + +From: Richard Mortimer + +[SPARC64]: Eliminate race condition reading Hummingbird STICK register + +Ensure a consistent value is read from the STICK register by ensuring +that both high and low are read without high changing due to a roll +over of the low register. + +Various Debian/SPARC users (myself include) have noticed problems with +Hummingbird based systems. The symptoms are that the system time is +seen to jump forward 3 days, 6 hours, 11 minutes give or take a few +seconds. In many cases the system then hangs some time afterwards. + +I've spotted a race condition in the code to read the STICK register. +I could not work out why 3d, 6h, 11m is important but guess that it is +due to the 2^32 jump of STICK (forwards on one read and then the next +read will seem to be backwards) during a timer interrupt. I'm guessing +that a change of -2^32 will get converted to a large unsigned +increment after the arithmetic manipulation between STICK, +nanoseconds, jiffies etc. + +I did a test where I modified __hbird_read_stick to artificially +inject rollover faults forcefully every few seconds. With this I saw +the clock jump over 6 times in 12 hours compared to once every month +or so. + +Signed-off-by: Richard Mortimer +Signed-off-by: David S. Miller +Signed-off-by: Chris Wright +--- + arch/sparc64/kernel/time.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- linux-2.6.15.1.orig/arch/sparc64/kernel/time.c ++++ linux-2.6.15.1/arch/sparc64/kernel/time.c +@@ -280,9 +280,9 @@ static struct sparc64_tick_ops stick_ope + * Since STICK is constantly updating, we have to access it carefully. + * + * The sequence we use to read is: +- * 1) read low +- * 2) read high +- * 3) read low again, if it rolled over increment high by 1 ++ * 1) read high ++ * 2) read low ++ * 3) read high again, if it rolled re-read both low and high again. + * + * Writing STICK safely is also tricky: + * 1) write low to zero +@@ -295,18 +295,18 @@ static struct sparc64_tick_ops stick_ope + static unsigned long __hbird_read_stick(void) + { + unsigned long ret, tmp1, tmp2, tmp3; +- unsigned long addr = HBIRD_STICK_ADDR; ++ unsigned long addr = HBIRD_STICK_ADDR+8; + +- __asm__ __volatile__("ldxa [%1] %5, %2\n\t" +- "add %1, 0x8, %1\n\t" +- "ldxa [%1] %5, %3\n\t" ++ __asm__ __volatile__("ldxa [%1] %5, %2\n" ++ "1:\n\t" + "sub %1, 0x8, %1\n\t" ++ "ldxa [%1] %5, %3\n\t" ++ "add %1, 0x8, %1\n\t" + "ldxa [%1] %5, %4\n\t" + "cmp %4, %2\n\t" +- "blu,a,pn %%xcc, 1f\n\t" +- " add %3, 1, %3\n" +- "1:\n\t" +- "sllx %3, 32, %3\n\t" ++ "bne,a,pn %%xcc, 1b\n\t" ++ " mov %4, %2\n\t" ++ "sllx %4, 32, %4\n\t" + "or %3, %4, %0\n\t" + : "=&r" (ret), "=&r" (addr), + "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3)