diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2009-08-17 20:02:06 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-08-17 20:02:06 +0100 |
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 aef63c8e3d2..370f4778712 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1054,6 +1054,11 @@ config HIGHMEM If unsure, say n. +config HIGHPTE + bool "Allocate 2nd-level pagetables from highmem" + depends on HIGHMEM + depends on !OUTER_CACHE + source "mm/Kconfig" config LEDS diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h index 3dcd64bf182..b12cc98bbe0 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); #define pgd_alloc(mm) get_pgd_slow(mm) #define pgd_free(mm, pgd) free_pgd_slow(mm, pgd) +#define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO) + /* * Allocate one PTE table. * @@ -57,7 +59,7 @@ pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) { pte_t *pte; - pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); + pte = (pte_t *)__get_free_page(PGALLOC_GFP); if (pte) { clean_dcache_area(pte, sizeof(pte_t) * PTRS_PER_PTE); pte += PTRS_PER_PTE; @@ -71,10 +73,16 @@ pte_alloc_one(struct mm_struct *mm, unsigned long addr) { struct page *pte; - pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0); +#ifdef CONFIG_HIGHPTE + pte = alloc_pages(PGALLOC_GFP | __GFP_HIGHMEM, 0); +#else + pte = alloc_pages(PGALLOC_GFP, 0); +#endif if (pte) { - void *page = page_address(pte); - clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE); + if (!PageHighMem(pte)) { + void *page = page_address(pte); + clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE); + } pgtable_page_ctor(pte); } diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 9655bce3d34..201ccaa11f6 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; #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) #define pte_page(pte) (pfn_to_page(pte_pfn(pte))) #define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) -#define pte_offset_map(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) -#define pte_offset_map_nested(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) -#define pte_unmap(pte) do { } while (0) -#define pte_unmap_nested(pte) do { } while (0) + +#define pte_offset_map(dir,addr) (__pte_map(dir, KM_PTE0) + __pte_index(addr)) +#define pte_offset_map_nested(dir,addr) (__pte_map(dir, KM_PTE1) + __pte_index(addr)) +#define pte_unmap(pte) __pte_unmap(pte, KM_PTE0) +#define pte_unmap_nested(pte) __pte_unmap(pte, KM_PTE1) + +#ifndef CONFIG_HIGHPTE +#define __pte_map(dir,km) pmd_page_vaddr(*(dir)) +#define __pte_unmap(pte,km) do { } while (0) +#else +#define __pte_map(dir,km) ((pte_t *)kmap_atomic(pmd_page(*(dir)), km) + PTRS_PER_PTE) +#define __pte_unmap(pte,km) kunmap_atomic((pte - PTRS_PER_PTE), km) +#endif #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext) diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 6fdcbb70982..5fa8dea5a37 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -16,6 +16,7 @@ #include <linux/kprobes.h> #include <linux/uaccess.h> #include <linux/page-flags.h> +#include <linux/highmem.h> #include <asm/system.h> #include <asm/pgtable.h> |