FROMLIST: arm64: Factor out TTBR0_EL1 post-update workaround into a specific asm...
[firefly-linux-kernel-4.4.55.git] / arch / arm64 / include / asm / assembler.h
1 /*
2  * Based on arch/arm/include/asm/assembler.h, arch/arm/mm/proc-macros.S
3  *
4  * Copyright (C) 1996-2000 Russell King
5  * Copyright (C) 2012 ARM Ltd.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 #ifndef __ASSEMBLY__
20 #error "Only include this from assembly code"
21 #endif
22
23 #ifndef __ASM_ASSEMBLER_H
24 #define __ASM_ASSEMBLER_H
25
26 #include <asm/asm-offsets.h>
27 #include <asm/cpufeature.h>
28 #include <asm/page.h>
29 #include <asm/pgtable-hwdef.h>
30 #include <asm/ptrace.h>
31 #include <asm/thread_info.h>
32
33 /*
34  * Stack pushing/popping (register pairs only). Equivalent to store decrement
35  * before, load increment after.
36  */
37         .macro  push, xreg1, xreg2
38         stp     \xreg1, \xreg2, [sp, #-16]!
39         .endm
40
41         .macro  pop, xreg1, xreg2
42         ldp     \xreg1, \xreg2, [sp], #16
43         .endm
44
45 /*
46  * Enable and disable interrupts.
47  */
48         .macro  disable_irq
49         msr     daifset, #2
50         .endm
51
52         .macro  enable_irq
53         msr     daifclr, #2
54         .endm
55
56 /*
57  * Enable and disable debug exceptions.
58  */
59         .macro  disable_dbg
60         msr     daifset, #8
61         .endm
62
63         .macro  enable_dbg
64         msr     daifclr, #8
65         .endm
66
67         .macro  disable_step_tsk, flgs, tmp
68         tbz     \flgs, #TIF_SINGLESTEP, 9990f
69         mrs     \tmp, mdscr_el1
70         bic     \tmp, \tmp, #1
71         msr     mdscr_el1, \tmp
72         isb     // Synchronise with enable_dbg
73 9990:
74         .endm
75
76         .macro  enable_step_tsk, flgs, tmp
77         tbz     \flgs, #TIF_SINGLESTEP, 9990f
78         disable_dbg
79         mrs     \tmp, mdscr_el1
80         orr     \tmp, \tmp, #1
81         msr     mdscr_el1, \tmp
82 9990:
83         .endm
84
85 /*
86  * Enable both debug exceptions and interrupts. This is likely to be
87  * faster than two daifclr operations, since writes to this register
88  * are self-synchronising.
89  */
90         .macro  enable_dbg_and_irq
91         msr     daifclr, #(8 | 2)
92         .endm
93
94 /*
95  * SMP data memory barrier
96  */
97         .macro  smp_dmb, opt
98         dmb     \opt
99         .endm
100
101 /*
102  * Emit an entry into the exception table
103  */
104         .macro          _asm_extable, from, to
105         .pushsection    __ex_table, "a"
106         .align          3
107         .long           (\from - .), (\to - .)
108         .popsection
109         .endm
110
111 #define USER(l, x...)                           \
112 9999:   x;                                      \
113         _asm_extable    9999b, l
114
115 /*
116  * Register aliases.
117  */
118 lr      .req    x30             // link register
119
120 /*
121  * Vector entry
122  */
123          .macro ventry  label
124         .align  7
125         b       \label
126         .endm
127
128 /*
129  * Select code when configured for BE.
130  */
131 #ifdef CONFIG_CPU_BIG_ENDIAN
132 #define CPU_BE(code...) code
133 #else
134 #define CPU_BE(code...)
135 #endif
136
137 /*
138  * Select code when configured for LE.
139  */
140 #ifdef CONFIG_CPU_BIG_ENDIAN
141 #define CPU_LE(code...)
142 #else
143 #define CPU_LE(code...) code
144 #endif
145
146 /*
147  * Define a macro that constructs a 64-bit value by concatenating two
148  * 32-bit registers. Note that on big endian systems the order of the
149  * registers is swapped.
150  */
151 #ifndef CONFIG_CPU_BIG_ENDIAN
152         .macro  regs_to_64, rd, lbits, hbits
153 #else
154         .macro  regs_to_64, rd, hbits, lbits
155 #endif
156         orr     \rd, \lbits, \hbits, lsl #32
157         .endm
158
159 /*
160  * Pseudo-ops for PC-relative adr/ldr/str <reg>, <symbol> where
161  * <symbol> is within the range +/- 4 GB of the PC.
162  */
163         /*
164          * @dst: destination register (64 bit wide)
165          * @sym: name of the symbol
166          * @tmp: optional scratch register to be used if <dst> == sp, which
167          *       is not allowed in an adrp instruction
168          */
169         .macro  adr_l, dst, sym, tmp=
170         .ifb    \tmp
171         adrp    \dst, \sym
172         add     \dst, \dst, :lo12:\sym
173         .else
174         adrp    \tmp, \sym
175         add     \dst, \tmp, :lo12:\sym
176         .endif
177         .endm
178
179         /*
180          * @dst: destination register (32 or 64 bit wide)
181          * @sym: name of the symbol
182          * @tmp: optional 64-bit scratch register to be used if <dst> is a
183          *       32-bit wide register, in which case it cannot be used to hold
184          *       the address
185          */
186         .macro  ldr_l, dst, sym, tmp=
187         .ifb    \tmp
188         adrp    \dst, \sym
189         ldr     \dst, [\dst, :lo12:\sym]
190         .else
191         adrp    \tmp, \sym
192         ldr     \dst, [\tmp, :lo12:\sym]
193         .endif
194         .endm
195
196         /*
197          * @src: source register (32 or 64 bit wide)
198          * @sym: name of the symbol
199          * @tmp: mandatory 64-bit scratch register to calculate the address
200          *       while <src> needs to be preserved.
201          */
202         .macro  str_l, src, sym, tmp
203         adrp    \tmp, \sym
204         str     \src, [\tmp, :lo12:\sym]
205         .endm
206
207         /*
208          * @sym: The name of the per-cpu variable
209          * @reg: Result of per_cpu(sym, smp_processor_id())
210          * @tmp: scratch register
211          */
212         .macro this_cpu_ptr, sym, reg, tmp
213         adr_l   \reg, \sym
214         mrs     \tmp, tpidr_el1
215         add     \reg, \reg, \tmp
216         .endm
217
218 /*
219  * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm)
220  */
221         .macro  vma_vm_mm, rd, rn
222         ldr     \rd, [\rn, #VMA_VM_MM]
223         .endm
224
225 /*
226  * mmid - get context id from mm pointer (mm->context.id)
227  */
228         .macro  mmid, rd, rn
229         ldr     \rd, [\rn, #MM_CONTEXT_ID]
230         .endm
231
232 /*
233  * dcache_line_size - get the minimum D-cache line size from the CTR register.
234  */
235         .macro  dcache_line_size, reg, tmp
236         mrs     \tmp, ctr_el0                   // read CTR
237         ubfm    \tmp, \tmp, #16, #19            // cache line size encoding
238         mov     \reg, #4                        // bytes per word
239         lsl     \reg, \reg, \tmp                // actual cache line size
240         .endm
241
242 /*
243  * icache_line_size - get the minimum I-cache line size from the CTR register.
244  */
245         .macro  icache_line_size, reg, tmp
246         mrs     \tmp, ctr_el0                   // read CTR
247         and     \tmp, \tmp, #0xf                // cache line size encoding
248         mov     \reg, #4                        // bytes per word
249         lsl     \reg, \reg, \tmp                // actual cache line size
250         .endm
251
252 /*
253  * tcr_set_idmap_t0sz - update TCR.T0SZ so that we can load the ID map
254  */
255         .macro  tcr_set_idmap_t0sz, valreg, tmpreg
256 #ifndef CONFIG_ARM64_VA_BITS_48
257         ldr_l   \tmpreg, idmap_t0sz
258         bfi     \valreg, \tmpreg, #TCR_T0SZ_OFFSET, #TCR_TxSZ_WIDTH
259 #endif
260         .endm
261
262 /*
263  * Macro to perform a data cache maintenance for the interval
264  * [kaddr, kaddr + size)
265  *
266  *      op:             operation passed to dc instruction
267  *      domain:         domain used in dsb instruciton
268  *      kaddr:          starting virtual address of the region
269  *      size:           size of the region
270  *      Corrupts:       kaddr, size, tmp1, tmp2
271  */
272         .macro dcache_by_line_op op, domain, kaddr, size, tmp1, tmp2
273         dcache_line_size \tmp1, \tmp2
274         add     \size, \kaddr, \size
275         sub     \tmp2, \tmp1, #1
276         bic     \kaddr, \kaddr, \tmp2
277 9998:
278         .if     (\op == cvau || \op == cvac)
279 alternative_if_not ARM64_WORKAROUND_CLEAN_CACHE
280         dc      \op, \kaddr
281 alternative_else
282         dc      civac, \kaddr
283 alternative_endif
284         .else
285         dc      \op, \kaddr
286         .endif
287         add     \kaddr, \kaddr, \tmp1
288         cmp     \kaddr, \size
289         b.lo    9998b
290         dsb     \domain
291         .endm
292
293 /*
294  * reset_pmuserenr_el0 - reset PMUSERENR_EL0 if PMUv3 present
295  */
296         .macro  reset_pmuserenr_el0, tmpreg
297         mrs     \tmpreg, id_aa64dfr0_el1        // Check ID_AA64DFR0_EL1 PMUVer
298         sbfx    \tmpreg, \tmpreg, #8, #4
299         cmp     \tmpreg, #1                     // Skip if no PMU present
300         b.lt    9000f
301         msr     pmuserenr_el0, xzr              // Disable PMU access from EL0
302 9000:
303         .endm
304
305 /*
306  * copy_page - copy src to dest using temp registers t1-t8
307  */
308         .macro copy_page dest:req src:req t1:req t2:req t3:req t4:req t5:req t6:req t7:req t8:req
309 9998:   ldp     \t1, \t2, [\src]
310         ldp     \t3, \t4, [\src, #16]
311         ldp     \t5, \t6, [\src, #32]
312         ldp     \t7, \t8, [\src, #48]
313         add     \src, \src, #64
314         stnp    \t1, \t2, [\dest]
315         stnp    \t3, \t4, [\dest, #16]
316         stnp    \t5, \t6, [\dest, #32]
317         stnp    \t7, \t8, [\dest, #48]
318         add     \dest, \dest, #64
319         tst     \src, #(PAGE_SIZE - 1)
320         b.ne    9998b
321         .endm
322
323 /*
324  * Annotate a function as position independent, i.e., safe to be called before
325  * the kernel virtual mapping is activated.
326  */
327 #define ENDPIPROC(x)                    \
328         .globl  __pi_##x;               \
329         .type   __pi_##x, %function;    \
330         .set    __pi_##x, x;            \
331         .size   __pi_##x, . - x;        \
332         ENDPROC(x)
333
334         /*
335          * Emit a 64-bit absolute little endian symbol reference in a way that
336          * ensures that it will be resolved at build time, even when building a
337          * PIE binary. This requires cooperation from the linker script, which
338          * must emit the lo32/hi32 halves individually.
339          */
340         .macro  le64sym, sym
341         .long   \sym\()_lo32
342         .long   \sym\()_hi32
343         .endm
344
345         /*
346          * mov_q - move an immediate constant into a 64-bit register using
347          *         between 2 and 4 movz/movk instructions (depending on the
348          *         magnitude and sign of the operand)
349          */
350         .macro  mov_q, reg, val
351         .if (((\val) >> 31) == 0 || ((\val) >> 31) == 0x1ffffffff)
352         movz    \reg, :abs_g1_s:\val
353         .else
354         .if (((\val) >> 47) == 0 || ((\val) >> 47) == 0x1ffff)
355         movz    \reg, :abs_g2_s:\val
356         .else
357         movz    \reg, :abs_g3:\val
358         movk    \reg, :abs_g2_nc:\val
359         .endif
360         movk    \reg, :abs_g1_nc:\val
361         .endif
362         movk    \reg, :abs_g0_nc:\val
363         .endm
364
365 /*
366  * Errata workaround post TTBR0_EL1 update.
367  */
368         .macro  post_ttbr0_update_workaround
369 #ifdef CONFIG_CAVIUM_ERRATUM_27456
370 alternative_if_not ARM64_WORKAROUND_CAVIUM_27456
371         nop
372         nop
373         nop
374 alternative_else
375         ic      iallu
376         dsb     nsh
377         isb
378 alternative_endif
379 #endif
380         .endm
381
382 #endif  /* __ASM_ASSEMBLER_H */