diff options
-rw-r--r-- | arch/sh/include/asm/pgalloc.h | 10 | ||||
-rw-r--r-- | arch/sh/include/asm/pgalloc_nopmd.h | 30 | ||||
-rw-r--r-- | arch/sh/include/asm/pgalloc_pmd.h | 41 | ||||
-rw-r--r-- | arch/sh/include/asm/pgtable.h | 4 | ||||
-rw-r--r-- | arch/sh/include/asm/pgtable_64.h | 11 | ||||
-rw-r--r-- | arch/sh/include/asm/pgtable_pmd.h | 4 | ||||
-rw-r--r-- | arch/sh/mm/Kconfig | 4 | ||||
-rw-r--r-- | arch/sh/mm/Makefile | 2 | ||||
-rw-r--r-- | arch/sh/mm/cache-sh4.c | 13 | ||||
-rw-r--r-- | arch/sh/mm/pgtable.c | 57 |
10 files changed, 73 insertions, 103 deletions
diff --git a/arch/sh/include/asm/pgalloc.h b/arch/sh/include/asm/pgalloc.h index 4ea27855c3b5..e106474996b2 100644 --- a/arch/sh/include/asm/pgalloc.h +++ b/arch/sh/include/asm/pgalloc.h | |||
@@ -6,10 +6,13 @@ | |||
6 | 6 | ||
7 | #define QUICK_PT 1 /* Other page table pages that are zero on free */ | 7 | #define QUICK_PT 1 /* Other page table pages that are zero on free */ |
8 | 8 | ||
9 | extern pgd_t *pgd_alloc(struct mm_struct *); | ||
10 | extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); | ||
11 | |||
9 | #ifdef CONFIG_PGTABLE_LEVELS_3 | 12 | #ifdef CONFIG_PGTABLE_LEVELS_3 |
10 | #include <asm/pgalloc_pmd.h> | 13 | extern void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd); |
11 | #else | 14 | extern pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address); |
12 | #include <asm/pgalloc_nopmd.h> | 15 | extern void pmd_free(struct mm_struct *mm, pmd_t *pmd); |
13 | #endif | 16 | #endif |
14 | 17 | ||
15 | static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, | 18 | static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, |
@@ -67,7 +70,6 @@ do { \ | |||
67 | 70 | ||
68 | static inline void check_pgt_cache(void) | 71 | static inline void check_pgt_cache(void) |
69 | { | 72 | { |
70 | __check_pgt_cache(); | ||
71 | quicklist_trim(QUICK_PT, NULL, 25, 16); | 73 | quicklist_trim(QUICK_PT, NULL, 25, 16); |
72 | } | 74 | } |
73 | 75 | ||
diff --git a/arch/sh/include/asm/pgalloc_nopmd.h b/arch/sh/include/asm/pgalloc_nopmd.h deleted file mode 100644 index e4b344c37e74..000000000000 --- a/arch/sh/include/asm/pgalloc_nopmd.h +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | #ifndef __ASM_SH_PGALLOC_NOPMD_H | ||
2 | #define __ASM_SH_PGALLOC_NOPMD_H | ||
3 | |||
4 | #define QUICK_PGD 0 /* We preserve special mappings over free */ | ||
5 | |||
6 | static inline void pgd_ctor(void *x) | ||
7 | { | ||
8 | pgd_t *pgd = x; | ||
9 | |||
10 | memcpy(pgd + USER_PTRS_PER_PGD, | ||
11 | swapper_pg_dir + USER_PTRS_PER_PGD, | ||
12 | (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); | ||
13 | } | ||
14 | |||
15 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) | ||
16 | { | ||
17 | return quicklist_alloc(QUICK_PGD, GFP_KERNEL | __GFP_REPEAT, pgd_ctor); | ||
18 | } | ||
19 | |||
20 | static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) | ||
21 | { | ||
22 | quicklist_free(QUICK_PGD, NULL, pgd); | ||
23 | } | ||
24 | |||
25 | static inline void __check_pgt_cache(void) | ||
26 | { | ||
27 | quicklist_trim(QUICK_PGD, NULL, 25, 16); | ||
28 | } | ||
29 | |||
30 | #endif /* __ASM_SH_PGALLOC_NOPMD_H */ | ||
diff --git a/arch/sh/include/asm/pgalloc_pmd.h b/arch/sh/include/asm/pgalloc_pmd.h deleted file mode 100644 index 20f75cc4eb09..000000000000 --- a/arch/sh/include/asm/pgalloc_pmd.h +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | #ifndef __ASM_SH_PGALLOC_PMD_H | ||
2 | #define __ASM_SH_PGALLOC_PMD_H | ||
3 | |||
4 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) | ||
5 | { | ||
6 | pgd_t *pgd; | ||
7 | int i; | ||
8 | |||
9 | pgd = kzalloc(sizeof(*pgd) * PTRS_PER_PGD, GFP_KERNEL | __GFP_REPEAT); | ||
10 | |||
11 | for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) | ||
12 | pgd[i] = swapper_pg_dir[i]; | ||
13 | |||
14 | return pgd; | ||
15 | } | ||
16 | |||
17 | static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) | ||
18 | { | ||
19 | kfree(pgd); | ||
20 | } | ||
21 | |||
22 | static inline void __check_pgt_cache(void) | ||
23 | { | ||
24 | } | ||
25 | |||
26 | static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) | ||
27 | { | ||
28 | set_pud(pud, __pud((unsigned long)pmd)); | ||
29 | } | ||
30 | |||
31 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address) | ||
32 | { | ||
33 | return quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL); | ||
34 | } | ||
35 | |||
36 | static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) | ||
37 | { | ||
38 | quicklist_free(QUICK_PT, NULL, pmd); | ||
39 | } | ||
40 | |||
41 | #endif /* __ASM_SH_PGALLOC_PMD_H */ | ||
diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h index 9effcc3b0d10..78598ec33d0a 100644 --- a/arch/sh/include/asm/pgtable.h +++ b/arch/sh/include/asm/pgtable.h | |||
@@ -141,9 +141,9 @@ typedef pte_t *pte_addr_t; | |||
141 | #define pte_pfn(x) ((unsigned long)(((x).pte_low >> PAGE_SHIFT))) | 141 | #define pte_pfn(x) ((unsigned long)(((x).pte_low >> PAGE_SHIFT))) |
142 | 142 | ||
143 | /* | 143 | /* |
144 | * No page table caches to initialise | 144 | * Initialise the page table caches |
145 | */ | 145 | */ |
146 | #define pgtable_cache_init() do { } while (0) | 146 | extern void pgtable_cache_init(void); |
147 | 147 | ||
148 | struct vm_area_struct; | 148 | struct vm_area_struct; |
149 | 149 | ||
diff --git a/arch/sh/include/asm/pgtable_64.h b/arch/sh/include/asm/pgtable_64.h index 17cdbecc3adc..dd381588c695 100644 --- a/arch/sh/include/asm/pgtable_64.h +++ b/arch/sh/include/asm/pgtable_64.h | |||
@@ -43,11 +43,6 @@ static __inline__ void set_pte(pte_t *pteptr, pte_t pteval) | |||
43 | } | 43 | } |
44 | #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) | 44 | #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) |
45 | 45 | ||
46 | static __inline__ void pmd_set(pmd_t *pmdp,pte_t *ptep) | ||
47 | { | ||
48 | pmd_val(*pmdp) = (unsigned long) ptep; | ||
49 | } | ||
50 | |||
51 | /* | 46 | /* |
52 | * PGD defines. Top level. | 47 | * PGD defines. Top level. |
53 | */ | 48 | */ |
@@ -203,12 +198,6 @@ static __inline__ void pmd_set(pmd_t *pmdp,pte_t *ptep) | |||
203 | #define pgprot_writecombine(prot) __pgprot(pgprot_val(prot) & ~_PAGE_CACHABLE) | 198 | #define pgprot_writecombine(prot) __pgprot(pgprot_val(prot) & ~_PAGE_CACHABLE) |
204 | 199 | ||
205 | /* | 200 | /* |
206 | * Handling allocation failures during page table setup. | ||
207 | */ | ||
208 | extern void __handle_bad_pmd_kernel(pmd_t * pmd); | ||
209 | #define __handle_bad_pmd(x) __handle_bad_pmd_kernel(x) | ||
210 | |||
211 | /* | ||
212 | * PTE level access routines. | 201 | * PTE level access routines. |
213 | * | 202 | * |
214 | * Note1: | 203 | * Note1: |
diff --git a/arch/sh/include/asm/pgtable_pmd.h b/arch/sh/include/asm/pgtable_pmd.h index 78dc36e1c2dd..42a180e534a8 100644 --- a/arch/sh/include/asm/pgtable_pmd.h +++ b/arch/sh/include/asm/pgtable_pmd.h | |||
@@ -17,11 +17,11 @@ | |||
17 | #define USER_PTRS_PER_PGD 2 | 17 | #define USER_PTRS_PER_PGD 2 |
18 | 18 | ||
19 | /* PMD bits */ | 19 | /* PMD bits */ |
20 | #define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT - 3)) | 20 | #define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT - PTE_MAGNITUDE)) |
21 | #define PMD_SIZE (1UL << PMD_SHIFT) | 21 | #define PMD_SIZE (1UL << PMD_SHIFT) |
22 | #define PMD_MASK (~(PMD_SIZE-1)) | 22 | #define PMD_MASK (~(PMD_SIZE-1)) |
23 | 23 | ||
24 | #define PTRS_PER_PMD (PAGE_SIZE / sizeof(pmd_t)) | 24 | #define PTRS_PER_PMD ((1 << PGDIR_SHIFT) / PMD_SIZE) |
25 | 25 | ||
26 | #define pmd_ERROR(e) \ | 26 | #define pmd_ERROR(e) \ |
27 | printk("%s:%d: bad pmd %016llx.\n", __FILE__, __LINE__, pmd_val(e)) | 27 | printk("%s:%d: bad pmd %016llx.\n", __FILE__, __LINE__, pmd_val(e)) |
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig index a5dedf590a78..358c860aeb9b 100644 --- a/arch/sh/mm/Kconfig +++ b/arch/sh/mm/Kconfig | |||
@@ -219,7 +219,7 @@ config PAGE_SIZE_4KB | |||
219 | 219 | ||
220 | config PAGE_SIZE_8KB | 220 | config PAGE_SIZE_8KB |
221 | bool "8kB" | 221 | bool "8kB" |
222 | depends on !MMU || X2TLB && !PGTABLE_LEVELS_3 | 222 | depends on !MMU || X2TLB |
223 | help | 223 | help |
224 | This enables 8kB pages as supported by SH-X2 and later MMUs. | 224 | This enables 8kB pages as supported by SH-X2 and later MMUs. |
225 | 225 | ||
@@ -231,7 +231,7 @@ config PAGE_SIZE_16KB | |||
231 | 231 | ||
232 | config PAGE_SIZE_64KB | 232 | config PAGE_SIZE_64KB |
233 | bool "64kB" | 233 | bool "64kB" |
234 | depends on !MMU || CPU_SH4 && !PGTABLE_LEVELS_3 || CPU_SH5 | 234 | depends on !MMU || CPU_SH4 || CPU_SH5 |
235 | help | 235 | help |
236 | This enables support for 64kB pages, possible on all SH-4 | 236 | This enables support for 64kB pages, possible on all SH-4 |
237 | CPUs and later. | 237 | CPUs and later. |
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile index 8a70535fa7ce..dd5010c708e0 100644 --- a/arch/sh/mm/Makefile +++ b/arch/sh/mm/Makefile | |||
@@ -15,7 +15,7 @@ obj-y += $(cacheops-y) | |||
15 | 15 | ||
16 | mmu-y := nommu.o extable_32.o | 16 | mmu-y := nommu.o extable_32.o |
17 | mmu-$(CONFIG_MMU) := extable_$(BITS).o fault_$(BITS).o \ | 17 | mmu-$(CONFIG_MMU) := extable_$(BITS).o fault_$(BITS).o \ |
18 | ioremap_$(BITS).o kmap.o tlbflush_$(BITS).o | 18 | ioremap_$(BITS).o kmap.o pgtable.o tlbflush_$(BITS).o |
19 | 19 | ||
20 | obj-y += $(mmu-y) | 20 | obj-y += $(mmu-y) |
21 | obj-$(CONFIG_DEBUG_FS) += asids-debugfs.o | 21 | obj-$(CONFIG_DEBUG_FS) += asids-debugfs.o |
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c index 560ddb6bc8a7..a2301daeefa3 100644 --- a/arch/sh/mm/cache-sh4.c +++ b/arch/sh/mm/cache-sh4.c | |||
@@ -109,6 +109,7 @@ static inline void flush_cache_one(unsigned long start, unsigned long phys) | |||
109 | static void sh4_flush_dcache_page(void *arg) | 109 | static void sh4_flush_dcache_page(void *arg) |
110 | { | 110 | { |
111 | struct page *page = arg; | 111 | struct page *page = arg; |
112 | unsigned long addr = (unsigned long)page_address(page); | ||
112 | #ifndef CONFIG_SMP | 113 | #ifndef CONFIG_SMP |
113 | struct address_space *mapping = page_mapping(page); | 114 | struct address_space *mapping = page_mapping(page); |
114 | 115 | ||
@@ -116,16 +117,8 @@ static void sh4_flush_dcache_page(void *arg) | |||
116 | set_bit(PG_dcache_dirty, &page->flags); | 117 | set_bit(PG_dcache_dirty, &page->flags); |
117 | else | 118 | else |
118 | #endif | 119 | #endif |
119 | { | 120 | flush_cache_one(CACHE_OC_ADDRESS_ARRAY | |
120 | unsigned long phys = page_to_phys(page); | 121 | (addr & shm_align_mask), page_to_phys(page)); |
121 | unsigned long addr = CACHE_OC_ADDRESS_ARRAY; | ||
122 | int i, n; | ||
123 | |||
124 | /* Loop all the D-cache */ | ||
125 | n = boot_cpu_data.dcache.n_aliases; | ||
126 | for (i = 0; i < n; i++, addr += PAGE_SIZE) | ||
127 | flush_cache_one(addr, phys); | ||
128 | } | ||
129 | 122 | ||
130 | wmb(); | 123 | wmb(); |
131 | } | 124 | } |
diff --git a/arch/sh/mm/pgtable.c b/arch/sh/mm/pgtable.c new file mode 100644 index 000000000000..e1bc5483cc07 --- /dev/null +++ b/arch/sh/mm/pgtable.c | |||
@@ -0,0 +1,57 @@ | |||
1 | #include <linux/mm.h> | ||
2 | |||
3 | #define PGALLOC_GFP GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO | ||
4 | |||
5 | static struct kmem_cache *pgd_cachep; | ||
6 | |||
7 | #ifdef CONFIG_PGTABLE_LEVELS_3 | ||
8 | static struct kmem_cache *pmd_cachep; | ||
9 | #endif | ||
10 | |||
11 | void pgd_ctor(void *x) | ||
12 | { | ||
13 | pgd_t *pgd = x; | ||
14 | |||
15 | memcpy(pgd + USER_PTRS_PER_PGD, | ||
16 | swapper_pg_dir + USER_PTRS_PER_PGD, | ||
17 | (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); | ||
18 | } | ||
19 | |||
20 | void pgtable_cache_init(void) | ||
21 | { | ||
22 | pgd_cachep = kmem_cache_create("pgd_cache", | ||
23 | PTRS_PER_PGD * (1<<PTE_MAGNITUDE), | ||
24 | PAGE_SIZE, SLAB_PANIC, pgd_ctor); | ||
25 | #ifdef CONFIG_PGTABLE_LEVELS_3 | ||
26 | pmd_cachep = kmem_cache_create("pmd_cache", | ||
27 | PTRS_PER_PMD * (1<<PTE_MAGNITUDE), | ||
28 | PAGE_SIZE, SLAB_PANIC, NULL); | ||
29 | #endif | ||
30 | } | ||
31 | |||
32 | pgd_t *pgd_alloc(struct mm_struct *mm) | ||
33 | { | ||
34 | return kmem_cache_alloc(pgd_cachep, PGALLOC_GFP); | ||
35 | } | ||
36 | |||
37 | void pgd_free(struct mm_struct *mm, pgd_t *pgd) | ||
38 | { | ||
39 | kmem_cache_free(pgd_cachep, pgd); | ||
40 | } | ||
41 | |||
42 | #ifdef CONFIG_PGTABLE_LEVELS_3 | ||
43 | void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) | ||
44 | { | ||
45 | set_pud(pud, __pud((unsigned long)pmd)); | ||
46 | } | ||
47 | |||
48 | pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address) | ||
49 | { | ||
50 | return kmem_cache_alloc(pmd_cachep, PGALLOC_GFP); | ||
51 | } | ||
52 | |||
53 | void pmd_free(struct mm_struct *mm, pmd_t *pmd) | ||
54 | { | ||
55 | kmem_cache_free(pmd_cachep, pmd); | ||
56 | } | ||
57 | #endif /* CONFIG_PGTABLE_LEVELS_3 */ | ||