[PATCH] Hugepage consolidation
A lot of the code in arch/*/mm/hugetlbpage.c is quite similar. This patch attempts to consolidate a lot of the code across the arch's, putting the combined version in mm/hugetlb.c. There are a couple of uglyish hacks in order to covert all the hugepage archs, but the result is a very large reduction in the total amount of code. It also means things like hugepage lazy allocation could be implemented in one place, instead of six. Tested, at least a little, on ppc64, i386 and x86_64. Notes: - this patch changes the meaning of set_huge_pte() to be more analagous to set_pte() - does SH4 need s special huge_ptep_get_and_clear()?? Acked-by: William Lee Irwin <wli@holomorphy.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
committed by
Linus Torvalds
parent
1e7e5a9048
commit
63551ae0fe
@@ -68,6 +68,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
|
||||
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
|
||||
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
|
||||
#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
|
||||
#define ARCH_HAS_HUGETLB_CLEAN_STALE_PGTABLE
|
||||
#endif
|
||||
|
||||
#define pgd_val(x) ((x).pgd)
|
||||
|
||||
@@ -236,6 +236,7 @@ static inline pte_t pte_mkexec(pte_t pte) { (pte).pte_low |= _PAGE_USER; return
|
||||
static inline pte_t pte_mkdirty(pte_t pte) { (pte).pte_low |= _PAGE_DIRTY; return pte; }
|
||||
static inline pte_t pte_mkyoung(pte_t pte) { (pte).pte_low |= _PAGE_ACCESSED; return pte; }
|
||||
static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte_low |= _PAGE_RW; return pte; }
|
||||
static inline pte_t pte_mkhuge(pte_t pte) { (pte).pte_low |= _PAGE_PRESENT | _PAGE_PSE; return pte; }
|
||||
|
||||
#ifdef CONFIG_X86_PAE
|
||||
# include <asm/pgtable-3level.h>
|
||||
@@ -275,7 +276,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
|
||||
*/
|
||||
|
||||
#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
|
||||
#define mk_pte_huge(entry) ((entry).pte_low |= _PAGE_PRESENT | _PAGE_PSE)
|
||||
|
||||
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
||||
{
|
||||
|
||||
@@ -283,6 +283,7 @@ ia64_phys_addr_valid (unsigned long addr)
|
||||
#define pte_mkyoung(pte) (__pte(pte_val(pte) | _PAGE_A))
|
||||
#define pte_mkclean(pte) (__pte(pte_val(pte) & ~_PAGE_D))
|
||||
#define pte_mkdirty(pte) (__pte(pte_val(pte) | _PAGE_D))
|
||||
#define pte_mkhuge(pte) (__pte(pte_val(pte) | _PAGE_P))
|
||||
|
||||
/*
|
||||
* Macro to a page protection value as "uncacheable". Note that "protection" is really a
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#define HPAGE_SIZE (1UL << HPAGE_SHIFT)
|
||||
#define HPAGE_MASK (~(HPAGE_SIZE-1))
|
||||
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT-PAGE_SHIFT)
|
||||
#define ARCH_HAS_SETCLEAR_HUGE_PTE
|
||||
#endif
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
@@ -196,6 +196,7 @@ static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _
|
||||
static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
|
||||
static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
|
||||
static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
|
||||
static inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
|
||||
|
||||
/*
|
||||
* Macro and implementation to make a page protection as uncachable.
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#define HPAGE_SIZE (1UL << HPAGE_SHIFT)
|
||||
#define HPAGE_MASK (~(HPAGE_SIZE-1))
|
||||
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT-PAGE_SHIFT)
|
||||
#define ARCH_HAS_SETCLEAR_HUGE_PTE
|
||||
#endif
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
@@ -430,6 +430,8 @@ extern inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) |
|
||||
extern inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_EXECUTE)); return pte; }
|
||||
extern inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
|
||||
extern inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
|
||||
extern inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
|
||||
|
||||
|
||||
/*
|
||||
* Conversion functions: convert a page and protection to a page entry.
|
||||
|
||||
@@ -95,6 +95,8 @@ typedef unsigned long pgprot_t;
|
||||
#define HPAGE_SIZE (_AC(1,UL) << HPAGE_SHIFT)
|
||||
#define HPAGE_MASK (~(HPAGE_SIZE - 1UL))
|
||||
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
|
||||
#define ARCH_HAS_SETCLEAR_HUGE_PTE
|
||||
#define ARCH_HAS_HUGETLB_PREFAULT_HOOK
|
||||
#endif
|
||||
|
||||
#define TASK_UNMAPPED_BASE (test_thread_flag(TIF_32BIT) ? \
|
||||
|
||||
@@ -286,6 +286,7 @@ static inline pte_t pte_modify(pte_t orig_pte, pgprot_t new_prot)
|
||||
#define pte_mkyoung(pte) (__pte(pte_val(pte) | _PAGE_ACCESSED | _PAGE_R))
|
||||
#define pte_mkwrite(pte) (__pte(pte_val(pte) | _PAGE_WRITE))
|
||||
#define pte_mkdirty(pte) (__pte(pte_val(pte) | _PAGE_MODIFIED | _PAGE_W))
|
||||
#define pte_mkhuge(pte) (__pte(pte_val(pte) | _PAGE_SZHUGE))
|
||||
|
||||
/* to find an entry in a page-table-directory. */
|
||||
#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT)
|
||||
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
|
||||
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
|
||||
#define ARCH_HAS_HUGETLB_CLEAN_STALE_PGTABLE
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
@@ -253,6 +253,7 @@ extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;
|
||||
extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
|
||||
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
|
||||
|
||||
#define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
|
||||
extern inline pte_t pte_rdprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
|
||||
extern inline pte_t pte_exprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
|
||||
extern inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
|
||||
@@ -263,6 +264,7 @@ extern inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _
|
||||
extern inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
|
||||
extern inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
|
||||
extern inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
|
||||
extern inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | __LARGE_PTE)); return pte; }
|
||||
|
||||
struct vm_area_struct;
|
||||
|
||||
@@ -290,7 +292,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
|
||||
*/
|
||||
#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT))
|
||||
|
||||
#define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
|
||||
static inline int pmd_large(pmd_t pte) {
|
||||
return (pmd_val(pte) & __LARGE_PTE) == __LARGE_PTE;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
|
||||
#include <linux/mempolicy.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
struct ctl_table;
|
||||
|
||||
@@ -22,12 +23,6 @@ int hugetlb_report_meminfo(char *);
|
||||
int hugetlb_report_node_meminfo(int, char *);
|
||||
int is_hugepage_mem_enough(size_t);
|
||||
unsigned long hugetlb_total_pages(void);
|
||||
struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
|
||||
int write);
|
||||
struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
|
||||
pmd_t *pmd, int write);
|
||||
int is_aligned_hugepage_range(unsigned long addr, unsigned long len);
|
||||
int pmd_huge(pmd_t pmd);
|
||||
struct page *alloc_huge_page(void);
|
||||
void free_huge_page(struct page *);
|
||||
|
||||
@@ -35,6 +30,17 @@ extern unsigned long max_huge_pages;
|
||||
extern const unsigned long hugetlb_zero, hugetlb_infinity;
|
||||
extern int sysctl_hugetlb_shm_group;
|
||||
|
||||
/* arch callbacks */
|
||||
|
||||
pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr);
|
||||
pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr);
|
||||
struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
|
||||
int write);
|
||||
struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
|
||||
pmd_t *pmd, int write);
|
||||
int is_aligned_hugepage_range(unsigned long addr, unsigned long len);
|
||||
int pmd_huge(pmd_t pmd);
|
||||
|
||||
#ifndef ARCH_HAS_HUGEPAGE_ONLY_RANGE
|
||||
#define is_hugepage_only_range(mm, addr, len) 0
|
||||
#define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) \
|
||||
@@ -48,6 +54,28 @@ extern int sysctl_hugetlb_shm_group;
|
||||
int prepare_hugepage_range(unsigned long addr, unsigned long len);
|
||||
#endif
|
||||
|
||||
#ifndef ARCH_HAS_SETCLEAR_HUGE_PTE
|
||||
#define set_huge_pte_at(mm, addr, ptep, pte) set_pte_at(mm, addr, ptep, pte)
|
||||
#define huge_ptep_get_and_clear(mm, addr, ptep) ptep_get_and_clear(mm, addr, ptep)
|
||||
#else
|
||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte);
|
||||
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep);
|
||||
#endif
|
||||
|
||||
#ifndef ARCH_HAS_HUGETLB_PREFAULT_HOOK
|
||||
#define hugetlb_prefault_arch_hook(mm) do { } while (0)
|
||||
#else
|
||||
void hugetlb_prefault_arch_hook(struct mm_struct *mm);
|
||||
#endif
|
||||
|
||||
#ifndef ARCH_HAS_HUGETLB_CLEAN_STALE_PGTABLE
|
||||
#define hugetlb_clean_stale_pgtable(pte) BUG()
|
||||
#else
|
||||
void hugetlb_clean_stale_pgtable(pte_t *pte);
|
||||
#endif
|
||||
|
||||
#else /* !CONFIG_HUGETLB_PAGE */
|
||||
|
||||
static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
|
||||
|
||||
Reference in New Issue
Block a user