Merge branches 'pm-cpuidle', 'pm-cpufreq' and 'pm-sleep'
[sfrench/cifs-2.6.git] / arch / arm / lib / copy_to_user.S
1 /*
2  *  linux/arch/arm/lib/copy_to_user.S
3  *
4  *  Author:     Nicolas Pitre
5  *  Created:    Sep 29, 2005
6  *  Copyright:  MontaVista Software, Inc.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License version 2 as
10  *  published by the Free Software Foundation.
11  */
12
13 #include <linux/linkage.h>
14 #include <asm/assembler.h>
15 #include <asm/unwind.h>
16
17 /*
18  * Prototype:
19  *
20  *      size_t arm_copy_to_user(void *to, const void *from, size_t n)
21  *
22  * Purpose:
23  *
24  *      copy a block to user memory from kernel memory
25  *
26  * Params:
27  *
28  *      to = user memory
29  *      from = kernel memory
30  *      n = number of bytes to copy
31  *
32  * Return value:
33  *
34  *      Number of bytes NOT copied.
35  */
36
37 #define LDR1W_SHIFT     0
38
39         .macro ldr1w ptr reg abort
40         W(ldr) \reg, [\ptr], #4
41         .endm
42
43         .macro ldr4w ptr reg1 reg2 reg3 reg4 abort
44         ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4}
45         .endm
46
47         .macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
48         ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
49         .endm
50
51         .macro ldr1b ptr reg cond=al abort
52         ldr\cond\()b \reg, [\ptr], #1
53         .endm
54
55 #ifdef CONFIG_CPU_USE_DOMAINS
56
57 #ifndef CONFIG_THUMB2_KERNEL
58 #define STR1W_SHIFT     0
59 #else
60 #define STR1W_SHIFT     1
61 #endif
62
63         .macro str1w ptr reg abort
64         strusr  \reg, \ptr, 4, abort=\abort
65         .endm
66
67         .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
68         str1w \ptr, \reg1, \abort
69         str1w \ptr, \reg2, \abort
70         str1w \ptr, \reg3, \abort
71         str1w \ptr, \reg4, \abort
72         str1w \ptr, \reg5, \abort
73         str1w \ptr, \reg6, \abort
74         str1w \ptr, \reg7, \abort
75         str1w \ptr, \reg8, \abort
76         .endm
77
78 #else
79
80 #define STR1W_SHIFT     0
81
82         .macro str1w ptr reg abort
83         USERL(\abort, W(str) \reg, [\ptr], #4)
84         .endm
85
86         .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
87         USERL(\abort, stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8})
88         .endm
89
90 #endif /* CONFIG_CPU_USE_DOMAINS */
91
92         .macro str1b ptr reg cond=al abort
93         strusr  \reg, \ptr, 1, \cond, abort=\abort
94         .endm
95
96         .macro enter reg1 reg2
97         mov     r3, #0
98         stmdb   sp!, {r0, r2, r3, \reg1, \reg2}
99         .endm
100
101         .macro usave reg1 reg2
102         UNWIND( .save {r0, r2, r3, \reg1, \reg2}        )
103         .endm
104
105         .macro exit reg1 reg2
106         add     sp, sp, #8
107         ldmfd   sp!, {r0, \reg1, \reg2}
108         .endm
109
110         .text
111
112 ENTRY(__copy_to_user_std)
113 WEAK(arm_copy_to_user)
114 #ifdef CONFIG_CPU_SPECTRE
115         get_thread_info r3
116         ldr     r3, [r3, #TI_ADDR_LIMIT]
117         uaccess_mask_range_ptr r0, r2, r3, ip
118 #endif
119
120 #include "copy_template.S"
121
122 ENDPROC(arm_copy_to_user)
123 ENDPROC(__copy_to_user_std)
124
125         .pushsection .text.fixup,"ax"
126         .align 0
127         copy_abort_preamble
128         ldmfd   sp!, {r1, r2, r3}
129         sub     r0, r0, r1
130         rsb     r0, r0, r2
131         copy_abort_end
132         .popsection