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