diff options
Diffstat (limited to 'arch/arm/mm/mm-armv.c')
-rw-r--r-- | arch/arm/mm/mm-armv.c | 48 |
1 files changed, 32 insertions, 16 deletions
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index fb5b40289de2..9e50127be635 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c | |||
@@ -354,7 +354,7 @@ void __init build_mem_type_table(void) | |||
354 | { | 354 | { |
355 | struct cachepolicy *cp; | 355 | struct cachepolicy *cp; |
356 | unsigned int cr = get_cr(); | 356 | unsigned int cr = get_cr(); |
357 | unsigned int user_pgprot; | 357 | unsigned int user_pgprot, kern_pgprot; |
358 | int cpu_arch = cpu_architecture(); | 358 | int cpu_arch = cpu_architecture(); |
359 | int i; | 359 | int i; |
360 | 360 | ||
@@ -381,7 +381,7 @@ void __init build_mem_type_table(void) | |||
381 | } | 381 | } |
382 | 382 | ||
383 | cp = &cache_policies[cachepolicy]; | 383 | cp = &cache_policies[cachepolicy]; |
384 | user_pgprot = cp->pte; | 384 | kern_pgprot = user_pgprot = cp->pte; |
385 | 385 | ||
386 | /* | 386 | /* |
387 | * ARMv6 and above have extended page tables. | 387 | * ARMv6 and above have extended page tables. |
@@ -393,6 +393,7 @@ void __init build_mem_type_table(void) | |||
393 | */ | 393 | */ |
394 | mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4; | 394 | mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4; |
395 | mem_types[MT_ROM].prot_sect &= ~PMD_BIT4; | 395 | mem_types[MT_ROM].prot_sect &= ~PMD_BIT4; |
396 | |||
396 | /* | 397 | /* |
397 | * Mark cache clean areas and XIP ROM read only | 398 | * Mark cache clean areas and XIP ROM read only |
398 | * from SVC mode and no access from userspace. | 399 | * from SVC mode and no access from userspace. |
@@ -412,32 +413,47 @@ void __init build_mem_type_table(void) | |||
412 | * (iow, non-global) | 413 | * (iow, non-global) |
413 | */ | 414 | */ |
414 | user_pgprot |= L_PTE_ASID; | 415 | user_pgprot |= L_PTE_ASID; |
416 | |||
417 | #ifdef CONFIG_SMP | ||
418 | /* | ||
419 | * Mark memory with the "shared" attribute for SMP systems | ||
420 | */ | ||
421 | user_pgprot |= L_PTE_SHARED; | ||
422 | kern_pgprot |= L_PTE_SHARED; | ||
423 | mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; | ||
424 | #endif | ||
415 | } | 425 | } |
416 | 426 | ||
427 | for (i = 0; i < 16; i++) { | ||
428 | unsigned long v = pgprot_val(protection_map[i]); | ||
429 | v = (v & ~(L_PTE_BUFFERABLE|L_PTE_CACHEABLE)) | user_pgprot; | ||
430 | protection_map[i] = __pgprot(v); | ||
431 | } | ||
432 | |||
433 | mem_types[MT_LOW_VECTORS].prot_pte |= kern_pgprot; | ||
434 | mem_types[MT_HIGH_VECTORS].prot_pte |= kern_pgprot; | ||
435 | |||
417 | if (cpu_arch >= CPU_ARCH_ARMv5) { | 436 | if (cpu_arch >= CPU_ARCH_ARMv5) { |
418 | mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; | 437 | #ifndef CONFIG_SMP |
419 | mem_types[MT_HIGH_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; | 438 | /* |
439 | * Only use write-through for non-SMP systems | ||
440 | */ | ||
441 | mem_types[MT_LOW_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE; | ||
442 | mem_types[MT_HIGH_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE; | ||
443 | #endif | ||
420 | } else { | 444 | } else { |
421 | mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte; | ||
422 | mem_types[MT_HIGH_VECTORS].prot_pte |= cp->pte; | ||
423 | mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1); | 445 | mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1); |
424 | } | 446 | } |
425 | 447 | ||
448 | pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | | ||
449 | L_PTE_DIRTY | L_PTE_WRITE | | ||
450 | L_PTE_EXEC | kern_pgprot); | ||
451 | |||
426 | mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; | 452 | mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; |
427 | mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; | 453 | mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; |
428 | mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd; | 454 | mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd; |
429 | mem_types[MT_ROM].prot_sect |= cp->pmd; | 455 | mem_types[MT_ROM].prot_sect |= cp->pmd; |
430 | 456 | ||
431 | for (i = 0; i < 16; i++) { | ||
432 | unsigned long v = pgprot_val(protection_map[i]); | ||
433 | v = (v & ~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot; | ||
434 | protection_map[i] = __pgprot(v); | ||
435 | } | ||
436 | |||
437 | pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | | ||
438 | L_PTE_DIRTY | L_PTE_WRITE | | ||
439 | L_PTE_EXEC | cp->pte); | ||
440 | |||
441 | switch (cp->pmd) { | 457 | switch (cp->pmd) { |
442 | case PMD_SECT_WT: | 458 | case PMD_SECT_WT: |
443 | mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT; | 459 | mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT; |