Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 349778
b: refs/heads/master
c: 89a7791
h: refs/heads/master
v: v3
  • Loading branch information
David S. Miller committed Feb 13, 2013
1 parent a963174 commit 23c2dc7
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b9156ebb7beef015745f917f373abc137efc3400
refs/heads/master: 89a77915e0f56dc7b9f9082ba787895b6a83f809
14 changes: 6 additions & 8 deletions trunk/arch/sparc/include/asm/pgtable_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
#define PMD_PADDR _AC(0xfffffffe,UL)
#define PMD_PADDR_SHIFT _AC(11,UL)

#ifdef CONFIG_TRANSPARENT_HUGEPAGE
#define PMD_ISHUGE _AC(0x00000001,UL)

/* This is the PMD layout when PMD_ISHUGE is set. With 4MB huge
Expand All @@ -86,7 +85,6 @@
#define PMD_HUGE_ACCESSED _AC(0x00000080,UL)
#define PMD_HUGE_EXEC _AC(0x00000040,UL)
#define PMD_HUGE_SPLITTING _AC(0x00000020,UL)
#endif

/* PGDs point to PMD tables which are 8K aligned. */
#define PGD_PADDR _AC(0xfffffffc,UL)
Expand Down Expand Up @@ -628,6 +626,12 @@ static inline unsigned long pte_special(pte_t pte)
return pte_val(pte) & _PAGE_SPECIAL;
}

static inline int pmd_large(pmd_t pmd)
{
return (pmd_val(pmd) & (PMD_ISHUGE | PMD_HUGE_PRESENT)) ==
(PMD_ISHUGE | PMD_HUGE_PRESENT);
}

#ifdef CONFIG_TRANSPARENT_HUGEPAGE
static inline int pmd_young(pmd_t pmd)
{
Expand All @@ -646,12 +650,6 @@ static inline unsigned long pmd_pfn(pmd_t pmd)
return val >> (PAGE_SHIFT - PMD_PADDR_SHIFT);
}

static inline int pmd_large(pmd_t pmd)
{
return (pmd_val(pmd) & (PMD_ISHUGE | PMD_HUGE_PRESENT)) ==
(PMD_ISHUGE | PMD_HUGE_PRESENT);
}

static inline int pmd_trans_splitting(pmd_t pmd)
{
return (pmd_val(pmd) & (PMD_ISHUGE|PMD_HUGE_SPLITTING)) ==
Expand Down
59 changes: 57 additions & 2 deletions trunk/arch/sparc/mm/gup.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,56 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
return 1;
}

static int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
unsigned long end, int write, struct page **pages,
int *nr)
{
struct page *head, *page, *tail;
u32 mask;
int refs;

mask = PMD_HUGE_PRESENT;
if (write)
mask |= PMD_HUGE_WRITE;
if ((pmd_val(pmd) & mask) != mask)
return 0;

refs = 0;
head = pmd_page(pmd);
page = head + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
tail = page;
do {
VM_BUG_ON(compound_head(page) != head);
pages[*nr] = page;
(*nr)++;
page++;
refs++;
} while (addr += PAGE_SIZE, addr != end);

if (!page_cache_add_speculative(head, refs)) {
*nr -= refs;
return 0;
}

if (unlikely(pmd_val(pmd) != pmd_val(*pmdp))) {
*nr -= refs;
while (refs--)
put_page(head);
return 0;
}

/* Any tail page need their mapcount reference taken before we
* return.
*/
while (refs--) {
if (PageTail(tail))
get_huge_page_tail(tail);
tail++;
}

return 1;
}

static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
int write, struct page **pages, int *nr)
{
Expand All @@ -77,9 +127,14 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
pmd_t pmd = *pmdp;

next = pmd_addr_end(addr, end);
if (pmd_none(pmd))
if (pmd_none(pmd) || pmd_trans_splitting(pmd))
return 0;
if (!gup_pte_range(pmd, addr, next, write, pages, nr))
if (unlikely(pmd_large(pmd))) {
if (!gup_huge_pmd(pmdp, pmd, addr, next,
write, pages, nr))
return 0;
} else if (!gup_pte_range(pmd, addr, next, write,
pages, nr))
return 0;
} while (pmdp++, addr = next, addr != end);

Expand Down

0 comments on commit 23c2dc7

Please sign in to comment.