summaryrefslogtreecommitdiff
path: root/arch/arm/mm/proc-v7-3level.S
blob: 2d0f4905fabef302ed114af7511504efe135f633 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/*
 * arch/arm/mm/proc-v7-3level.S
 *
 * Copyright (C) 2001 Deep Blue Solutions Ltd.
 * Copyright (C) 2011 ARM Ltd.
 * Author: Catalin Marinas <catalin.marinas@arm.com>
 *   based on arch/arm/mm/proc-v7-2level.S
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#define TTB_IRGN_NC	(0 << 8)
#define TTB_IRGN_WBWA	(1 << 8)
#define TTB_IRGN_WT	(2 << 8)
#define TTB_IRGN_WB	(3 << 8)
#define TTB_RGN_NC	(0 << 10)
#define TTB_RGN_OC_WBWA	(1 << 10)
#define TTB_RGN_OC_WT	(2 << 10)
#define TTB_RGN_OC_WB	(3 << 10)
#define TTB_S		(3 << 12)
#define TTB_EAE		(1 << 31)

/* PTWs cacheable, inner WB not shareable, outer WB not shareable */
#define TTB_FLAGS_UP	(TTB_IRGN_WB|TTB_RGN_OC_WB)
#define PMD_FLAGS_UP	(PMD_SECT_WB)

/* PTWs cacheable, inner WBWA shareable, outer WBWA not shareable */
#define TTB_FLAGS_SMP	(TTB_IRGN_WBWA|TTB_S|TTB_RGN_OC_WBWA)
#define PMD_FLAGS_SMP	(PMD_SECT_WBWA|PMD_SECT_S)


/* 
 * alternate versions of these two functions came from the omap5
 * patchset...since v3.1 their definition migrated here and to -2stage
 * archived them defaulting to keeping mainline versions
 */

#define MAINLINE_V7_FUNCS

#ifdef MAINLINE_V7_FUNCS 

/*                                                                              
 * cpu_v7_switch_mm(pgd_phys, tsk)                                              
 *                                                                              
 * Set the translation table base pointer to be pgd_phys (physical address of   
 * the new TTB).                                                                
 */                                                                             
