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

Commit bd951303 authored by Steve Capper's avatar Steve Capper Committed by Linus Torvalds
Browse files

arm: mm: introduce special ptes for LPAE



We need a mechanism to tag ptes as being special, this indicates that no
attempt should be made to access the underlying struct page * associated
with the pte.  This is used by the fast_gup when operating on ptes as it
has no means to access VMAs (that also contain this information)
locklessly.

The L_PTE_SPECIAL bit is already allocated for LPAE, this patch modifies
pte_special and pte_mkspecial to make use of it, and defines
__HAVE_ARCH_PTE_SPECIAL.

This patch also excludes special ptes from the icache/dcache sync logic.

Signed-off-by: default avatarSteve Capper <steve.capper@linaro.org>
Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Cc: Dann Frazier <dann.frazier@canonical.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 2667f50e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -182,6 +182,8 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
#define pmd_addr_end(addr,end) (end)

#define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
#define pte_special(pte)	(0)
static inline pte_t pte_mkspecial(pte_t pte) { return pte; }

/*
 * We don't have huge page support for short descriptors, for the moment
+7 −0
Original line number Diff line number Diff line
@@ -213,6 +213,13 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
#define pmd_isclear(pmd, val)	(!(pmd_val(pmd) & (val)))

#define pmd_young(pmd)		(pmd_isset((pmd), PMD_SECT_AF))
#define pte_special(pte)	(pte_isset((pte), L_PTE_SPECIAL))
static inline pte_t pte_mkspecial(pte_t pte)
{
	pte_val(pte) |= L_PTE_SPECIAL;
	return pte;
}
#define	__HAVE_ARCH_PTE_SPECIAL

#define __HAVE_ARCH_PMD_WRITE
#define pmd_write(pmd)		(pmd_isclear((pmd), L_PMD_SECT_RDONLY))
+2 −4
Original line number Diff line number Diff line
@@ -226,7 +226,6 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
#define pte_dirty(pte)		(pte_isset((pte), L_PTE_DIRTY))
#define pte_young(pte)		(pte_isset((pte), L_PTE_YOUNG))
#define pte_exec(pte)		(pte_isclear((pte), L_PTE_XN))
#define pte_special(pte)	(0)

#define pte_valid_user(pte)	\
	(pte_valid(pte) && pte_isset((pte), L_PTE_USER) && pte_young(pte))
@@ -245,6 +244,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
	unsigned long ext = 0;

	if (addr < TASK_SIZE && pte_valid_user(pteval)) {
		if (!pte_special(pteval))
			__sync_icache_dcache(pteval);
		ext |= PTE_EXT_NG;
	}
@@ -264,8 +264,6 @@ PTE_BIT_FUNC(mkyoung, |= L_PTE_YOUNG);
PTE_BIT_FUNC(mkexec,   &= ~L_PTE_XN);
PTE_BIT_FUNC(mknexec,   |= L_PTE_XN);

static inline pte_t pte_mkspecial(pte_t pte) { return pte; }

static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
	const pteval_t mask = L_PTE_XN | L_PTE_RDONLY | L_PTE_USER |