pa_memcpy() is the major memcpy implementation in the parisc kernel which is
used to do any kind of userspace/kernel memory copies.
Al Viro noticed various bugs in the implementation of pa_mempcy(), most notably
that in case of faults it may report back to have copied more bytes than it
actually did.
Fixing those bugs is quite hard in the C-implementation, because the compiler
is messing around with the registers and we are not guaranteed that specific
variables are always in the same processor registers. This makes proper fault
handling complicated.
This patch implements pa_memcpy() in assembler. That way we have correct fault
handling and adding a 64-bit copy routine was quite easy.
Runtime tested with 32- and 64bit kernels.
Reported-by: Al Viro <viro@ZenIV.linux.org.uk>
Cc: <stable@vger.kernel.org> # v4.9+
Signed-off-by: John David Anglin <dave.anglin@bell.net>
Signed-off-by: Helge Deller <deller@gmx.de>
Convert to the use of this_cpu_ptr().
Cc: "James E.J. Bottomley" <jejb@parisc-linux.org>
Cc: Helge Deller <deller@gmx.de>
Cc: linux-parisc@vger.kernel.org
Signed-off-by: Christoph Lameter <cl@linux.com>
Signed-off-by: Helge Deller <deller@gmx.de>
gcc (4.8.x) creates wrong code when the pa_memcpy() functions are
inlined. Especially in 32bit builds it calculates wrong return values
if we encounter a fault during execution of the memcpy.
Signed-off-by: Helge Deller <deller@gmx.de>
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>
Cc: <stable@vger.kernel.org> # 3.8+
Signed-off-by: Helge Deller <deller@gmx.de>
Avoid this warning, while still prevent gcc from optimizing away the exception code:
arch/parisc/lib/memcpy.c: In function ‘pa_memcpy’:
arch/parisc/lib/memcpy.c:256:2: warning: ‘dummy’ may be used uninitialized in this function [-Wuninitialized]
Signed-off-by: Helge Deller <deller@gmx.de>
Add CONFIG_DEBUG_STRICT_USER_COPY_CHECKS, copied from the x86
implementation. Tested with 32 and 64bit kernel.
Signed-off-by: Helge Deller <deller@gmx.de>
Signed-off-by: Kyle McMartin <kyle@mcmartin.ca>
>>>> I think this is what was intended? Note that this patch may affect
>>>> profiling.
>>> it really should be
>>>
>>> - if (likely(t1 & (sizeof(unsigned int)-1)) == 0) {
>>> + if (likely((t1 & (sizeof(unsigned int)-1)) == 0)) {
>>>
>>> randolph
Reported-by: Roel Kluin <roel.kluin@gmail.com>
Signed-off-by: Randolph Chung <tausq@parisc-linux.org>
Signed-off-by: Kyle McMartin <kyle@mcmartin.ca>
Make the following needlessly global code static:
- iomap.c: struct iomap_ops[]
- memcpy.c: pa_memcpy()
Signed-off-by: Adrian Bunk <bunk@kernel.org>
Cc: Matthew Wilcox <matthew@wil.cx>
Cc: Grant Grundler <grundler@parisc-linux.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Kyle McMartin <kyle@mcmartin.ca>
__FUNCTION__ is gcc-specific, use __func__
Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Cc: Kyle McMartin <kyle@mcmartin.ca>
Cc: Matthew Wilcox <willy@debian.org>
Cc: Grant Grundler <grundler@parisc-linux.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Kyle McMartin <kyle@mcmartin.ca>
"extern inline" will have different semantics with gcc 4.3, and "static
inline" is correct here.
Signed-off-by: Adrian Bunk <bunk@stusta.de>
Cc: Matthew Wilcox <willy@debian.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Kyle McMartin <kyle@mcmartin.ca>
- this macro unifies the code to add exception table entries
- additionally use ENTRY()/ENDPROC() at more places
Signed-off-by: Helge Deller <deller@gmx.de>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
Disable use of fpregs in pa_memcpy, and turn on the
-mdisable-fpregs flag.
Signed-off-by: Randolph Chung <tausq@parisc-linux.org>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!