aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2009-08-17 15:02:06 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2009-08-17 15:02:06 -0400
commit65cec8e3db606608fd1f8dfc4a1c7c37bfba9173 (patch)
treeb1e0ecd6380afa2286fffada08cddbd388640343
parent369842658a36bcea28ecb643ba4bdb53919330dd (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/Kconfig5
-rw-r--r--arch/arm/include/asm/pgalloc.h16
-rw-r--r--arch/arm/include/asm/pgtable.h17
-rw-r--r--arch/arm/mm/fault.c1
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
1057config HIGHPTE
1058 bool "Allocate 2nd-level pagetables from highmem"
1059 depends on HIGHMEM
1060 depends on !OUTER_CACHE
1061
1057source "mm/Kconfig" 1062source "mm/Kconfig"
1058 1063
1059config LEDS 1064config 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>