diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2009-08-17 15:02:06 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-08-17 15:02:06 -0400 |
commit | 65cec8e3db606608fd1f8dfc4a1c7c37bfba9173 (patch) | |
tree | b1e0ecd6380afa2286fffada08cddbd388640343 | |
parent | 369842658a36bcea28ecb643ba4bdb53919330dd (diff) |
ARM: implement highpte
Add the ARM implementation of highpte, which allows PTE tables to be
placed in highmem. Unfortunately, we do not offer highpte support
when support for L2 cache is enabled.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-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> |