Merge tag 'fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty...
[linux-2.6-block.git] / arch / arm / include / asm / assembler.h
1 /*
2  *  arch/arm/include/asm/assembler.h
3  *
4  *  Copyright (C) 1996-2000 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  *  This file contains arm architecture specific defines
11  *  for the different processors.
12  *
13  *  Do not include any C declarations in this file - it is included by
14  *  assembler source.
15  */
16 #ifndef __ASM_ASSEMBLER_H__
17 #define __ASM_ASSEMBLER_H__
18
19 #ifndef __ASSEMBLY__
20 #error "Only include this from assembly code"
21 #endif
22
23 #include <asm/ptrace.h>
24 #include <asm/domain.h>
25 #include <asm/opcodes-virt.h>
26
27 #define IOMEM(x)        (x)
28
29 /*
30  * Endian independent macros for shifting bytes within registers.
31  */
32 #ifndef __ARMEB__
33 #define pull            lsr
34 #define push            lsl
35 #define get_byte_0      lsl #0
36 #define get_byte_1      lsr #8
37 #define get_byte_2      lsr #16
38 #define get_byte_3      lsr #24
39 #define put_byte_0      lsl #0
40 #define put_byte_1      lsl #8
41 #define put_byte_2      lsl #16
42 #define put_byte_3      lsl #24
43 #else
44 #define pull            lsl
45 #define push            lsr
46 #define get_byte_0      lsr #24
47 #define get_byte_1      lsr #16
48 #define get_byte_2      lsr #8
49 #define get_byte_3      lsl #0
50 #define put_byte_0      lsl #24
51 #define put_byte_1      lsl #16
52 #define put_byte_2      lsl #8
53 #define put_byte_3      lsl #0
54 #endif
55
56 /*
57  * Data preload for architectures that support it
58  */
59 #if __LINUX_ARM_ARCH__ >= 5
60 #define PLD(code...)    code
61 #else
62 #define PLD(code...)
63 #endif
64
65 /*
66  * This can be used to enable code to cacheline align the destination
67  * pointer when bulk writing to memory.  Experiments on StrongARM and
68  * XScale didn't show this a worthwhile thing to do when the cache is not
69  * set to write-allocate (this would need further testing on XScale when WA
70  * is used).
71  *
72  * On Feroceon there is much to gain however, regardless of cache mode.
73  */
74 #ifdef CONFIG_CPU_FEROCEON
75 #define CALGN(code...) code
76 #else
77 #define CALGN(code...)
78 #endif
79
80 /*
81  * Enable and disable interrupts
82  */
83 #if __LINUX_ARM_ARCH__ >= 6
84         .macro  disable_irq_notrace
85         cpsid   i
86         .endm
87
88         .macro  enable_irq_notrace
89         cpsie   i
90         .endm
91 #else
92         .macro  disable_irq_notrace
93         msr     cpsr_c, #PSR_I_BIT | SVC_MODE
94         .endm
95
96         .macro  enable_irq_notrace
97         msr     cpsr_c, #SVC_MODE
98         .endm
99 #endif
100
101         .macro asm_trace_hardirqs_off
102 #if defined(CONFIG_TRACE_IRQFLAGS)
103         stmdb   sp!, {r0-r3, ip, lr}
104         bl      trace_hardirqs_off
105         ldmia   sp!, {r0-r3, ip, lr}
106 #endif
107         .endm
108
109         .macro asm_trace_hardirqs_on_cond, cond
110 #if defined(CONFIG_TRACE_IRQFLAGS)
111         /*
112          * actually the registers should be pushed and pop'd conditionally, but
113          * after bl the flags are certainly clobbered
114          */
115         stmdb   sp!, {r0-r3, ip, lr}
116         bl\cond trace_hardirqs_on
117         ldmia   sp!, {r0-r3, ip, lr}
118 #endif
119         .endm
120
121         .macro asm_trace_hardirqs_on
122         asm_trace_hardirqs_on_cond al
123         .endm
124
125         .macro disable_irq
126         disable_irq_notrace
127         asm_trace_hardirqs_off
128         .endm
129
130         .macro enable_irq
131         asm_trace_hardirqs_on
132         enable_irq_notrace
133         .endm
134 /*
135  * Save the current IRQ state and disable IRQs.  Note that this macro
136  * assumes FIQs are enabled, and that the processor is in SVC mode.
137  */
138         .macro  save_and_disable_irqs, oldcpsr
139         mrs     \oldcpsr, cpsr
140         disable_irq
141         .endm
142
143         .macro  save_and_disable_irqs_notrace, oldcpsr
144         mrs     \oldcpsr, cpsr
145         disable_irq_notrace
146         .endm
147
148 /*
149  * Restore interrupt state previously stored in a register.  We don't
150  * guarantee that this will preserve the flags.
151  */
152         .macro  restore_irqs_notrace, oldcpsr
153         msr     cpsr_c, \oldcpsr
154         .endm
155
156         .macro restore_irqs, oldcpsr
157         tst     \oldcpsr, #PSR_I_BIT
158         asm_trace_hardirqs_on_cond eq
159         restore_irqs_notrace \oldcpsr
160         .endm
161
162 #define USER(x...)                              \
163 9999:   x;                                      \
164         .pushsection __ex_table,"a";            \
165         .align  3;                              \
166         .long   9999b,9001f;                    \
167         .popsection
168
169 #ifdef CONFIG_SMP
170 #define ALT_SMP(instr...)                                       \
171 9998:   instr
172 /*
173  * Note: if you get assembler errors from ALT_UP() when building with
174  * CONFIG_THUMB2_KERNEL, you almost certainly need to use
175  * ALT_SMP( W(instr) ... )
176  */
177 #define ALT_UP(instr...)                                        \
178         .pushsection ".alt.smp.init", "a"                       ;\
179         .long   9998b                                           ;\
180 9997:   instr                                                   ;\
181         .if . - 9997b != 4                                      ;\
182                 .error "ALT_UP() content must assemble to exactly 4 bytes";\
183         .endif                                                  ;\
184         .popsection
185 #define ALT_UP_B(label)                                 \
186         .equ    up_b_offset, label - 9998b                      ;\
187         .pushsection ".alt.smp.init", "a"                       ;\
188         .long   9998b                                           ;\
189         W(b)    . + up_b_offset                                 ;\
190         .popsection
191 #else
192 #define ALT_SMP(instr...)
193 #define ALT_UP(instr...) instr
194 #define ALT_UP_B(label) b label
195 #endif
196
197 /*
198  * Instruction barrier
199  */
200         .macro  instr_sync
201 #if __LINUX_ARM_ARCH__ >= 7
202         isb
203 #elif __LINUX_ARM_ARCH__ == 6
204         mcr     p15, 0, r0, c7, c5, 4
205 #endif
206         .endm
207
208 /*
209  * SMP data memory barrier
210  */
211         .macro  smp_dmb mode
212 #ifdef CONFIG_SMP
213 #if __LINUX_ARM_ARCH__ >= 7
214         .ifeqs "\mode","arm"
215         ALT_SMP(dmb)
216         .else
217         ALT_SMP(W(dmb))
218         .endif
219 #elif __LINUX_ARM_ARCH__ == 6
220         ALT_SMP(mcr     p15, 0, r0, c7, c10, 5) @ dmb
221 #else
222 #error Incompatible SMP platform
223 #endif
224         .ifeqs "\mode","arm"
225         ALT_UP(nop)
226         .else
227         ALT_UP(W(nop))
228         .endif
229 #endif
230         .endm
231
232 #ifdef CONFIG_THUMB2_KERNEL
233         .macro  setmode, mode, reg
234         mov     \reg, #\mode
235         msr     cpsr_c, \reg
236         .endm
237 #else
238         .macro  setmode, mode, reg
239         msr     cpsr_c, #\mode
240         .endm
241 #endif
242
243 /*
244  * Helper macro to enter SVC mode cleanly and mask interrupts. reg is
245  * a scratch register for the macro to overwrite.
246  *
247  * This macro is intended for forcing the CPU into SVC mode at boot time.
248  * you cannot return to the original mode.
249  *
250  * Beware, it also clobers LR.
251  */
252 .macro safe_svcmode_maskall reg:req
253         mrs     \reg , cpsr
254         mov     lr , \reg
255         and     lr , lr , #MODE_MASK
256         cmp     lr , #HYP_MODE
257         orr     \reg , \reg , #PSR_I_BIT | PSR_F_BIT
258         bic     \reg , \reg , #MODE_MASK
259         orr     \reg , \reg , #SVC_MODE
260 THUMB(  orr     \reg , \reg , #PSR_T_BIT        )
261         bne     1f
262         orr     \reg, \reg, #PSR_A_BIT
263         adr     lr, BSYM(2f)
264         msr     spsr_cxsf, \reg
265         __MSR_ELR_HYP(14)
266         __ERET
267 1:      msr     cpsr_c, \reg
268 2:
269 .endm
270
271 /*
272  * STRT/LDRT access macros with ARM and Thumb-2 variants
273  */
274 #ifdef CONFIG_THUMB2_KERNEL
275
276         .macro  usraccoff, instr, reg, ptr, inc, off, cond, abort, t=TUSER()
277 9999:
278         .if     \inc == 1
279         \instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
280         .elseif \inc == 4
281         \instr\cond\()\t\().w \reg, [\ptr, #\off]
282         .else
283         .error  "Unsupported inc macro argument"
284         .endif
285
286         .pushsection __ex_table,"a"
287         .align  3
288         .long   9999b, \abort
289         .popsection
290         .endm
291
292         .macro  usracc, instr, reg, ptr, inc, cond, rept, abort
293         @ explicit IT instruction needed because of the label
294         @ introduced by the USER macro
295         .ifnc   \cond,al
296         .if     \rept == 1
297         itt     \cond
298         .elseif \rept == 2
299         ittt    \cond
300         .else
301         .error  "Unsupported rept macro argument"
302         .endif
303         .endif
304
305         @ Slightly optimised to avoid incrementing the pointer twice
306         usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort
307         .if     \rept == 2
308         usraccoff \instr, \reg, \ptr, \inc, \inc, \cond, \abort
309         .endif
310
311         add\cond \ptr, #\rept * \inc
312         .endm
313
314 #else   /* !CONFIG_THUMB2_KERNEL */
315
316         .macro  usracc, instr, reg, ptr, inc, cond, rept, abort, t=TUSER()
317         .rept   \rept
318 9999:
319         .if     \inc == 1
320         \instr\cond\()b\()\t \reg, [\ptr], #\inc
321         .elseif \inc == 4
322         \instr\cond\()\t \reg, [\ptr], #\inc
323         .else
324         .error  "Unsupported inc macro argument"
325         .endif
326
327         .pushsection __ex_table,"a"
328         .align  3
329         .long   9999b, \abort
330         .popsection
331         .endr
332         .endm
333
334 #endif  /* CONFIG_THUMB2_KERNEL */
335
336         .macro  strusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
337         usracc  str, \reg, \ptr, \inc, \cond, \rept, \abort
338         .endm
339
340         .macro  ldrusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
341         usracc  ldr, \reg, \ptr, \inc, \cond, \rept, \abort
342         .endm
343
344 /* Utility macro for declaring string literals */
345         .macro  string name:req, string
346         .type \name , #object
347 \name:
348         .asciz "\string"
349         .size \name , . - \name
350         .endm
351
352         .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req
353 #ifndef CONFIG_CPU_USE_DOMAINS
354         adds    \tmp, \addr, #\size - 1
355         sbcccs  \tmp, \tmp, \limit
356         bcs     \bad
357 #endif
358         .endm
359
360 #endif /* __ASM_ASSEMBLER_H__ */