]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fix timekeeping on sparc64 ultra-IIe machines, from DaveM
authorChris Wright <chrisw@sous-sol.org>
Tue, 24 Jan 2006 18:45:32 +0000 (10:45 -0800)
committerChris Wright <chrisw@sous-sol.org>
Tue, 24 Jan 2006 18:45:32 +0000 (10:45 -0800)
queue/series
queue/sparc64-fix-timekeeping-on-ultra-IIe-machines.patch [new file with mode: 0644]

index 35c626b95fa43e1f540bec8b43bc3ade73234892..a55dc214f6534843a9ba77507e91540444439a85 100644 (file)
@@ -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 (file)
index 0000000..36f7693
--- /dev/null
@@ -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" <davem@davemloft.net>
+Subject: [PATCH] Fix timekeeping on sparc64 ultra-IIe machines
+
+From: Richard Mortimer <richm@oldelvet.org.uk>
+
+[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 <richm@oldelvet.org.uk>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+ 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)