Skip to content

Commit

Permalink
hugetlb: introduce pud_huge
Browse files Browse the repository at this point in the history
Straight forward extensions for huge pages located in the PUD instead of
PMDs.

Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Nick Piggin <[email protected]>
Cc: Martin Schwidefsky <[email protected]>
Cc: Heiko Carstens <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Andi Kleen authored and torvalds committed Jul 24, 2008
1 parent 4abd32d commit ceb8687
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 5 deletions.
6 changes: 6 additions & 0 deletions arch/ia64/mm/hugetlbpage.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
5 changes: 5 additions & 0 deletions arch/powerpc/mm/hugetlbpage.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 5 additions & 0 deletions arch/s390/mm/hugetlbpage.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
5 changes: 5 additions & 0 deletions arch/sh/mm/hugetlbpage.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
5 changes: 5 additions & 0 deletions arch/sparc64/mm/hugetlbpage.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
25 changes: 24 additions & 1 deletion arch/x86/mm/hugetlbpage.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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 */
Expand Down
5 changes: 5 additions & 0 deletions include/linux/hugetlb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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; })
Expand Down
9 changes: 9 additions & 0 deletions mm/hugetlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
15 changes: 11 additions & 4 deletions mm/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit ceb8687

Please sign in to comment.