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.c62
1 files changed, 13 insertions, 49 deletions
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 79c01f540cbe..3c67e92f7d59 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -63,7 +63,7 @@ struct cachepolicy {
63 const char policy[16]; 63 const char policy[16];
64 unsigned int cr_mask; 64 unsigned int cr_mask;
65 unsigned int pmd; 65 unsigned int pmd;
66 unsigned int pte; 66 pteval_t pte;
67}; 67};
68 68
69static struct cachepolicy cache_policies[] __initdata = { 69static struct cachepolicy cache_policies[] __initdata = {
@@ -191,7 +191,7 @@ void adjust_cr(unsigned long mask, unsigned long set)
191} 191}
192#endif 192#endif
193 193
194#define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_WRITE 194#define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN
195#define PROT_SECT_DEVICE PMD_TYPE_SECT|PMD_SECT_AP_WRITE 195#define PROT_SECT_DEVICE PMD_TYPE_SECT|PMD_SECT_AP_WRITE
196 196
197static struct mem_type mem_types[] = { 197static struct mem_type mem_types[] = {
@@ -236,19 +236,18 @@ static struct mem_type mem_types[] = {
236 }, 236 },
237 [MT_LOW_VECTORS] = { 237 [MT_LOW_VECTORS] = {
238 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | 238 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
239 L_PTE_EXEC, 239 L_PTE_RDONLY,
240 .prot_l1 = PMD_TYPE_TABLE, 240 .prot_l1 = PMD_TYPE_TABLE,
241 .domain = DOMAIN_USER, 241 .domain = DOMAIN_USER,
242 }, 242 },
243 [MT_HIGH_VECTORS] = { 243 [MT_HIGH_VECTORS] = {
244 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | 244 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
245 L_PTE_USER | L_PTE_EXEC, 245 L_PTE_USER | L_PTE_RDONLY,
246 .prot_l1 = PMD_TYPE_TABLE, 246 .prot_l1 = PMD_TYPE_TABLE,
247 .domain = DOMAIN_USER, 247 .domain = DOMAIN_USER,
248 }, 248 },
249 [MT_MEMORY] = { 249 [MT_MEMORY] = {
250 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | 250 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,
251 L_PTE_WRITE | L_PTE_EXEC,
252 .prot_l1 = PMD_TYPE_TABLE, 251 .prot_l1 = PMD_TYPE_TABLE,
253 .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, 252 .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
254 .domain = DOMAIN_KERNEL, 253 .domain = DOMAIN_KERNEL,
@@ -259,21 +258,20 @@ static struct mem_type mem_types[] = {
259 }, 258 },
260 [MT_MEMORY_NONCACHED] = { 259 [MT_MEMORY_NONCACHED] = {
261 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | 260 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
262 L_PTE_WRITE | L_PTE_EXEC | L_PTE_MT_BUFFERABLE, 261 L_PTE_MT_BUFFERABLE,
263 .prot_l1 = PMD_TYPE_TABLE, 262 .prot_l1 = PMD_TYPE_TABLE,
264 .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, 263 .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
265 .domain = DOMAIN_KERNEL, 264 .domain = DOMAIN_KERNEL,
266 }, 265 },
267 [MT_MEMORY_DTCM] = { 266 [MT_MEMORY_DTCM] = {
268 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | 267 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
269 L_PTE_WRITE, 268 L_PTE_XN,
270 .prot_l1 = PMD_TYPE_TABLE, 269 .prot_l1 = PMD_TYPE_TABLE,
271 .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, 270 .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
272 .domain = DOMAIN_KERNEL, 271 .domain = DOMAIN_KERNEL,
273 }, 272 },
274 [MT_MEMORY_ITCM] = { 273 [MT_MEMORY_ITCM] = {
275 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | 274 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,
276 L_PTE_WRITE | L_PTE_EXEC,
277 .prot_l1 = PMD_TYPE_TABLE, 275 .prot_l1 = PMD_TYPE_TABLE,
278 .domain = DOMAIN_KERNEL, 276 .domain = DOMAIN_KERNEL,
279 }, 277 },
@@ -480,7 +478,7 @@ static void __init build_mem_type_table(void)
480 478
481 pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot); 479 pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot);
482 pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | 480 pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
483 L_PTE_DIRTY | L_PTE_WRITE | kern_pgprot); 481 L_PTE_DIRTY | kern_pgprot);
484 482
485 mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; 483 mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;
486 mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; 484 mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
@@ -536,7 +534,7 @@ static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned l
536{ 534{
537 if (pmd_none(*pmd)) { 535 if (pmd_none(*pmd)) {
538 pte_t *pte = early_alloc(2 * PTRS_PER_PTE * sizeof(pte_t)); 536 pte_t *pte = early_alloc(2 * PTRS_PER_PTE * sizeof(pte_t));
539 __pmd_populate(pmd, __pa(pte) | prot); 537 __pmd_populate(pmd, __pa(pte), prot);
540 } 538 }
541 BUG_ON(pmd_bad(*pmd)); 539 BUG_ON(pmd_bad(*pmd));
542 return pte_offset_kernel(pmd, addr); 540 return pte_offset_kernel(pmd, addr);
@@ -554,7 +552,7 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
554} 552}
555 553
556static void __init alloc_init_section(pgd_t *pgd, unsigned long addr, 554static void __init alloc_init_section(pgd_t *pgd, unsigned long addr,
557 unsigned long end, unsigned long phys, 555 unsigned long end, phys_addr_t phys,
558 const struct mem_type *type) 556 const struct mem_type *type)
559{ 557{
560 pmd_t *pmd = pmd_offset(pgd, addr); 558 pmd_t *pmd = pmd_offset(pgd, addr);
@@ -589,7 +587,8 @@ static void __init alloc_init_section(pgd_t *pgd, unsigned long addr,
589static void __init create_36bit_mapping(struct map_desc *md, 587static void __init create_36bit_mapping(struct map_desc *md,
590 const struct mem_type *type) 588 const struct mem_type *type)
591{ 589{
592 unsigned long phys, addr, length, end; 590 unsigned long addr, length, end;
591 phys_addr_t phys;
593 pgd_t *pgd; 592 pgd_t *pgd;
594 593
595 addr = md->virtual; 594 addr = md->virtual;
@@ -1044,38 +1043,3 @@ void __init paging_init(struct machine_desc *mdesc)
1044 empty_zero_page = virt_to_page(zero_page); 1043 empty_zero_page = virt_to_page(zero_page);
1045 __flush_dcache_page(NULL, empty_zero_page); 1044 __flush_dcache_page(NULL, empty_zero_page);
1046} 1045}
1047
1048/*
1049 * In order to soft-boot, we need to insert a 1:1 mapping in place of
1050 * the user-mode pages. This will then ensure that we have predictable
1051 * results when turning the mmu off
1052 */
1053void setup_mm_for_reboot(char mode)
1054{
1055 unsigned long base_pmdval;
1056 pgd_t *pgd;
1057 int i;
1058
1059 /*
1060 * We need to access to user-mode page tables here. For kernel threads
1061 * we don't have any user-mode mappings so we use the context that we
1062 * "borrowed".
1063 */
1064 pgd = current->active_mm->pgd;
1065
1066 base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
1067 if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
1068 base_pmdval |= PMD_BIT4;
1069
1070 for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
1071 unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
1072 pmd_t *pmd;
1073
1074 pmd = pmd_off(pgd, i << PGDIR_SHIFT);
1075 pmd[0] = __pmd(pmdval);
1076 pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
1077 flush_pmd_entry(pmd);
1078 }
1079
1080 local_flush_tlb_all();
1081}