1 From 49e011c979aee23801198617a0052b0b087583a6 Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.org>
3 Date: Mon, 13 Oct 2014 11:47:53 +0100
4 Subject: [PATCH 062/114] Improve __copy_to_user and __copy_from_user
7 Provide a __copy_from_user that uses memcpy. On BCM2708, use
8 optimised memcpy/memmove/memcmp/memset implementations.
10 arch/arm/include/asm/string.h | 5 +
11 arch/arm/include/asm/uaccess.h | 1 +
12 arch/arm/lib/Makefile | 15 +-
13 arch/arm/lib/arm-mem.h | 159 ++++++++++++
14 arch/arm/lib/copy_from_user.S | 4 +-
15 arch/arm/lib/exports_rpi.c | 37 +++
16 arch/arm/lib/memcmp_rpi.S | 285 +++++++++++++++++++++
17 arch/arm/lib/memcpy_rpi.S | 59 +++++
18 arch/arm/lib/memcpymove.h | 506 +++++++++++++++++++++++++++++++++++++
19 arch/arm/lib/memmove_rpi.S | 61 +++++
20 arch/arm/lib/memset_rpi.S | 121 +++++++++
21 arch/arm/lib/uaccess_with_memcpy.c | 112 +++++++-
22 12 files changed, 1359 insertions(+), 6 deletions(-)
23 create mode 100644 arch/arm/lib/arm-mem.h
24 create mode 100644 arch/arm/lib/exports_rpi.c
25 create mode 100644 arch/arm/lib/memcmp_rpi.S
26 create mode 100644 arch/arm/lib/memcpy_rpi.S
27 create mode 100644 arch/arm/lib/memcpymove.h
28 create mode 100644 arch/arm/lib/memmove_rpi.S
29 create mode 100644 arch/arm/lib/memset_rpi.S
31 diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h
32 index cf4f3aa..9fe7780 100644
33 --- a/arch/arm/include/asm/string.h
34 +++ b/arch/arm/include/asm/string.h
35 @@ -24,6 +24,11 @@ extern void * memchr(const void *, int, __kernel_size_t);
36 #define __HAVE_ARCH_MEMSET
37 extern void * memset(void *, int, __kernel_size_t);
39 +#ifdef CONFIG_MACH_BCM2708
40 +#define __HAVE_ARCH_MEMCMP
41 +extern int memcmp(const void *, const void *, size_t);
44 extern void __memzero(void *ptr, __kernel_size_t n);
46 #define memset(p,v,n) \
47 diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
48 index 4767eb9..bcd43de 100644
49 --- a/arch/arm/include/asm/uaccess.h
50 +++ b/arch/arm/include/asm/uaccess.h
51 @@ -475,6 +475,7 @@ do { \
54 extern unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n);
55 +extern unsigned long __must_check __copy_from_user_std(void *to, const void __user *from, unsigned long n);
56 extern unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n);
57 extern unsigned long __must_check __copy_to_user_std(void __user *to, const void *from, unsigned long n);
58 extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n);
59 diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
60 index 0573faa..498f5dd 100644
61 --- a/arch/arm/lib/Makefile
62 +++ b/arch/arm/lib/Makefile
65 lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \
66 csumpartialcopy.o csumpartialcopyuser.o clearbit.o \
67 - delay.o delay-loop.o findbit.o memchr.o memcpy.o \
68 - memmove.o memset.o memzero.o setbit.o \
69 - strchr.o strrchr.o \
70 + delay.o delay-loop.o findbit.o memchr.o memzero.o \
71 + setbit.o strchr.o strrchr.o \
72 testchangebit.o testclearbit.o testsetbit.o \
73 ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
74 ucmpdi2.o lib1funcs.o div64.o \
75 io-readsb.o io-writesb.o io-readsl.o io-writesl.o \
76 call_with_stack.o bswapsdi2.o
78 +# Choose optimised implementations for Raspberry Pi
79 +ifeq ($(CONFIG_MACH_BCM2708),y)
80 + CFLAGS_uaccess_with_memcpy.o += -DCOPY_FROM_USER_THRESHOLD=1600
81 + CFLAGS_uaccess_with_memcpy.o += -DCOPY_TO_USER_THRESHOLD=672
82 + obj-$(CONFIG_MODULES) += exports_rpi.o
83 + lib-y += memcpy_rpi.o memmove_rpi.o memset_rpi.o memcmp_rpi.o
85 + lib-y += memcpy.o memmove.o memset.o
88 mmu-y := clear_user.o copy_page.o getuser.o putuser.o
90 # the code in uaccess.S is not preemption safe and
91 diff --git a/arch/arm/lib/arm-mem.h b/arch/arm/lib/arm-mem.h
93 index 0000000..5d4bda1
95 +++ b/arch/arm/lib/arm-mem.h
98 +Copyright (c) 2013, Raspberry Pi Foundation
99 +Copyright (c) 2013, RISC OS Open Ltd
100 +All rights reserved.
102 +Redistribution and use in source and binary forms, with or without
103 +modification, are permitted provided that the following conditions are met:
104 + * Redistributions of source code must retain the above copyright
105 + notice, this list of conditions and the following disclaimer.
106 + * Redistributions in binary form must reproduce the above copyright
107 + notice, this list of conditions and the following disclaimer in the
108 + documentation and/or other materials provided with the distribution.
109 + * Neither the name of the copyright holder nor the
110 + names of its contributors may be used to endorse or promote products
111 + derived from this software without specific prior written permission.
113 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
114 +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
115 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
116 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
117 +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
118 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
119 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
120 +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
121 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
122 +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
131 +.macro preload_leading_step1 backwards, ptr, base
132 +/* If the destination is already 16-byte aligned, then we need to preload
133 + * between 0 and prefetch_distance (inclusive) cache lines ahead so there
134 + * are no gaps when the inner loop starts.
143 + .rept prefetch_distance+1
146 + .set OFFSET, OFFSET-32
148 + .set OFFSET, OFFSET+32
153 +.macro preload_leading_step2 backwards, ptr, base, leading_bytes, tmp
154 +/* However, if the destination is not 16-byte aligned, we may need to
155 + * preload one more cache line than that. The question we need to ask is:
156 + * are the leading bytes more than the amount by which the source
157 + * pointer will be rounded down for preloading, and if so, by how many
161 +/* Here we compare against how many bytes we are into the
162 + * cache line, counting down from the highest such address.
163 + * Effectively, we want to calculate
164 + * leading_bytes = dst&15
165 + * cacheline_offset = 31-((src-leading_bytes-1)&31)
166 + * extra_needed = leading_bytes - cacheline_offset
167 + * and test if extra_needed is <= 0, or rearranging:
168 + * leading_bytes + (src-leading_bytes-1)&31 <= 31
170 + mov tmp, base, lsl #32-5
171 + sbc tmp, tmp, leading_bytes, lsl #32-5
172 + adds tmp, tmp, leading_bytes, lsl #32-5
174 + pld [ptr, #-32*(prefetch_distance+1)]
176 +/* Effectively, we want to calculate
177 + * leading_bytes = (-dst)&15
178 + * cacheline_offset = (src+leading_bytes)&31
179 + * extra_needed = leading_bytes - cacheline_offset
180 + * and test if extra_needed is <= 0.
182 + mov tmp, base, lsl #32-5
183 + add tmp, tmp, leading_bytes, lsl #32-5
184 + rsbs tmp, tmp, leading_bytes, lsl #32-5
186 + pld [ptr, #32*(prefetch_distance+1)]
191 +.macro preload_trailing backwards, base, remain, tmp
192 + /* We need either 0, 1 or 2 extra preloads */
195 + mov tmp, tmp, lsl #32-5
197 + mov tmp, base, lsl #32-5
199 + adds tmp, tmp, remain, lsl #32-5
200 + adceqs tmp, tmp, #0
201 + /* The instruction above has two effects: ensures Z is only
202 + * set if C was clear (so Z indicates that both shifted quantities
203 + * were 0), and clears C if Z was set (so C indicates that the sum
204 + * of the shifted quantities was greater and not equal to 32) */
214 + pld [tmp, #-32*(prefetch_distance+1)]
216 + pld [tmp, #-32*prefetch_distance]
218 + pld [tmp, #32*(prefetch_distance+2)]
220 + pld [tmp, #32*(prefetch_distance+1)]
225 +.macro preload_all backwards, narrow_case, shift, base, remain, tmp0, tmp1
228 + bic tmp0, tmp0, #31
230 + sub tmp1, base, remain, lsl #shift
232 + bic tmp0, base, #31
234 + add tmp1, base, remain, lsl #shift
237 + bic tmp1, tmp1, #31
241 + /* In this case, all the data fits in either 1 or 2 cache lines */
246 + sub tmp0, tmp0, #32
248 + add tmp0, tmp0, #32
256 diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S
257 index 66a477a..3faddf7 100644
258 --- a/arch/arm/lib/copy_from_user.S
259 +++ b/arch/arm/lib/copy_from_user.S
264 -ENTRY(__copy_from_user)
265 +ENTRY(__copy_from_user_std)
266 +WEAK(__copy_from_user)
268 #include "copy_template.S"
270 ENDPROC(__copy_from_user)
271 +ENDPROC(__copy_from_user_std)
273 .pushsection .fixup,"ax"
275 diff --git a/arch/arm/lib/exports_rpi.c b/arch/arm/lib/exports_rpi.c
277 index 0000000..1f82604
279 +++ b/arch/arm/lib/exports_rpi.c
282 + * Copyright (c) 2014, Raspberry Pi (Trading) Ltd.
284 + * Redistribution and use in source and binary forms, with or without
285 + * modification, are permitted provided that the following conditions
287 + * 1. Redistributions of source code must retain the above copyright
288 + * notice, this list of conditions, and the following disclaimer,
289 + * without modification.
290 + * 2. Redistributions in binary form must reproduce the above copyright
291 + * notice, this list of conditions and the following disclaimer in the
292 + * documentation and/or other materials provided with the distribution.
293 + * 3. The names of the above-listed copyright holders may not be used
294 + * to endorse or promote products derived from this software without
295 + * specific prior written permission.
297 + * ALTERNATIVELY, this software may be distributed under the terms of the
298 + * GNU General Public License ("GPL") version 2, as published by the Free
299 + * Software Foundation.
301 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
302 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
303 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
304 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
305 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
306 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
307 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
308 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
309 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
310 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
311 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
314 +#include <linux/kernel.h>
315 +#include <linux/module.h>
317 +EXPORT_SYMBOL(memcmp);
318 diff --git a/arch/arm/lib/memcmp_rpi.S b/arch/arm/lib/memcmp_rpi.S
320 index 0000000..bf6e4ed
322 +++ b/arch/arm/lib/memcmp_rpi.S
325 +Copyright (c) 2013, Raspberry Pi Foundation
326 +Copyright (c) 2013, RISC OS Open Ltd
327 +All rights reserved.
329 +Redistribution and use in source and binary forms, with or without
330 +modification, are permitted provided that the following conditions are met:
331 + * Redistributions of source code must retain the above copyright
332 + notice, this list of conditions and the following disclaimer.
333 + * Redistributions in binary form must reproduce the above copyright
334 + notice, this list of conditions and the following disclaimer in the
335 + documentation and/or other materials provided with the distribution.
336 + * Neither the name of the copyright holder nor the
337 + names of its contributors may be used to endorse or promote products
338 + derived from this software without specific prior written permission.
340 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
341 +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
342 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
343 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
344 +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
345 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
346 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
347 +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
348 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
349 +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
352 +#include <linux/linkage.h>
353 +#include "arm-mem.h"
355 +/* Prevent the stack from becoming executable */
356 +#if defined(__linux__) && defined(__ELF__)
357 +.section .note.GNU-stack,"",%progbits
367 +.macro memcmp_process_head unaligned
369 + ldr DAT0, [S_1], #4
370 + ldr DAT1, [S_1], #4
371 + ldr DAT2, [S_1], #4
372 + ldr DAT3, [S_1], #4
374 + ldmia S_1!, {DAT0, DAT1, DAT2, DAT3}
376 + ldmia S_2!, {DAT4, DAT5, DAT6, DAT7}
379 +.macro memcmp_process_tail
387 +.macro memcmp_leading_31bytes
388 + movs DAT0, OFF, lsl #31
389 + ldrmib DAT0, [S_1], #1
390 + ldrcsh DAT1, [S_1], #2
391 + ldrmib DAT4, [S_2], #1
392 + ldrcsh DAT5, [S_2], #2
402 + movs DAT0, OFF, lsl #29
403 + ldrmi DAT0, [S_1], #4
404 + ldrcs DAT1, [S_1], #4
405 + ldrcs DAT2, [S_1], #4
406 + ldrmi DAT4, [S_2], #4
407 + ldmcsia S_2!, {DAT5, DAT6}
422 + memcmp_process_head 1
424 + memcmp_process_tail
428 +.macro memcmp_trailing_15bytes unaligned
431 + ldrcs DAT0, [S_1], #4
432 + ldrcs DAT1, [S_1], #4
434 + ldmcsia S_1!, {DAT0, DAT1}
436 + ldrmi DAT2, [S_1], #4
437 + ldmcsia S_2!, {DAT4, DAT5}
438 + ldrmi DAT6, [S_2], #4
450 + ldrcsh DAT0, [S_1], #2
452 + ldrcsh DAT4, [S_2], #2
463 +.macro memcmp_long_inner_loop unaligned
465 + memcmp_process_head unaligned
466 + pld [S_2, #prefetch_distance*32 + 16]
467 + memcmp_process_tail
468 + memcmp_process_head unaligned
470 + memcmp_process_tail
473 + /* Just before the final (prefetch_distance+1) 32-byte blocks,
474 + * deal with final preloads */
475 + preload_trailing 0, S_1, N, DAT0
476 + preload_trailing 0, S_2, N, DAT0
477 + add N, N, #(prefetch_distance+2)*32 - 16
479 + memcmp_process_head unaligned
480 + memcmp_process_tail
483 + /* Trailing words and bytes */
486 + memcmp_trailing_15bytes unaligned
487 +199: /* Reached end without detecting a difference */
490 + pop {DAT1-DAT6, pc}
493 +.macro memcmp_short_inner_loop unaligned
494 + subs N, N, #16 /* simplifies inner loop termination */
497 + memcmp_process_head unaligned
498 + memcmp_process_tail
501 +122: /* Trailing words and bytes */
504 + memcmp_trailing_15bytes unaligned
505 +199: /* Reached end without detecting a difference */
508 + pop {DAT1-DAT6, pc}
512 + * int memcmp(const void *s1, const void *s2, size_t n);
514 + * a1 = pointer to buffer 1
515 + * a2 = pointer to buffer 2
516 + * a3 = number of bytes to compare (as unsigned chars)
518 + * a1 = >0/=0/<0 if s1 >/=/< s2
521 +.set prefetch_distance, 2
537 + push {DAT1-DAT6, lr}
538 + setend be /* lowest-addressed bytes are most significant */
540 + /* To preload ahead as we go, we need at least (prefetch_distance+2) 32-byte blocks */
541 + cmp N, #(prefetch_distance+3)*32 - 1
545 + /* Adjust N so that the decrement instruction can also test for
546 + * inner loop termination. We want it to stop when there are
547 + * (prefetch_distance+1) complete blocks to go. */
548 + sub N, N, #(prefetch_distance+2)*32
549 + preload_leading_step1 0, DAT0, S_1
550 + preload_leading_step1 0, DAT1, S_2
553 + rsb OFF, S_2, #0 /* no need to AND with 15 here */
554 + preload_leading_step2 0, DAT0, S_1, OFF, DAT2
555 + preload_leading_step2 0, DAT1, S_2, OFF, DAT2
556 + memcmp_leading_31bytes
557 +154: /* Second source now cacheline (32-byte) aligned; we have at
558 + * least one prefetch to go. */
559 + /* Prefetch offset is best selected such that it lies in the
560 + * first 8 of each 32 bytes - but it's just as easy to aim for
563 + rsb OFF, OFF, #32*prefetch_distance
566 + memcmp_long_inner_loop 0
567 +140: memcmp_long_inner_loop 1
569 +170: /* Short case */
572 + preload_all 0, 0, 0, S_1, N, DAT0, DAT1
573 + preload_all 0, 0, 0, S_2, N, DAT0, DAT1
578 + ldrb DAT0, [S_1], #1
579 + ldrb DAT4, [S_2], #1
584 +174: /* Second source now 4-byte aligned; we have 0 or more bytes to go */
587 + memcmp_short_inner_loop 0
588 +140: memcmp_short_inner_loop 1
590 +200: /* Difference found: determine sign. */
594 + pop {DAT1-DAT6, pc}
609 diff --git a/arch/arm/lib/memcpy_rpi.S b/arch/arm/lib/memcpy_rpi.S
611 index 0000000..15ff2bd
613 +++ b/arch/arm/lib/memcpy_rpi.S
616 +Copyright (c) 2013, Raspberry Pi Foundation
617 +Copyright (c) 2013, RISC OS Open Ltd
618 +All rights reserved.
620 +Redistribution and use in source and binary forms, with or without
621 +modification, are permitted provided that the following conditions are met:
622 + * Redistributions of source code must retain the above copyright
623 + notice, this list of conditions and the following disclaimer.
624 + * Redistributions in binary form must reproduce the above copyright
625 + notice, this list of conditions and the following disclaimer in the
626 + documentation and/or other materials provided with the distribution.
627 + * Neither the name of the copyright holder nor the
628 + names of its contributors may be used to endorse or promote products
629 + derived from this software without specific prior written permission.
631 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
632 +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
633 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
634 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
635 +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
636 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
637 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
638 +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
639 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
640 +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
643 +#include <linux/linkage.h>
644 +#include "arm-mem.h"
645 +#include "memcpymove.h"
647 +/* Prevent the stack from becoming executable */
648 +#if defined(__linux__) && defined(__ELF__)
649 +.section .note.GNU-stack,"",%progbits
660 + * void *memcpy(void * restrict s1, const void * restrict s2, size_t n);
662 + * a1 = pointer to destination
663 + * a2 = pointer to source
664 + * a3 = number of bytes to copy
669 +.set prefetch_distance, 3
674 diff --git a/arch/arm/lib/memcpymove.h b/arch/arm/lib/memcpymove.h
676 index 0000000..d8be584
678 +++ b/arch/arm/lib/memcpymove.h
681 +Copyright (c) 2013, Raspberry Pi Foundation
682 +Copyright (c) 2013, RISC OS Open Ltd
683 +All rights reserved.
685 +Redistribution and use in source and binary forms, with or without
686 +modification, are permitted provided that the following conditions are met:
687 + * Redistributions of source code must retain the above copyright
688 + notice, this list of conditions and the following disclaimer.
689 + * Redistributions in binary form must reproduce the above copyright
690 + notice, this list of conditions and the following disclaimer in the
691 + documentation and/or other materials provided with the distribution.
692 + * Neither the name of the copyright holder nor the
693 + names of its contributors may be used to endorse or promote products
694 + derived from this software without specific prior written permission.
696 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
697 +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
698 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
699 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
700 +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
701 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
702 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
703 +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
704 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
705 +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
708 +.macro unaligned_words backwards, align, use_pld, words, r0, r1, r2, r3, r4, r5, r6, r7, r8
711 + mov r1, r0, lsl #32-align*8
713 + orr r1, r1, r0, lsr #align*8
716 + mov r0, r1, lsr #align*8
718 + orr r0, r0, r1, lsl #32-align*8
724 + mov r2, r0, lsl #32-align*8
726 + orr r2, r2, r1, lsr #align*8
727 + mov r1, r1, lsl #32-align*8
728 + orr r1, r1, r0, lsr #align*8
732 + mov r0, r2, lsr #align*8
734 + orr r0, r0, r1, lsl #32-align*8
735 + mov r1, r1, lsr #align*8
736 + orr r1, r1, r2, lsl #32-align*8
742 + mov r4, r0, lsl #32-align*8
744 + orr r4, r4, r3, lsr #align*8
745 + mov r3, r3, lsl #32-align*8
746 + orr r3, r3, r2, lsr #align*8
747 + mov r2, r2, lsl #32-align*8
748 + orr r2, r2, r1, lsr #align*8
749 + mov r1, r1, lsl #32-align*8
750 + orr r1, r1, r0, lsr #align*8
751 + stmdb D!, {r1, r2, r3, r4}
754 + mov r0, r4, lsr #align*8
756 + orr r0, r0, r1, lsl #32-align*8
757 + mov r1, r1, lsr #align*8
758 + orr r1, r1, r2, lsl #32-align*8
759 + mov r2, r2, lsr #align*8
760 + orr r2, r2, r3, lsl #32-align*8
761 + mov r3, r3, lsr #align*8
762 + orr r3, r3, r4, lsl #32-align*8
763 + stmia D!, {r0, r1, r2, r3}
767 + ldmdb S!, {r4, r5, r6, r7}
768 + mov r8, r0, lsl #32-align*8
769 + ldmdb S!, {r0, r1, r2, r3}
773 + orr r8, r8, r7, lsr #align*8
774 + mov r7, r7, lsl #32-align*8
775 + orr r7, r7, r6, lsr #align*8
776 + mov r6, r6, lsl #32-align*8
777 + orr r6, r6, r5, lsr #align*8
778 + mov r5, r5, lsl #32-align*8
779 + orr r5, r5, r4, lsr #align*8
780 + mov r4, r4, lsl #32-align*8
781 + orr r4, r4, r3, lsr #align*8
782 + mov r3, r3, lsl #32-align*8
783 + orr r3, r3, r2, lsr #align*8
784 + mov r2, r2, lsl #32-align*8
785 + orr r2, r2, r1, lsr #align*8
786 + mov r1, r1, lsl #32-align*8
787 + orr r1, r1, r0, lsr #align*8
788 + stmdb D!, {r5, r6, r7, r8}
789 + stmdb D!, {r1, r2, r3, r4}
791 + ldmib S!, {r1, r2, r3, r4}
792 + mov r0, r8, lsr #align*8
793 + ldmib S!, {r5, r6, r7, r8}
797 + orr r0, r0, r1, lsl #32-align*8
798 + mov r1, r1, lsr #align*8
799 + orr r1, r1, r2, lsl #32-align*8
800 + mov r2, r2, lsr #align*8
801 + orr r2, r2, r3, lsl #32-align*8
802 + mov r3, r3, lsr #align*8
803 + orr r3, r3, r4, lsl #32-align*8
804 + mov r4, r4, lsr #align*8
805 + orr r4, r4, r5, lsl #32-align*8
806 + mov r5, r5, lsr #align*8
807 + orr r5, r5, r6, lsl #32-align*8
808 + mov r6, r6, lsr #align*8
809 + orr r6, r6, r7, lsl #32-align*8
810 + mov r7, r7, lsr #align*8
811 + orr r7, r7, r8, lsl #32-align*8
812 + stmia D!, {r0, r1, r2, r3}
813 + stmia D!, {r4, r5, r6, r7}
818 +.macro memcpy_leading_15bytes backwards, align
819 + movs DAT1, DAT2, lsl #31
822 + ldrmib DAT0, [S, #-1]!
823 + ldrcsh DAT1, [S, #-2]!
824 + strmib DAT0, [D, #-1]!
825 + strcsh DAT1, [D, #-2]!
827 + ldrmib DAT0, [S], #1
828 + ldrcsh DAT1, [S], #2
829 + strmib DAT0, [D], #1
830 + strcsh DAT1, [D], #2
832 + movs DAT1, DAT2, lsl #29
834 + ldrmi DAT0, [S, #-4]!
836 + ldmcsdb S!, {DAT1, DAT2}
838 + ldrcs DAT2, [S, #-4]!
839 + ldrcs DAT1, [S, #-4]!
841 + strmi DAT0, [D, #-4]!
842 + stmcsdb D!, {DAT1, DAT2}
844 + ldrmi DAT0, [S], #4
846 + ldmcsia S!, {DAT1, DAT2}
848 + ldrcs DAT1, [S], #4
849 + ldrcs DAT2, [S], #4
851 + strmi DAT0, [D], #4
852 + stmcsia D!, {DAT1, DAT2}
856 +.macro memcpy_trailing_15bytes backwards, align
860 + ldmcsdb S!, {DAT0, DAT1}
862 + ldrcs DAT1, [S, #-4]!
863 + ldrcs DAT0, [S, #-4]!
865 + ldrmi DAT2, [S, #-4]!
866 + stmcsdb D!, {DAT0, DAT1}
867 + strmi DAT2, [D, #-4]!
870 + ldmcsia S!, {DAT0, DAT1}
872 + ldrcs DAT0, [S], #4
873 + ldrcs DAT1, [S], #4
875 + ldrmi DAT2, [S], #4
876 + stmcsia D!, {DAT0, DAT1}
877 + strmi DAT2, [D], #4
881 + ldrcsh DAT0, [S, #-2]!
882 + ldrmib DAT1, [S, #-1]
883 + strcsh DAT0, [D, #-2]!
884 + strmib DAT1, [D, #-1]
886 + ldrcsh DAT0, [S], #2
888 + strcsh DAT0, [D], #2
893 +.macro memcpy_long_inner_loop backwards, align
896 + ldr DAT0, [S, #-align]!
898 + ldr LAST, [S, #-align]!
904 + ldmdb S!, {DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, LAST}
906 + stmdb D!, {DAT4, DAT5, DAT6, LAST}
907 + stmdb D!, {DAT0, DAT1, DAT2, DAT3}
909 + ldmia S!, {DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, LAST}
911 + stmia D!, {DAT0, DAT1, DAT2, DAT3}
912 + stmia D!, {DAT4, DAT5, DAT6, LAST}
915 + unaligned_words backwards, align, 1, 8, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7, LAST
919 + /* Just before the final (prefetch_distance+1) 32-byte blocks, deal with final preloads */
920 + preload_trailing backwards, S, N, OFF
921 + add N, N, #(prefetch_distance+2)*32 - 32
925 + ldmdb S!, {DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, LAST}
926 + stmdb D!, {DAT4, DAT5, DAT6, LAST}
927 + stmdb D!, {DAT0, DAT1, DAT2, DAT3}
929 + ldmia S!, {DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, LAST}
930 + stmia D!, {DAT0, DAT1, DAT2, DAT3}
931 + stmia D!, {DAT4, DAT5, DAT6, LAST}
934 + unaligned_words backwards, align, 0, 8, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7, LAST
941 + ldmnedb S!, {DAT0, DAT1, DAT2, LAST}
942 + stmnedb D!, {DAT0, DAT1, DAT2, LAST}
944 + ldmneia S!, {DAT0, DAT1, DAT2, LAST}
945 + stmneia D!, {DAT0, DAT1, DAT2, LAST}
949 + unaligned_words backwards, align, 0, 4, DAT0, DAT1, DAT2, DAT3, LAST
952 + /* Trailing words and bytes */
958 + memcpy_trailing_15bytes backwards, align
960 + pop {DAT3, DAT4, DAT5, DAT6, DAT7}
961 + pop {D, DAT1, DAT2, pc}
964 +.macro memcpy_medium_inner_loop backwards, align
968 + ldmdb S!, {DAT0, DAT1, DAT2, LAST}
970 + ldr LAST, [S, #-4]!
971 + ldr DAT2, [S, #-4]!
972 + ldr DAT1, [S, #-4]!
973 + ldr DAT0, [S, #-4]!
975 + stmdb D!, {DAT0, DAT1, DAT2, LAST}
978 + ldmia S!, {DAT0, DAT1, DAT2, LAST}
985 + stmia D!, {DAT0, DAT1, DAT2, LAST}
989 + /* Trailing words and bytes */
992 + memcpy_trailing_15bytes backwards, align
994 + pop {D, DAT1, DAT2, pc}
997 +.macro memcpy_short_inner_loop backwards, align
1001 + ldmnedb S!, {DAT0, DAT1, DAT2, LAST}
1003 + ldrne LAST, [S, #-4]!
1004 + ldrne DAT2, [S, #-4]!
1005 + ldrne DAT1, [S, #-4]!
1006 + ldrne DAT0, [S, #-4]!
1008 + stmnedb D!, {DAT0, DAT1, DAT2, LAST}
1011 + ldmneia S!, {DAT0, DAT1, DAT2, LAST}
1013 + ldrne DAT0, [S], #4
1014 + ldrne DAT1, [S], #4
1015 + ldrne DAT2, [S], #4
1016 + ldrne LAST, [S], #4
1018 + stmneia D!, {DAT0, DAT1, DAT2, LAST}
1020 + memcpy_trailing_15bytes backwards, align
1022 + pop {D, DAT1, DAT2, pc}
1025 +.macro memcpy backwards
1042 + push {D, DAT1, DAT2, lr}
1044 + .cfi_def_cfa_offset 16
1045 + .cfi_rel_offset D, 0
1048 + .cfi_undefined DAT0
1049 + .cfi_rel_offset DAT1, 4
1050 + .cfi_rel_offset DAT2, 8
1051 + .cfi_undefined LAST
1052 + .cfi_rel_offset lr, 12
1059 + /* See if we're guaranteed to have at least one 16-byte aligned 16-byte write */
1062 + /* To preload ahead as we go, we need at least (prefetch_distance+2) 32-byte blocks */
1063 + cmp N, #(prefetch_distance+3)*32 - 1
1067 + push {DAT3, DAT4, DAT5, DAT6, DAT7}
1069 + .cfi_def_cfa_offset 36
1070 + .cfi_rel_offset D, 20
1071 + .cfi_rel_offset DAT1, 24
1072 + .cfi_rel_offset DAT2, 28
1073 + .cfi_rel_offset DAT3, 0
1074 + .cfi_rel_offset DAT4, 4
1075 + .cfi_rel_offset DAT5, 8
1076 + .cfi_rel_offset DAT6, 12
1077 + .cfi_rel_offset DAT7, 16
1078 + .cfi_rel_offset lr, 32
1080 + /* Adjust N so that the decrement instruction can also test for
1081 + * inner loop termination. We want it to stop when there are
1082 + * (prefetch_distance+1) complete blocks to go. */
1083 + sub N, N, #(prefetch_distance+2)*32
1084 + preload_leading_step1 backwards, DAT0, S
1086 + /* Bug in GAS: it accepts, but mis-assembles the instruction
1087 + * ands DAT2, D, #60, 2
1088 + * which sets DAT2 to the number of leading bytes until destination is aligned and also clears C (sets borrow)
1095 + rsb DAT2, DAT2, #16 /* number of leading bytes until destination aligned */
1097 + preload_leading_step2 backwards, DAT0, S, DAT2, OFF
1098 + memcpy_leading_15bytes backwards, 1
1099 +154: /* Destination now 16-byte aligned; we have at least one prefetch as well as at least one 16-byte output block */
1100 + /* Prefetch offset is best selected such that it lies in the first 8 of each 32 bytes - but it's just as easy to aim for the first one */
1104 + sub OFF, OFF, #32*(prefetch_distance+1)
1107 + rsb OFF, OFF, #32*prefetch_distance
1109 + movs DAT0, S, lsl #31
1113 + memcpy_long_inner_loop backwards, 0
1114 +155: memcpy_long_inner_loop backwards, 1
1115 +156: memcpy_long_inner_loop backwards, 2
1116 +157: memcpy_long_inner_loop backwards, 3
1118 + .cfi_def_cfa_offset 16
1119 + .cfi_rel_offset D, 0
1120 + .cfi_rel_offset DAT1, 4
1121 + .cfi_rel_offset DAT2, 8
1122 + .cfi_same_value DAT3
1123 + .cfi_same_value DAT4
1124 + .cfi_same_value DAT5
1125 + .cfi_same_value DAT6
1126 + .cfi_same_value DAT7
1127 + .cfi_rel_offset lr, 12
1129 +160: /* Medium case */
1130 + preload_all backwards, 0, 0, S, N, DAT2, OFF
1131 + sub N, N, #16 /* simplifies inner loop termination */
1138 + rsb DAT2, DAT2, #16
1140 + memcpy_leading_15bytes backwards, align
1141 +164: /* Destination now 16-byte aligned; we have at least one 16-byte output block */
1144 + memcpy_medium_inner_loop backwards, 0
1145 +140: memcpy_medium_inner_loop backwards, 1
1147 +170: /* Short case, less than 31 bytes, so no guarantee of at least one 16-byte block */
1150 + preload_all backwards, 1, 0, S, N, DAT2, LAST
1156 + ldrb DAT0, [S, #-1]!
1157 + strb DAT0, [D, #-1]!
1159 + ldrb DAT0, [S], #1
1160 + strb DAT0, [D], #1
1164 +174: /* Destination now 4-byte aligned; we have 0 or more output bytes to go */
1167 + memcpy_short_inner_loop backwards, 0
1168 +140: memcpy_short_inner_loop backwards, 1
1186 diff --git a/arch/arm/lib/memmove_rpi.S b/arch/arm/lib/memmove_rpi.S
1187 new file mode 100644
1188 index 0000000..8b0760c
1190 +++ b/arch/arm/lib/memmove_rpi.S
1193 +Copyright (c) 2013, Raspberry Pi Foundation
1194 +Copyright (c) 2013, RISC OS Open Ltd
1195 +All rights reserved.
1197 +Redistribution and use in source and binary forms, with or without
1198 +modification, are permitted provided that the following conditions are met:
1199 + * Redistributions of source code must retain the above copyright
1200 + notice, this list of conditions and the following disclaimer.
1201 + * Redistributions in binary form must reproduce the above copyright
1202 + notice, this list of conditions and the following disclaimer in the
1203 + documentation and/or other materials provided with the distribution.
1204 + * Neither the name of the copyright holder nor the
1205 + names of its contributors may be used to endorse or promote products
1206 + derived from this software without specific prior written permission.
1208 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
1209 +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1210 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1211 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
1212 +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1213 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1214 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1215 +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1216 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1217 +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1220 +#include <linux/linkage.h>
1221 +#include "arm-mem.h"
1222 +#include "memcpymove.h"
1224 +/* Prevent the stack from becoming executable */
1225 +#if defined(__linux__) && defined(__ELF__)
1226 +.section .note.GNU-stack,"",%progbits
1231 + .object_arch armv4
1237 + * void *memmove(void *s1, const void *s2, size_t n);
1239 + * a1 = pointer to destination
1240 + * a2 = pointer to source
1241 + * a3 = number of bytes to copy
1246 +.set prefetch_distance, 3
1250 + bpl memcpy /* pl works even over -1 - 0 and 0x7fffffff - 0x80000000 boundaries */
1253 diff --git a/arch/arm/lib/memset_rpi.S b/arch/arm/lib/memset_rpi.S
1254 new file mode 100644
1255 index 0000000..2cde883
1257 +++ b/arch/arm/lib/memset_rpi.S
1260 +Copyright (c) 2013, Raspberry Pi Foundation
1261 +Copyright (c) 2013, RISC OS Open Ltd
1262 +All rights reserved.
1264 +Redistribution and use in source and binary forms, with or without
1265 +modification, are permitted provided that the following conditions are met:
1266 + * Redistributions of source code must retain the above copyright
1267 + notice, this list of conditions and the following disclaimer.
1268 + * Redistributions in binary form must reproduce the above copyright
1269 + notice, this list of conditions and the following disclaimer in the
1270 + documentation and/or other materials provided with the distribution.
1271 + * Neither the name of the copyright holder nor the
1272 + names of its contributors may be used to endorse or promote products
1273 + derived from this software without specific prior written permission.
1275 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
1276 +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1277 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1278 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
1279 +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1280 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1281 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1282 +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1283 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1284 +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1287 +#include <linux/linkage.h>
1288 +#include "arm-mem.h"
1290 +/* Prevent the stack from becoming executable */
1291 +#if defined(__linux__) && defined(__ELF__)
1292 +.section .note.GNU-stack,"",%progbits
1297 + .object_arch armv4
1303 + * void *memset(void *s, int c, size_t n);
1305 + * a1 = pointer to buffer to fill
1306 + * a2 = byte pattern to fill with (caller-narrowed)
1307 + * a3 = number of bytes to fill
1319 + orr DAT0, DAT0, lsl #8
1321 + orr DAT0, DAT0, lsl #16
1324 + /* See if we're guaranteed to have at least one 16-byte aligned 16-byte write */
1328 +161: sub N, N, #16 /* simplifies inner loop termination */
1329 + /* Leading words and bytes */
1332 + rsb DAT3, S, #0 /* bits 0-3 = number of leading bytes until aligned */
1333 + movs DAT2, DAT3, lsl #31
1335 + strmib DAT0, [S], #1
1337 + strcsh DAT0, [S], #2
1338 + movs DAT2, DAT3, lsl #29
1340 + strmi DAT0, [S], #4
1342 + stmcsia S!, {DAT0, DAT1}
1343 +164: /* Delayed set up of DAT2 and DAT3 so we could use them as scratch registers above */
1346 + /* Now the inner loop of 16-byte stores */
1347 +165: stmia S!, {DAT0, DAT1, DAT2, DAT3}
1350 +166: /* Trailing words and bytes */
1351 + movs N, N, lsl #29
1352 + stmcsia S!, {DAT0, DAT1}
1353 + strmi DAT0, [S], #4
1355 + strcsh DAT0, [S], #2
1359 +170: /* Short case */
1366 + strb DAT0, [S], #1
1370 + stmneia S!, {DAT0, DAT1, DAT2, DAT3}
1380 diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c
1381 index 3e58d71..0622891 100644
1382 --- a/arch/arm/lib/uaccess_with_memcpy.c
1383 +++ b/arch/arm/lib/uaccess_with_memcpy.c
1385 #include <asm/current.h>
1386 #include <asm/page.h>
1388 +#ifndef COPY_FROM_USER_THRESHOLD
1389 +#define COPY_FROM_USER_THRESHOLD 64
1392 +#ifndef COPY_TO_USER_THRESHOLD
1393 +#define COPY_TO_USER_THRESHOLD 64
1397 pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
1399 @@ -85,7 +93,44 @@ pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
1403 -static unsigned long noinline
1405 +pin_page_for_read(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
1407 + unsigned long addr = (unsigned long)_addr;
1414 + pgd = pgd_offset(current->mm, addr);
1415 + if (unlikely(pgd_none(*pgd) || pgd_bad(*pgd)))
1419 + pud = pud_offset(pgd, addr);
1420 + if (unlikely(pud_none(*pud) || pud_bad(*pud)))
1425 + pmd = pmd_offset(pud, addr);
1426 + if (unlikely(pmd_none(*pmd) || pmd_bad(*pmd)))
1429 + pte = pte_offset_map_lock(current->mm, pmd, addr, &ptl);
1430 + if (unlikely(!pte_present(*pte) || !pte_young(*pte))) {
1431 + pte_unmap_unlock(pte, ptl);
1441 +unsigned long noinline
1442 __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
1445 @@ -135,6 +180,54 @@ out:
1449 +unsigned long noinline
1450 +__copy_from_user_memcpy(void *to, const void __user *from, unsigned long n)
1454 + if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
1455 + memcpy(to, (const void *)from, n);
1459 + /* the mmap semaphore is taken only if not in an atomic context */
1460 + atomic = in_atomic();
1463 + down_read(¤t->mm->mmap_sem);
1469 + while (!pin_page_for_read(from, &pte, &ptl)) {
1472 + up_read(¤t->mm->mmap_sem);
1473 + if (__get_user(temp, (char __user *)from))
1476 + down_read(¤t->mm->mmap_sem);
1479 + tocopy = (~(unsigned long)from & ~PAGE_MASK) + 1;
1483 + memcpy(to, (const void *)from, tocopy);
1488 + pte_unmap_unlock(pte, ptl);
1491 + up_read(¤t->mm->mmap_sem);
1498 __copy_to_user(void __user *to, const void *from, unsigned long n)
1500 @@ -145,10 +238,25 @@ __copy_to_user(void __user *to, const void *from, unsigned long n)
1501 * With frame pointer disabled, tail call optimization kicks in
1502 * as well making this test almost invisible.
1505 + if (n < COPY_TO_USER_THRESHOLD)
1506 return __copy_to_user_std(to, from, n);
1507 return __copy_to_user_memcpy(to, from, n);
1511 +__copy_from_user(void *to, const void __user *from, unsigned long n)
1514 + * This test is stubbed out of the main function above to keep
1515 + * the overhead for small copies low by avoiding a large
1516 + * register dump on the stack just to reload them right away.
1517 + * With frame pointer disabled, tail call optimization kicks in
1518 + * as well making this test almost invisible.
1520 + if (n < COPY_FROM_USER_THRESHOLD)
1521 + return __copy_from_user_std(to, from, n);
1522 + return __copy_from_user_memcpy(to, from, n);
1525 static unsigned long noinline
1526 __clear_user_memset(void __user *addr, unsigned long n)