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>
This commit is contained in:
Russell King 2009-08-17 20:02:06 +01:00 committed by Russell King
parent 369842658a
commit 65cec8e3db
4 changed files with 31 additions and 8 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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)

View File

@ -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>