Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9e695d2e authored by David Miller's avatar David Miller Committed by Linus Torvalds
Browse files

sparc64: Support transparent huge pages.



This is relatively easy since PMD's now cover exactly 4MB of memory.

Our PMD entries are 32-bits each, so we use a special encoding.  The
lowest bit, PMD_ISHUGE, determines the interpretation.  This is possible
because sparc64's page tables are purely software entities so we can use
whatever encoding scheme we want.  We just have to make the TLB miss
assembler page table walkers aware of the layout.

set_pmd_at() works much like set_pte_at() but it has to operate in two
page from a table of non-huge PTEs, so we have to queue up TLB flushes
based upon what mappings are valid in the PTE table.  In the second regime
we are going from huge-page to non-huge-page, and in that case we need
only queue up a single TLB flush to push out the huge page mapping.

We still have 5 bits remaining in the huge PMD encoding so we can very
likely support any new pieces of THP state tracking that might get added
in the future.

With lots of help from Johannes Weiner.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Gerald Schaefer <gerald.schaefer@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent f5c8ad47
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -10,7 +10,10 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
			      pte_t *ptep);

void hugetlb_prefault_arch_hook(struct mm_struct *mm);
static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm)
{
	hugetlb_setup(mm);
}

static inline int is_hugepage_only_range(struct mm_struct *mm,
					 unsigned long addr,
+1 −1
Original line number Diff line number Diff line
@@ -82,7 +82,7 @@ struct tsb_config {

#define MM_TSB_BASE	0

#ifdef CONFIG_HUGETLB_PAGE
#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
#define MM_TSB_HUGE	1
#define MM_NUM_TSBS	2
#else
+1 −1
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ static inline void tsb_context_switch(struct mm_struct *mm)
{
	__tsb_context_switch(__pa(mm->pgd),
			     &mm->context.tsb_block[0],
#ifdef CONFIG_HUGETLB_PAGE
#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
			     (mm->context.tsb_block[1].tsb ?
			      &mm->context.tsb_block[1] :
			      NULL)
+6 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@

#define HPAGE_SHIFT		22

#ifdef CONFIG_HUGETLB_PAGE
#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
#define HPAGE_SIZE		(_AC(1,UL) << HPAGE_SHIFT)
#define HPAGE_MASK		(~(HPAGE_SIZE - 1UL))
#define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
@@ -26,6 +26,11 @@

#ifndef __ASSEMBLY__

#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
struct mm_struct;
extern void hugetlb_setup(struct mm_struct *mm);
#endif

#define WANT_PAGE_VIRTUAL

extern void _clear_page(void *page);
+2 −2
Original line number Diff line number Diff line
@@ -45,8 +45,8 @@ extern pgtable_t pte_alloc_one(struct mm_struct *mm,
extern void pte_free_kernel(struct mm_struct *mm, pte_t *pte);
extern void pte_free(struct mm_struct *mm, pgtable_t ptepage);

#define pmd_populate_kernel(MM, PMD, PTE)	pmd_set(PMD, PTE)
#define pmd_populate(MM, PMD, PTE)		pmd_set(PMD, PTE)
#define pmd_populate_kernel(MM, PMD, PTE)	pmd_set(MM, PMD, PTE)
#define pmd_populate(MM, PMD, PTE)		pmd_set(MM, PMD, PTE)
#define pmd_pgtable(PMD)			((pte_t *)__pmd_page(PMD))

#define check_pgt_cache()	do { } while (0)
Loading