]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Jul 2013 20:17:36 +0000 (13:17 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Jul 2013 20:17:36 +0000 (13:17 -0700)
added patches:
parisc-document-the-shadow-registers.patch
parisc-fix-gcc-miscompilation-in-pa_memcpy.patch

queue-3.10/parisc-document-the-shadow-registers.patch [new file with mode: 0644]
queue-3.10/parisc-fix-gcc-miscompilation-in-pa_memcpy.patch [new file with mode: 0644]
queue-3.10/series

diff --git a/queue-3.10/parisc-document-the-shadow-registers.patch b/queue-3.10/parisc-document-the-shadow-registers.patch
new file mode 100644 (file)
index 0000000..ec88346
--- /dev/null
@@ -0,0 +1,33 @@
+From a83f58bcb24003b9de2364de7c829a263423ead7 Mon Sep 17 00:00:00 2001
+From: Helge Deller <deller@gmx.de>
+Date: Sat, 29 Jun 2013 13:24:16 +0200
+Subject: parisc: document the shadow registers
+
+From: Helge Deller <deller@gmx.de>
+
+commit a83f58bcb24003b9de2364de7c829a263423ead7 upstream.
+
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ Documentation/parisc/registers |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/Documentation/parisc/registers
++++ b/Documentation/parisc/registers
+@@ -78,6 +78,14 @@ Shadow Registers            used by interruption h
+ TOC enable bit                        1
+ =========================================================================
++
++The PA-RISC architecture defines 7 registers as "shadow registers".
++Those are used in RETURN FROM INTERRUPTION AND RESTORE instruction to reduce
++the state save and restore time by eliminating the need for general register
++(GR) saves and restores in interruption handlers.
++Shadow registers are the GRs 1, 8, 9, 16, 17, 24, and 25.
++
++=========================================================================
+ Register usage notes, originally from John Marvin, with some additional
+ notes from Randolph Chung.
diff --git a/queue-3.10/parisc-fix-gcc-miscompilation-in-pa_memcpy.patch b/queue-3.10/parisc-fix-gcc-miscompilation-in-pa_memcpy.patch
new file mode 100644 (file)
index 0000000..c03b54f
--- /dev/null
@@ -0,0 +1,229 @@
+From 5b879d78bc0818aa710f5d4d9abbfc2aca075cc3 Mon Sep 17 00:00:00 2001
+From: Helge Deller <deller@gmx.de>
+Date: Thu, 4 Jul 2013 22:34:11 +0200
+Subject: parisc: Fix gcc miscompilation in pa_memcpy()
+
+From: Helge Deller <deller@gmx.de>
+
+commit 5b879d78bc0818aa710f5d4d9abbfc2aca075cc3 upstream.
+
+When running the LTP testsuite one may hit this kernel BUG() with the
+write06 testcase:
+
+kernel BUG at mm/filemap.c:2023!
+CPU: 1 PID: 8614 Comm: writev01 Not tainted 3.10.0-rc7-64bit-c3000+ #6
+IASQ: 0000000000000000 0000000000000000 IAOQ: 00000000401e6e84 00000000401e6e88
+ IIR: 03ffe01f    ISR: 0000000010340000  IOR: 000001fbe0380820
+ CPU:        1   CR30: 00000000bef80000 CR31: ffffffffffffffff
+ ORIG_R28: 00000000bdc192c0
+ IAOQ[0]: iov_iter_advance+0x3c/0xc0
+ IAOQ[1]: iov_iter_advance+0x40/0xc0
+ RP(r2): generic_file_buffered_write+0x204/0x3f0
+Backtrace:
+ [<00000000401e764c>] generic_file_buffered_write+0x204/0x3f0
+ [<00000000401eab24>] __generic_file_aio_write+0x244/0x448
+ [<00000000401eadc0>] generic_file_aio_write+0x98/0x150
+ [<000000004024f460>] do_sync_readv_writev+0xc0/0x130
+ [<000000004025037c>] compat_do_readv_writev+0x12c/0x340
+ [<00000000402505f8>] compat_writev+0x68/0xa0
+ [<0000000040251d88>] compat_SyS_writev+0x98/0xf8
+
+Reason for this crash is a gcc miscompilation in the fault handlers of
+pa_memcpy() which return the fault address instead of the copied bytes.
+Since this seems to be a generic problem with gcc-4.7.x (and below), it's
+better to simplify the fault handlers in pa_memcpy to avoid this problem.
+
+Here is a simple reproducer for the problem:
+
+int main(int argc, char **argv)
+{
+       int fd, nbytes;
+       struct iovec wr_iovec[] = {
+               { "TEST STRING                     ",32},
+               { (char*)0x40005000,32} }; // random memory.
+       fd = open(DATA_FILE, O_RDWR | O_CREAT, 0666);
+       nbytes = writev(fd, wr_iovec, 2);
+       printf("return value = %d, errno %d (%s)\n",
+               nbytes, errno, strerror(errno));
+       return 0;
+}
+
+In addition, John David Anglin wrote:
+There is no gcc PR as pa_memcpy is not legitimate C code. There is an
+implicit assumption that certain variables will contain correct values
+when an exception occurs and the code randomly jumps to one of the
+exception blocks.  There is no guarantee of this.  If a PR was filed, it
+would likely be marked as invalid.
+
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: John David Anglin <dave.anglin@bell.net>
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/parisc/lib/memcpy.c |   79 +++++++++++++++++++++++++++++------------------
+ 1 file changed, 50 insertions(+), 29 deletions(-)
+
+--- a/arch/parisc/lib/memcpy.c
++++ b/arch/parisc/lib/memcpy.c
+@@ -2,6 +2,7 @@
+  *    Optimized memory copy routines.
+  *
+  *    Copyright (C) 2004 Randolph Chung <tausq@debian.org>
++ *    Copyright (C) 2013 Helge Deller <deller@gmx.de>
+  *
+  *    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
+@@ -153,17 +154,21 @@ static inline void prefetch_dst(const vo
+ #define prefetch_dst(addr) do { } while(0)
+ #endif
++#define PA_MEMCPY_OK          0
++#define PA_MEMCPY_LOAD_ERROR  1
++#define PA_MEMCPY_STORE_ERROR 2
++
+ /* Copy from a not-aligned src to an aligned dst, using shifts. Handles 4 words
+  * per loop.  This code is derived from glibc. 
+  */
+-static inline unsigned long copy_dstaligned(unsigned long dst, unsigned long src, unsigned long len, unsigned long o_dst, unsigned long o_src, unsigned long o_len)
++static inline unsigned long copy_dstaligned(unsigned long dst,
++                                      unsigned long src, unsigned long len)
+ {
+       /* gcc complains that a2 and a3 may be uninitialized, but actually
+        * they cannot be.  Initialize a2/a3 to shut gcc up.
+        */
+       register unsigned int a0, a1, a2 = 0, a3 = 0;
+       int sh_1, sh_2;
+-      struct exception_data *d;
+       /* prefetch_src((const void *)src); */
+@@ -197,7 +202,7 @@ static inline unsigned long copy_dstalig
+                       goto do2;
+               case 0:
+                       if (len == 0)
+-                              return 0;
++                              return PA_MEMCPY_OK;
+                       /* a3 = ((unsigned int *) src)[0];
+                          a0 = ((unsigned int *) src)[1]; */
+                       ldw(s_space, 0, src, a3, cda_ldw_exc);
+@@ -256,42 +261,35 @@ do0:
+       preserve_branch(handle_load_error);
+       preserve_branch(handle_store_error);
+-      return 0;
++      return PA_MEMCPY_OK;
+ handle_load_error:
+       __asm__ __volatile__ ("cda_ldw_exc:\n");
+-      d = &__get_cpu_var(exception_data);
+-      DPRINTF("cda_ldw_exc: o_len=%lu fault_addr=%lu o_src=%lu ret=%lu\n",
+-              o_len, d->fault_addr, o_src, o_len - d->fault_addr + o_src);
+-      return o_len * 4 - d->fault_addr + o_src;
++      return PA_MEMCPY_LOAD_ERROR;
+ handle_store_error:
+       __asm__ __volatile__ ("cda_stw_exc:\n");
+-      d = &__get_cpu_var(exception_data);
+-      DPRINTF("cda_stw_exc: o_len=%lu fault_addr=%lu o_dst=%lu ret=%lu\n",
+-              o_len, d->fault_addr, o_dst, o_len - d->fault_addr + o_dst);
+-      return o_len * 4 - d->fault_addr + o_dst;
++      return PA_MEMCPY_STORE_ERROR;
+ }
+-/* Returns 0 for success, otherwise, returns number of bytes not transferred. */
+-static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
++/* Returns PA_MEMCPY_OK, PA_MEMCPY_LOAD_ERROR or PA_MEMCPY_STORE_ERROR.
++ * In case of an access fault the faulty address can be read from the per_cpu
++ * exception data struct. */
++static unsigned long pa_memcpy_internal(void *dstp, const void *srcp,
++                                      unsigned long len)
+ {
+       register unsigned long src, dst, t1, t2, t3;
+       register unsigned char *pcs, *pcd;
+       register unsigned int *pws, *pwd;
+       register double *pds, *pdd;
+-      unsigned long ret = 0;
+-      unsigned long o_dst, o_src, o_len;
+-      struct exception_data *d;
++      unsigned long ret;
+       src = (unsigned long)srcp;
+       dst = (unsigned long)dstp;
+       pcs = (unsigned char *)srcp;
+       pcd = (unsigned char *)dstp;
+-      o_dst = dst; o_src = src; o_len = len;
+-
+       /* prefetch_src((const void *)srcp); */
+       if (len < THRESHOLD)
+@@ -401,7 +399,7 @@ byte_copy:
+               len--;
+       }
+-      return 0;
++      return PA_MEMCPY_OK;
+ unaligned_copy:
+       /* possibly we are aligned on a word, but not on a double... */
+@@ -438,8 +436,7 @@ unaligned_copy:
+               src = (unsigned long)pcs;
+       }
+-      ret = copy_dstaligned(dst, src, len / sizeof(unsigned int), 
+-              o_dst, o_src, o_len);
++      ret = copy_dstaligned(dst, src, len / sizeof(unsigned int));
+       if (ret)
+               return ret;
+@@ -454,17 +451,41 @@ unaligned_copy:
+ handle_load_error:
+       __asm__ __volatile__ ("pmc_load_exc:\n");
+-      d = &__get_cpu_var(exception_data);
+-      DPRINTF("pmc_load_exc: o_len=%lu fault_addr=%lu o_src=%lu ret=%lu\n",
+-              o_len, d->fault_addr, o_src, o_len - d->fault_addr + o_src);
+-      return o_len - d->fault_addr + o_src;
++      return PA_MEMCPY_LOAD_ERROR;
+ handle_store_error:
+       __asm__ __volatile__ ("pmc_store_exc:\n");
++      return PA_MEMCPY_STORE_ERROR;
++}
++
++
++/* Returns 0 for success, otherwise, returns number of bytes not transferred. */
++static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
++{
++      unsigned long ret, fault_addr, reference;
++      struct exception_data *d;
++
++      ret = pa_memcpy_internal(dstp, srcp, len);
++      if (likely(ret == PA_MEMCPY_OK))
++              return 0;
++
++      /* if a load or store fault occured we can get the faulty addr */
+       d = &__get_cpu_var(exception_data);
+-      DPRINTF("pmc_store_exc: o_len=%lu fault_addr=%lu o_dst=%lu ret=%lu\n",
+-              o_len, d->fault_addr, o_dst, o_len - d->fault_addr + o_dst);
+-      return o_len - d->fault_addr + o_dst;
++      fault_addr = d->fault_addr;
++
++      /* error in load or store? */
++      if (ret == PA_MEMCPY_LOAD_ERROR)
++              reference = (unsigned long) srcp;
++      else
++              reference = (unsigned long) dstp;
++
++      DPRINTF("pa_memcpy: fault type = %lu, len=%lu fault_addr=%lu ref=%lu\n",
++              ret, len, fault_addr, reference);
++
++      if (fault_addr >= reference)
++              return len - (fault_addr - reference);
++      else
++              return len;
+ }
+ #ifdef __KERNEL__
index 063b6ee99837579c45911493b70a826b8824300a..dde1db740484ebc702446d88f63b968addd41423 100644 (file)
@@ -18,3 +18,5 @@ drivers-hv-switch-to-use-mb-instead-of-smp_mb.patch
 pcmcia-at91_cf-fix-gpio_get_value-in-at91_cf_get_status.patch
 cgroup-fix-umount-vs-cgroup_event_remove-race.patch
 cgroup-fix-rcu-accesses-to-task-cgroups.patch
+parisc-document-the-shadow-registers.patch
+parisc-fix-gcc-miscompilation-in-pa_memcpy.patch