First version
[3rdparty/ote_partner/tlk.git] / arch / arm / include / arch / arm / mmu_ldesc_macros.h
1 /*
2  * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 #include <config.h>
24 #include <arch/arm/mmu_ldesc.h>
25
26 #define MMU_PTE_L2_BLOCK_MMIO_FLAGS     \
27         (MMU_MEMORY_SET_ATTR_IDX(MMU_MEMORY_STRONGLY_ORDERED) | \
28          MMU_MEMORY_ACCESS_FLAG |       \
29          MMU_MEMORY_AP_P_RW_U_NA | 0x1)
30
31 #define MMU_PTE_L2_BLOCK_KERN_FLAGS     \
32         (MMU_MEMORY_SET_ATTR_IDX(MMU_MEMORY_WB_OUTER_NO_ALLOC_INNER_ALLOC) | \
33          MMU_MEMORY_ACCESS_FLAG |       \
34          MMU_MEMORY_AP_P_RW_U_NA | 0x1)
35
36 #define MMU_PTE_L3_KERN_FLAGS   \
37         (MMU_MEMORY_SET_ATTR_IDX(MMU_MEMORY_WB_OUTER_NO_ALLOC_INNER_ALLOC) | \
38          MMU_MEMORY_ACCESS_FLAG |       \
39          MMU_MEMORY_AP_P_RW_U_NA | 0x3)
40
41 #define MMU_TTBCR_FLAGS         \
42         (MMU_MEMORY_TTBCR_EAE | MMU_MEMORY_TTBCR_A1 | \
43          MMU_MEMORY_TTBCR_OUTER_RGN1(MMU_MEMORY_RGN_WRITE_BACK_ALLOCATE) | \
44          MMU_MEMORY_TTBCR_OUTER_RGN0(MMU_MEMORY_RGN_WRITE_BACK_ALLOCATE) | \
45          MMU_MEMORY_TTBCR_INNER_RGN1(MMU_MEMORY_RGN_WRITE_BACK_ALLOCATE) | \
46          MMU_MEMORY_TTBCR_INNER_RGN0(MMU_MEMORY_RGN_WRITE_BACK_ALLOCATE) | \
47          MMU_MEMORY_TTBCR_T1SZ | MMU_MEMORY_TTBCR_T0SZ)
48
49 /* loads 32-bit value into a register */
50 .macro mov32, reg, val
51         movw    \reg, #:lower16:\val
52         movt    \reg, #:upper16:\val
53 .endm
54
55 /* size/align check of carveout */
56 .macro mmu_desc_phy_align, base, size, tmp
57         mov32   \tmp, (MMU_L2_BLOCK_SIZE - 1)
58         tst     \base, \tmp
59         bne     .               @ base not aligned
60         cmp     \size, #0
61         beq     .               @ size is zero
62         tst     \size, \tmp
63         bne     .               @ size not aligned
64 .endm
65
66 /* create NULL 2MB entry to guarantee a NULL ptr fault */
67 .macro mmu_desc_create_null_entry, pt, tmp
68         mov     \tmp, #0
69         str     \tmp, [\pt], #4
70         str     \tmp, [\pt], #4         @ write PTE and upper 0
71 .endm
72
73 /* create identity 2MB entries for MMIO */
74 .macro mmu_desc_create_ident_mapping, pt, pte, idx, zero
75         /* create second level identity entries */
76         mov32   \pte, MMU_PTE_L2_BLOCK_MMIO_FLAGS
77         mov     \idx, #1
78         mov     \zero, #0
79 1:
80         add     \pte, \pte, #(1 << MMU_L2_BLOCK_SHIFT)
81         stmia   \pt!, {\pte, \zero}     @ write PTE and upper 0
82         add     \idx, #1
83         cmp     \idx, #0x800            @ # of 2MB mappings in 32bit VA
84         blt     1b
85 .endm
86
87 /* map phys carveout with L3 entries */
88 .macro mmu_desc_map_phys_l3, virt, phys, len, pt, l2, tmp, tmp2, zero
89         /* setup L2 entries */
90         mov32   \tmp, ((1 << MMU_L3_MAP_SHIFT) - 1)
91         add     \tmp2, \len, \tmp
92         lsr     \tmp2, \tmp2, #MMU_L3_MAP_SHIFT                 @ roundup to L3 map size
93         lsl     \tmp2, \tmp2, #MMU_L3_SIZE_SHIFT                @ bytes of L3 tables
94         lsr     \tmp2, \tmp2, #MMU_MEMORY_TTBR_L3_VADDR_SHIFT   @ # of L2 entries
95
96         lsr     \tmp, \virt, #MMU_MEMORY_TTBR_L2_VADDR_SHIFT
97         add     \l2, \tmp, lsl #MMU_ENTRY_SHIFT         @ starting L2 entry
98         orr     \tmp, \pt, #0x3
99 2:
100         stmia   \l2!, {\tmp, \zero}             @ write PTE for level 3
101         add     \tmp, \tmp, #(1 << MMU_MEMORY_TTBR_L3_VADDR_SHIFT)
102         subs    \tmp2, \tmp2, #0x1
103         bne     2b
104
105         /* setup L3 entries */
106         mov32   \tmp, MMU_PTE_L3_KERN_FLAGS
107         add     \phys, \phys, \tmp                      @ setup PTE
108         lsr     \virt, \virt, #MMU_MEMORY_TTBR_L3_VADDR_SHIFT
109         mov32   \tmp2, MMU_MEMORY_TTBR_L3_INDEX_MASK
110         and     \virt, \virt, \tmp2
111         add     \pt, \virt, lsl #MMU_ENTRY_SHIFT        @ starting PT entry
112         mov32   \tmp2, (1 << MMU_MEMORY_TTBR_L3_VADDR_SHIFT)
113         mov     \tmp, \len
114 3:
115         stmia   \pt!, {\phys, \zero}                    @ write PTE and upper 0
116         add     \phys, \phys, \tmp2
117         subs    \tmp, \tmp, #(1 << MMU_MEMORY_TTBR_L3_VADDR_SHIFT)
118         bne     3b
119
120         /* clear what remains of the page */
121         mov32   \tmp, (MMU_MEMORY_TTBR_L3_SIZE - 1)
122         ands    \tmp, \pt, \tmp
123         beq     5f                              @ done, ended on a page
124
125         mov32   \tmp2, MMU_MEMORY_TTBR_L3_SIZE
126         sub     \tmp, \tmp2, \tmp               @ bytes until end of page
127         mov     \tmp2, \zero
128 4:
129         stmia   \pt!, {\tmp2, \zero}            @ write PTE and upper 0
130         subs    \tmp, \tmp, #(1 << MMU_ENTRY_SHIFT)
131         bne     4b
132 5:
133 .endm
134
135 /* map phys carveout with L2 block entries */
136 .macro mmu_desc_map_phys_l2, virt, phys, len, pt, tmp
137         mov32   \tmp, MMU_PTE_L2_BLOCK_KERN_FLAGS
138         add     \phys, \phys, \tmp
139         lsr     \virt, \virt, #(MMU_L2_BLOCK_SHIFT - MMU_ENTRY_SHIFT)
140         add     \pt, \pt, \virt
141         add     \len, \phys, \len
142         mov     \tmp, #0
143 1:
144         stmia   \pt!, {\phys, \tmp}     @ write PTE and upper 0
145         add     \phys, \phys, #(1 << MMU_L2_BLOCK_SHIFT)
146         cmp     \phys, \len
147         bne     1b
148 .endm
149
150 /* map phys carveout in L1 */
151 .macro mmu_desc_map_phys_l1, phys, pt, zero
152         orr     \phys, \phys, #0x3
153         /* write first level entries (with the 4 parts of the main tt) */
154         stmia   \pt!, {\phys, \zero}            @ index 0
155         add     \phys, \phys, #(1 << 12)
156         stmia   \pt!, {\phys, \zero}            @ index 1
157         add     \phys, \phys, #(1 << 12)
158         stmia   \pt!, {\phys, \zero}            @ index 2
159         add     \phys, \phys, #(1 << 12)
160         stmia   \pt!, {\phys, \zero}            @ index 3
161 .endm
162
163 /* init MMU registers and enable */
164 .macro mmu_desc_init_mmu, pt1, pt2, tmp
165         /* init kernel referenced mem attribs */
166         mov32   \tmp, MMU_MEMORY_ATTR_INDIR_0
167         mcr     p15, 0, \tmp, c10, c2, 0        @ MAIR0
168         mov32   \tmp, MMU_MEMORY_ATTR_INDIR_1
169         mcr     p15, 0, \tmp, c10, c2, 1        @ MAIR1
170
171         mov32   \tmp, MMU_TTBCR_FLAGS
172         mcr     p15, 0, \tmp, c2, c0, 2         @ TTBCR
173
174         mov     \tmp, #0
175         mcrr    p15, 1, \pt1, \tmp, c2          @ TTBR1 64bit write (tmp | pt1)
176
177         mrc     p15, 0, \tmp, c1, c0, 0
178         orr     \tmp, \tmp, #1
179         mcr     p15, 0, \tmp, c1, c0, 0         @ SCTLR
180 .endm
181
182 .macro mmu_desc_switch_pt, new, asid, tmp, tmp2
183         /*
184          * This is a thread that's part of a task, so switch the setup
185          * user mode context (i.e. make sure the user mode pagetables
186          * are loaded and update the VFP state).
187          *
188          * When switching user-mode translation tables we need to be sure that
189          * no pages are prefetched from the outgoing table.  To do this we
190          * we must first switch to the global translation table (ttbr1)
191          * using the following sequence:
192          *
193          *   1- switch ttbr0 to global translation table ttbr1
194          *   2- ISB
195          *   4- DSB
196          *   5- switch ttbr0 to new translation table for this thread
197          */
198         mrrc    p15, 1, \tmp, \tmp2, c2         @ get ttbr1
199         mcrr    p15, 0, \tmp, \tmp2, c2         @ load into ttbr0
200         isb
201         dsb                                     @ ARM_ERRATA_754322
202         lsl     \asid, \asid, #16               @ asid is bits[55:48]
203         mcrr    p15, 0, \new, \asid, c2         @ load into ttbr0
204 .endm
205
206 #define MMU_DESC_CONTEXT_INTS   7
207
208 /* save MMU context */
209 .macro mmu_desc_save_context, base, tmp, tmp2
210         mrc     p15, 0, \tmp, c10, c2, 0        @ MAIR0
211         str     \tmp, [\base], #4
212         mrc     p15, 0, \tmp, c10, c2, 1        @ MAIR1
213         str     \tmp, [\base], #4
214         mrc     p15, 0, \tmp, c2, c0, 2         @ TTBCR
215         str     \tmp, [\base], #4
216         mrrc    p15, 0, \tmp, \tmp2, c2         @ TTBR0 64bit
217         str     \tmp, [\base], #4
218         str     \tmp2, [\base], #4
219         mrrc    p15, 1, \tmp, \tmp2, c2         @ TTBR1 64bit
220         str     \tmp, [\base], #4
221         str     \tmp2, [\base], #4
222 .endm
223
224 /* restore MMU context */
225 .macro mmu_desc_restore_context, base, tmp, tmp2
226         ldr     \tmp, [\base], #4
227         mcr     p15, 0, \tmp, c10, c2, 0        @ MAIR0
228         ldr     \tmp, [\base], #4
229         mcr     p15, 0, \tmp, c10, c2, 1        @ MAIR1
230         ldr     \tmp, [\base], #4
231         mcr     p15, 0, \tmp, c2, c0, 2         @ TTBCR
232         ldr     \tmp, [\base], #4
233         ldr     \tmp2, [\base], #4
234         mcrr    p15, 0, \tmp, \tmp2, c2         @ TTBR0 64bit
235         ldr     \tmp, [\base], #4
236         ldr     \tmp2, [\base], #4
237         mcrr    p15, 1, \tmp, \tmp2, c2         @ TTBR1 64bit
238 .endm