diff options
-rw-r--r-- | arch/arm/Kconfig | 5 | ||||
-rw-r--r-- | arch/arm/include/asm/pgalloc.h | 16 | ||||
-rw-r--r-- | arch/arm/include/asm/pgtable.h | 17 | ||||
-rw-r--r-- | arch/arm/mm/fault.c | 1 |
4 files changed, 31 insertions, 8 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index aef63c8e3d2d..370f47787122 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -1054,6 +1054,11 @@ config HIGHMEM | |||
1054 | 1054 | ||
1055 | If unsure, say n. | 1055 | If unsure, say n. |
1056 | 1056 | ||
1057 | config HIGHPTE | ||
1058 | bool "Allocate 2nd-level pagetables from highmem" | ||
1059 | depends on HIGHMEM | ||
1060 | depends on !OUTER_CACHE | ||
1061 | |||
1057 | source "mm/Kconfig" | 1062 | source "mm/Kconfig" |
1058 | 1063 | ||
1059 | config LEDS | 1064 | config LEDS |
diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h index 3dcd64bf1824..b12cc98bbe04 100644 --- a/arch/arm/include/asm/pgalloc.h +++ b/arch/arm/include/asm/pgalloc.h | |||
@@ -36,6 +36,8 @@ extern void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd); | |||
36 | #define pgd_alloc(mm) get_pgd_slow(mm) | 36 | #define pgd_alloc(mm) get_pgd_slow(mm) |
37 | #define pgd_free(mm, pgd) free_pgd_slow(mm, pgd) | 37 | #define pgd_free(mm, pgd) free_pgd_slow(mm, pgd) |
38 | 38 | ||
39 | #define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO) | ||
40 | |||
39 | /* | 41 | /* |
40 | * Allocate one PTE table. | 42 | * Allocate one PTE table. |
41 | * | 43 | * |
@@ -57,7 +59,7 @@ pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) | |||
57 | { | 59 | { |
58 | pte_t *pte; | 60 | pte_t *pte; |
59 | 61 | ||
60 | pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); | 62 | pte = (pte_t *)__get_free_page(PGALLOC_GFP); |
61 | if (pte) { | 63 | if (pte) { |
62 | clean_dcache_area(pte, sizeof(pte_t) * PTRS_PER_PTE); | 64 | clean_dcache_area(pte, sizeof(pte_t) * PTRS_PER_PTE); |
63 | pte += PTRS_PER_PTE; | 65 | pte += PTRS_PER_PTE; |
@@ -71,10 +73,16 @@ pte_alloc_one(struct mm_struct *mm, unsigned long addr) | |||
71 | { | 73 | { |
72 | struct page *pte; | 74 | struct page *pte; |
73 | 75 | ||
74 | pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0); | 76 | #ifdef CONFIG_HIGHPTE |
77 | pte = alloc_pages(PGALLOC_GFP | __GFP_HIGHMEM, 0); | ||
78 | #else | ||
79 | pte = alloc_pages(PGALLOC_GFP, 0); | ||
80 | #endif | ||
75 | if (pte) { | 81 | if (pte) { |
76 | void *page = page_address(pte); | 82 | if (!PageHighMem(pte)) { |
77 | clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE); | 83 | void *page = page_address(pte); |
84 | clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE); | ||
85 | } | ||
78 | pgtable_page_ctor(pte); | 86 | pgtable_page_ctor(pte); |
79 | } | 87 | } |
80 | 88 | ||
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 9655bce3d345..201ccaa11f61 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h | |||
@@ -262,10 +262,19 @@ extern struct page *empty_zero_page; | |||
262 | #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) | 262 | #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) |
263 | #define pte_page(pte) (pfn_to_page(pte_pfn(pte))) | 263 | #define pte_page(pte) (pfn_to_page(pte_pfn(pte))) |
264 | #define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) | 264 | #define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) |
265 | #define pte_offset_map(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) | 265 | |
266 | #define pte_offset_map_nested(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) | 266 | #define pte_offset_map(dir,addr) (__pte_map(dir, KM_PTE0) + __pte_index(addr)) |
267 | #define pte_unmap(pte) do { } while (0) | 267 | #define pte_offset_map_nested(dir,addr) (__pte_map(dir, KM_PTE1) + __pte_index(addr)) |
268 | #define pte_unmap_nested(pte) do { } while (0) | 268 | #define pte_unmap(pte) __pte_unmap(pte, KM_PTE0) |
269 | #define pte_unmap_nested(pte) __pte_unmap(pte, KM_PTE1) | ||
270 | |||
271 | #ifndef CONFIG_HIGHPTE | ||
272 | #define __pte_map(dir,km) pmd_page_vaddr(*(dir)) | ||
273 | #define __pte_unmap(pte,km) do { } while (0) | ||
274 | #else | ||
275 | #define __pte_map(dir,km) ((pte_t *)kmap_atomic(pmd_page(*(dir)), km) + PTRS_PER_PTE) | ||
276 | #define __pte_unmap(pte,km) kunmap_atomic((pte - PTRS_PER_PTE), km) | ||
277 | #endif | ||
269 | 278 | ||
270 | #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext) | 279 | #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext) |
271 | 280 | ||
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 6fdcbb709827..5fa8dea5a371 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/kprobes.h> | 16 | #include <linux/kprobes.h> |
17 | #include <linux/uaccess.h> | 17 | #include <linux/uaccess.h> |
18 | #include <linux/page-flags.h> | 18 | #include <linux/page-flags.h> |
19 | #include <linux/highmem.h> | ||
19 | 20 | ||
20 | #include <asm/system.h> | 21 | #include <asm/system.h> |
21 | #include <asm/pgtable.h> | 22 | #include <asm/pgtable.h> |