ENTRY(cpu_v7_switch_mm)                                                         
#ifdef CONFIG_MMU                                                               
        ldr     r1, [r1, #MM_CONTEXT_ID]        @ get mm->context.id            
        and     r3, r1, #0xff                                                   
        mov     r3, r3, lsl #(48 - 32)          @ ASID                          
        mcrr    p15, 0, r0, r3, c2              @ set TTB 0                     
        isb                                                                     
#endif                                                                          
        mov     pc, lr                                                          
ENDPROC(cpu_v7_switch_mm)
#else

/*                                                                              
 *      cpu_v7_switch_mm(pgd_phys, tsk)                                         
 *                                                                              
 *      Set the translation table base pointer to be pgd_phys                   
 *                                                                              
 *      - pgd_phys - physical address of new TTB                                
 *                                                                              
 *      It is assumed that:                                                     
 *      - we are not using split page tables                                    
 */                                                                             
ENTRY(cpu_v7_switch_mm)                                                         
#ifdef CONFIG_MMU                                                               
        mov     r2, #0                                                          
        ldr     r1, [r1, #MM_CONTEXT_ID]        @ get mm->context.id            
        ALT_SMP(orr     r0, r0, #TTB_FLAGS_SMP)                                 
        ALT_UP(orr      r0, r0, #TTB_FLAGS_UP)                                  
#ifdef CONFIG_ARM_ERRATA_430973                                                 
        mcr     p15, 0, r2, c7, c5, 6           @ flush BTAC/BTB                
#endif                                                                          
        mrc     p15, 0, r2, c2, c0, 1           @ load TTB 1                    
        mcr     p15, 0, r2, c2, c0, 0           @ into TTB 0                    
        isb                                                                     
#ifdef CONFIG_ARM_ERRATA_754322                                                 
        dsb                                                                     
#endif                                                                          
        mcr     p15, 0, r1, c13, c0, 1          @ set context ID                
        isb                                                                     
        mcr     p15, 0, r0, c2, c0, 0           @ set TTB 0                     
        isb                                                                     
#endif                                                                          
        mov     pc, lr                                                          
ENDPROC(cpu_v7_switch_mm) 
#endif

#ifdef MAINLINE_V7_FUNCS
/*
 * cpu_v7_set_pte_ext(ptep, pte)
 *
 * Set a level 2 translation table entry.
 * - ptep - pointer to level 3 translation table entry
 * - pte - PTE value to store (64-bit in r2 and r3)
 */
ENTRY(cpu_v7_set_pte_ext)
#ifdef CONFIG_MMU
	tst	r2, #L_PTE_PRESENT
	beq	1f
	tst	r3, #1 << (55 - 32)		@ L_PTE_DIRTY
	orreq	r2, #L_PTE_RDONLY
1:	strd	r2, r3, [r0]
	mcr	p15, 0, r0, c7, c10, 1		@ flush_pte
#endif
	mov	pc, lr
ENDPROC(cpu_v7_set_pte_ext)
#else

/*                                                                              
 *      cpu_v7_set_pte_ext(ptep, pte)                                           
 *                                                                              
 *      Set a level 2 translation table entry.                                  
 *                                                                              
 *      - ptep  - pointer to level 2 translation table entry                    
 *                (hardware version is stored at +2048 bytes)                   
 *      - pte   - PTE value to store                                            
 *      - ext   - value for extended PTE bits                                   
 */                                                                             
ENTRY(cpu_v7_set_pte_ext)                                                       
#ifdef CONFIG_MMU                                                               
        str     r1, [r0]                        @ linux version                 
                                                                                
        bic     r3, r1, #0x000003f0                                             
        bic     r3, r3, #PTE_TYPE_MASK                                          
        orr     r3, r3, r2                                                      
        orr     r3, r3, #PTE_EXT_AP0 | 2                                        
                                                                                
        tst     r1, #1 << 4                                                     
        orrne   r3, r3, #PTE_EXT_TEX(1)                                         
                                                                                
        eor     r1, r1, #L_PTE_DIRTY                                            
        tst     r1, #L_PTE_RDONLY | L_PTE_DIRTY                                 
        orrne   r3, r3, #PTE_EXT_APX                                            
                                                                                
        tst     r1, #L_PTE_USER                                                 
        orrne   r3, r3, #PTE_EXT_AP1                                            
#ifdef CONFIG_CPU_USE_DOMAINS                                                   
        @ allow kernel read/write access to read-only user pages                
        tstne   r3, #PTE_EXT_APX                                                
        bicne   r3, r3, #PTE_EXT_APX | PTE_EXT_AP0                              
#endif                                                                          
                                                                                
        tst     r1, #L_PTE_XN                                                   
        orrne   r3, r3, #PTE_EXT_XN                                             
                                                                                
        tst     r1, #L_PTE_YOUNG                                                
        tstne   r1, #L_PTE_PRESENT                                              
        moveq   r3, #0                                                          
                                                                                
 ARM(   str     r3, [r0, #2048]! )                                              
 THUMB( add     r0, r0, #2048 )                                                 
 THUMB( str     r3, [r0] )                                                      
        mcr     p15, 0, r0, c7, c10, 1          @ flush_pte                     
#endif                                                                          
        mov     pc, lr                                                          
ENDPROC(cpu_v7_set_pte_ext)
#endif

	/*
	 * Memory region attributes for LPAE (defined in pgtable-3level.h):
	 *
	 *   n = AttrIndx[2:0]
	 *
	 *			n	MAIR
	 *   UNCACHED		000	00000000
	 *   BUFFERABLE		001	01000100
	 *   DEV_WC		001	01000100
	 *   WRITETHROUGH	010	10101010
	 *   WRITEBACK		011	11101110
	 *   DEV_CACHED		011	11101110
	 *   DEV_SHARED		100	00000100
	 *   DEV_NONSHARED	100	00000100
	 *   unused		101
	 *   unused		110
	 *   WRITEALLOC		111	11111111
	 */
.equ	PRRR,	0xeeaa4400			@ MAIR0
.equ	NMRR,	0xff000004			@ MAIR1

	/*
	 * Macro for setting up the TTBRx and TTBCR registers.
	 * - \ttbr1 updated.
	 */
	.macro	v7_ttb_setup, zero, ttbr0, ttbr1, tmp
	ldr	\tmp, =swapper_pg_dir		@ swapper_pg_dir virtual address
	cmp	\ttbr1, \tmp			@ PHYS_OFFSET > PAGE_OFFSET? (branch below)
	mrc	p15, 0, \tmp, c2, c0, 2		@ TTB control register
	orr	\tmp, \tmp, #TTB_EAE
	ALT_SMP(orr	\tmp, \tmp, #TTB_FLAGS_SMP)
	ALT_UP(orr	\tmp, \tmp, #TTB_FLAGS_UP)
	ALT_SMP(orr	\tmp, \tmp, #TTB_FLAGS_SMP << 16)
	ALT_UP(orr	\tmp, \tmp, #TTB_FLAGS_UP << 16)
	/*
	 * TTBR0/TTBR1 split (PAGE_OFFSET):
	 *   0x40000000: T0SZ = 2, T1SZ = 0 (not used)
	 *   0x80000000: T0SZ = 0, T1SZ = 1
	 *   0xc0000000: T0SZ = 0, T1SZ = 2
	 *
	 * Only use this feature if PHYS_OFFSET <= PAGE_OFFSET, otherwise
	 * booting secondary CPUs would end up using TTBR1 for the identity
	 * mapping set up in TTBR0.
	 */
	bhi	9001f				@ PHYS_OFFSET > PAGE_OFFSET?
	orr	\tmp, \tmp, #(((PAGE_OFFSET >> 30) - 1) << 16) @ TTBCR.T1SZ
#if defined CONFIG_VMSPLIT_2G
	/* PAGE_OFFSET == 0x80000000, T1SZ == 1 */
	add	\ttbr1, \ttbr1, #1 << 4		@ skip two L1 entries
#elif defined CONFIG_VMSPLIT_3G
	/* PAGE_OFFSET == 0xc0000000, T1SZ == 2 */
	add	\ttbr1, \ttbr1, #4096 * (1 + 3)	@ only L2 used, skip pgd+3*pmd
#endif
	/* CONFIG_VMSPLIT_1G does not need TTBR1 adjustment */
9001:	mcr	p15, 0, \tmp, c2, c0, 2		@ TTB control register
	mcrr	p15, 1, \ttbr1, \zero, c2	@ load TTBR1
	.endm

	__CPUINIT

	/*
	 *   AT
	 *  TFR   EV X F   IHD LR    S
	 * .EEE ..EE PUI. .TAT 4RVI ZWRS BLDP WCAM
	 * rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced
	 *   11    0 110    1  0011 1100 .111 1101 < we want
	 */
	.align	2
	.type	v7_crval, #object
v7_crval:
	crval	clear=0x0120c302, mmuset=0x30c23c7d, ucset=0x00c01c7c

	.previous