diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/include/asm/pgalloc.h | 39 | ||||
-rw-r--r-- | arch/arm/include/asm/pgtable.h | 31 | ||||
-rw-r--r-- | arch/arm/mm/fault.c | 2 | ||||
-rw-r--r-- | arch/arm/mm/proc-macros.S | 10 | ||||
-rw-r--r-- | arch/arm/mm/proc-v7.S | 8 |
5 files changed, 41 insertions, 49 deletions
diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h index 1f1064b519c0..9763be04f77e 100644 --- a/arch/arm/include/asm/pgalloc.h +++ b/arch/arm/include/asm/pgalloc.h | |||
@@ -35,6 +35,11 @@ extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); | |||
35 | 35 | ||
36 | #define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO) | 36 | #define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO) |
37 | 37 | ||
38 | static inline void clean_pte_table(pte_t *pte) | ||
39 | { | ||
40 | clean_dcache_area(pte + PTE_HWTABLE_PTRS, PTE_HWTABLE_SIZE); | ||
41 | } | ||
42 | |||
38 | /* | 43 | /* |
39 | * Allocate one PTE table. | 44 | * Allocate one PTE table. |
40 | * | 45 | * |
@@ -42,14 +47,14 @@ extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); | |||
42 | * into one table thus: | 47 | * into one table thus: |
43 | * | 48 | * |
44 | * +------------+ | 49 | * +------------+ |
45 | * | h/w pt 0 | | ||
46 | * +------------+ | ||
47 | * | h/w pt 1 | | ||
48 | * +------------+ | ||
49 | * | Linux pt 0 | | 50 | * | Linux pt 0 | |
50 | * +------------+ | 51 | * +------------+ |
51 | * | Linux pt 1 | | 52 | * | Linux pt 1 | |
52 | * +------------+ | 53 | * +------------+ |
54 | * | h/w pt 0 | | ||
55 | * +------------+ | ||
56 | * | h/w pt 1 | | ||
57 | * +------------+ | ||
53 | */ | 58 | */ |
54 | static inline pte_t * | 59 | static inline pte_t * |
55 | pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) | 60 | pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) |
@@ -57,10 +62,8 @@ pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) | |||
57 | pte_t *pte; | 62 | pte_t *pte; |
58 | 63 | ||
59 | pte = (pte_t *)__get_free_page(PGALLOC_GFP); | 64 | pte = (pte_t *)__get_free_page(PGALLOC_GFP); |
60 | if (pte) { | 65 | if (pte) |
61 | clean_dcache_area(pte, sizeof(pte_t) * PTRS_PER_PTE); | 66 | clean_pte_table(pte); |
62 | pte += PTRS_PER_PTE; | ||
63 | } | ||
64 | 67 | ||
65 | return pte; | 68 | return pte; |
66 | } | 69 | } |
@@ -76,10 +79,8 @@ pte_alloc_one(struct mm_struct *mm, unsigned long addr) | |||
76 | pte = alloc_pages(PGALLOC_GFP, 0); | 79 | pte = alloc_pages(PGALLOC_GFP, 0); |
77 | #endif | 80 | #endif |
78 | if (pte) { | 81 | if (pte) { |
79 | if (!PageHighMem(pte)) { | 82 | if (!PageHighMem(pte)) |
80 | void *page = page_address(pte); | 83 | clean_pte_table(page_address(pte)); |
81 | clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE); | ||
82 | } | ||
83 | pgtable_page_ctor(pte); | 84 | pgtable_page_ctor(pte); |
84 | } | 85 | } |
85 | 86 | ||
@@ -91,10 +92,8 @@ pte_alloc_one(struct mm_struct *mm, unsigned long addr) | |||
91 | */ | 92 | */ |
92 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | 93 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) |
93 | { | 94 | { |
94 | if (pte) { | 95 | if (pte) |
95 | pte -= PTRS_PER_PTE; | ||
96 | free_page((unsigned long)pte); | 96 | free_page((unsigned long)pte); |
97 | } | ||
98 | } | 97 | } |
99 | 98 | ||
100 | static inline void pte_free(struct mm_struct *mm, pgtable_t pte) | 99 | static inline void pte_free(struct mm_struct *mm, pgtable_t pte) |
@@ -106,7 +105,7 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t pte) | |||
106 | static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte, | 105 | static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte, |
107 | unsigned long prot) | 106 | unsigned long prot) |
108 | { | 107 | { |
109 | unsigned long pmdval = pte | prot; | 108 | unsigned long pmdval = (pte + PTE_HWTABLE_OFF) | prot; |
110 | pmdp[0] = __pmd(pmdval); | 109 | pmdp[0] = __pmd(pmdval); |
111 | pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); | 110 | pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); |
112 | flush_pmd_entry(pmdp); | 111 | flush_pmd_entry(pmdp); |
@@ -121,14 +120,10 @@ static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte, | |||
121 | static inline void | 120 | static inline void |
122 | pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) | 121 | pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) |
123 | { | 122 | { |
124 | unsigned long pte_ptr = (unsigned long)ptep; | ||
125 | |||
126 | /* | 123 | /* |
127 | * The pmd must be loaded with the physical | 124 | * The pmd must be loaded with the physical address of the PTE table |
128 | * address of the PTE table | ||
129 | */ | 125 | */ |
130 | pte_ptr -= PTRS_PER_PTE * sizeof(void *); | 126 | __pmd_populate(pmdp, __pa(ptep), _PAGE_KERNEL_TABLE); |
131 | __pmd_populate(pmdp, __pa(pte_ptr), _PAGE_KERNEL_TABLE); | ||
132 | } | 127 | } |
133 | 128 | ||
134 | static inline void | 129 | static inline void |
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 50eb0b4278ec..e582214b00df 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h | |||
@@ -55,7 +55,7 @@ | |||
55 | * Therefore, we tweak the implementation slightly - we tell Linux that we | 55 | * Therefore, we tweak the implementation slightly - we tell Linux that we |
56 | * have 2048 entries in the first level, each of which is 8 bytes (iow, two | 56 | * have 2048 entries in the first level, each of which is 8 bytes (iow, two |
57 | * hardware pointers to the second level.) The second level contains two | 57 | * hardware pointers to the second level.) The second level contains two |
58 | * hardware PTE tables arranged contiguously, followed by Linux versions | 58 | * hardware PTE tables arranged contiguously, preceded by Linux versions |
59 | * which contain the state information Linux needs. We, therefore, end up | 59 | * which contain the state information Linux needs. We, therefore, end up |
60 | * with 512 entries in the "PTE" level. | 60 | * with 512 entries in the "PTE" level. |
61 | * | 61 | * |
@@ -63,15 +63,15 @@ | |||
63 | * | 63 | * |
64 | * pgd pte | 64 | * pgd pte |
65 | * | | | 65 | * | | |
66 | * +--------+ +0 | 66 | * +--------+ |
67 | * | |-----> +------------+ +0 | 67 | * | | +------------+ +0 |
68 | * +- - - - + | Linux pt 0 | | ||
69 | * | | +------------+ +1024 | ||
70 | * +--------+ +0 | Linux pt 1 | | ||
71 | * | |-----> +------------+ +2048 | ||
68 | * +- - - - + +4 | h/w pt 0 | | 72 | * +- - - - + +4 | h/w pt 0 | |
69 | * | |-----> +------------+ +1024 | 73 | * | |-----> +------------+ +3072 |
70 | * +--------+ +8 | h/w pt 1 | | 74 | * +--------+ +8 | h/w pt 1 | |
71 | * | | +------------+ +2048 | ||
72 | * +- - - - + | Linux pt 0 | | ||
73 | * | | +------------+ +3072 | ||
74 | * +--------+ | Linux pt 1 | | ||
75 | * | | +------------+ +4096 | 75 | * | | +------------+ +4096 |
76 | * | 76 | * |
77 | * See L_PTE_xxx below for definitions of bits in the "Linux pt", and | 77 | * See L_PTE_xxx below for definitions of bits in the "Linux pt", and |
@@ -103,6 +103,10 @@ | |||
103 | #define PTRS_PER_PMD 1 | 103 | #define PTRS_PER_PMD 1 |
104 | #define PTRS_PER_PGD 2048 | 104 | #define PTRS_PER_PGD 2048 |
105 | 105 | ||
106 | #define PTE_HWTABLE_PTRS (PTRS_PER_PTE) | ||
107 | #define PTE_HWTABLE_OFF (PTE_HWTABLE_PTRS * sizeof(pte_t)) | ||
108 | #define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u32)) | ||
109 | |||
106 | /* | 110 | /* |
107 | * PMD_SHIFT determines the size of the area a second-level page table can map | 111 | * PMD_SHIFT determines the size of the area a second-level page table can map |
108 | * PGDIR_SHIFT determines what a third-level page table entry can map | 112 | * PGDIR_SHIFT determines what a third-level page table entry can map |
@@ -323,12 +327,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | |||
323 | 327 | ||
324 | static inline pte_t *pmd_page_vaddr(pmd_t pmd) | 328 | static inline pte_t *pmd_page_vaddr(pmd_t pmd) |
325 | { | 329 | { |
326 | phys_addr_t ptr; | 330 | return __va(pmd_val(pmd) & PAGE_MASK); |
327 | |||
328 | ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * sizeof(void *) - 1); | ||
329 | ptr += PTRS_PER_PTE * sizeof(void *); | ||
330 | |||
331 | return __va(ptr); | ||
332 | } | 331 | } |
333 | 332 | ||
334 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd))) | 333 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd))) |
@@ -341,8 +340,8 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) | |||
341 | #define __pte_map(pmd) pmd_page_vaddr(*(pmd)) | 340 | #define __pte_map(pmd) pmd_page_vaddr(*(pmd)) |
342 | #define __pte_unmap(pte) do { } while (0) | 341 | #define __pte_unmap(pte) do { } while (0) |
343 | #else | 342 | #else |
344 | #define __pte_map(pmd) ((pte_t *)kmap_atomic(pmd_page(*(pmd))) + PTRS_PER_PTE) | 343 | #define __pte_map(pmd) (pte_t *)kmap_atomic(pmd_page(*(pmd))) |
345 | #define __pte_unmap(pte) kunmap_atomic((pte - PTRS_PER_PTE)) | 344 | #define __pte_unmap(pte) kunmap_atomic(pte) |
346 | #endif | 345 | #endif |
347 | 346 | ||
348 | #define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) | 347 | #define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) |
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/proc-macros.S b/arch/arm/mm/proc-macros.S index 7d63beaf9745..cbedf9c46b9d 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S | |||
@@ -121,7 +121,7 @@ | |||
121 | .endm | 121 | .endm |
122 | 122 | ||
123 | .macro armv6_set_pte_ext pfx | 123 | .macro armv6_set_pte_ext pfx |
124 | str r1, [r0], #-2048 @ linux version | 124 | str r1, [r0], #2048 @ linux version |
125 | 125 | ||
126 | bic r3, r1, #0x000003fc | 126 | bic r3, r1, #0x000003fc |
127 | bic r3, r3, #PTE_TYPE_MASK | 127 | bic r3, r3, #PTE_TYPE_MASK |
@@ -170,7 +170,7 @@ | |||
170 | * 1111 0xff r/w r/w | 170 | * 1111 0xff r/w r/w |
171 | */ | 171 | */ |
172 | .macro armv3_set_pte_ext wc_disable=1 | 172 | .macro armv3_set_pte_ext wc_disable=1 |
173 | str r1, [r0], #-2048 @ linux version | 173 | str r1, [r0], #2048 @ linux version |
174 | 174 | ||
175 | eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY | 175 | eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY |
176 | 176 | ||
@@ -193,7 +193,7 @@ | |||
193 | bicne r2, r2, #PTE_BUFFERABLE | 193 | bicne r2, r2, #PTE_BUFFERABLE |
194 | #endif | 194 | #endif |
195 | .endif | 195 | .endif |
196 | str r2, [r0] @ hardware version | 196 | str r2, [r0] @ hardware version |
197 | .endm | 197 | .endm |
198 | 198 | ||
199 | 199 | ||
@@ -213,7 +213,7 @@ | |||
213 | * 1111 11 r/w r/w | 213 | * 1111 11 r/w r/w |
214 | */ | 214 | */ |
215 | .macro xscale_set_pte_ext_prologue | 215 | .macro xscale_set_pte_ext_prologue |
216 | str r1, [r0], #-2048 @ linux version | 216 | str r1, [r0] @ linux version |
217 | 217 | ||
218 | eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY | 218 | eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY |
219 | 219 | ||
@@ -232,7 +232,7 @@ | |||
232 | tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ present and young? | 232 | tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ present and young? |
233 | movne r2, #0 @ no -> fault | 233 | movne r2, #0 @ no -> fault |
234 | 234 | ||
235 | str r2, [r0] @ hardware version | 235 | str r2, [r0, #2048]! @ hardware version |
236 | mov ip, #0 | 236 | mov ip, #0 |
237 | mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line | 237 | mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line |
238 | mcr p15, 0, ip, c7, c10, 4 @ data write barrier | 238 | 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 53cbe2225153..89c31a6dae5c 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 |
@@ -158,7 +156,7 @@ ENTRY(cpu_v7_set_pte_ext) | |||
158 | tstne r1, #L_PTE_PRESENT | 156 | tstne r1, #L_PTE_PRESENT |
159 | moveq r3, #0 | 157 | moveq r3, #0 |
160 | 158 | ||
161 | str r3, [r0] | 159 | str r3, [r0, #2048]! |
162 | mcr p15, 0, r0, c7, c10, 1 @ flush_pte | 160 | mcr p15, 0, r0, c7, c10, 1 @ flush_pte |
163 | #endif | 161 | #endif |
164 | mov pc, lr | 162 | mov pc, lr |