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 коммит произвёл Russell King
Родитель 369842658a
Коммит 65cec8e3db
4 изменённых файлов: 31 добавлений и 8 удалений

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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