Skip to content

Commit

Permalink
ARM: implement highpte
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Russell King authored and Russell King committed Aug 17, 2009
1 parent 3698426 commit 65cec8e
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 8 deletions.
5 changes: 5 additions & 0 deletions arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 12 additions & 4 deletions arch/arm/include/asm/pgalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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;
Expand All @@ -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);
}

Expand Down
17 changes: 13 additions & 4 deletions arch/arm/include/asm/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
1 change: 1 addition & 0 deletions arch/arm/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down

0 comments on commit 65cec8e

Please sign in to comment.