diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-06 17:33:19 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-06 17:33:19 -0500 |
commit | 28cdac6690cb113856293bf79b40de33dbd8f974 (patch) | |
tree | 64cd8ca8376ccf9a12faee3588c15a5839f9a28b /arch/arm/mm | |
parent | 4073723acb9cdcdbe4df9c0e0c376c65d1697e43 (diff) | |
parent | 36bb94ba36f332de767cfaa3af6a5136435a3a9c (diff) |
Merge branch 'pgt' (early part) into devel
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/mm/fault-armv.c | 2 | ||||
-rw-r--r-- | arch/arm/mm/fault.c | 2 | ||||
-rw-r--r-- | arch/arm/mm/idmap.c | 67 | ||||
-rw-r--r-- | arch/arm/mm/mm.h | 2 | ||||
-rw-r--r-- | arch/arm/mm/mmu.c | 62 | ||||
-rw-r--r-- | arch/arm/mm/pgd.c | 37 | ||||
-rw-r--r-- | arch/arm/mm/proc-macros.S | 30 | ||||
-rw-r--r-- | arch/arm/mm/proc-v7.S | 18 | ||||
-rw-r--r-- | arch/arm/mm/proc-xscale.S | 4 |
10 files changed, 128 insertions, 100 deletions
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index d63b6c413758..00d74a04af3a 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile | |||
@@ -5,8 +5,8 @@ | |||
5 | obj-y := dma-mapping.o extable.o fault.o init.o \ | 5 | obj-y := dma-mapping.o extable.o fault.o init.o \ |
6 | iomap.o | 6 | iomap.o |
7 | 7 | ||
8 | obj-$(CONFIG_MMU) += fault-armv.o flush.o ioremap.o mmap.o \ | 8 | obj-$(CONFIG_MMU) += fault-armv.o flush.o idmap.o ioremap.o \ |
9 | pgd.o mmu.o vmregion.o | 9 | mmap.o pgd.o mmu.o vmregion.o |
10 | 10 | ||
11 | ifneq ($(CONFIG_MMU),y) | 11 | ifneq ($(CONFIG_MMU),y) |
12 | obj-y += nommu.o | 12 | obj-y += nommu.o |
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 83e59f870426..01210dba0221 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c | |||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | #include "mm.h" | 27 | #include "mm.h" |
28 | 28 | ||
29 | static unsigned long shared_pte_mask = L_PTE_MT_BUFFERABLE; | 29 | static pteval_t shared_pte_mask = L_PTE_MT_BUFFERABLE; |
30 | 30 | ||
31 | #if __LINUX_ARM_ARCH__ < 6 | 31 | #if __LINUX_ARM_ARCH__ < 6 |
32 | /* | 32 | /* |
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 1e21e125fe3a..f10f9bac2206 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -108,7 +108,7 @@ void show_pte(struct mm_struct *mm, unsigned long addr) | |||
108 | 108 | ||
109 | pte = pte_offset_map(pmd, addr); | 109 | pte = pte_offset_map(pmd, addr); |
110 | printk(", *pte=%08lx", pte_val(*pte)); | 110 | printk(", *pte=%08lx", pte_val(*pte)); |
111 | printk(", *ppte=%08lx", pte_val(pte[-PTRS_PER_PTE])); | 111 | printk(", *ppte=%08lx", pte_val(pte[PTE_HWTABLE_PTRS])); |
112 | pte_unmap(pte); | 112 | pte_unmap(pte); |
113 | } while(0); | 113 | } while(0); |
114 | 114 | ||
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c new file mode 100644 index 000000000000..57299446f787 --- /dev/null +++ b/arch/arm/mm/idmap.c | |||
@@ -0,0 +1,67 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | |||
3 | #include <asm/cputype.h> | ||
4 | #include <asm/pgalloc.h> | ||
5 | #include <asm/pgtable.h> | ||
6 | |||
7 | static void idmap_add_pmd(pgd_t *pgd, unsigned long addr, unsigned long end, | ||
8 | unsigned long prot) | ||
9 | { | ||
10 | pmd_t *pmd = pmd_offset(pgd, addr); | ||
11 | |||
12 | addr = (addr & PMD_MASK) | prot; | ||
13 | pmd[0] = __pmd(addr); | ||
14 | addr += SECTION_SIZE; | ||
15 | pmd[1] = __pmd(addr); | ||
16 | flush_pmd_entry(pmd); | ||
17 | } | ||
18 | |||
19 | void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) | ||
20 | { | ||
21 | unsigned long prot, next; | ||
22 | |||
23 | prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE; | ||
24 | if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) | ||
25 | prot |= PMD_BIT4; | ||
26 | |||
27 | pgd += pgd_index(addr); | ||
28 | do { | ||
29 | next = pgd_addr_end(addr, end); | ||
30 | idmap_add_pmd(pgd, addr, next, prot); | ||
31 | } while (pgd++, addr = next, addr != end); | ||
32 | } | ||
33 | |||
34 | #ifdef CONFIG_SMP | ||
35 | static void idmap_del_pmd(pgd_t *pgd, unsigned long addr, unsigned long end) | ||
36 | { | ||
37 | pmd_t *pmd = pmd_offset(pgd, addr); | ||
38 | pmd_clear(pmd); | ||
39 | } | ||
40 | |||
41 | void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end) | ||
42 | { | ||
43 | unsigned long next; | ||
44 | |||
45 | pgd += pgd_index(addr); | ||
46 | do { | ||
47 | next = pgd_addr_end(addr, end); | ||
48 | idmap_del_pmd(pgd, addr, next); | ||
49 | } while (pgd++, addr = next, addr != end); | ||
50 | } | ||
51 | #endif | ||
52 | |||
53 | /* | ||
54 | * In order to soft-boot, we need to insert a 1:1 mapping in place of | ||
55 | * the user-mode pages. This will then ensure that we have predictable | ||
56 | * results when turning the mmu off | ||
57 | */ | ||
58 | void setup_mm_for_reboot(char mode) | ||
59 | { | ||
60 | /* | ||
61 | * We need to access to user-mode page tables here. For kernel threads | ||
62 | * we don't have any user-mode mappings so we use the context that we | ||
63 | * "borrowed". | ||
64 | */ | ||
65 | identity_mapping_add(current->active_mm->pgd, 0, TASK_SIZE); | ||
66 | local_flush_tlb_all(); | ||
67 | } | ||
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index 6630620380a4..36960df5fb76 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h | |||
@@ -16,7 +16,7 @@ static inline pmd_t *pmd_off_k(unsigned long virt) | |||
16 | } | 16 | } |
17 | 17 | ||
18 | struct mem_type { | 18 | struct mem_type { |
19 | unsigned int prot_pte; | 19 | pteval_t prot_pte; |
20 | unsigned int prot_l1; | 20 | unsigned int prot_l1; |
21 | unsigned int prot_sect; | 21 | unsigned int prot_sect; |
22 | unsigned int domain; | 22 | unsigned int domain; |
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 | } | ||
diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c index 69bbfc6645a6..93292a18cf77 100644 --- a/arch/arm/mm/pgd.c +++ b/arch/arm/mm/pgd.c | |||
@@ -17,12 +17,10 @@ | |||
17 | 17 | ||
18 | #include "mm.h" | 18 | #include "mm.h" |
19 | 19 | ||
20 | #define FIRST_KERNEL_PGD_NR (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD) | ||
21 | |||
22 | /* | 20 | /* |
23 | * need to get a 16k page for level 1 | 21 | * need to get a 16k page for level 1 |
24 | */ | 22 | */ |
25 | pgd_t *get_pgd_slow(struct mm_struct *mm) | 23 | pgd_t *pgd_alloc(struct mm_struct *mm) |
26 | { | 24 | { |
27 | pgd_t *new_pgd, *init_pgd; | 25 | pgd_t *new_pgd, *init_pgd; |
28 | pmd_t *new_pmd, *init_pmd; | 26 | pmd_t *new_pmd, *init_pmd; |
@@ -32,14 +30,14 @@ pgd_t *get_pgd_slow(struct mm_struct *mm) | |||
32 | if (!new_pgd) | 30 | if (!new_pgd) |
33 | goto no_pgd; | 31 | goto no_pgd; |
34 | 32 | ||
35 | memset(new_pgd, 0, FIRST_KERNEL_PGD_NR * sizeof(pgd_t)); | 33 | memset(new_pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); |
36 | 34 | ||
37 | /* | 35 | /* |
38 | * Copy over the kernel and IO PGD entries | 36 | * Copy over the kernel and IO PGD entries |
39 | */ | 37 | */ |
40 | init_pgd = pgd_offset_k(0); | 38 | init_pgd = pgd_offset_k(0); |
41 | memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR, | 39 | memcpy(new_pgd + USER_PTRS_PER_PGD, init_pgd + USER_PTRS_PER_PGD, |
42 | (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t)); | 40 | (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); |
43 | 41 | ||
44 | clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t)); | 42 | clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t)); |
45 | 43 | ||
@@ -73,28 +71,29 @@ no_pgd: | |||
73 | return NULL; | 71 | return NULL; |
74 | } | 72 | } |
75 | 73 | ||
76 | void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd) | 74 | void pgd_free(struct mm_struct *mm, pgd_t *pgd_base) |
77 | { | 75 | { |
76 | pgd_t *pgd; | ||
78 | pmd_t *pmd; | 77 | pmd_t *pmd; |
79 | pgtable_t pte; | 78 | pgtable_t pte; |
80 | 79 | ||
81 | if (!pgd) | 80 | if (!pgd_base) |
82 | return; | 81 | return; |
83 | 82 | ||
84 | /* pgd is always present and good */ | 83 | pgd = pgd_base + pgd_index(0); |
85 | pmd = pmd_off(pgd, 0); | 84 | if (pgd_none_or_clear_bad(pgd)) |
86 | if (pmd_none(*pmd)) | 85 | goto no_pgd; |
87 | goto free; | 86 | |
88 | if (pmd_bad(*pmd)) { | 87 | pmd = pmd_offset(pgd, 0); |
89 | pmd_ERROR(*pmd); | 88 | if (pmd_none_or_clear_bad(pmd)) |
90 | pmd_clear(pmd); | 89 | goto no_pmd; |
91 | goto free; | ||
92 | } | ||
93 | 90 | ||
94 | pte = pmd_pgtable(*pmd); | 91 | pte = pmd_pgtable(*pmd); |
95 | pmd_clear(pmd); | 92 | pmd_clear(pmd); |
96 | pte_free(mm, pte); | 93 | pte_free(mm, pte); |
94 | no_pmd: | ||
95 | pgd_clear(pgd); | ||
97 | pmd_free(mm, pmd); | 96 | pmd_free(mm, pmd); |
98 | free: | 97 | no_pgd: |
99 | free_pages((unsigned long) pgd, 2); | 98 | free_pages((unsigned long) pgd_base, 2); |
100 | } | 99 | } |
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S index f8f777df8d72..e32fa499194c 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S | |||
@@ -91,7 +91,7 @@ | |||
91 | #if L_PTE_SHARED != PTE_EXT_SHARED | 91 | #if L_PTE_SHARED != PTE_EXT_SHARED |
92 | #error PTE shared bit mismatch | 92 | #error PTE shared bit mismatch |
93 | #endif | 93 | #endif |
94 | #if (L_PTE_EXEC+L_PTE_USER+L_PTE_WRITE+L_PTE_DIRTY+L_PTE_YOUNG+\ | 94 | #if (L_PTE_XN+L_PTE_USER+L_PTE_RDONLY+L_PTE_DIRTY+L_PTE_YOUNG+\ |
95 | L_PTE_FILE+L_PTE_PRESENT) > L_PTE_SHARED | 95 | L_PTE_FILE+L_PTE_PRESENT) > L_PTE_SHARED |
96 | #error Invalid Linux PTE bit settings | 96 | #error Invalid Linux PTE bit settings |
97 | #endif | 97 | #endif |
@@ -135,7 +135,7 @@ | |||
135 | .endm | 135 | .endm |
136 | 136 | ||
137 | .macro armv6_set_pte_ext pfx | 137 | .macro armv6_set_pte_ext pfx |
138 | str r1, [r0], #-2048 @ linux version | 138 | str r1, [r0], #2048 @ linux version |
139 | 139 | ||
140 | bic r3, r1, #0x000003fc | 140 | bic r3, r1, #0x000003fc |
141 | bic r3, r3, #PTE_TYPE_MASK | 141 | bic r3, r3, #PTE_TYPE_MASK |
@@ -146,9 +146,9 @@ | |||
146 | and r2, r1, #L_PTE_MT_MASK | 146 | and r2, r1, #L_PTE_MT_MASK |
147 | ldr r2, [ip, r2] | 147 | ldr r2, [ip, r2] |
148 | 148 | ||
149 | tst r1, #L_PTE_WRITE | 149 | eor r1, r1, #L_PTE_DIRTY |
150 | tstne r1, #L_PTE_DIRTY | 150 | tst r1, #L_PTE_DIRTY|L_PTE_RDONLY |
151 | orreq r3, r3, #PTE_EXT_APX | 151 | orrne r3, r3, #PTE_EXT_APX |
152 | 152 | ||
153 | tst r1, #L_PTE_USER | 153 | tst r1, #L_PTE_USER |
154 | orrne r3, r3, #PTE_EXT_AP1 | 154 | orrne r3, r3, #PTE_EXT_AP1 |
@@ -158,8 +158,8 @@ | |||
158 | bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 | 158 | bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 |
159 | #endif | 159 | #endif |
160 | 160 | ||
161 | tst r1, #L_PTE_EXEC | 161 | tst r1, #L_PTE_XN |
162 | orreq r3, r3, #PTE_EXT_XN | 162 | orrne r3, r3, #PTE_EXT_XN |
163 | 163 | ||
164 | orr r3, r3, r2 | 164 | orr r3, r3, r2 |
165 | 165 | ||
@@ -187,9 +187,9 @@ | |||
187 | * 1111 0xff r/w r/w | 187 | * 1111 0xff r/w r/w |
188 | */ | 188 | */ |
189 | .macro armv3_set_pte_ext wc_disable=1 | 189 | .macro armv3_set_pte_ext wc_disable=1 |
190 | str r1, [r0], #-2048 @ linux version | 190 | str r1, [r0], #2048 @ linux version |
191 | 191 | ||
192 | eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY | 192 | eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
193 | 193 | ||
194 | bic r2, r1, #PTE_SMALL_AP_MASK @ keep C, B bits | 194 | bic r2, r1, #PTE_SMALL_AP_MASK @ keep C, B bits |
195 | bic r2, r2, #PTE_TYPE_MASK | 195 | bic r2, r2, #PTE_TYPE_MASK |
@@ -198,7 +198,7 @@ | |||
198 | tst r3, #L_PTE_USER @ user? | 198 | tst r3, #L_PTE_USER @ user? |
199 | orrne r2, r2, #PTE_SMALL_AP_URO_SRW | 199 | orrne r2, r2, #PTE_SMALL_AP_URO_SRW |
200 | 200 | ||
201 | tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ write and dirty? | 201 | tst r3, #L_PTE_RDONLY | L_PTE_DIRTY @ write and dirty? |
202 | orreq r2, r2, #PTE_SMALL_AP_UNO_SRW | 202 | orreq r2, r2, #PTE_SMALL_AP_UNO_SRW |
203 | 203 | ||
204 | tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ present and young? | 204 | tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ present and young? |
@@ -210,7 +210,7 @@ | |||
210 | bicne r2, r2, #PTE_BUFFERABLE | 210 | bicne r2, r2, #PTE_BUFFERABLE |
211 | #endif | 211 | #endif |
212 | .endif | 212 | .endif |
213 | str r2, [r0] @ hardware version | 213 | str r2, [r0] @ hardware version |
214 | .endm | 214 | .endm |
215 | 215 | ||
216 | 216 | ||
@@ -230,9 +230,9 @@ | |||
230 | * 1111 11 r/w r/w | 230 | * 1111 11 r/w r/w |
231 | */ | 231 | */ |
232 | .macro xscale_set_pte_ext_prologue | 232 | .macro xscale_set_pte_ext_prologue |
233 | str r1, [r0], #-2048 @ linux version | 233 | str r1, [r0] @ linux version |
234 | 234 | ||
235 | eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY | 235 | eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
236 | 236 | ||
237 | bic r2, r1, #PTE_SMALL_AP_MASK @ keep C, B bits | 237 | bic r2, r1, #PTE_SMALL_AP_MASK @ keep C, B bits |
238 | orr r2, r2, #PTE_TYPE_EXT @ extended page | 238 | orr r2, r2, #PTE_TYPE_EXT @ extended page |
@@ -240,7 +240,7 @@ | |||
240 | tst r3, #L_PTE_USER @ user? | 240 | tst r3, #L_PTE_USER @ user? |
241 | orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w | 241 | orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w |
242 | 242 | ||
243 | tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ write and dirty? | 243 | tst r3, #L_PTE_RDONLY | L_PTE_DIRTY @ write and dirty? |
244 | orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w | 244 | orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w |
245 | @ combined with user -> user r/w | 245 | @ combined with user -> user r/w |
246 | .endm | 246 | .endm |
@@ -249,7 +249,7 @@ | |||
249 | tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ present and young? | 249 | tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ present and young? |
250 | movne r2, #0 @ no -> fault | 250 | movne r2, #0 @ no -> fault |
251 | 251 | ||
252 | str r2, [r0] @ hardware version | 252 | str r2, [r0, #2048]! @ hardware version |
253 | mov ip, #0 | 253 | mov ip, #0 |
254 | mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line | 254 | mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line |
255 | mcr p15, 0, ip, c7, c10, 4 @ data write barrier | 255 | mcr p15, 0, ip, c7, c10, 4 @ data write barrier |
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 7401f4d7e676..b49fab21517c 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S | |||
@@ -124,15 +124,13 @@ ENDPROC(cpu_v7_switch_mm) | |||
124 | * Set a level 2 translation table entry. | 124 | * Set a level 2 translation table entry. |
125 | * | 125 | * |
126 | * - ptep - pointer to level 2 translation table entry | 126 | * - ptep - pointer to level 2 translation table entry |
127 | * (hardware version is stored at -1024 bytes) | 127 | * (hardware version is stored at +2048 bytes) |
128 | * - pte - PTE value to store | 128 | * - pte - PTE value to store |
129 | * - ext - value for extended PTE bits | 129 | * - ext - value for extended PTE bits |
130 | */ | 130 | */ |
131 | ENTRY(cpu_v7_set_pte_ext) | 131 | ENTRY(cpu_v7_set_pte_ext) |
132 | #ifdef CONFIG_MMU | 132 | #ifdef CONFIG_MMU |
133 | ARM( str r1, [r0], #-2048 ) @ linux version | 133 | str r1, [r0] @ linux version |
134 | THUMB( str r1, [r0] ) @ linux version | ||
135 | THUMB( sub r0, r0, #2048 ) | ||
136 | 134 | ||
137 | bic r3, r1, #0x000003f0 | 135 | bic r3, r1, #0x000003f0 |
138 | bic r3, r3, #PTE_TYPE_MASK | 136 | bic r3, r3, #PTE_TYPE_MASK |
@@ -142,9 +140,9 @@ ENTRY(cpu_v7_set_pte_ext) | |||
142 | tst r1, #1 << 4 | 140 | tst r1, #1 << 4 |
143 | orrne r3, r3, #PTE_EXT_TEX(1) | 141 | orrne r3, r3, #PTE_EXT_TEX(1) |
144 | 142 | ||
145 | tst r1, #L_PTE_WRITE | 143 | eor r1, r1, #L_PTE_DIRTY |
146 | tstne r1, #L_PTE_DIRTY | 144 | tst r1, #L_PTE_RDONLY | L_PTE_DIRTY |
147 | orreq r3, r3, #PTE_EXT_APX | 145 | orrne r3, r3, #PTE_EXT_APX |
148 | 146 | ||
149 | tst r1, #L_PTE_USER | 147 | tst r1, #L_PTE_USER |
150 | orrne r3, r3, #PTE_EXT_AP1 | 148 | orrne r3, r3, #PTE_EXT_AP1 |
@@ -154,14 +152,14 @@ ENTRY(cpu_v7_set_pte_ext) | |||
154 | bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 | 152 | bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 |
155 | #endif | 153 | #endif |
156 | 154 | ||
157 | tst r1, #L_PTE_EXEC | 155 | tst r1, #L_PTE_XN |
158 | orreq r3, r3, #PTE_EXT_XN | 156 | orrne r3, r3, #PTE_EXT_XN |
159 | 157 | ||
160 | tst r1, #L_PTE_YOUNG | 158 | tst r1, #L_PTE_YOUNG |
161 | tstne r1, #L_PTE_PRESENT | 159 | tstne r1, #L_PTE_PRESENT |
162 | moveq r3, #0 | 160 | moveq r3, #0 |
163 | 161 | ||
164 | str r3, [r0] | 162 | str r3, [r0, #2048]! |
165 | mcr p15, 0, r0, c7, c10, 1 @ flush_pte | 163 | mcr p15, 0, r0, c7, c10, 1 @ flush_pte |
166 | #endif | 164 | #endif |
167 | mov pc, lr | 165 | mov pc, lr |
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 523408c0bb38..5a37c5e45c41 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S | |||
@@ -500,8 +500,8 @@ ENTRY(cpu_xscale_set_pte_ext) | |||
500 | @ | 500 | @ |
501 | @ Erratum 40: must set memory to write-through for user read-only pages | 501 | @ Erratum 40: must set memory to write-through for user read-only pages |
502 | @ | 502 | @ |
503 | and ip, r1, #(L_PTE_MT_MASK | L_PTE_USER | L_PTE_WRITE) & ~(4 << 2) | 503 | and ip, r1, #(L_PTE_MT_MASK | L_PTE_USER | L_PTE_RDONLY) & ~(4 << 2) |
504 | teq ip, #L_PTE_MT_WRITEBACK | L_PTE_USER | 504 | teq ip, #L_PTE_MT_WRITEBACK | L_PTE_USER | L_PTE_RDONLY |
505 | 505 | ||
506 | moveq r1, #L_PTE_MT_WRITETHROUGH | 506 | moveq r1, #L_PTE_MT_WRITETHROUGH |
507 | and r1, r1, #L_PTE_MT_MASK | 507 | and r1, r1, #L_PTE_MT_MASK |