aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/mmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mm/mmu.c')
-rw-r--r--arch/arm/mm/mmu.c74
1 files changed, 42 insertions, 32 deletions
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index e7af83e569d7..8ba754064559 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -66,27 +66,27 @@ static struct cachepolicy cache_policies[] __initdata = {
66 .policy = "uncached", 66 .policy = "uncached",
67 .cr_mask = CR_W|CR_C, 67 .cr_mask = CR_W|CR_C,
68 .pmd = PMD_SECT_UNCACHED, 68 .pmd = PMD_SECT_UNCACHED,
69 .pte = 0, 69 .pte = L_PTE_MT_UNCACHED,
70 }, { 70 }, {
71 .policy = "buffered", 71 .policy = "buffered",
72 .cr_mask = CR_C, 72 .cr_mask = CR_C,
73 .pmd = PMD_SECT_BUFFERED, 73 .pmd = PMD_SECT_BUFFERED,
74 .pte = PTE_BUFFERABLE, 74 .pte = L_PTE_MT_BUFFERABLE,
75 }, { 75 }, {
76 .policy = "writethrough", 76 .policy = "writethrough",
77 .cr_mask = 0, 77 .cr_mask = 0,
78 .pmd = PMD_SECT_WT, 78 .pmd = PMD_SECT_WT,
79 .pte = PTE_CACHEABLE, 79 .pte = L_PTE_MT_WRITETHROUGH,
80 }, { 80 }, {
81 .policy = "writeback", 81 .policy = "writeback",
82 .cr_mask = 0, 82 .cr_mask = 0,
83 .pmd = PMD_SECT_WB, 83 .pmd = PMD_SECT_WB,
84 .pte = PTE_BUFFERABLE|PTE_CACHEABLE, 84 .pte = L_PTE_MT_WRITEBACK,
85 }, { 85 }, {
86 .policy = "writealloc", 86 .policy = "writealloc",
87 .cr_mask = 0, 87 .cr_mask = 0,
88 .pmd = PMD_SECT_WBWA, 88 .pmd = PMD_SECT_WBWA,
89 .pte = PTE_BUFFERABLE|PTE_CACHEABLE, 89 .pte = L_PTE_MT_WRITEALLOC,
90 } 90 }
91}; 91};
92 92
@@ -184,29 +184,28 @@ void adjust_cr(unsigned long mask, unsigned long set)
184 184
185static struct mem_type mem_types[] = { 185static struct mem_type mem_types[] = {
186 [MT_DEVICE] = { /* Strongly ordered / ARMv6 shared device */ 186 [MT_DEVICE] = { /* Strongly ordered / ARMv6 shared device */
187 .prot_pte = PROT_PTE_DEVICE, 187 .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED |
188 L_PTE_SHARED,
188 .prot_l1 = PMD_TYPE_TABLE, 189 .prot_l1 = PMD_TYPE_TABLE,
189 .prot_sect = PROT_SECT_DEVICE | PMD_SECT_UNCACHED, 190 .prot_sect = PROT_SECT_DEVICE | PMD_SECT_UNCACHED,
190 .domain = DOMAIN_IO, 191 .domain = DOMAIN_IO,
191 }, 192 },
192 [MT_DEVICE_NONSHARED] = { /* ARMv6 non-shared device */ 193 [MT_DEVICE_NONSHARED] = { /* ARMv6 non-shared device */
193 .prot_pte = PROT_PTE_DEVICE, 194 .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_NONSHARED,
194 .prot_pte_ext = PTE_EXT_TEX(2),
195 .prot_l1 = PMD_TYPE_TABLE, 195 .prot_l1 = PMD_TYPE_TABLE,
196 .prot_sect = PROT_SECT_DEVICE | PMD_SECT_TEX(2), 196 .prot_sect = PROT_SECT_DEVICE | PMD_SECT_TEX(2),
197 .domain = DOMAIN_IO, 197 .domain = DOMAIN_IO,
198 }, 198 },
199 [MT_DEVICE_CACHED] = { /* ioremap_cached */ 199 [MT_DEVICE_CACHED] = { /* ioremap_cached */
200 .prot_pte = PROT_PTE_DEVICE | L_PTE_CACHEABLE | L_PTE_BUFFERABLE, 200 .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_CACHED,
201 .prot_l1 = PMD_TYPE_TABLE, 201 .prot_l1 = PMD_TYPE_TABLE,
202 .prot_sect = PROT_SECT_DEVICE | PMD_SECT_WB, 202 .prot_sect = PROT_SECT_DEVICE | PMD_SECT_WB,
203 .domain = DOMAIN_IO, 203 .domain = DOMAIN_IO,
204 }, 204 },
205 [MT_DEVICE_IXP2000] = { /* IXP2400 requires XCB=101 for on-chip I/O */ 205 [MT_DEVICE_WC] = { /* ioremap_wc */
206 .prot_pte = PROT_PTE_DEVICE, 206 .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_WC,
207 .prot_l1 = PMD_TYPE_TABLE, 207 .prot_l1 = PMD_TYPE_TABLE,
208 .prot_sect = PROT_SECT_DEVICE | PMD_SECT_BUFFERABLE | 208 .prot_sect = PROT_SECT_DEVICE | PMD_SECT_BUFFERABLE,
209 PMD_SECT_TEX(1),
210 .domain = DOMAIN_IO, 209 .domain = DOMAIN_IO,
211 }, 210 },
212 [MT_CACHECLEAN] = { 211 [MT_CACHECLEAN] = {
@@ -251,7 +250,7 @@ static void __init build_mem_type_table(void)
251{ 250{
252 struct cachepolicy *cp; 251 struct cachepolicy *cp;
253 unsigned int cr = get_cr(); 252 unsigned int cr = get_cr();
254 unsigned int user_pgprot, kern_pgprot; 253 unsigned int user_pgprot, kern_pgprot, vecs_pgprot;
255 int cpu_arch = cpu_architecture(); 254 int cpu_arch = cpu_architecture();
256 int i; 255 int i;
257 256
@@ -269,6 +268,20 @@ static void __init build_mem_type_table(void)
269 cachepolicy = CPOLICY_WRITEBACK; 268 cachepolicy = CPOLICY_WRITEBACK;
270 ecc_mask = 0; 269 ecc_mask = 0;
271 } 270 }
271#ifdef CONFIG_SMP
272 cachepolicy = CPOLICY_WRITEALLOC;
273#endif
274
275 /*
276 * On non-Xscale3 ARMv5-and-older systems, use CB=01
277 * (Uncached/Buffered) for ioremap_wc() mappings. On XScale3
278 * and ARMv6+, use TEXCB=00100 mappings (Inner/Outer Uncacheable
279 * in xsc3 parlance, Uncached Normal in ARMv6 parlance).
280 */
281 if (cpu_is_xsc3() || cpu_arch >= CPU_ARCH_ARMv6) {
282 mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_TEX(1);
283 mem_types[MT_DEVICE_WC].prot_sect &= ~PMD_SECT_BUFFERABLE;
284 }
272 285
273 /* 286 /*
274 * ARMv5 and lower, bit 4 must be set for page tables. 287 * ARMv5 and lower, bit 4 must be set for page tables.
@@ -290,7 +303,15 @@ static void __init build_mem_type_table(void)
290 } 303 }
291 304
292 cp = &cache_policies[cachepolicy]; 305 cp = &cache_policies[cachepolicy];
293 kern_pgprot = user_pgprot = cp->pte; 306 vecs_pgprot = kern_pgprot = user_pgprot = cp->pte;
307
308#ifndef CONFIG_SMP
309 /*
310 * Only use write-through for non-SMP systems
311 */
312 if (cpu_arch >= CPU_ARCH_ARMv5 && cachepolicy > CPOLICY_WRITETHROUGH)
313 vecs_pgprot = cache_policies[CPOLICY_WRITETHROUGH].pte;
314#endif
294 315
295 /* 316 /*
296 * Enable CPU-specific coherency if supported. 317 * Enable CPU-specific coherency if supported.
@@ -318,7 +339,6 @@ static void __init build_mem_type_table(void)
318 /* 339 /*
319 * Mark the device area as "shared device" 340 * Mark the device area as "shared device"
320 */ 341 */
321 mem_types[MT_DEVICE].prot_pte |= L_PTE_BUFFERABLE;
322 mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED; 342 mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
323 343
324#ifdef CONFIG_SMP 344#ifdef CONFIG_SMP
@@ -327,30 +347,21 @@ static void __init build_mem_type_table(void)
327 */ 347 */
328 user_pgprot |= L_PTE_SHARED; 348 user_pgprot |= L_PTE_SHARED;
329 kern_pgprot |= L_PTE_SHARED; 349 kern_pgprot |= L_PTE_SHARED;
350 vecs_pgprot |= L_PTE_SHARED;
330 mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; 351 mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
331#endif 352#endif
332 } 353 }
333 354
334 for (i = 0; i < 16; i++) { 355 for (i = 0; i < 16; i++) {
335 unsigned long v = pgprot_val(protection_map[i]); 356 unsigned long v = pgprot_val(protection_map[i]);
336 v = (v & ~(L_PTE_BUFFERABLE|L_PTE_CACHEABLE)) | user_pgprot; 357 protection_map[i] = __pgprot(v | user_pgprot);
337 protection_map[i] = __pgprot(v);
338 } 358 }
339 359
340 mem_types[MT_LOW_VECTORS].prot_pte |= kern_pgprot; 360 mem_types[MT_LOW_VECTORS].prot_pte |= vecs_pgprot;
341 mem_types[MT_HIGH_VECTORS].prot_pte |= kern_pgprot; 361 mem_types[MT_HIGH_VECTORS].prot_pte |= vecs_pgprot;
342 362
343 if (cpu_arch >= CPU_ARCH_ARMv5) { 363 if (cpu_arch < CPU_ARCH_ARMv5)
344#ifndef CONFIG_SMP
345 /*
346 * Only use write-through for non-SMP systems
347 */
348 mem_types[MT_LOW_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE;
349 mem_types[MT_HIGH_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE;
350#endif
351 } else {
352 mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1); 364 mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1);
353 }
354 365
355 pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot); 366 pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot);
356 pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | 367 pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
@@ -398,8 +409,7 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
398 409
399 pte = pte_offset_kernel(pmd, addr); 410 pte = pte_offset_kernel(pmd, addr);
400 do { 411 do {
401 set_pte_ext(pte, pfn_pte(pfn, __pgprot(type->prot_pte)), 412 set_pte_ext(pte, pfn_pte(pfn, __pgprot(type->prot_pte)), 0);
402 type->prot_pte_ext);
403 pfn++; 413 pfn++;
404 } while (pte++, addr += PAGE_SIZE, addr != end); 414 } while (pte++, addr += PAGE_SIZE, addr != end);
405} 415}