Linux-2.6.12-rc2
[linux-3.10.git] / arch / arm / mm / copypage-xscale.S
1 /*
2  *  linux/arch/arm/lib/copypage-xscale.S
3  *
4  *  Copyright (C) 2001 Russell King
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10 #include <linux/linkage.h>
11 #include <linux/init.h>
12 #include <asm/constants.h>
13
14 /*
15  * General note:
16  *  We don't really want write-allocate cache behaviour for these functions
17  *  since that will just eat through 8K of the cache.
18  */
19
20         .text
21         .align  5
22 /*
23  * XScale optimised copy_user_page
24  *  r0 = destination
25  *  r1 = source
26  *  r2 = virtual user address of ultimate destination page
27  *
28  * The source page may have some clean entries in the cache already, but we
29  * can safely ignore them - break_cow() will flush them out of the cache
30  * if we eventually end up using our copied page.
31  *
32  * What we could do is use the mini-cache to buffer reads from the source
33  * page.  We rely on the mini-cache being smaller than one page, so we'll
34  * cycle through the complete cache anyway.
35  */
36 ENTRY(xscale_mc_copy_user_page)
37         stmfd   sp!, {r4, r5, lr}
38         mov     r5, r0
39         mov     r0, r1
40         bl      map_page_minicache
41         mov     r1, r5
42         mov     lr, #PAGE_SZ/64-1
43
44         /*
45          * Strangely enough, best performance is achieved
46          * when prefetching destination as well.  (NP)
47          */
48         pld     [r0, #0]
49         pld     [r0, #32]
50         pld     [r1, #0]
51         pld     [r1, #32]
52
53 1:      pld     [r0, #64]
54         pld     [r0, #96]
55         pld     [r1, #64]
56         pld     [r1, #96]
57
58 2:      ldrd    r2, [r0], #8
59         ldrd    r4, [r0], #8
60         mov     ip, r1
61         strd    r2, [r1], #8
62         ldrd    r2, [r0], #8
63         strd    r4, [r1], #8
64         ldrd    r4, [r0], #8
65         strd    r2, [r1], #8
66         strd    r4, [r1], #8
67         mcr     p15, 0, ip, c7, c10, 1          @ clean D line
68         ldrd    r2, [r0], #8
69         mcr     p15, 0, ip, c7, c6, 1           @ invalidate D line
70         ldrd    r4, [r0], #8
71         mov     ip, r1
72         strd    r2, [r1], #8
73         ldrd    r2, [r0], #8
74         strd    r4, [r1], #8
75         ldrd    r4, [r0], #8
76         strd    r2, [r1], #8
77         strd    r4, [r1], #8
78         mcr     p15, 0, ip, c7, c10, 1          @ clean D line
79         subs    lr, lr, #1
80         mcr     p15, 0, ip, c7, c6, 1           @ invalidate D line
81         bgt     1b
82         beq     2b
83
84         ldmfd   sp!, {r4, r5, pc}
85
86         .align  5
87 /*
88  * XScale optimised clear_user_page
89  *  r0 = destination
90  *  r1 = virtual user address of ultimate destination page
91  */
92 ENTRY(xscale_mc_clear_user_page)
93         mov     r1, #PAGE_SZ/32
94         mov     r2, #0
95         mov     r3, #0
96 1:      mov     ip, r0
97         strd    r2, [r0], #8
98         strd    r2, [r0], #8
99         strd    r2, [r0], #8
100         strd    r2, [r0], #8
101         mcr     p15, 0, ip, c7, c10, 1          @ clean D line
102         subs    r1, r1, #1
103         mcr     p15, 0, ip, c7, c6, 1           @ invalidate D line
104         bne     1b
105         mov     pc, lr
106
107         __INITDATA
108
109         .type   xscale_mc_user_fns, #object
110 ENTRY(xscale_mc_user_fns)
111         .long   xscale_mc_clear_user_page
112         .long   xscale_mc_copy_user_page
113         .size   xscale_mc_user_fns, . - xscale_mc_user_fns