hugetlb: introduce pud_huge
authorAndi Kleen <ak@suse.de>
Thu, 24 Jul 2008 04:27:50 +0000 (21:27 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 24 Jul 2008 17:47:18 +0000 (10:47 -0700)
Straight forward extensions for huge pages located in the PUD instead of
PMDs.

Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Nick Piggin <npiggin@suse.de>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/ia64/mm/hugetlbpage.c
arch/powerpc/mm/hugetlbpage.c
arch/s390/mm/hugetlbpage.c
arch/sh/mm/hugetlbpage.c
arch/sparc64/mm/hugetlbpage.c
arch/x86/mm/hugetlbpage.c
include/linux/hugetlb.h
mm/hugetlb.c
mm/memory.c

index 6170f097d2554d60f2828302393172e57d3839b8..c45fc7f5a979b6064b7e8a403de1922b21adf6df 100644 (file)
@@ -107,6 +107,12 @@ int pmd_huge(pmd_t pmd)
 {
        return 0;
 }
+
+int pud_huge(pud_t pud)
+{
+       return 0;
+}
+
 struct page *
 follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int write)
 {
index c94dc71af989277007c33ee3f804ee561d944c33..63db7adce7175d5a372b5f402cbfd78ed126aafe 100644 (file)
@@ -369,6 +369,11 @@ int pmd_huge(pmd_t pmd)
        return 0;
 }
 
+int pud_huge(pud_t pud)
+{
+       return 0;
+}
+
 struct page *
 follow_huge_pmd(struct mm_struct *mm, unsigned long address,
                pmd_t *pmd, int write)
index 9162dc84f77f685c6f66383276660d6d7c049a71..f28c43d2f61dd6b679b8cc8afb14c12e57e33273 100644 (file)
@@ -120,6 +120,11 @@ int pmd_huge(pmd_t pmd)
        return !!(pmd_val(pmd) & _SEGMENT_ENTRY_LARGE);
 }
 
+int pud_huge(pud_t pud)
+{
+       return 0;
+}
+
 struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
                             pmd_t *pmdp, int write)
 {
index 2f9dbe0ef4acd57144e8575919aadd0442ddc054..9304117039c4f887d7a94f70e48a73c6d1549ef8 100644 (file)
@@ -79,6 +79,11 @@ int pmd_huge(pmd_t pmd)
        return 0;
 }
 
+int pud_huge(pud_t pud)
+{
+       return 0;
+}
+
 struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
                             pmd_t *pmd, int write)
 {
index 1307b23f6a7636e1d040a5a16232e283da8578fe..f27d10369e0cdea561c78c7e3be4e0b326ffd8be 100644 (file)
@@ -295,6 +295,11 @@ int pmd_huge(pmd_t pmd)
        return 0;
 }
 
+int pud_huge(pud_t pud)
+{
+       return 0;
+}
+
 struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
                             pmd_t *pmd, int write)
 {
index 52476fde8996669d7eed87e7f96ea2984a3a308a..a4789e87a31556de14895457b89cca24c49c88d7 100644 (file)
@@ -189,6 +189,11 @@ int pmd_huge(pmd_t pmd)
        return 0;
 }
 
+int pud_huge(pud_t pud)
+{
+       return 0;
+}
+
 struct page *
 follow_huge_pmd(struct mm_struct *mm, unsigned long address,
                pmd_t *pmd, int write)
@@ -209,6 +214,11 @@ int pmd_huge(pmd_t pmd)
        return !!(pmd_val(pmd) & _PAGE_PSE);
 }
 
+int pud_huge(pud_t pud)
+{
+       return 0;
+}
+
 struct page *
 follow_huge_pmd(struct mm_struct *mm, unsigned long address,
                pmd_t *pmd, int write)
@@ -217,9 +227,22 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
 
        page = pte_page(*(pte_t *)pmd);
        if (page)
