GNU Linux-libre 4.9.309-gnu1
[releases.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 #include <asm/asm-offsets.h>
27 #include <asm/page.h>
28 #include <asm/thread_info.h>
29
30 #define IOMEM(x)        (x)
31
32 /*
33  * Endian independent macros for shifting bytes within registers.
34  */
35 #ifndef __ARMEB__
36 #define lspull          lsr
37 #define lspush          lsl
38 #define get_byte_0      lsl #0
39 #define get_byte_1      lsr #8
40 #define get_byte_2      lsr #16
41 #define get_byte_3      lsr #24
42 #define put_byte_0      lsl #0
43 #define put_byte_1      lsl #8
44 #define put_byte_2      lsl #16
45 #define put_byte_3      lsl #24
46 #else
47 #define lspull          lsl
48 #define lspush          lsr
49 #define get_byte_0      lsr #24
50 #define get_byte_1      lsr #16
51 #define get_byte_2      lsr #8
52 #define get_byte_3      lsl #0
53 #define put_byte_0      lsl #24
54 #define put_byte_1      lsl #16
55 #define put_byte_2      lsl #8
56 #define put_byte_3      lsl #0
57 #endif
58
59 /* Select code for any configuration running in BE8 mode */
60 #ifdef CONFIG_CPU_ENDIAN_BE8
61 #define ARM_BE8(code...) code
62 #else
63 #define ARM_BE8(code...)
64 #endif
65
66 /*
67  * Data preload for architectures that support it
68  */
69 #if __LINUX_ARM_ARCH__ >= 5
70 #define PLD(code...)    code
71 #else
72 #define PLD(code...)
73 #endif
74
75 /*
76  * This can be used to enable code to cacheline align the destination
77  * pointer when bulk writing to memory.  Experiments on StrongARM and
78  * XScale didn't show this a worthwhile thing to do when the cache is not
79  * set to write-allocate (this would need further testing on XScale when WA
80  * is used).
81  *
82  * On Feroceon there is much to gain however, regardless of cache mode.
83  */
84 #ifdef CONFIG_CPU_FEROCEON
85 #define CALGN(code...) code
86 #else
87 #define CALGN(code...)
88 #endif
89
90 /*
91  * Enable and disable interrupts
92  */
93 #if __LINUX_ARM_ARCH__ >= 6
94         .macro  disable_irq_notrace
95         cpsid   i
96         .endm
97
98         .macro  enable_irq_notrace
99         cpsie   i
100         .endm
101 #else
102         .macro  disable_irq_notrace
103         msr     cpsr_c, #PSR_I_BIT | SVC_MODE
104         .endm
105
106         .macro  enable_irq_notrace
107         msr     cpsr_c, #SVC_MODE
108         .endm
109 #endif
110
111 #if __LINUX_ARM_ARCH__ < 7
112         .macro  dsb, args
113         mcr     p15, 0, r0, c7, c10, 4
114         .endm
115
116         .macro  isb, args
117         mcr     p15, 0, r0, c7, c5, 4
118         .endm
119 #endif
120
121         .macro asm_trace_hardirqs_off, save=1
122 #if defined(CONFIG_TRACE_IRQFLAGS)
123         .if \save
124         stmdb   sp!, {r0-r3, ip, lr}
125         .endif
126         bl      trace_hardirqs_off
127         .if \save
128         ldmia   sp!, {r0-r3, ip, lr}
129         .endif
130 #endif
131         .endm
132
133         .macro asm_trace_hardirqs_on, cond=al, save=1
134 #if defined(CONFIG_TRACE_IRQFLAGS)
135         /*
136          * actually the registers should be pushed and pop'd conditionally, but
137          * after bl the flags are certainly clobbered
138          */
139         .if \save
140         stmdb   sp!, {r0-r3, ip, lr}
141         .endif
142         bl\cond trace_hardirqs_on
143         .if \save
144         ldmia   sp!, {r0-r3, ip, lr}
145         .endif
146 #endif
147         .endm
148
149         .macro disable_irq, save=1
150         disable_irq_notrace
151         asm_trace_hardirqs_off \save
152         .endm
153
154         .macro enable_irq
155         asm_trace_hardirqs_on
156         enable_irq_notrace
157         .endm
158 /*
159  * Save the current IRQ state and disable IRQs.  Note that this macro
160  * assumes FIQs are enabled, and that the processor is in SVC mode.
161  */
162         .macro  save_and_disable_irqs, oldcpsr
163 #ifdef CONFIG_CPU_V7M
164         mrs     \oldcpsr, primask
165 #else
166         mrs     \oldcpsr, cpsr
167 #endif
168         disable_irq
169         .endm
170
171         .macro  save_and_disable_irqs_notrace, oldcpsr
172 #ifdef CONFIG_CPU_V7M
173         mrs     \oldcpsr, primask
174 #else
175         mrs     \oldcpsr, cpsr
176 #endif
177         disable_irq_notrace
178         .endm
179
180 /*
181  * Restore interrupt state previously stored in a register.  We don't
182  * guarantee that this will preserve the flags.
183  */
184         .macro  restore_irqs_notrace, oldcpsr
185 #ifdef CONFIG_CPU_V7M
186         msr     primask, \oldcpsr
187 #else
188         msr     cpsr_c, \oldcpsr
189 #endif
190         .endm
191
192         .macro restore_irqs, oldcpsr
193         tst     \oldcpsr, #PSR_I_BIT
194         asm_trace_hardirqs_on cond=eq
195         restore_irqs_notrace \oldcpsr
196         .endm
197
198 /*
199  * Assembly version of "adr rd, BSYM(sym)".  This should only be used to
200  * reference local symbols in the same assembly file which are to be
201  * resolved by the assembler.  Other usage is undefined.
202  */
203         .irp    c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
204         .macro  badr\c, rd, sym
205 #ifdef CONFIG_THUMB2_KERNEL
206         adr\c   \rd, \sym + 1
207 #else
208         adr\c   \rd, \sym
209 #endif
210         .endm
211         .endr
212
213 /*
214  * Get current thread_info.
215  */
216         .macro  get_thread_info, rd
217  ARM(   mov     \rd, sp, lsr #THREAD_SIZE_ORDER + PAGE_SHIFT    )
218  THUMB( mov     \rd, sp                 )
219  THUMB( lsr     \rd, \rd, #THREAD_SIZE_ORDER + PAGE_SHIFT       )
220         mov     \rd, \rd, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT
221         .endm
222
223 /*
224  * Increment/decrement the preempt count.
225  */
226 #ifdef CONFIG_PREEMPT_COUNT
227         .macro  inc_preempt_count, ti, tmp
228         ldr     \tmp, [\ti, #TI_PREEMPT]        @ get preempt count
229         add     \tmp, \tmp, #1                  @ increment it
230         str     \tmp, [\ti, #TI_PREEMPT]
231         .endm
232
233         .macro  dec_preempt_count, ti, tmp
234         ldr     \tmp, [\ti, #TI_PREEMPT]        @ get preempt count
235         sub     \tmp, \tmp, #1                  @ decrement it
236         str     \tmp, [\ti, #TI_PREEMPT]
237         .endm
238
239         .macro  dec_preempt_count_ti, ti, tmp
240         get_thread_info \ti
241         dec_preempt_count \ti, \tmp
242         .endm
243 #else
244         .macro  inc_preempt_count, ti, tmp
245         .endm
246
247         .macro  dec_preempt_count, ti, tmp
248         .endm
249
250         .macro  dec_preempt_count_ti, ti, tmp
251         .endm
252 #endif
253
254 #define USER(x...)                              \
255 9999:   x;                                      \
256         .pushsection __ex_table,"a";            \
257         .align  3;                              \
258         .long   9999b,9001f;                    \
259         .popsection
260
261 #ifdef CONFIG_SMP
262 #define ALT_SMP(instr...)                                       \
263 9998:   instr
264 /*
265  * Note: if you get assembler errors from ALT_UP() when building with
266  * CONFIG_THUMB2_KERNEL, you almost certainly need to use
267  * ALT_SMP( W(instr) ... )
268  */
269 #define ALT_UP(instr...)                                        \
270         .pushsection ".alt.smp.init", "a"                       ;\
271         .long   9998b                                           ;\
272 9997:   instr                                                   ;\
273         .if . - 9997b == 2                                      ;\
274                 nop                                             ;\
275         .endif                                                  ;\
276         .if . - 9997b != 4                                      ;\
277                 .error "ALT_UP() content must assemble to exactly 4 bytes";\
278         .endif                                                  ;\
279         .popsection
280 #define ALT_UP_B(label)                                 \
281         .equ    up_b_offset, label - 9998b                      ;\
282         .pushsection ".alt.smp.init", "a"                       ;\
283         .long   9998b                                           ;\
284         W(b)    . + up_b_offset                                 ;\
285         .popsection
286 #else
287 #define ALT_SMP(instr...)
288 #define ALT_UP(instr...) instr
289 #define ALT_UP_B(label) b label
290 #endif
291
292 /*
293  * Instruction barrier
294  */
295         .macro  instr_sync
296 #if __LINUX_ARM_ARCH__ >= 7
297         isb
298 #elif __LINUX_ARM_ARCH__ == 6
299         mcr     p15, 0, r0, c7, c5, 4
300 #endif
301         .endm
302
303 /*
304  * SMP data memory barrier
305  */
306         .macro  smp_dmb mode
307 #ifdef CONFIG_SMP
308 #if __LINUX_ARM_ARCH__ >= 7
309         .ifeqs "\mode","arm"
310         ALT_SMP(dmb     ish)
311         .else
312         ALT_SMP(W(dmb)  ish)
313         .endif
314 #elif __LINUX_ARM_ARCH__ == 6
315         ALT_SMP(mcr     p15, 0, r0, c7, c10, 5) @ dmb
316 #else
317 #error Incompatible SMP platform
318 #endif
319         .ifeqs "\mode","arm"
320         ALT_UP(nop)
321         .else
322         ALT_UP(W(nop))
323         .endif
324 #endif
325         .endm
326
327 #if defined(CONFIG_CPU_V7M)
328         /*
329          * setmode is used to assert to be in svc mode during boot. For v7-M
330          * this is done in __v7m_setup, so setmode can be empty here.
331          */
332         .macro  setmode, mode, reg
333         .endm
334 #elif defined(CONFIG_THUMB2_KERNEL)
335         .macro  setmode, mode, reg
336         mov     \reg, #\mode
337         msr     cpsr_c, \reg
338         .endm
339 #else
340         .macro  setmode, mode, reg
341         msr     cpsr_c, #\mode
342         .endm
343 #endif
344
345 /*
346  * Helper macro to enter SVC mode cleanly and mask interrupts. reg is
347  * a scratch register for the macro to overwrite.
348  *
349  * This macro is intended for forcing the CPU into SVC mode at boot time.
350  * you cannot return to the original mode.
351  */
352 .macro safe_svcmode_maskall reg:req
353 #if __LINUX_ARM_ARCH__ >= 6 && !defined(CONFIG_CPU_V7M)
354         mrs     \reg , cpsr
355         eor     \reg, \reg, #HYP_MODE
356         tst     \reg, #MODE_MASK
357         bic     \reg , \reg , #MODE_MASK
358         orr     \reg , \reg , #PSR_I_BIT | PSR_F_BIT | SVC_MODE
359 THUMB(  orr     \reg , \reg , #PSR_T_BIT        )
360         bne     1f
361         orr     \reg, \reg, #PSR_A_BIT
362         badr    lr, 2f
363         msr     spsr_cxsf, \reg
364         __MSR_ELR_HYP(14)
365         __ERET
366 1:      msr     cpsr_c, \reg
367 2:
368 #else
369 /*
370  * workaround for possibly broken pre-v6 hardware
371  * (akita, Sharp Zaurus C-1000, PXA270-based)
372  */
373         setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, \reg
374 #endif
375 .endm
376
377 /*
378  * STRT/LDRT access macros with ARM and Thumb-2 variants
379  */
380 #ifdef CONFIG_THUMB2_KERNEL
381
382         .macro  usraccoff, instr, reg, ptr, inc, off, cond, abort, t=TUSER()
383 9999:
384         .if     \inc == 1
385         \instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
386         .elseif \inc == 4
387         \instr\cond\()\t\().w \reg, [\ptr, #\off]
388         .else
389         .error  "Unsupported inc macro argument"
390         .endif
391
392         .pushsection __ex_table,"a"
393         .align  3
394         .long   9999b, \abort
395         .popsection
396         .endm
397
398         .macro  usracc, instr, reg, ptr, inc, cond, rept, abort
399         @ explicit IT instruction needed because of the label
400         @ introduced by the USER macro
401         .ifnc   \cond,al
402         .if     \rept == 1
403         itt     \cond
404         .elseif \rept == 2
405         ittt    \cond
406         .else
407         .error  "Unsupported rept macro argument"
408         .endif
409         .endif
410
411         @ Slightly optimised to avoid incrementing the pointer twice
412         usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort
413         .if     \rept == 2
414         usraccoff \instr, \reg, \ptr, \inc, \inc, \cond, \abort
415         .endif
416
417         add\cond \ptr, #\rept * \inc
418         .endm
419
420 #else   /* !CONFIG_THUMB2_KERNEL */
421
422         .macro  usracc, instr, reg, ptr, inc, cond, rept, abort, t=TUSER()
423         .rept   \rept
424 9999:
425         .if     \inc == 1
426         \instr\cond\()b\()\t \reg, [\ptr], #\inc
427         .elseif \inc == 4
428         \instr\cond\()\t \reg, [\ptr], #\inc
429         .else
430         .error  "Unsupported inc macro argument"
431         .endif
432
433         .pushsection __ex_table,"a"
434         .align  3
435         .long   9999b, \abort
436         .popsection
437         .endr
438         .endm
439
440 #endif  /* CONFIG_THUMB2_KERNEL */
441
442         .macro  strusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
443         usracc  str, \reg, \ptr, \inc, \cond, \rept, \abort
444         .endm
445
446         .macro  ldrusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
447         usracc  ldr, \reg, \ptr, \inc, \cond, \rept, \abort
448         .endm
449
450 /* Utility macro for declaring string literals */
451         .macro  string name:req, string
452         .type \name , #object
453 \name:
454         .asciz "\string"
455         .size \name , . - \name
456         .endm
457
458         .macro  csdb
459 #ifdef CONFIG_THUMB2_KERNEL
460         .inst.w 0xf3af8014
461 #else
462         .inst   0xe320f014
463 #endif
464         .endm
465
466         .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req
467 #ifndef CONFIG_CPU_USE_DOMAINS
468         adds    \tmp, \addr, #\size - 1
469         sbcccs  \tmp, \tmp, \limit
470         bcs     \bad
471 #ifdef CONFIG_CPU_SPECTRE
472         movcs   \addr, #0
473         csdb
474 #endif
475 #endif
476         .endm
477
478         .macro uaccess_mask_range_ptr, addr:req, size:req, limit:req, tmp:req
479 #ifdef CONFIG_CPU_SPECTRE
480         sub     \tmp, \limit, #1
481         subs    \tmp, \tmp, \addr       @ tmp = limit - 1 - addr
482         addhs   \tmp, \tmp, #1          @ if (tmp >= 0) {
483         subhss  \tmp, \tmp, \size       @ tmp = limit - (addr + size) }
484         movlo   \addr, #0               @ if (tmp < 0) addr = NULL
485         csdb
486 #endif
487         .endm
488
489         .macro  uaccess_disable, tmp, isb=1
490 #ifdef CONFIG_CPU_SW_DOMAIN_PAN
491         /*
492          * Whenever we re-enter userspace, the domains should always be
493          * set appropriately.
494          */
495         mov     \tmp, #DACR_UACCESS_DISABLE
496         mcr     p15, 0, \tmp, c3, c0, 0         @ Set domain register
497         .if     \isb
498         instr_sync
499         .endif
500 #endif
501         .endm
502
503         .macro  uaccess_enable, tmp, isb=1
504 #ifdef CONFIG_CPU_SW_DOMAIN_PAN
505         /*
506          * Whenever we re-enter userspace, the domains should always be
507          * set appropriately.
508          */
509         mov     \tmp, #DACR_UACCESS_ENABLE
510         mcr     p15, 0, \tmp, c3, c0, 0
511         .if     \isb
512         instr_sync
513         .endif
514 #endif
515         .endm
516
517         .macro  uaccess_save, tmp
518 #ifdef CONFIG_CPU_SW_DOMAIN_PAN
519         mrc     p15, 0, \tmp, c3, c0, 0
520         str     \tmp, [sp, #SVC_DACR]
521 #endif
522         .endm
523
524         .macro  uaccess_restore
525 #ifdef CONFIG_CPU_SW_DOMAIN_PAN
526         ldr     r0, [sp, #SVC_DACR]
527         mcr     p15, 0, r0, c3, c0, 0
528 #endif
529         .endm
530
531         .irp    c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
532         .macro  ret\c, reg
533 #if __LINUX_ARM_ARCH__ < 6
534         mov\c   pc, \reg
535 #else
536         .ifeqs  "\reg", "lr"
537         bx\c    \reg
538         .else
539         mov\c   pc, \reg
540         .endif
541 #endif
542         .endm
543         .endr
544
545         .macro  ret.w, reg
546         ret     \reg
547 #ifdef CONFIG_THUMB2_KERNEL
548         nop
549 #endif
550         .endm
551
552         .macro  bug, msg, line
553 #ifdef CONFIG_THUMB2_KERNEL
554 1:      .inst   0xde02
555 #else
556 1:      .inst   0xe7f001f2
557 #endif
558 #ifdef CONFIG_DEBUG_BUGVERBOSE
559         .pushsection .rodata.str, "aMS", %progbits, 1
560 2:      .asciz  "\msg"
561         .popsection
562         .pushsection __bug_table, "aw"
563         .align  2
564         .word   1b, 2b
565         .hword  \line
566         .popsection
567 #endif
568         .endm
569
570 #ifdef CONFIG_KPROBES
571 #define _ASM_NOKPROBE(entry)                            \
572         .pushsection "_kprobe_blacklist", "aw" ;        \
573         .balign 4 ;                                     \
574         .long entry;                                    \
575         .popsection
576 #else
577 #define _ASM_NOKPROBE(entry)
578 #endif
579
580 #endif /* __ASM_ASSEMBLER_H__ */