diff options
Diffstat (limited to 'arch/arm/mm/mmu.c')
-rw-r--r-- | arch/arm/mm/mmu.c | 62 |
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 | ||
69 | static struct cachepolicy cache_policies[] __initdata = { | 69 | static 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 | ||
197 | static struct mem_type mem_types[] = { | 197 | static 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 | ||
556 | static void __init alloc_init_section(pgd_t *pgd, unsigned long addr, | 554 | static 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, | |||
589 | static void __init create_36bit_mapping(struct map_desc *md, | 587 | static 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 | */ | ||
1053 | void 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 | } | ||