-               page += ((address & ~HPAGE_MASK) >> PAGE_SHIFT);
+               page += ((address & ~PMD_MASK) >> PAGE_SHIFT);
        return page;
 }
+
+struct page *
+follow_huge_pud(struct mm_struct *mm, unsigned long address,
+               pud_t *pud, int write)
+{
+       struct page *page;
+
+       page = pte_page(*(pte_t *)pud);
+       if (page)
+               page += ((address & ~PUD_MASK) >> PAGE_SHIFT);
+       return page;
+}
+
 #endif
 
 /* x86_64 also uses this file */
index 58c0de32e7f0099882bf7611c13847acc8ef3b6f..b2c17f62cacbf169742a69509adf31e82639cb21 100644 (file)
@@ -50,7 +50,10 @@ 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);
+struct page *follow_huge_pud(struct mm_struct *mm, unsigned long address,
+                               pud_t *pud, int write);
 int pmd_huge(pmd_t pmd);
+int pud_huge(pud_t pmd);
 void hugetlb_change_protection(struct vm_area_struct *vma,
                unsigned long address, unsigned long end, pgprot_t newprot);
 
@@ -78,8 +81,10 @@ static inline unsigned long hugetlb_total_pages(void)
 #define hugetlb_report_meminfo(buf)            0
 #define hugetlb_report_node_meminfo(n, buf)    0
 #define follow_huge_pmd(mm, addr, pmd, write)  NULL
+#define follow_huge_pud(mm, addr, pud, write)  NULL
 #define prepare_hugepage_range(file, addr, len)        (-EINVAL)
 #define pmd_huge(x)    0
+#define pud_huge(x)    0
 #define is_hugepage_only_range(mm, addr, len)  0
 #define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) ({BUG(); 0; })
 #define hugetlb_fault(mm, vma, addr, write)    ({ BUG(); 0; })
index 0c74c14dd2f7a367de4b034c0c5e0d870c02b905..107c1ce223cbd44bc0392c6c8a4c6c6fb4438193 100644 (file)
@@ -1996,6 +1996,15 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        return ret;
 }
 
+/* Can be overriden by architectures */
+__attribute__((weak)) struct page *
+follow_huge_pud(struct mm_struct *mm, unsigned long address,
+              pud_t *pud, int write)
+{
+       BUG();
+       return NULL;
+}
+
 int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
                        struct page **pages, struct vm_area_struct **vmas,
                        unsigned long *position, int *length, int i,
index 02fc6b1047b025a403621fded8a8d5bbe6ba38c4..262e3eb6601a7ca1601c16a69d82814e7a9ea52b 100644 (file)
@@ -998,19 +998,24 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
                goto no_page_table;
 
        pud = pud_offset(pgd, address);
-       if (pud_none(*pud) || unlikely(pud_bad(*pud)))
+       if (pud_none(*pud))
+               goto no_page_table;
+       if (pud_huge(*pud)) {
+               BUG_ON(flags & FOLL_GET);
+               page = follow_huge_pud(mm, address, pud, flags & FOLL_WRITE);
+               goto out;
+       }
+       if (unlikely(pud_bad(*pud)))
                goto no_page_table;
-       
+
        pmd = pmd_offset(pud, address);
        if (pmd_none(*pmd))
                goto no_page_table;
-
        if (pmd_huge(*pmd)) {
                BUG_ON(flags & FOLL_GET);
                page = follow_huge_pmd(mm, address, pmd, flags & FOLL_WRITE);
                goto out;
        }
-
        if (unlikely(pmd_bad(*pmd)))
                goto no_page_table;
 
@@ -1567,6 +1572,8 @@ static int apply_to_pmd_range(struct mm_struct *mm, pud_t *pud,
        unsigned long next;
        int err;
 
+       BUG_ON(pud_huge(*pud));
+
        pmd = pmd_alloc(mm, pud, addr);
        if (!pmd)
                return -ENOMEM;