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:
parent
369842658a
commit
65cec8e3db
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user