aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/include/asm/pgalloc.h
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-11-15 19:16:01 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-12-22 06:05:32 -0500
commitd30e45eeabefadc6039d7f876a59e5f5f6cb11c6 (patch)
tree9873141aac1042fe8b230aa525599135f5411e36 /arch/arm/include/asm/pgalloc.h
parentf6e3354d02aa1f30672e3671098c12cb49c7da25 (diff)
ARM: pgtable: switch order of Linux vs hardware page tables
This switches the ordering of the Linux vs hardware page tables in each page, thereby eliminating some of the arithmetic in the page table walks. As we now place the Linux page table at the beginning of the page, we can deal with the offset in the pgt by simply masking it away, along with the other control bits. This also makes the arithmetic all be positive, rather than a mixture. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/include/asm/pgalloc.h')
-rw-r--r--arch/arm/include/asm/pgalloc.h39
1 files changed, 17 insertions, 22 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
38static 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 */
54static inline pte_t * 59static inline pte_t *
55pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) 60pte_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 */
92static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) 93static 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
100static inline void pte_free(struct mm_struct *mm, pgtable_t pte) 99static 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)
106static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte, 105static 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,
121static inline void 120static inline void
122pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) 121pmd_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
134static inline void 129static inline void