GNU Linux-libre 4.9.337-gnu1
[releases.git] / arch / arm / mm / proc-macros.S
1 /*
2  * We need constants.h for:
3  *  VMA_VM_MM
4  *  VMA_VM_FLAGS
5  *  VM_EXEC
6  */
7 #include <linux/const.h>
8 #include <asm/asm-offsets.h>
9 #include <asm/thread_info.h>
10
11 #ifdef CONFIG_CPU_V7M
12 #include <asm/v7m.h>
13 #endif
14
15 /*
16  * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm)
17  */
18         .macro  vma_vm_mm, rd, rn
19         ldr     \rd, [\rn, #VMA_VM_MM]
20         .endm
21
22 /*
23  * vma_vm_flags - get vma->vm_flags
24  */
25         .macro  vma_vm_flags, rd, rn
26         ldr     \rd, [\rn, #VMA_VM_FLAGS]
27         .endm
28
29         .macro  tsk_mm, rd, rn
30         ldr     \rd, [\rn, #TI_TASK]
31         ldr     \rd, [\rd, #TSK_ACTIVE_MM]
32         .endm
33
34 /*
35  * act_mm - get current->active_mm
36  */
37         .macro  act_mm, rd
38         bic     \rd, sp, #(THREAD_SIZE - 1) & ~63
39         bic     \rd, \rd, #63
40         ldr     \rd, [\rd, #TI_TASK]
41         ldr     \rd, [\rd, #TSK_ACTIVE_MM]
42         .endm
43
44 /*
45  * mmid - get context id from mm pointer (mm->context.id)
46  * note, this field is 64bit, so in big-endian the two words are swapped too.
47  */
48         .macro  mmid, rd, rn
49 #ifdef __ARMEB__
50         ldr     \rd, [\rn, #MM_CONTEXT_ID + 4 ]
51 #else
52         ldr     \rd, [\rn, #MM_CONTEXT_ID]
53 #endif
54         .endm
55
56 /*
57  * mask_asid - mask the ASID from the context ID
58  */
59         .macro  asid, rd, rn
60         and     \rd, \rn, #255
61         .endm
62
63         .macro  crval, clear, mmuset, ucset
64 #ifdef CONFIG_MMU
65         .word   \clear
66         .word   \mmuset
67 #else
68         .word   \clear
69         .word   \ucset
70 #endif
71         .endm
72
73 /*
74  * dcache_line_size - get the minimum D-cache line size from the CTR register
75  * on ARMv7.
76  */
77         .macro  dcache_line_size, reg, tmp
78 #ifdef CONFIG_CPU_V7M
79         movw    \tmp, #:lower16:BASEADDR_V7M_SCB + V7M_SCB_CTR
80         movt    \tmp, #:upper16:BASEADDR_V7M_SCB + V7M_SCB_CTR
81         ldr     \tmp, [\tmp]
82 #else
83         mrc     p15, 0, \tmp, c0, c0, 1         @ read ctr
84 #endif
85         lsr     \tmp, \tmp, #16
86         and     \tmp, \tmp, #0xf                @ cache line size encoding
87         mov     \reg, #4                        @ bytes per word
88         mov     \reg, \reg, lsl \tmp            @ actual cache line size
89         .endm
90
91 /*
92  * icache_line_size - get the minimum I-cache line size from the CTR register
93  * on ARMv7.
94  */
95         .macro  icache_line_size, reg, tmp
96 #ifdef CONFIG_CPU_V7M
97         movw    \tmp, #:lower16:BASEADDR_V7M_SCB + V7M_SCB_CTR
98         movt    \tmp, #:upper16:BASEADDR_V7M_SCB + V7M_SCB_CTR
99         ldr     \tmp, [\tmp]
100 #else
101         mrc     p15, 0, \tmp, c0, c0, 1         @ read ctr
102 #endif
103         and     \tmp, \tmp, #0xf                @ cache line size encoding
104         mov     \reg, #4                        @ bytes per word
105         mov     \reg, \reg, lsl \tmp            @ actual cache line size
106         .endm
107
108 /*
109  * Sanity check the PTE configuration for the code below - which makes
110  * certain assumptions about how these bits are laid out.
111  */
112 #ifdef CONFIG_MMU
113 #if L_PTE_SHARED != PTE_EXT_SHARED
114 #error PTE shared bit mismatch
115 #endif
116 #if !defined (CONFIG_ARM_LPAE) && \
117         (L_PTE_XN+L_PTE_USER+L_PTE_RDONLY+L_PTE_DIRTY+L_PTE_YOUNG+\
118          L_PTE_PRESENT) > L_PTE_SHARED
119 #error Invalid Linux PTE bit settings
120 #endif
121 #endif  /* CONFIG_MMU */
122
123 /*
124  * The ARMv6 and ARMv7 set_pte_ext translation function.
125  *
126  * Permission translation:
127  *  YUWD  APX AP1 AP0   SVC     User
128  *  0xxx   0   0   0    no acc  no acc
129  *  100x   1   0   1    r/o     no acc
130  *  10x0   1   0   1    r/o     no acc
131  *  1011   0   0   1    r/w     no acc
132  *  110x   1   1   1    r/o     r/o
133  *  11x0   1   1   1    r/o     r/o
134  *  1111   0   1   1    r/w     r/w
135  */
136         .macro  armv6_mt_table pfx
137 \pfx\()_mt_table:
138         .long   0x00                                            @ L_PTE_MT_UNCACHED
139         .long   PTE_EXT_TEX(1)                                  @ L_PTE_MT_BUFFERABLE
140         .long   PTE_CACHEABLE                                   @ L_PTE_MT_WRITETHROUGH
141         .long   PTE_CACHEABLE | PTE_BUFFERABLE                  @ L_PTE_MT_WRITEBACK
142         .long   PTE_BUFFERABLE                                  @ L_PTE_MT_DEV_SHARED
143         .long   0x00                                            @ unused
144         .long   0x00                                            @ L_PTE_MT_MINICACHE (not present)
145         .long   PTE_EXT_TEX(1) | PTE_CACHEABLE | PTE_BUFFERABLE @ L_PTE_MT_WRITEALLOC
146         .long   0x00                                            @ unused
147         .long   PTE_EXT_TEX(1)                                  @ L_PTE_MT_DEV_WC
148         .long   0x00                                            @ unused
149         .long   PTE_CACHEABLE | PTE_BUFFERABLE                  @ L_PTE_MT_DEV_CACHED
150         .long   PTE_EXT_TEX(2)                                  @ L_PTE_MT_DEV_NONSHARED
151         .long   0x00                                            @ unused
152         .long   0x00                                            @ unused
153         .long   PTE_CACHEABLE | PTE_BUFFERABLE | PTE_EXT_APX    @ L_PTE_MT_VECTORS
154         .endm
155
156         .macro  armv6_set_pte_ext pfx
157         str     r1, [r0], #2048                 @ linux version
158
159         bic     r3, r1, #0x000003fc
160         bic     r3, r3, #PTE_TYPE_MASK
161         orr     r3, r3, r2
162         orr     r3, r3, #PTE_EXT_AP0 | 2
163
164         adr     ip, \pfx\()_mt_table
165         and     r2, r1, #L_PTE_MT_MASK
166         ldr     r2, [ip, r2]
167
168         eor     r1, r1, #L_PTE_DIRTY
169         tst     r1, #L_PTE_DIRTY|L_PTE_RDONLY
170         orrne   r3, r3, #PTE_EXT_APX
171
172         tst     r1, #L_PTE_USER
173         orrne   r3, r3, #PTE_EXT_AP1
174         tstne   r3, #PTE_EXT_APX
175
176         @ user read-only -> kernel read-only
177         bicne   r3, r3, #PTE_EXT_AP0
178
179         tst     r1, #L_PTE_XN
180         orrne   r3, r3, #PTE_EXT_XN
181
182         eor     r3, r3, r2
183
184         tst     r1, #L_PTE_YOUNG
185         tstne   r1, #L_PTE_PRESENT
186         moveq   r3, #0
187         tstne   r1, #L_PTE_NONE
188         movne   r3, #0
189
190         str     r3, [r0]
191         mcr     p15, 0, r0, c7, c10, 1          @ flush_pte
192         .endm
193
194
195 /*
196  * The ARMv3, ARMv4 and ARMv5 set_pte_ext translation function,
197  * covering most CPUs except Xscale and Xscale 3.
198  *
199  * Permission translation:
200  *  YUWD   AP   SVC     User
201  *  0xxx  0x00  no acc  no acc
202  *  100x  0x00  r/o     no acc
203  *  10x0  0x00  r/o     no acc
204  *  1011  0x55  r/w     no acc
205  *  110x  0xaa  r/w     r/o
206  *  11x0  0xaa  r/w     r/o
207  *  1111  0xff  r/w     r/w
208  */
209         .macro  armv3_set_pte_ext wc_disable=1
210         str     r1, [r0], #2048                 @ linux version
211
212         eor     r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY
213
214         bic     r2, r1, #PTE_SMALL_AP_MASK      @ keep C, B bits
215         bic     r2, r2, #PTE_TYPE_MASK
216         orr     r2, r2, #PTE_TYPE_SMALL
217
218         tst     r3, #L_PTE_USER                 @ user?
219         orrne   r2, r2, #PTE_SMALL_AP_URO_SRW
220
221         tst     r3, #L_PTE_RDONLY | L_PTE_DIRTY @ write and dirty?
222         orreq   r2, r2, #PTE_SMALL_AP_UNO_SRW
223
224         tst     r3, #L_PTE_PRESENT | L_PTE_YOUNG        @ present and young?
225         movne   r2, #0
226
227         .if     \wc_disable
228 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
229         tst     r2, #PTE_CACHEABLE
230         bicne   r2, r2, #PTE_BUFFERABLE
231 #endif
232         .endif
233         str     r2, [r0]                @ hardware version
234         .endm
235
236
237 /*
238  * Xscale set_pte_ext translation, split into two halves to cope
239  * with work-arounds.  r3 must be preserved by code between these
240  * two macros.
241  *
242  * Permission translation:
243  *  YUWD  AP    SVC     User
244  *  0xxx  00    no acc  no acc
245  *  100x  00    r/o     no acc
246  *  10x0  00    r/o     no acc
247  *  1011  01    r/w     no acc
248  *  110x  10    r/w     r/o
249  *  11x0  10    r/w     r/o
250  *  1111  11    r/w     r/w
251  */
252         .macro  xscale_set_pte_ext_prologue
253         str     r1, [r0]                        @ linux version
254
255         eor     r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY
256
257         bic     r2, r1, #PTE_SMALL_AP_MASK      @ keep C, B bits
258         orr     r2, r2, #PTE_TYPE_EXT           @ extended page
259
260         tst     r3, #L_PTE_USER                 @ user?
261         orrne   r2, r2, #PTE_EXT_AP_URO_SRW     @ yes -> user r/o, system r/w
262
263         tst     r3, #L_PTE_RDONLY | L_PTE_DIRTY @ write and dirty?
264         orreq   r2, r2, #PTE_EXT_AP_UNO_SRW     @ yes -> user n/a, system r/w
265                                                 @ combined with user -> user r/w
266         .endm
267
268         .macro  xscale_set_pte_ext_epilogue
269         tst     r3, #L_PTE_PRESENT | L_PTE_YOUNG        @ present and young?
270         movne   r2, #0                          @ no -> fault
271
272         str     r2, [r0, #2048]!                @ hardware version
273         mov     ip, #0
274         mcr     p15, 0, r0, c7, c10, 1          @ clean L1 D line
275         mcr     p15, 0, ip, c7, c10, 4          @ data write barrier
276         .endm
277
278 .macro define_processor_functions name:req, dabort:req, pabort:req, nommu=0, suspend=0, bugs=0
279 /*
280  * If we are building for big.Little with branch predictor hardening,
281  * we need the processor function tables to remain available after boot.
282  */
283 #if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
284         .section ".rodata"
285 #endif
286         .type   \name\()_processor_functions, #object
287         .align 2
288 ENTRY(\name\()_processor_functions)
289         .word   \dabort
290         .word   \pabort
291         .word   cpu_\name\()_proc_init
292         .word   \bugs
293         .word   cpu_\name\()_proc_fin
294         .word   cpu_\name\()_reset
295         .word   cpu_\name\()_do_idle
296         .word   cpu_\name\()_dcache_clean_area
297         .word   cpu_\name\()_switch_mm
298
299         .if \nommu
300         .word   0
301         .else
302         .word   cpu_\name\()_set_pte_ext
303         .endif
304
305         .if \suspend
306         .word   cpu_\name\()_suspend_size
307 #ifdef CONFIG_ARM_CPU_SUSPEND
308         .word   cpu_\name\()_do_suspend
309         .word   cpu_\name\()_do_resume
310 #else
311         .word   0
312         .word   0
313 #endif
314         .else
315         .word   0
316         .word   0
317         .word   0
318         .endif
319
320         .size   \name\()_processor_functions, . - \name\()_processor_functions
321 #if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
322         .previous
323 #endif
324 .endm
325
326 .macro define_cache_functions name:req
327         .align 2
328         .type   \name\()_cache_fns, #object
329 ENTRY(\name\()_cache_fns)
330         .long   \name\()_flush_icache_all
331         .long   \name\()_flush_kern_cache_all
332         .long   \name\()_flush_kern_cache_louis
333         .long   \name\()_flush_user_cache_all
334         .long   \name\()_flush_user_cache_range
335         .long   \name\()_coherent_kern_range
336         .long   \name\()_coherent_user_range
337         .long   \name\()_flush_kern_dcache_area
338         .long   \name\()_dma_map_area
339         .long   \name\()_dma_unmap_area
340         .long   \name\()_dma_flush_range
341         .size   \name\()_cache_fns, . - \name\()_cache_fns
342 .endm
343
344 .macro define_tlb_functions name:req, flags_up:req, flags_smp
345         .type   \name\()_tlb_fns, #object
346         .align 2
347 ENTRY(\name\()_tlb_fns)
348         .long   \name\()_flush_user_tlb_range
349         .long   \name\()_flush_kern_tlb_range
350         .ifnb \flags_smp
351                 ALT_SMP(.long   \flags_smp )
352                 ALT_UP(.long    \flags_up )
353         .else
354                 .long   \flags_up
355         .endif
356         .size   \name\()_tlb_fns, . - \name\()_tlb_fns
357 .endm
358
359 .macro globl_equ x, y
360         .globl  \x
361         .equ    \x, \y
362 .endm
363
364 .macro  initfn, func, base
365         .long   \func - \base
366 .endm
367
368         /*
369          * Macro to calculate the log2 size for the protection region
370          * registers. This calculates rd = log2(size) - 1.  tmp must
371          * not be the same register as rd.
372          */
373 .macro  pr_sz, rd, size, tmp
374         mov     \tmp, \size, lsr #12
375         mov     \rd, #11
376 1:      movs    \tmp, \tmp, lsr #1
377         addne   \rd, \rd, #1
378         bne     1b
379 .endm
380
381         /*
382          * Macro to generate a protection region register value
383          * given a pre-masked address, size, and enable bit.
384          * Corrupts size.
385          */
386 .macro  pr_val, dest, addr, size, enable
387         pr_sz   \dest, \size, \size             @ calculate log2(size) - 1
388         orr     \dest, \addr, \dest, lsl #1     @ mask in the region size
389         orr     \dest, \dest, \enable
390 .endm