From 8fe2573e491ae4291b36b2d5ff44641c80973f3e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 17 Jul 2013 13:17:36 -0700 Subject: [PATCH] 3.10-stable patches added patches: parisc-document-the-shadow-registers.patch parisc-fix-gcc-miscompilation-in-pa_memcpy.patch --- ...parisc-document-the-shadow-registers.patch | 33 +++ ...-fix-gcc-miscompilation-in-pa_memcpy.patch | 229 ++++++++++++++++++ queue-3.10/series | 2 + 3 files changed, 264 insertions(+) create mode 100644 queue-3.10/parisc-document-the-shadow-registers.patch create mode 100644 queue-3.10/parisc-fix-gcc-miscompilation-in-pa_memcpy.patch 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 index 00000000000..ec88346c973 --- /dev/null +++ b/queue-3.10/parisc-document-the-shadow-registers.patch @@ -0,0 +1,33 @@ +From a83f58bcb24003b9de2364de7c829a263423ead7 Mon Sep 17 00:00:00 2001 +From: Helge Deller +Date: Sat, 29 Jun 2013 13:24:16 +0200 +Subject: parisc: document the shadow registers + +From: Helge Deller + +commit a83f58bcb24003b9de2364de7c829a263423ead7 upstream. + +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..c03b54f7c48 --- /dev/null +++ b/queue-3.10/parisc-fix-gcc-miscompilation-in-pa_memcpy.patch @@ -0,0 +1,229 @@ +From 5b879d78bc0818aa710f5d4d9abbfc2aca075cc3 Mon Sep 17 00:00:00 2001 +From: Helge Deller +Date: Thu, 4 Jul 2013 22:34:11 +0200 +Subject: parisc: Fix gcc miscompilation in pa_memcpy() + +From: Helge Deller + +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 +Signed-off-by: John David Anglin +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman + +--- + 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 ++ * Copyright (C) 2013 Helge Deller + * + * 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__ diff --git a/queue-3.10/series b/queue-3.10/series index 063b6ee9983..dde1db74048 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -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 -- 2.47.3