aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ia64/mm/hugetlbpage.c6
-rw-r--r--arch/powerpc/mm/hugetlbpage.c5
-rw-r--r--arch/s390/mm/hugetlbpage.c5
-rw-r--r--arch/sh/mm/hugetlbpage.c5
-rw-r--r--arch/sparc64/mm/hugetlbpage.c5
-rw-r--r--arch/x86/mm/hugetlbpage.c25
-rw-r--r--include/linux/hugetlb.h5
-rw-r--r--mm/hugetlb.c9
-rw-r--r--mm/memory.c15
9 files changed, 75 insertions, 5 deletions
diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
index 6170f097d255..c45fc7f5a979 100644
--- a/arch/ia64/mm/hugetlbpage.c
+++ b/arch/ia64/mm/hugetlbpage.c
@@ -107,6 +107,12 @@ int pmd_huge(pmd_t pmd)
107{ 107{
108 return 0; 108 return 0;
109} 109}
110
111int pud_huge(pud_t pud)
112{
113 return 0;
114}
115
110struct page * 116struct page *
111follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int write) 117follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int write)
112{ 118{
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index c94dc71af989..63db7adce717 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -369,6 +369,11 @@ int pmd_huge(pmd_t pmd)
369 return 0; 369 return 0;
370} 370}
371 371
372int pud_huge(pud_t pud)
373{
374 return 0;
375}
376
372struct page * 377struct page *
373follow_huge_pmd(struct mm_struct *mm, unsigned long address, 378follow_huge_pmd(struct mm_struct *mm, unsigned long address,
374 pmd_t *pmd, int write) 379 pmd_t *pmd, int write)
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
index 9162dc84f77f..f28c43d2f61d 100644
--- a/arch/s390/mm/hugetlbpage.c
+++ b/arch/s390/mm/hugetlbpage.c
@@ -120,6 +120,11 @@ int pmd_huge(pmd_t pmd)
120 return !!(pmd_val(pmd) & _SEGMENT_ENTRY_LARGE); 120 return !!(pmd_val(pmd) & _SEGMENT_ENTRY_LARGE);
121} 121}
122 122
123int pud_huge(pud_t pud)
124{
125 return 0;
126}
127
123struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address, 128struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
124 pmd_t *pmdp, int write) 129 pmd_t *pmdp, int write)
125{ 130{
diff --git a/arch/sh/mm/hugetlbpage.c b/arch/sh/mm/hugetlbpage.c
index 2f9dbe0ef4ac..9304117039c4 100644
--- a/arch/sh/mm/hugetlbpage.c
+++ b/arch/sh/mm/hugetlbpage.c
@@ -79,6 +79,11 @@ int pmd_huge(pmd_t pmd)
79 return 0; 79 return 0;
80} 80}
81 81
82int pud_huge(pud_t pud)
83{
84 return 0;
85}
86
82struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address, 87struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
83 pmd_t *pmd, int write) 88 pmd_t *pmd, int write)
84{ 89{
diff --git a/arch/sparc64/mm/hugetlbpage.c b/arch/sparc64/mm/hugetlbpage.c
index 1307b23f6a76..f27d10369e0c 100644
--- a/arch/sparc64/mm/hugetlbpage.c
+++ b/arch/sparc64/mm/hugetlbpage.c
@@ -295,6 +295,11 @@ int pmd_huge(pmd_t pmd)
295 return 0; 295 return 0;
296} 296}
297 297
298int pud_huge(pud_t pud)
299{
300 return 0;
301}
302
298struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address, 303struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
299 pmd_t *pmd, int write) 304 pmd_t *pmd, int write)
300{ 305{
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index 52476fde8996..a4789e87a315 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -189,6 +189,11 @@ int pmd_huge(pmd_t pmd)
189 return 0; 189 return 0;
190} 190}
191 191
192int pud_huge(pud_t pud)
193{
194 return 0;
195}
196
192struct page * 197struct page *
193follow_huge_pmd(struct mm_struct *mm, unsigned long address, 198follow_huge_pmd(struct mm_struct *mm, unsigned long address,
194 pmd_t *pmd, int write) 199 pmd_t *pmd, int write)
@@ -209,6 +214,11 @@ int pmd_huge(pmd_t pmd)
209 return !!(pmd_val(pmd) & _PAGE_PSE); 214 return !!(pmd_val(pmd) & _PAGE_PSE);
210} 215}
211 216
217int pud_huge(pud_t pud)
218{
219 return 0;
220}
221
212struct page * 222struct page *
213follow_huge_pmd(struct mm_struct *mm, unsigned long address, 223follow_huge_pmd(struct mm_struct *mm, unsigned long address,
214 pmd_t *pmd, int write) 224 pmd_t *pmd, int write)
@@ -217,9 +227,22 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
217 227
218 page = pte_page(*(pte_t *)pmd); 228 page = pte_page(*(pte_t *)pmd);
219 if (page) 229 if (page)
220 page += ((address & ~HPAGE_MASK) >> PAGE_SHIFT); 230 page += ((address & ~PMD_MASK) >> PAGE_SHIFT);
221 return page; 231 return page;
222} 232}
233
234struct page *
235follow_huge_pud(struct mm_struct *mm, unsigned long address,
236 pud_t *pud, int write)
237{
238 struct page *page;
239
240 page = pte_page(*(pte_t *)pud);
241 if (page)
242 page += ((address & ~PUD_MASK) >> PAGE_SHIFT);
243 return page;
244}
245
223#endif 246#endif
224 247
225/* x86_64 also uses this file */ 248/* x86_64 also uses this file */
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 58c0de32e7f0..b2c17f62cacb 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -50,7 +50,10 @@ struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
50 int write); 50 int write);
51struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address, 51struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
52 pmd_t *pmd, int write); 52 pmd_t *pmd, int write);
53struct page *follow_huge_pud(struct mm_struct *mm, unsigned long address,
54 pud_t *pud, int write);
53int pmd_huge(pmd_t pmd); 55int pmd_huge(pmd_t pmd);
56int pud_huge(pud_t pmd);
54void hugetlb_change_protection(struct vm_area_struct *vma, 57void hugetlb_change_protection(struct vm_area_struct *vma,
55 unsigned long address, unsigned long end, pgprot_t newprot); 58 unsigned long address, unsigned long end, pgprot_t newprot);
56 59
@@ -78,8 +81,10 @@ static inline unsigned long hugetlb_total_pages(void)
78#define hugetlb_report_meminfo(buf) 0 81#define hugetlb_report_meminfo(buf) 0
79#define hugetlb_report_node_meminfo(n, buf) 0 82#define hugetlb_report_node_meminfo(n, buf) 0
80#define follow_huge_pmd(mm, addr, pmd, write) NULL 83#define follow_huge_pmd(mm, addr, pmd, write) NULL
84#define follow_huge_pud(mm, addr, pud, write) NULL
81#define prepare_hugepage_range(file, addr, len) (-EINVAL) 85#define prepare_hugepage_range(file, addr, len) (-EINVAL)
82#define pmd_huge(x) 0 86#define pmd_huge(x) 0
87#define pud_huge(x) 0
83#define is_hugepage_only_range(mm, addr, len) 0 88#define is_hugepage_only_range(mm, addr, len) 0
84#define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) ({BUG(); 0; }) 89#define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) ({BUG(); 0; })
85#define hugetlb_fault(mm, vma, addr, write) ({ BUG(); 0; }) 90#define hugetlb_fault(mm, vma, addr, write) ({ BUG(); 0; })
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 0c74c14dd2f7..107c1ce223cb 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1996,6 +1996,15 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
1996 return ret; 1996 return ret;
1997} 1997}
1998 1998
1999/* Can be overriden by architectures */
2000__attribute__((weak)) struct page *
2001follow_huge_pud(struct mm_struct *mm, unsigned long address,
2002 pud_t *pud, int write)
2003{
2004 BUG();
2005 return NULL;
2006}
2007
1999int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, 2008int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
2000 struct page **pages, struct vm_area_struct **vmas, 2009 struct page **pages, struct vm_area_struct **vmas,
2001 unsigned long *position, int *length, int i, 2010 unsigned long *position, int *length, int i,
diff --git a/mm/memory.c b/mm/memory.c
index 02fc6b1047b0..262e3eb6601a 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -998,19 +998,24 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
998 goto no_page_table; 998 goto no_page_table;
999 999
1000 pud = pud_offset(pgd, address); 1000 pud = pud_offset(pgd, address);
1001 if (pud_none(*pud) || unlikely(pud_bad(*pud))) 1001 if (pud_none(*pud))
1002 goto no_page_table;
1003 if (pud_huge(*pud)) {
1004 BUG_ON(flags & FOLL_GET);
1005 page = follow_huge_pud(mm, address, pud, flags & FOLL_WRITE);
1006 goto out;
1007 }
1008 if (unlikely(pud_bad(*pud)))
1002 goto no_page_table; 1009 goto no_page_table;
1003 1010
1004 pmd = pmd_offset(pud, address); 1011 pmd = pmd_offset(pud, address);
1005 if (pmd_none(*pmd)) 1012 if (pmd_none(*pmd))
1006 goto no_page_table; 1013 goto no_page_table;
1007
1008 if (pmd_huge(*pmd)) { 1014 if (pmd_huge(*pmd)) {
1009 BUG_ON(flags & FOLL_GET); 1015 BUG_ON(flags & FOLL_GET);
1010 page = follow_huge_pmd(mm, address, pmd, flags & FOLL_WRITE); 1016 page = follow_huge_pmd(mm, address, pmd, flags & FOLL_WRITE);
1011 goto out; 1017 goto out;
1012 } 1018 }
1013
1014 if (unlikely(pmd_bad(*pmd))) 1019 if (unlikely(pmd_bad(*pmd)))
1015 goto no_page_table; 1020 goto no_page_table;
1016 1021
@@ -1567,6 +1572,8 @@ static int apply_to_pmd_range(struct mm_struct *mm, pud_t *pud,
1567 unsigned long next; 1572 unsigned long next;
1568 int err; 1573 int err;
1569 1574
1575 BUG_ON(pud_huge(*pud));
1576
1570 pmd = pmd_alloc(mm, pud, addr); 1577 pmd = pmd_alloc(mm, pud, addr);
1571 if (!pmd) 1578 if (!pmd)
1572 return -ENOMEM; 1579 return -ENOMEM;