Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Russell King and committed by
Russell King
65cec8e3 36984265

+31 -8
+5
arch/arm/Kconfig
··· 1054 1054 1055 1055 If unsure, say n. 1056 1056 1057 + config HIGHPTE 1058 + bool "Allocate 2nd-level pagetables from highmem" 1059 + depends on HIGHMEM 1060 + depends on !OUTER_CACHE 1061 + 1057 1062 source "mm/Kconfig" 1058 1063 1059 1064 config LEDS
+12 -4
arch/arm/include/asm/pgalloc.h
··· 36 36 #define pgd_alloc(mm) get_pgd_slow(mm) 37 37 #define pgd_free(mm, pgd) free_pgd_slow(mm, pgd) 38 38 39 + #define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO) 40 + 39 41 /* 40 42 * Allocate one PTE table. 41 43 * ··· 59 57 { 60 58 pte_t *pte; 61 59 62 - pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); 60 + pte = (pte_t *)__get_free_page(PGALLOC_GFP); 63 61 if (pte) { 64 62 clean_dcache_area(pte, sizeof(pte_t) * PTRS_PER_PTE); 65 63 pte += PTRS_PER_PTE; ··· 73 71 { 74 72 struct page *pte; 75 73 76 - pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0); 74 + #ifdef CONFIG_HIGHPTE 75 + pte = alloc_pages(PGALLOC_GFP | __GFP_HIGHMEM, 0); 76 + #else 77 + pte = alloc_pages(PGALLOC_GFP, 0); 78 + #endif 77 79 if (pte) { 78 - void *page = page_address(pte); 79 - clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE); 80 + if (!PageHighMem(pte)) { 81 + void *page = page_address(pte); 82 + clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE); 83 + } 80 84 pgtable_page_ctor(pte); 81 85 } 82 86
+13 -4
arch/arm/include/asm/pgtable.h
··· 262 262 #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) 263 263 #define pte_page(pte) (pfn_to_page(pte_pfn(pte))) 264 264 #define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) 265 - #define pte_offset_map(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) 266 - #define pte_offset_map_nested(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) 267 - #define pte_unmap(pte) do { } while (0) 268 - #define pte_unmap_nested(pte) do { } while (0) 265 + 266 + #define pte_offset_map(dir,addr) (__pte_map(dir, KM_PTE0) + __pte_index(addr)) 267 + #define pte_offset_map_nested(dir,addr) (__pte_map(dir, KM_PTE1) + __pte_index(addr)) 268 + #define pte_unmap(pte) __pte_unmap(pte, KM_PTE0) 269 + #define pte_unmap_nested(pte) __pte_unmap(pte, KM_PTE1) 270 + 271 + #ifndef CONFIG_HIGHPTE 272 + #define __pte_map(dir,km) pmd_page_vaddr(*(dir)) 273 + #define __pte_unmap(pte,km) do { } while (0) 274 + #else 275 + #define __pte_map(dir,km) ((pte_t *)kmap_atomic(pmd_page(*(dir)), km) + PTRS_PER_PTE) 276 + #define __pte_unmap(pte,km) kunmap_atomic((pte - PTRS_PER_PTE), km) 277 + #endif 269 278 270 279 #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext) 271 280
+1
arch/arm/mm/fault.c
··· 16 16 #include <linux/kprobes.h> 17 17 #include <linux/uaccess.h> 18 18 #include <linux/page-flags.h> 19 + #include <linux/highmem.h> 19 20 20 21 #include <asm/system.h> 21 22 #include <asm/pgtable.h>