ramips: add support for PandoraBox PBR-M1
[15.05/openwrt.git] / target / linux / brcm2708 / patches-3.18 / 0062-Improve-__copy_to_user-and-__copy_from_user-performa.patch
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
5  performance
6
7 Provide a __copy_from_user that uses memcpy. On BCM2708, use
8 optimised memcpy/memmove/memcmp/memset implementations.
9 ---
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
30
31 --- a/arch/arm/include/asm/string.h
32 +++ b/arch/arm/include/asm/string.h
33 @@ -24,6 +24,11 @@ extern void * memchr(const void *, int,
34  #define __HAVE_ARCH_MEMSET
35  extern void * memset(void *, int, __kernel_size_t);
36  
37 +#ifdef CONFIG_MACH_BCM2708
38 +#define __HAVE_ARCH_MEMCMP
39 +extern int memcmp(const void *, const void *, size_t);
40 +#endif
41 +
42  extern void __memzero(void *ptr, __kernel_size_t n);
43  
44  #define memset(p,v,n)                                                  \
45 --- a/arch/arm/include/asm/uaccess.h
46 +++ b/arch/arm/include/asm/uaccess.h
47 @@ -475,6 +475,7 @@ do {                                                                        \
48  
49  #ifdef CONFIG_MMU
50  extern unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n);
51 +extern unsigned long __must_check __copy_from_user_std(void *to, const void __user *from, unsigned long n);
52  extern unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n);
53  extern unsigned long __must_check __copy_to_user_std(void __user *to, const void *from, unsigned long n);
54  extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n);
55 --- a/arch/arm/lib/Makefile
56 +++ b/arch/arm/lib/Makefile
57 @@ -6,15 +6,24 @@
58  
59  lib-y          := backtrace.o changebit.o csumipv6.o csumpartial.o   \
60                    csumpartialcopy.o csumpartialcopyuser.o clearbit.o \
61 -                  delay.o delay-loop.o findbit.o memchr.o memcpy.o   \
62 -                  memmove.o memset.o memzero.o setbit.o              \
63 -                  strchr.o strrchr.o                                 \
64 +                  delay.o delay-loop.o findbit.o memchr.o memzero.o  \
65 +                  setbit.o strchr.o strrchr.o                        \
66                    testchangebit.o testclearbit.o testsetbit.o        \
67                    ashldi3.o ashrdi3.o lshrdi3.o muldi3.o             \
68                    ucmpdi2.o lib1funcs.o div64.o                      \
69                    io-readsb.o io-writesb.o io-readsl.o io-writesl.o  \
70                    call_with_stack.o bswapsdi2.o
71  
72 +# Choose optimised implementations for Raspberry Pi
73 +ifeq ($(CONFIG_MACH_BCM2708),y)
74 +  CFLAGS_uaccess_with_memcpy.o += -DCOPY_FROM_USER_THRESHOLD=1600
75 +  CFLAGS_uaccess_with_memcpy.o += -DCOPY_TO_USER_THRESHOLD=672
76 +  obj-$(CONFIG_MODULES) += exports_rpi.o
77 +  lib-y        += memcpy_rpi.o memmove_rpi.o memset_rpi.o memcmp_rpi.o
78 +else
79 +  lib-y        += memcpy.o memmove.o memset.o
80 +endif
81 +
82  mmu-y  := clear_user.o copy_page.o getuser.o putuser.o
83  
84  # the code in uaccess.S is not preemption safe and
85 --- /dev/null
86 +++ b/arch/arm/lib/arm-mem.h
87 @@ -0,0 +1,159 @@
88 +/*
89 +Copyright (c) 2013, Raspberry Pi Foundation
90 +Copyright (c) 2013, RISC OS Open Ltd
91 +All rights reserved.
92 +
93 +Redistribution and use in source and binary forms, with or without
94 +modification, are permitted provided that the following conditions are met:
95 +    * Redistributions of source code must retain the above copyright
96 +      notice, this list of conditions and the following disclaimer.
97 +    * Redistributions in binary form must reproduce the above copyright
98 +      notice, this list of conditions and the following disclaimer in the
99 +      documentation and/or other materials provided with the distribution.
100 +    * Neither the name of the copyright holder nor the
101 +      names of its contributors may be used to endorse or promote products
102 +      derived from this software without specific prior written permission.
103 +
104 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
105 +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
106 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
107 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
108 +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
109 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
110 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
111 +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
112 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
113 +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
114 +*/
115 +
116 +.macro myfunc fname
117 + .func fname
118 + .global fname
119 +fname:
120 +.endm
121 +
122 +.macro preload_leading_step1  backwards, ptr, base
123 +/* If the destination is already 16-byte aligned, then we need to preload
124 + * between 0 and prefetch_distance (inclusive) cache lines ahead so there
125 + * are no gaps when the inner loop starts.
126 + */
127 + .if backwards
128 +        sub     ptr, base, #1
129 +        bic     ptr, ptr, #31
130 + .else
131 +        bic     ptr, base, #31
132 + .endif
133 + .set OFFSET, 0
134 + .rept prefetch_distance+1
135 +        pld     [ptr, #OFFSET]
136 +  .if backwards
137 +   .set OFFSET, OFFSET-32
138 +  .else
139 +   .set OFFSET, OFFSET+32
140 +  .endif
141 + .endr
142 +.endm
143 +
144 +.macro preload_leading_step2  backwards, ptr, base, leading_bytes, tmp
145 +/* However, if the destination is not 16-byte aligned, we may need to
146 + * preload one more cache line than that. The question we need to ask is:
147 + * are the leading bytes more than the amount by which the source
148 + * pointer will be rounded down for preloading, and if so, by how many
149 + * cache lines?
150 + */
151 + .if backwards
152 +/* Here we compare against how many bytes we are into the
153 + * cache line, counting down from the highest such address.
154 + * Effectively, we want to calculate
155 + *     leading_bytes = dst&15
156 + *     cacheline_offset = 31-((src-leading_bytes-1)&31)
157 + *     extra_needed = leading_bytes - cacheline_offset
158 + * and test if extra_needed is <= 0, or rearranging:
159 + *     leading_bytes + (src-leading_bytes-1)&31 <= 31
160 + */
161 +        mov     tmp, base, lsl #32-5
162 +        sbc     tmp, tmp, leading_bytes, lsl #32-5
163 +        adds    tmp, tmp, leading_bytes, lsl #32-5
164 +        bcc     61f
165 +        pld     [ptr, #-32*(prefetch_distance+1)]
166 + .else
167 +/* Effectively, we want to calculate
168 + *     leading_bytes = (-dst)&15
169 + *     cacheline_offset = (src+leading_bytes)&31
170 + *     extra_needed = leading_bytes - cacheline_offset
171 + * and test if extra_needed is <= 0.
172 + */
173 +        mov     tmp, base, lsl #32-5
174 +        add     tmp, tmp, leading_bytes, lsl #32-5
175 +        rsbs    tmp, tmp, leading_bytes, lsl #32-5
176 +        bls     61f
177 +        pld     [ptr, #32*(prefetch_distance+1)]
178 + .endif
179 +61:
180 +.endm
181 +
182 +.macro preload_trailing  backwards, base, remain, tmp
183 +        /* We need either 0, 1 or 2 extra preloads */
184 + .if backwards
185 +        rsb     tmp, base, #0
186 +        mov     tmp, tmp, lsl #32-5
187 + .else
188 +        mov     tmp, base, lsl #32-5
189 + .endif
190 +        adds    tmp, tmp, remain, lsl #32-5
191 +        adceqs  tmp, tmp, #0
192 +        /* The instruction above has two effects: ensures Z is only
193 +         * set if C was clear (so Z indicates that both shifted quantities
194 +         * were 0), and clears C if Z was set (so C indicates that the sum
195 +         * of the shifted quantities was greater and not equal to 32) */
196 +        beq     82f
197 + .if backwards
198 +        sub     tmp, base, #1
199 +        bic     tmp, tmp, #31
200 + .else
201 +        bic     tmp, base, #31
202 + .endif
203 +        bcc     81f
204 + .if backwards
205 +        pld     [tmp, #-32*(prefetch_distance+1)]
206 +81:
207 +        pld     [tmp, #-32*prefetch_distance]
208 + .else
209 +        pld     [tmp, #32*(prefetch_distance+2)]
210 +81:
211 +        pld     [tmp, #32*(prefetch_distance+1)]
212 + .endif
213 +82:
214 +.endm
215 +
216 +.macro preload_all    backwards, narrow_case, shift, base, remain, tmp0, tmp1
217 + .if backwards
218 +        sub     tmp0, base, #1
219 +        bic     tmp0, tmp0, #31
220 +        pld     [tmp0]
221 +        sub     tmp1, base, remain, lsl #shift
222 + .else
223 +        bic     tmp0, base, #31
224 +        pld     [tmp0]
225 +        add     tmp1, base, remain, lsl #shift
226 +        sub     tmp1, tmp1, #1
227 + .endif
228 +        bic     tmp1, tmp1, #31
229 +        cmp     tmp1, tmp0
230 +        beq     92f
231 + .if narrow_case
232 +        /* In this case, all the data fits in either 1 or 2 cache lines */
233 +        pld     [tmp1]
234 + .else
235 +91:
236 +  .if backwards
237 +        sub     tmp0, tmp0, #32
238 +  .else
239 +        add     tmp0, tmp0, #32
240 +  .endif
241 +        cmp     tmp0, tmp1
242 +        pld     [tmp0]
243 +        bne     91b
244 + .endif
245 +92:
246 +.endm
247 --- a/arch/arm/lib/copy_from_user.S
248 +++ b/arch/arm/lib/copy_from_user.S
249 @@ -84,11 +84,13 @@
250  
251         .text
252  
253 -ENTRY(__copy_from_user)
254 +ENTRY(__copy_from_user_std)
255 +WEAK(__copy_from_user)
256  
257  #include "copy_template.S"
258  
259  ENDPROC(__copy_from_user)
260 +ENDPROC(__copy_from_user_std)
261  
262         .pushsection .fixup,"ax"
263         .align 0
264 --- /dev/null
265 +++ b/arch/arm/lib/exports_rpi.c
266 @@ -0,0 +1,37 @@
267 +/**
268 + * Copyright (c) 2014, Raspberry Pi (Trading) Ltd.
269 + *
270 + * Redistribution and use in source and binary forms, with or without
271 + * modification, are permitted provided that the following conditions
272 + * are met:
273 + * 1. Redistributions of source code must retain the above copyright
274 + *    notice, this list of conditions, and the following disclaimer,
275 + *    without modification.
276 + * 2. Redistributions in binary form must reproduce the above copyright
277 + *    notice, this list of conditions and the following disclaimer in the
278 + *    documentation and/or other materials provided with the distribution.
279 + * 3. The names of the above-listed copyright holders may not be used
280 + *    to endorse or promote products derived from this software without
281 + *    specific prior written permission.
282 + *
283 + * ALTERNATIVELY, this software may be distributed under the terms of the
284 + * GNU General Public License ("GPL") version 2, as published by the Free
285 + * Software Foundation.
286 + *
287 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
288 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
289 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
290 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
291 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
292 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
293 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
294 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
295 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
296 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
297 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
298 + */
299 +
300 +#include <linux/kernel.h>
301 +#include <linux/module.h>
302 +
303 +EXPORT_SYMBOL(memcmp);
304 --- /dev/null
305 +++ b/arch/arm/lib/memcmp_rpi.S
306 @@ -0,0 +1,285 @@
307 +/*
308 +Copyright (c) 2013, Raspberry Pi Foundation
309 +Copyright (c) 2013, RISC OS Open Ltd
310 +All rights reserved.
311 +
312 +Redistribution and use in source and binary forms, with or without
313 +modification, are permitted provided that the following conditions are met:
314 +    * Redistributions of source code must retain the above copyright
315 +      notice, this list of conditions and the following disclaimer.
316 +    * Redistributions in binary form must reproduce the above copyright
317 +      notice, this list of conditions and the following disclaimer in the
318 +      documentation and/or other materials provided with the distribution.
319 +    * Neither the name of the copyright holder nor the
320 +      names of its contributors may be used to endorse or promote products
321 +      derived from this software without specific prior written permission.
322 +
323 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
324 +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
325 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
326 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
327 +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
328 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
329 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
330 +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
331 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
332 +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
333 +*/
334 +
335 +#include <linux/linkage.h>
336 +#include "arm-mem.h"
337 +
338 +/* Prevent the stack from becoming executable */
339 +#if defined(__linux__) && defined(__ELF__)
340 +.section .note.GNU-stack,"",%progbits
341 +#endif
342 +
343 +    .text
344 +    .arch armv6
345 +    .object_arch armv4
346 +    .arm
347 +    .altmacro
348 +    .p2align 2
349 +
350 +.macro memcmp_process_head  unaligned
351 + .if unaligned
352 +        ldr     DAT0, [S_1], #4
353 +        ldr     DAT1, [S_1], #4
354 +        ldr     DAT2, [S_1], #4
355 +        ldr     DAT3, [S_1], #4
356 + .else
357 +        ldmia   S_1!, {DAT0, DAT1, DAT2, DAT3}
358 + .endif
359 +        ldmia   S_2!, {DAT4, DAT5, DAT6, DAT7}
360 +.endm
361 +
362 +.macro memcmp_process_tail
363 +        cmp     DAT0, DAT4
364 +        cmpeq   DAT1, DAT5
365 +        cmpeq   DAT2, DAT6
366 +        cmpeq   DAT3, DAT7
367 +        bne     200f
368 +.endm
369 +
370 +.macro memcmp_leading_31bytes
371 +        movs    DAT0, OFF, lsl #31
372 +        ldrmib  DAT0, [S_1], #1
373 +        ldrcsh  DAT1, [S_1], #2
374 +        ldrmib  DAT4, [S_2], #1
375 +        ldrcsh  DAT5, [S_2], #2
376 +        movpl   DAT0, #0
377 +        movcc   DAT1, #0
378 +        movpl   DAT4, #0
379 +        movcc   DAT5, #0
380 +        submi   N, N, #1
381 +        subcs   N, N, #2
382 +        cmp     DAT0, DAT4
383 +        cmpeq   DAT1, DAT5
384 +        bne     200f
385 +        movs    DAT0, OFF, lsl #29
386 +        ldrmi   DAT0, [S_1], #4
387 +        ldrcs   DAT1, [S_1], #4
388 +        ldrcs   DAT2, [S_1], #4
389 +        ldrmi   DAT4, [S_2], #4
390 +        ldmcsia S_2!, {DAT5, DAT6}
391 +        movpl   DAT0, #0
392 +        movcc   DAT1, #0
393 +        movcc   DAT2, #0
394 +        movpl   DAT4, #0
395 +        movcc   DAT5, #0
396 +        movcc   DAT6, #0
397 +        submi   N, N, #4
398 +        subcs   N, N, #8
399 +        cmp     DAT0, DAT4
400 +        cmpeq   DAT1, DAT5
401 +        cmpeq   DAT2, DAT6
402 +        bne     200f
403 +        tst     OFF, #16
404 +        beq     105f
405 +        memcmp_process_head  1
406 +        sub     N, N, #16
407 +        memcmp_process_tail
408 +105:
409 +.endm
410 +
411 +.macro memcmp_trailing_15bytes  unaligned
412 +        movs    N, N, lsl #29
413 + .if unaligned
414 +        ldrcs   DAT0, [S_1], #4
415 +        ldrcs   DAT1, [S_1], #4
416 + .else
417 +        ldmcsia S_1!, {DAT0, DAT1}
418 + .endif
419 +        ldrmi   DAT2, [S_1], #4
420 +        ldmcsia S_2!, {DAT4, DAT5}
421 +        ldrmi   DAT6, [S_2], #4
422 +        movcc   DAT0, #0
423 +        movcc   DAT1, #0
424 +        movpl   DAT2, #0
425 +        movcc   DAT4, #0
426 +        movcc   DAT5, #0
427 +        movpl   DAT6, #0
428 +        cmp     DAT0, DAT4
429 +        cmpeq   DAT1, DAT5
430 +        cmpeq   DAT2, DAT6
431 +        bne     200f
432 +        movs    N, N, lsl #2
433 +        ldrcsh  DAT0, [S_1], #2
434 +        ldrmib  DAT1, [S_1]
435 +        ldrcsh  DAT4, [S_2], #2
436 +        ldrmib  DAT5, [S_2]
437 +        movcc   DAT0, #0
438 +        movpl   DAT1, #0
439 +        movcc   DAT4, #0
440 +        movpl   DAT5, #0
441 +        cmp     DAT0, DAT4
442 +        cmpeq   DAT1, DAT5
443 +        bne     200f
444 +.endm
445 +
446 +.macro memcmp_long_inner_loop  unaligned
447 +110:
448 +        memcmp_process_head  unaligned
449 +        pld     [S_2, #prefetch_distance*32 + 16]
450 +        memcmp_process_tail
451 +        memcmp_process_head  unaligned
452 +        pld     [S_1, OFF]
453 +        memcmp_process_tail
454 +        subs    N, N, #32
455 +        bhs     110b
456 +        /* Just before the final (prefetch_distance+1) 32-byte blocks,
457 +         * deal with final preloads */
458 +        preload_trailing  0, S_1, N, DAT0
459 +        preload_trailing  0, S_2, N, DAT0
460 +        add     N, N, #(prefetch_distance+2)*32 - 16
461 +120:
462 +        memcmp_process_head  unaligned
463 +        memcmp_process_tail
464 +        subs    N, N, #16
465 +        bhs     120b
466 +        /* Trailing words and bytes */
467 +        tst     N, #15
468 +        beq     199f
469 +        memcmp_trailing_15bytes  unaligned
470 +199:    /* Reached end without detecting a difference */
471 +        mov     a1, #0
472 +        setend  le
473 +        pop     {DAT1-DAT6, pc}
474 +.endm
475 +
476 +.macro memcmp_short_inner_loop  unaligned
477 +        subs    N, N, #16     /* simplifies inner loop termination */
478 +        blo     122f
479 +120:
480 +        memcmp_process_head  unaligned
481 +        memcmp_process_tail
482 +        subs    N, N, #16
483 +        bhs     120b
484 +122:    /* Trailing words and bytes */
485 +        tst     N, #15
486 +        beq     199f
487 +        memcmp_trailing_15bytes  unaligned
488 +199:    /* Reached end without detecting a difference */
489 +        mov     a1, #0
490 +        setend  le
491 +        pop     {DAT1-DAT6, pc}
492 +.endm
493 +
494 +/*
495 + * int memcmp(const void *s1, const void *s2, size_t n);
496 + * On entry:
497 + * a1 = pointer to buffer 1
498 + * a2 = pointer to buffer 2
499 + * a3 = number of bytes to compare (as unsigned chars)
500 + * On exit:
501 + * a1 = >0/=0/<0 if s1 >/=/< s2
502 + */
503 +
504 +.set prefetch_distance, 2
505 +
506 +ENTRY(memcmp)
507 +        S_1     .req    a1
508 +        S_2     .req    a2
509 +        N       .req    a3
510 +        DAT0    .req    a4
511 +        DAT1    .req    v1
512 +        DAT2    .req    v2
513 +        DAT3    .req    v3
514 +        DAT4    .req    v4
515 +        DAT5    .req    v5
516 +        DAT6    .req    v6
517 +        DAT7    .req    ip
518 +        OFF     .req    lr
519 +
520 +        push    {DAT1-DAT6, lr}
521 +        setend  be /* lowest-addressed bytes are most significant */
522 +
523 +        /* To preload ahead as we go, we need at least (prefetch_distance+2) 32-byte blocks */
524 +        cmp     N, #(prefetch_distance+3)*32 - 1
525 +        blo     170f
526 +
527 +        /* Long case */
528 +        /* Adjust N so that the decrement instruction can also test for
529 +         * inner loop termination. We want it to stop when there are
530 +         * (prefetch_distance+1) complete blocks to go. */
531 +        sub     N, N, #(prefetch_distance+2)*32
532 +        preload_leading_step1  0, DAT0, S_1
533 +        preload_leading_step1  0, DAT1, S_2
534 +        tst     S_2, #31
535 +        beq     154f
536 +        rsb     OFF, S_2, #0 /* no need to AND with 15 here */
537 +        preload_leading_step2  0, DAT0, S_1, OFF, DAT2
538 +        preload_leading_step2  0, DAT1, S_2, OFF, DAT2
539 +        memcmp_leading_31bytes
540 +154:    /* Second source now cacheline (32-byte) aligned; we have at
541 +         * least one prefetch to go. */
542 +        /* Prefetch offset is best selected such that it lies in the
543 +         * first 8 of each 32 bytes - but it's just as easy to aim for
544 +         * the first one */
545 +        and     OFF, S_1, #31
546 +        rsb     OFF, OFF, #32*prefetch_distance
547 +        tst     S_1, #3
548 +        bne     140f
549 +        memcmp_long_inner_loop  0
550 +140:    memcmp_long_inner_loop  1
551 +
552 +170:    /* Short case */
553 +        teq     N, #0
554 +        beq     199f
555 +        preload_all 0, 0, 0, S_1, N, DAT0, DAT1
556 +        preload_all 0, 0, 0, S_2, N, DAT0, DAT1
557 +        tst     S_2, #3
558 +        beq     174f
559 +172:    subs    N, N, #1
560 +        blo     199f
561 +        ldrb    DAT0, [S_1], #1
562 +        ldrb    DAT4, [S_2], #1
563 +        cmp     DAT0, DAT4
564 +        bne     200f
565 +        tst     S_2, #3
566 +        bne     172b
567 +174:    /* Second source now 4-byte aligned; we have 0 or more bytes to go */
568 +        tst     S_1, #3
569 +        bne     140f
570 +        memcmp_short_inner_loop  0
571 +140:    memcmp_short_inner_loop  1
572 +
573 +200:    /* Difference found: determine sign. */
574 +        movhi   a1, #1
575 +        movlo   a1, #-1
576 +        setend  le
577 +        pop     {DAT1-DAT6, pc}
578 +
579 +        .unreq  S_1
580 +        .unreq  S_2
581 +        .unreq  N
582 +        .unreq  DAT0
583 +        .unreq  DAT1
584 +        .unreq  DAT2
585 +        .unreq  DAT3
586 +        .unreq  DAT4
587 +        .unreq  DAT5
588 +        .unreq  DAT6
589 +        .unreq  DAT7
590 +        .unreq  OFF
591 +ENDPROC(memcmp)
592 --- /dev/null
593 +++ b/arch/arm/lib/memcpy_rpi.S
594 @@ -0,0 +1,59 @@
595 +/*
596 +Copyright (c) 2013, Raspberry Pi Foundation
597 +Copyright (c) 2013, RISC OS Open Ltd
598 +All rights reserved.
599 +
600 +Redistribution and use in source and binary forms, with or without
601 +modification, are permitted provided that the following conditions are met:
602 +    * Redistributions of source code must retain the above copyright
603 +      notice, this list of conditions and the following disclaimer.
604 +    * Redistributions in binary form must reproduce the above copyright
605 +      notice, this list of conditions and the following disclaimer in the
606 +      documentation and/or other materials provided with the distribution.
607 +    * Neither the name of the copyright holder nor the
608 +      names of its contributors may be used to endorse or promote products
609 +      derived from this software without specific prior written permission.
610 +
611 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
612 +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
613 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
614 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
615 +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
616 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
617 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
618 +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
619 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
620 +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
621 +*/
622 +
623 +#include <linux/linkage.h>
624 +#include "arm-mem.h"
625 +#include "memcpymove.h"
626 +
627 +/* Prevent the stack from becoming executable */
628 +#if defined(__linux__) && defined(__ELF__)
629 +.section .note.GNU-stack,"",%progbits
630 +#endif
631 +
632 +    .text
633 +    .arch armv6
634 +    .object_arch armv4
635 +    .arm
636 +    .altmacro
637 +    .p2align 2
638 +
639 +/*
640 + * void *memcpy(void * restrict s1, const void * restrict s2, size_t n);
641 + * On entry:
642 + * a1 = pointer to destination
643 + * a2 = pointer to source
644 + * a3 = number of bytes to copy
645 + * On exit:
646 + * a1 preserved
647 + */
648 +
649 +.set prefetch_distance, 3
650 +
651 +ENTRY(memcpy)
652 +        memcpy  0
653 +ENDPROC(memcpy)
654 --- /dev/null
655 +++ b/arch/arm/lib/memcpymove.h
656 @@ -0,0 +1,506 @@
657 +/*
658 +Copyright (c) 2013, Raspberry Pi Foundation
659 +Copyright (c) 2013, RISC OS Open Ltd
660 +All rights reserved.
661 +
662 +Redistribution and use in source and binary forms, with or without
663 +modification, are permitted provided that the following conditions are met:
664 +    * Redistributions of source code must retain the above copyright
665 +      notice, this list of conditions and the following disclaimer.
666 +    * Redistributions in binary form must reproduce the above copyright
667 +      notice, this list of conditions and the following disclaimer in the
668 +      documentation and/or other materials provided with the distribution.
669 +    * Neither the name of the copyright holder nor the
670 +      names of its contributors may be used to endorse or promote products
671 +      derived from this software without specific prior written permission.
672 +
673 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
674 +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
675 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
676 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
677 +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
678 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
679 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
680 +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
681 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
682 +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
683 +*/
684 +
685 +.macro unaligned_words  backwards, align, use_pld, words, r0, r1, r2, r3, r4, r5, r6, r7, r8
686 + .if words == 1
687 +  .if backwards
688 +        mov     r1, r0, lsl #32-align*8
689 +        ldr     r0, [S, #-4]!
690 +        orr     r1, r1, r0, lsr #align*8
691 +        str     r1, [D, #-4]!
692 +  .else
693 +        mov     r0, r1, lsr #align*8
694 +        ldr     r1, [S, #4]!
695 +        orr     r0, r0, r1, lsl #32-align*8
696 +        str     r0, [D], #4
697 +  .endif
698 + .elseif words == 2
699 +  .if backwards
700 +        ldr     r1, [S, #-4]!
701 +        mov     r2, r0, lsl #32-align*8
702 +        ldr     r0, [S, #-4]!
703 +        orr     r2, r2, r1, lsr #align*8
704 +        mov     r1, r1, lsl #32-align*8
705 +        orr     r1, r1, r0, lsr #align*8
706 +        stmdb   D!, {r1, r2}
707 +  .else
708 +        ldr     r1, [S, #4]!
709 +        mov     r0, r2, lsr #align*8
710 +        ldr     r2, [S, #4]!
711 +        orr     r0, r0, r1, lsl #32-align*8
712 +        mov     r1, r1, lsr #align*8
713 +        orr     r1, r1, r2, lsl #32-align*8
714 +        stmia   D!, {r0, r1}
715 +  .endif
716 + .elseif words == 4
717 +  .if backwards
718 +        ldmdb   S!, {r2, r3}
719 +        mov     r4, r0, lsl #32-align*8
720 +        ldmdb   S!, {r0, r1}
721 +        orr     r4, r4, r3, lsr #align*8
722 +        mov     r3, r3, lsl #32-align*8
723 +        orr     r3, r3, r2, lsr #align*8
724 +        mov     r2, r2, lsl #32-align*8
725 +        orr     r2, r2, r1, lsr #align*8
726 +        mov     r1, r1, lsl #32-align*8
727 +        orr     r1, r1, r0, lsr #align*8
728 +        stmdb   D!, {r1, r2, r3, r4}
729 +  .else
730 +        ldmib   S!, {r1, r2}
731 +        mov     r0, r4, lsr #align*8
732 +        ldmib   S!, {r3, r4}
733 +        orr     r0, r0, r1, lsl #32-align*8
734 +        mov     r1, r1, lsr #align*8
735 +        orr     r1, r1, r2, lsl #32-align*8
736 +        mov     r2, r2, lsr #align*8
737 +        orr     r2, r2, r3, lsl #32-align*8
738 +        mov     r3, r3, lsr #align*8
739 +        orr     r3, r3, r4, lsl #32-align*8
740 +        stmia   D!, {r0, r1, r2, r3}
741 +  .endif
742 + .elseif words == 8
743 +  .if backwards
744 +        ldmdb   S!, {r4, r5, r6, r7}
745 +        mov     r8, r0, lsl #32-align*8
746 +        ldmdb   S!, {r0, r1, r2, r3}
747 +   .if use_pld
748 +        pld     [S, OFF]
749 +   .endif
750 +        orr     r8, r8, r7, lsr #align*8
751 +        mov     r7, r7, lsl #32-align*8
752 +        orr     r7, r7, r6, lsr #align*8
753 +        mov     r6, r6, lsl #32-align*8
754 +        orr     r6, r6, r5, lsr #align*8
755 +        mov     r5, r5, lsl #32-align*8
756 +        orr     r5, r5, r4, lsr #align*8
757 +        mov     r4, r4, lsl #32-align*8
758 +        orr     r4, r4, r3, lsr #align*8
759 +        mov     r3, r3, lsl #32-align*8
760 +        orr     r3, r3, r2, lsr #align*8
761 +        mov     r2, r2, lsl #32-align*8
762 +        orr     r2, r2, r1, lsr #align*8
763 +        mov     r1, r1, lsl #32-align*8
764 +        orr     r1, r1, r0, lsr #align*8
765 +        stmdb   D!, {r5, r6, r7, r8}
766 +        stmdb   D!, {r1, r2, r3, r4}
767 +  .else
768 +        ldmib   S!, {r1, r2, r3, r4}
769 +        mov     r0, r8, lsr #align*8
770 +        ldmib   S!, {r5, r6, r7, r8}
771 +   .if use_pld
772 +        pld     [S, OFF]
773 +   .endif
774 +        orr     r0, r0, r1, lsl #32-align*8
775 +        mov     r1, r1, lsr #align*8
776 +        orr     r1, r1, r2, lsl #32-align*8
777 +        mov     r2, r2, lsr #align*8
778 +        orr     r2, r2, r3, lsl #32-align*8
779 +        mov     r3, r3, lsr #align*8
780 +        orr     r3, r3, r4, lsl #32-align*8
781 +        mov     r4, r4, lsr #align*8
782 +        orr     r4, r4, r5, lsl #32-align*8
783 +        mov     r5, r5, lsr #align*8
784 +        orr     r5, r5, r6, lsl #32-align*8
785 +        mov     r6, r6, lsr #align*8
786 +        orr     r6, r6, r7, lsl #32-align*8
787 +        mov     r7, r7, lsr #align*8
788 +        orr     r7, r7, r8, lsl #32-align*8
789 +        stmia   D!, {r0, r1, r2, r3}
790 +        stmia   D!, {r4, r5, r6, r7}
791 +  .endif
792 + .endif
793 +.endm
794 +
795 +.macro memcpy_leading_15bytes  backwards, align
796 +        movs    DAT1, DAT2, lsl #31
797 +        sub     N, N, DAT2
798 + .if backwards
799 +        ldrmib  DAT0, [S, #-1]!
800 +        ldrcsh  DAT1, [S, #-2]!
801 +        strmib  DAT0, [D, #-1]!
802 +        strcsh  DAT1, [D, #-2]!
803 + .else
804 +        ldrmib  DAT0, [S], #1
805 +        ldrcsh  DAT1, [S], #2
806 +        strmib  DAT0, [D], #1
807 +        strcsh  DAT1, [D], #2
808 + .endif
809 +        movs    DAT1, DAT2, lsl #29
810 + .if backwards
811 +        ldrmi   DAT0, [S, #-4]!
812 +  .if align == 0
813 +        ldmcsdb S!, {DAT1, DAT2}
814 +  .else
815 +        ldrcs   DAT2, [S, #-4]!
816 +        ldrcs   DAT1, [S, #-4]!
817 +  .endif
818 +        strmi   DAT0, [D, #-4]!
819 +        stmcsdb D!, {DAT1, DAT2}
820 + .else
821 +        ldrmi   DAT0, [S], #4
822 +  .if align == 0
823 +        ldmcsia S!, {DAT1, DAT2}
824 +  .else
825 +        ldrcs   DAT1, [S], #4
826 +        ldrcs   DAT2, [S], #4
827 +  .endif
828 +        strmi   DAT0, [D], #4
829 +        stmcsia D!, {DAT1, DAT2}
830 + .endif
831 +.endm
832 +
833 +.macro memcpy_trailing_15bytes  backwards, align
834 +        movs    N, N, lsl #29
835 + .if backwards
836 +  .if align == 0
837 +        ldmcsdb S!, {DAT0, DAT1}
838 +  .else
839 +        ldrcs   DAT1, [S, #-4]!
840 +        ldrcs   DAT0, [S, #-4]!
841 +  .endif
842 +        ldrmi   DAT2, [S, #-4]!
843 +        stmcsdb D!, {DAT0, DAT1}
844 +        strmi   DAT2, [D, #-4]!
845 + .else
846 +  .if align == 0
847 +        ldmcsia S!, {DAT0, DAT1}
848 +  .else
849 +        ldrcs   DAT0, [S], #4
850 +        ldrcs   DAT1, [S], #4
851 +  .endif
852 +        ldrmi   DAT2, [S], #4
853 +        stmcsia D!, {DAT0, DAT1}
854 +        strmi   DAT2, [D], #4
855 + .endif
856 +        movs    N, N, lsl #2
857 + .if backwards
858 +        ldrcsh  DAT0, [S, #-2]!
859 +        ldrmib  DAT1, [S, #-1]
860 +        strcsh  DAT0, [D, #-2]!
861 +        strmib  DAT1, [D, #-1]
862 + .else
863 +        ldrcsh  DAT0, [S], #2
864 +        ldrmib  DAT1, [S]
865 +        strcsh  DAT0, [D], #2
866 +        strmib  DAT1, [D]
867 + .endif
868 +.endm
869 +
870 +.macro memcpy_long_inner_loop  backwards, align
871 + .if align != 0
872 +  .if backwards
873 +        ldr     DAT0, [S, #-align]!
874 +  .else
875 +        ldr     LAST, [S, #-align]!
876 +  .endif
877 + .endif
878 +110:
879 + .if align == 0
880 +  .if backwards
881 +        ldmdb   S!, {DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, LAST}
882 +        pld     [S, OFF]
883 +        stmdb   D!, {DAT4, DAT5, DAT6, LAST}
884 +        stmdb   D!, {DAT0, DAT1, DAT2, DAT3}
885 +  .else
886 +        ldmia   S!, {DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, LAST}
887 +        pld     [S, OFF]
888 +        stmia   D!, {DAT0, DAT1, DAT2, DAT3}
889 +        stmia   D!, {DAT4, DAT5, DAT6, LAST}
890 +  .endif
891 + .else
892 +        unaligned_words  backwards, align, 1, 8, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7, LAST
893 + .endif
894 +        subs    N, N, #32
895 +        bhs     110b
896 +        /* Just before the final (prefetch_distance+1) 32-byte blocks, deal with final preloads */
897 +        preload_trailing  backwards, S, N, OFF
898 +        add     N, N, #(prefetch_distance+2)*32 - 32
899 +120:
900 + .if align == 0
901 +  .if backwards
902 +        ldmdb   S!, {DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, LAST}
903 +        stmdb   D!, {DAT4, DAT5, DAT6, LAST}
904 +        stmdb   D!, {DAT0, DAT1, DAT2, DAT3}
905 +  .else
906 +        ldmia   S!, {DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, LAST}
907 +        stmia   D!, {DAT0, DAT1, DAT2, DAT3}
908 +        stmia   D!, {DAT4, DAT5, DAT6, LAST}
909 +  .endif
910 + .else
911 +        unaligned_words  backwards, align, 0, 8, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7, LAST
912 + .endif
913 +        subs    N, N, #32
914 +        bhs     120b
915 +        tst     N, #16
916 + .if align == 0
917 +  .if backwards
918 +        ldmnedb S!, {DAT0, DAT1, DAT2, LAST}
919 +        stmnedb D!, {DAT0, DAT1, DAT2, LAST}
920 +  .else
921 +        ldmneia S!, {DAT0, DAT1, DAT2, LAST}
922 +        stmneia D!, {DAT0, DAT1, DAT2, LAST}
923 +  .endif
924 + .else
925 +        beq     130f
926 +        unaligned_words  backwards, align, 0, 4, DAT0, DAT1, DAT2, DAT3, LAST
927 +130:
928 + .endif
929 +        /* Trailing words and bytes */
930 +        tst      N, #15
931 +        beq      199f
932 + .if align != 0
933 +        add     S, S, #align
934 + .endif
935 +        memcpy_trailing_15bytes  backwards, align
936 +199:
937 +        pop     {DAT3, DAT4, DAT5, DAT6, DAT7}
938 +        pop     {D, DAT1, DAT2, pc}
939 +.endm
940 +
941 +.macro memcpy_medium_inner_loop  backwards, align
942 +120:
943 + .if backwards
944 +  .if align == 0
945 +        ldmdb   S!, {DAT0, DAT1, DAT2, LAST}
946 +  .else
947 +        ldr     LAST, [S, #-4]!
948 +        ldr     DAT2, [S, #-4]!
949 +        ldr     DAT1, [S, #-4]!
950 +        ldr     DAT0, [S, #-4]!
951 +  .endif
952 +        stmdb   D!, {DAT0, DAT1, DAT2, LAST}
953 + .else
954 +  .if align == 0
955 +        ldmia   S!, {DAT0, DAT1, DAT2, LAST}
956 +  .else
957 +        ldr     DAT0, [S], #4
958 +        ldr     DAT1, [S], #4
959 +        ldr     DAT2, [S], #4
960 +        ldr     LAST, [S], #4
961 +  .endif
962 +        stmia   D!, {DAT0, DAT1, DAT2, LAST}
963 + .endif
964 +        subs     N, N, #16
965 +        bhs      120b
966 +        /* Trailing words and bytes */
967 +        tst      N, #15
968 +        beq      199f
969 +        memcpy_trailing_15bytes  backwards, align
970 +199:
971 +        pop     {D, DAT1, DAT2, pc}
972 +.endm
973 +
974 +.macro memcpy_short_inner_loop  backwards, align
975 +        tst     N, #16
976 + .if backwards
977 +  .if align == 0
978 +        ldmnedb S!, {DAT0, DAT1, DAT2, LAST}
979 +  .else
980 +        ldrne   LAST, [S, #-4]!
981 +        ldrne   DAT2, [S, #-4]!
982 +        ldrne   DAT1, [S, #-4]!
983 +        ldrne   DAT0, [S, #-4]!
984 +  .endif
985 +        stmnedb D!, {DAT0, DAT1, DAT2, LAST}
986 + .else
987 +  .if align == 0
988 +        ldmneia S!, {DAT0, DAT1, DAT2, LAST}
989 +  .else
990 +        ldrne   DAT0, [S], #4
991 +        ldrne   DAT1, [S], #4
992 +        ldrne   DAT2, [S], #4
993 +        ldrne   LAST, [S], #4
994 +  .endif
995 +        stmneia D!, {DAT0, DAT1, DAT2, LAST}
996 + .endif
997 +        memcpy_trailing_15bytes  backwards, align
998 +199:
999 +        pop     {D, DAT1, DAT2, pc}
1000 +.endm
1001 +
1002 +.macro memcpy backwards
1003 +        D       .req    a1
1004 +        S       .req    a2
1005 +        N       .req    a3
1006 +        DAT0    .req    a4
1007 +        DAT1    .req    v1
1008 +        DAT2    .req    v2
1009 +        DAT3    .req    v3
1010 +        DAT4    .req    v4
1011 +        DAT5    .req    v5
1012 +        DAT6    .req    v6
1013 +        DAT7    .req    sl
1014 +        LAST    .req    ip
1015 +        OFF     .req    lr
1016 +
1017 +        .cfi_startproc
1018 +
1019 +        push    {D, DAT1, DAT2, lr}
1020 +
1021 +        .cfi_def_cfa_offset 16
1022 +        .cfi_rel_offset D, 0
1023 +        .cfi_undefined  S
1024 +        .cfi_undefined  N
1025 +        .cfi_undefined  DAT0
1026 +        .cfi_rel_offset DAT1, 4
1027 +        .cfi_rel_offset DAT2, 8
1028 +        .cfi_undefined  LAST
1029 +        .cfi_rel_offset lr, 12
1030 +
1031 + .if backwards
1032 +        add     D, D, N
1033 +        add     S, S, N
1034 + .endif
1035 +
1036 +        /* See if we're guaranteed to have at least one 16-byte aligned 16-byte write */
1037 +        cmp     N, #31
1038 +        blo     170f
1039 +        /* To preload ahead as we go, we need at least (prefetch_distance+2) 32-byte blocks */
1040 +        cmp     N, #(prefetch_distance+3)*32 - 1
1041 +        blo     160f
1042 +
1043 +        /* Long case */
1044 +        push    {DAT3, DAT4, DAT5, DAT6, DAT7}
1045 +
1046 +        .cfi_def_cfa_offset 36
1047 +        .cfi_rel_offset D, 20
1048 +        .cfi_rel_offset DAT1, 24
1049 +        .cfi_rel_offset DAT2, 28
1050 +        .cfi_rel_offset DAT3, 0
1051 +        .cfi_rel_offset DAT4, 4
1052 +        .cfi_rel_offset DAT5, 8
1053 +        .cfi_rel_offset DAT6, 12
1054 +        .cfi_rel_offset DAT7, 16
1055 +        .cfi_rel_offset lr, 32
1056 +
1057 +        /* Adjust N so that the decrement instruction can also test for
1058 +         * inner loop termination. We want it to stop when there are
1059 +         * (prefetch_distance+1) complete blocks to go. */
1060 +        sub     N, N, #(prefetch_distance+2)*32
1061 +        preload_leading_step1  backwards, DAT0, S
1062 + .if backwards
1063 +        /* Bug in GAS: it accepts, but mis-assembles the instruction
1064 +         * ands    DAT2, D, #60, 2
1065 +         * which sets DAT2 to the number of leading bytes until destination is aligned and also clears C (sets borrow)
1066 +         */
1067 +        .word   0xE210513C
1068 +        beq     154f
1069 + .else
1070 +        ands    DAT2, D, #15
1071 +        beq     154f
1072 +        rsb     DAT2, DAT2, #16 /* number of leading bytes until destination aligned */
1073 + .endif
1074 +        preload_leading_step2  backwards, DAT0, S, DAT2, OFF
1075 +        memcpy_leading_15bytes backwards, 1
1076 +154:    /* Destination now 16-byte aligned; we have at least one prefetch as well as at least one 16-byte output block */
1077 +        /* 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 */
1078 + .if backwards
1079 +        rsb     OFF, S, #3
1080 +        and     OFF, OFF, #28
1081 +        sub     OFF, OFF, #32*(prefetch_distance+1)
1082 + .else
1083 +        and     OFF, S, #28
1084 +        rsb     OFF, OFF, #32*prefetch_distance
1085 + .endif
1086 +        movs    DAT0, S, lsl #31
1087 +        bhi     157f
1088 +        bcs     156f
1089 +        bmi     155f
1090 +        memcpy_long_inner_loop  backwards, 0
1091 +155:    memcpy_long_inner_loop  backwards, 1
1092 +156:    memcpy_long_inner_loop  backwards, 2
1093 +157:    memcpy_long_inner_loop  backwards, 3
1094 +
1095 +        .cfi_def_cfa_offset 16
1096 +        .cfi_rel_offset D, 0
1097 +        .cfi_rel_offset DAT1, 4
1098 +        .cfi_rel_offset DAT2, 8
1099 +        .cfi_same_value DAT3
1100 +        .cfi_same_value DAT4
1101 +        .cfi_same_value DAT5
1102 +        .cfi_same_value DAT6
1103 +        .cfi_same_value DAT7
1104 +        .cfi_rel_offset lr, 12
1105 +
1106 +160:    /* Medium case */
1107 +        preload_all  backwards, 0, 0, S, N, DAT2, OFF
1108 +        sub     N, N, #16     /* simplifies inner loop termination */
1109 + .if backwards
1110 +        ands    DAT2, D, #15
1111 +        beq     164f
1112 + .else
1113 +        ands    DAT2, D, #15
1114 +        beq     164f
1115 +        rsb     DAT2, DAT2, #16
1116 + .endif
1117 +        memcpy_leading_15bytes backwards, align
1118 +164:    /* Destination now 16-byte aligned; we have at least one 16-byte output block */
1119 +        tst     S, #3
1120 +        bne     140f
1121 +        memcpy_medium_inner_loop  backwards, 0
1122 +140:    memcpy_medium_inner_loop  backwards, 1
1123 +
1124 +170:    /* Short case, less than 31 bytes, so no guarantee of at least one 16-byte block */
1125 +        teq     N, #0
1126 +        beq     199f
1127 +        preload_all  backwards, 1, 0, S, N, DAT2, LAST
1128 +        tst     D, #3
1129 +        beq     174f
1130 +172:    subs    N, N, #1
1131 +        blo     199f
1132 + .if backwards
1133 +        ldrb    DAT0, [S, #-1]!
1134 +        strb    DAT0, [D, #-1]!
1135 + .else
1136 +        ldrb    DAT0, [S], #1
1137 +        strb    DAT0, [D], #1
1138 + .endif
1139 +        tst     D, #3
1140 +        bne     172b
1141 +174:    /* Destination now 4-byte aligned; we have 0 or more output bytes to go */
1142 +        tst     S, #3
1143 +        bne     140f
1144 +        memcpy_short_inner_loop  backwards, 0
1145 +140:    memcpy_short_inner_loop  backwards, 1
1146 +
1147 +        .cfi_endproc
1148 +
1149 +        .unreq  D
1150 +        .unreq  S
1151 +        .unreq  N
1152 +        .unreq  DAT0
1153 +        .unreq  DAT1
1154 +        .unreq  DAT2
1155 +        .unreq  DAT3
1156 +        .unreq  DAT4
1157 +        .unreq  DAT5
1158 +        .unreq  DAT6
1159 +        .unreq  DAT7
1160 +        .unreq  LAST
1161 +        .unreq  OFF
1162 +.endm
1163 --- /dev/null
1164 +++ b/arch/arm/lib/memmove_rpi.S
1165 @@ -0,0 +1,61 @@
1166 +/*
1167 +Copyright (c) 2013, Raspberry Pi Foundation
1168 +Copyright (c) 2013, RISC OS Open Ltd
1169 +All rights reserved.
1170 +
1171 +Redistribution and use in source and binary forms, with or without
1172 +modification, are permitted provided that the following conditions are met:
1173 +    * Redistributions of source code must retain the above copyright
1174 +      notice, this list of conditions and the following disclaimer.
1175 +    * Redistributions in binary form must reproduce the above copyright
1176 +      notice, this list of conditions and the following disclaimer in the
1177 +      documentation and/or other materials provided with the distribution.
1178 +    * Neither the name of the copyright holder nor the
1179 +      names of its contributors may be used to endorse or promote products
1180 +      derived from this software without specific prior written permission.
1181 +
1182 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
1183 +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1184 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1185 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
1186 +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1187 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1188 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1189 +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1190 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1191 +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1192 +*/
1193 +
1194 +#include <linux/linkage.h>
1195 +#include "arm-mem.h"
1196 +#include "memcpymove.h"
1197 +
1198 +/* Prevent the stack from becoming executable */
1199 +#if defined(__linux__) && defined(__ELF__)
1200 +.section .note.GNU-stack,"",%progbits
1201 +#endif
1202 +
1203 +    .text
1204 +    .arch armv6
1205 +    .object_arch armv4
1206 +    .arm
1207 +    .altmacro
1208 +    .p2align 2
1209 +
1210 +/*
1211 + * void *memmove(void *s1, const void *s2, size_t n);
1212 + * On entry:
1213 + * a1 = pointer to destination
1214 + * a2 = pointer to source
1215 + * a3 = number of bytes to copy
1216 + * On exit:
1217 + * a1 preserved
1218 + */
1219 +
1220 +.set prefetch_distance, 3
1221 +
1222 +ENTRY(memmove)
1223 +        cmp     a2, a1
1224 +        bpl     memcpy  /* pl works even over -1 - 0 and 0x7fffffff - 0x80000000 boundaries */
1225 +        memcpy  1
1226 +ENDPROC(memmove)
1227 --- /dev/null
1228 +++ b/arch/arm/lib/memset_rpi.S
1229 @@ -0,0 +1,121 @@
1230 +/*
1231 +Copyright (c) 2013, Raspberry Pi Foundation
1232 +Copyright (c) 2013, RISC OS Open Ltd
1233 +All rights reserved.
1234 +
1235 +Redistribution and use in source and binary forms, with or without
1236 +modification, are permitted provided that the following conditions are met:
1237 +    * Redistributions of source code must retain the above copyright
1238 +      notice, this list of conditions and the following disclaimer.
1239 +    * Redistributions in binary form must reproduce the above copyright
1240 +      notice, this list of conditions and the following disclaimer in the
1241 +      documentation and/or other materials provided with the distribution.
1242 +    * Neither the name of the copyright holder nor the
1243 +      names of its contributors may be used to endorse or promote products
1244 +      derived from this software without specific prior written permission.
1245 +
1246 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
1247 +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1248 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1249 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
1250 +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1251 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1252 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1253 +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1254 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1255 +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1256 +*/
1257 +
1258 +#include <linux/linkage.h>
1259 +#include "arm-mem.h"
1260 +
1261 +/* Prevent the stack from becoming executable */
1262 +#if defined(__linux__) && defined(__ELF__)
1263 +.section .note.GNU-stack,"",%progbits
1264 +#endif
1265 +
1266 +    .text
1267 +    .arch armv6
1268 +    .object_arch armv4
1269 +    .arm
1270 +    .altmacro
1271 +    .p2align 2
1272 +
1273 +/*
1274 + *  void *memset(void *s, int c, size_t n);
1275 + *  On entry:
1276 + *  a1 = pointer to buffer to fill
1277 + *  a2 = byte pattern to fill with (caller-narrowed)
1278 + *  a3 = number of bytes to fill
1279 + *  On exit:
1280 + *  a1 preserved
1281 + */
1282 +ENTRY(memset)
1283 +        S       .req    a1
1284 +        DAT0    .req    a2
1285 +        N       .req    a3
1286 +        DAT1    .req    a4
1287 +        DAT2    .req    ip
1288 +        DAT3    .req    lr
1289 +
1290 +        orr     DAT0, DAT0, lsl #8
1291 +        push    {S, lr}
1292 +        orr     DAT0, DAT0, lsl #16
1293 +        mov     DAT1, DAT0
1294 +
1295 +        /* See if we're guaranteed to have at least one 16-byte aligned 16-byte write */
1296 +        cmp     N, #31
1297 +        blo     170f
1298 +
1299 +161:    sub     N, N, #16     /* simplifies inner loop termination */
1300 +        /* Leading words and bytes */
1301 +        tst     S, #15
1302 +        beq     164f
1303 +        rsb     DAT3, S, #0   /* bits 0-3 = number of leading bytes until aligned */
1304 +        movs    DAT2, DAT3, lsl #31
1305 +        submi   N, N, #1
1306 +        strmib  DAT0, [S], #1
1307 +        subcs   N, N, #2
1308 +        strcsh  DAT0, [S], #2
1309 +        movs    DAT2, DAT3, lsl #29
1310 +        submi   N, N, #4
1311 +        strmi   DAT0, [S], #4
1312 +        subcs   N, N, #8
1313 +        stmcsia S!, {DAT0, DAT1}
1314 +164:    /* Delayed set up of DAT2 and DAT3 so we could use them as scratch registers above */
1315 +        mov     DAT2, DAT0
1316 +        mov     DAT3, DAT0
1317 +        /* Now the inner loop of 16-byte stores */
1318 +165:    stmia   S!, {DAT0, DAT1, DAT2, DAT3}
1319 +        subs    N, N, #16
1320 +        bhs     165b
1321 +166:    /* Trailing words and bytes */
1322 +        movs    N, N, lsl #29
1323 +        stmcsia S!, {DAT0, DAT1}
1324 +        strmi   DAT0, [S], #4
1325 +        movs    N, N, lsl #2
1326 +        strcsh  DAT0, [S], #2
1327 +        strmib  DAT0, [S]
1328 +199:    pop     {S, pc}
1329 +
1330 +170:    /* Short case */
1331 +        mov     DAT2, DAT0
1332 +        mov     DAT3, DAT0
1333 +        tst     S, #3
1334 +        beq     174f
1335 +172:    subs    N, N, #1
1336 +        blo     199b
1337 +        strb    DAT0, [S], #1
1338 +        tst     S, #3
1339 +        bne     172b
1340 +174:    tst     N, #16
1341 +        stmneia S!, {DAT0, DAT1, DAT2, DAT3}
1342 +        b       166b
1343 +
1344 +        .unreq  S
1345 +        .unreq  DAT0
1346 +        .unreq  N
1347 +        .unreq  DAT1
1348 +        .unreq  DAT2
1349 +        .unreq  DAT3
1350 +ENDPROC(memset)
1351 --- a/arch/arm/lib/uaccess_with_memcpy.c
1352 +++ b/arch/arm/lib/uaccess_with_memcpy.c
1353 @@ -22,6 +22,14 @@
1354  #include <asm/current.h>
1355  #include <asm/page.h>
1356  
1357 +#ifndef COPY_FROM_USER_THRESHOLD
1358 +#define COPY_FROM_USER_THRESHOLD 64
1359 +#endif
1360 +
1361 +#ifndef COPY_TO_USER_THRESHOLD
1362 +#define COPY_TO_USER_THRESHOLD 64
1363 +#endif
1364 +
1365  static int
1366  pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
1367  {
1368 @@ -85,7 +93,44 @@ pin_page_for_write(const void __user *_a
1369         return 1;
1370  }
1371  
1372 -static unsigned long noinline
1373 +static int
1374 +pin_page_for_read(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
1375 +{
1376 +       unsigned long addr = (unsigned long)_addr;
1377 +       pgd_t *pgd;
1378 +       pmd_t *pmd;
1379 +       pte_t *pte;
1380 +       pud_t *pud;
1381 +       spinlock_t *ptl;
1382 +
1383 +       pgd = pgd_offset(current->mm, addr);
1384 +       if (unlikely(pgd_none(*pgd) || pgd_bad(*pgd)))
1385 +       {
1386 +               return 0;
1387 +       }
1388 +       pud = pud_offset(pgd, addr);
1389 +       if (unlikely(pud_none(*pud) || pud_bad(*pud)))
1390 +       {
1391 +               return 0;
1392 +       }
1393 +
1394 +       pmd = pmd_offset(pud, addr);
1395 +       if (unlikely(pmd_none(*pmd) || pmd_bad(*pmd)))
1396 +               return 0;
1397 +
1398 +       pte = pte_offset_map_lock(current->mm, pmd, addr, &ptl);
1399 +       if (unlikely(!pte_present(*pte) || !pte_young(*pte))) {
1400 +               pte_unmap_unlock(pte, ptl);
1401 +               return 0;
1402 +       }
1403 +
1404 +       *ptep = pte;
1405 +       *ptlp = ptl;
1406 +
1407 +       return 1;
1408 +}
1409 +
1410 +unsigned long noinline
1411  __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
1412  {
1413         int atomic;
1414 @@ -135,6 +180,54 @@ out:
1415         return n;
1416  }
1417  
1418 +unsigned long noinline
1419 +__copy_from_user_memcpy(void *to, const void __user *from, unsigned long n)
1420 +{
1421 +       int atomic;
1422 +
1423 +       if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
1424 +               memcpy(to, (const void *)from, n);
1425 +               return 0;
1426 +       }
1427 +
1428 +       /* the mmap semaphore is taken only if not in an atomic context */
1429 +       atomic = in_atomic();
1430 +
1431 +       if (!atomic)
1432 +               down_read(&current->mm->mmap_sem);
1433 +       while (n) {
1434 +               pte_t *pte;
1435 +               spinlock_t *ptl;
1436 +               int tocopy;
1437 +
1438 +               while (!pin_page_for_read(from, &pte, &ptl)) {
1439 +                       char temp;
1440 +                       if (!atomic)
1441 +                               up_read(&current->mm->mmap_sem);
1442 +                       if (__get_user(temp, (char __user *)from))
1443 +                               goto out;
1444 +                       if (!atomic)
1445 +                               down_read(&current->mm->mmap_sem);
1446 +               }
1447 +
1448 +               tocopy = (~(unsigned long)from & ~PAGE_MASK) + 1;
1449 +               if (tocopy > n)
1450 +                       tocopy = n;
1451 +
1452 +               memcpy(to, (const void *)from, tocopy);
1453 +               to += tocopy;
1454 +               from += tocopy;
1455 +               n -= tocopy;
1456 +
1457 +               pte_unmap_unlock(pte, ptl);
1458 +       }
1459 +       if (!atomic)
1460 +               up_read(&current->mm->mmap_sem);
1461 +
1462 +out:
1463 +       return n;
1464 +}
1465 +
1466  unsigned long
1467  __copy_to_user(void __user *to, const void *from, unsigned long n)
1468  {
1469 @@ -145,10 +238,25 @@ __copy_to_user(void __user *to, const vo
1470          * With frame pointer disabled, tail call optimization kicks in
1471          * as well making this test almost invisible.
1472          */
1473 -       if (n < 64)
1474 +       if (n < COPY_TO_USER_THRESHOLD)
1475                 return __copy_to_user_std(to, from, n);
1476         return __copy_to_user_memcpy(to, from, n);
1477  }
1478 +
1479 +unsigned long
1480 +__copy_from_user(void *to, const void __user *from, unsigned long n)
1481 +{
1482 +       /*
1483 +        * This test is stubbed out of the main function above to keep
1484 +        * the overhead for small copies low by avoiding a large
1485 +        * register dump on the stack just to reload them right away.
1486 +        * With frame pointer disabled, tail call optimization kicks in
1487 +        * as well making this test almost invisible.
1488 +        */
1489 +       if (n < COPY_FROM_USER_THRESHOLD)
1490 +               return __copy_from_user_std(to, from, n);
1491 +       return __copy_from_user_memcpy(to, from, n);
1492 +}
1493         
1494  static unsigned long noinline
1495  __clear_user_memset(void __user *addr, unsigned long n)