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

Commit af074848 authored by Steve Capper's avatar Steve Capper
Browse files

ARM64: mm: THP support.



Bring Transparent HugePage support to ARM. The size of a
transparent huge page depends on the normal page size. A
transparent huge page is always represented as a pmd.

If PAGE_SIZE is 4KB, THPs are 2MB.
If PAGE_SIZE is 64KB, THPs are 512MB.

Signed-off-by: default avatarSteve Capper <steve.capper@linaro.org>
Acked-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent d03bb145
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -189,6 +189,9 @@ config ARCH_WANT_GENERAL_HUGETLB
config ARCH_WANT_HUGE_PMD_SHARE
config ARCH_WANT_HUGE_PMD_SHARE
	def_bool y if !ARM64_64K_PAGES
	def_bool y if !ARM64_64K_PAGES


config HAVE_ARCH_TRANSPARENT_HUGEPAGE
	def_bool y

source "mm/Kconfig"
source "mm/Kconfig"


config FORCE_MAX_ZONEORDER
config FORCE_MAX_ZONEORDER
+4 −0
Original line number Original line Diff line number Diff line
@@ -42,6 +42,10 @@
/*
/*
 * Section
 * Section
 */
 */
#define PMD_SECT_VALID		(_AT(pmdval_t, 1) << 0)
#define PMD_SECT_PROT_NONE	(_AT(pmdval_t, 1) << 2)
#define PMD_SECT_USER		(_AT(pmdval_t, 1) << 6)		/* AP[1] */
#define PMD_SECT_RDONLY		(_AT(pmdval_t, 1) << 7)		/* AP[2] */
#define PMD_SECT_S		(_AT(pmdval_t, 3) << 8)
#define PMD_SECT_S		(_AT(pmdval_t, 3) << 8)
#define PMD_SECT_AF		(_AT(pmdval_t, 1) << 10)
#define PMD_SECT_AF		(_AT(pmdval_t, 1) << 10)
#define PMD_SECT_NG		(_AT(pmdval_t, 1) << 11)
#define PMD_SECT_NG		(_AT(pmdval_t, 1) << 11)
+55 −0
Original line number Original line Diff line number Diff line
@@ -187,6 +187,61 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,


#define __HAVE_ARCH_PTE_SPECIAL
#define __HAVE_ARCH_PTE_SPECIAL


/*
 * Software PMD bits for THP
 */

#define PMD_SECT_DIRTY		(_AT(pmdval_t, 1) << 55)
#define PMD_SECT_SPLITTING	(_AT(pmdval_t, 1) << 57)

/*
 * THP definitions.
 */
#define pmd_young(pmd)		(pmd_val(pmd) & PMD_SECT_AF)

#define __HAVE_ARCH_PMD_WRITE
#define pmd_write(pmd)		(!(pmd_val(pmd) & PMD_SECT_RDONLY))

#ifdef CONFIG_TRANSPARENT_HUGEPAGE
#define pmd_trans_huge(pmd)	(pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT))
#define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING)
#endif

#define PMD_BIT_FUNC(fn,op) \
static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }

PMD_BIT_FUNC(wrprotect,	|= PMD_SECT_RDONLY);
PMD_BIT_FUNC(mkold,	&= ~PMD_SECT_AF);
PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING);
PMD_BIT_FUNC(mkwrite,   &= ~PMD_SECT_RDONLY);
PMD_BIT_FUNC(mkdirty,   |= PMD_SECT_DIRTY);
PMD_BIT_FUNC(mkyoung,   |= PMD_SECT_AF);
PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK);

#define pmd_mkhuge(pmd)		(__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))

#define pmd_pfn(pmd)		(((pmd_val(pmd) & PMD_MASK) & PHYS_MASK) >> PAGE_SHIFT)
#define pfn_pmd(pfn,prot)	(__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
#define mk_pmd(page,prot)	pfn_pmd(page_to_pfn(page),prot)

#define pmd_page(pmd)           pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))

static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
{
	const pmdval_t mask = PMD_SECT_USER | PMD_SECT_PXN | PMD_SECT_UXN |
			      PMD_SECT_RDONLY | PMD_SECT_PROT_NONE |
			      PMD_SECT_VALID;
	pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask);
	return pmd;
}

#define set_pmd_at(mm, addr, pmdp, pmd)	set_pmd(pmdp, pmd)

static inline int has_transparent_hugepage(void)
{
	return 1;
}

/*
/*
 * Mark the prot value as uncacheable and unbufferable.
 * Mark the prot value as uncacheable and unbufferable.
 */
 */
+6 −0
Original line number Original line Diff line number Diff line
@@ -187,4 +187,10 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,


#define tlb_migrate_finish(mm)		do { } while (0)
#define tlb_migrate_finish(mm)		do { } while (0)


static inline void
tlb_remove_pmd_tlb_entry(struct mmu_gather *tlb, pmd_t *pmdp, unsigned long addr)
{
	tlb_add_flush(tlb, addr);
}

#endif
#endif
+2 −0
Original line number Original line Diff line number Diff line
@@ -117,6 +117,8 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
	dsb();
	dsb();
}
}


#define update_mmu_cache_pmd(vma, address, pmd) do { } while (0)

#endif
#endif


#endif
#endif