Commit 0cbe3e26 authored by Aneesh Kumar K.V's avatar Aneesh Kumar K.V Committed by Linus Torvalds
Browse files

mm: update ptep_modify_prot_start/commit to take vm_area_struct as arg

Patch series "NestMMU pte upgrade workaround for mprotect", v5.

We can upgrade pte access (R -> RW transition) via mprotect.  We need to
make sure we follow the recommended pte update sequence as outlined in
commit bd5050e3 ("powerpc/mm/radix: Change pte relax sequence to
handle nest MMU hang") for such updates.  This patch series does that.

This patch (of 5):

Some architectures may want to call flush_tlb_range from these helpers.

Link: http://lkml.kernel.org/r/20190116085035.29729-2-aneesh.kumar@linux.ibm.com


Signed-off-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 8bb4e7a2
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -1069,8 +1069,8 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
}
}


#define __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION
#define __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION
pte_t ptep_modify_prot_start(struct mm_struct *, unsigned long, pte_t *);
pte_t ptep_modify_prot_start(struct vm_area_struct *, unsigned long, pte_t *);
void ptep_modify_prot_commit(struct mm_struct *, unsigned long, pte_t *, pte_t);
void ptep_modify_prot_commit(struct vm_area_struct *, unsigned long, pte_t *, pte_t);


#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
+4 −2
Original line number Original line Diff line number Diff line
@@ -301,12 +301,13 @@ pte_t ptep_xchg_lazy(struct mm_struct *mm, unsigned long addr,
}
}
EXPORT_SYMBOL(ptep_xchg_lazy);
EXPORT_SYMBOL(ptep_xchg_lazy);


pte_t ptep_modify_prot_start(struct mm_struct *mm, unsigned long addr,
pte_t ptep_modify_prot_start(struct vm_area_struct *vma, unsigned long addr,
			     pte_t *ptep)
			     pte_t *ptep)
{
{
	pgste_t pgste;
	pgste_t pgste;
	pte_t old;
	pte_t old;
	int nodat;
	int nodat;
	struct mm_struct *mm = vma->vm_mm;


	preempt_disable();
	preempt_disable();
	pgste = ptep_xchg_start(mm, addr, ptep);
	pgste = ptep_xchg_start(mm, addr, ptep);
@@ -319,10 +320,11 @@ pte_t ptep_modify_prot_start(struct mm_struct *mm, unsigned long addr,
	return old;
	return old;
}
}


void ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
void ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr,
			     pte_t *ptep, pte_t pte)
			     pte_t *ptep, pte_t pte)
{
{
	pgste_t pgste;
	pgste_t pgste;
	struct mm_struct *mm = vma->vm_mm;


	if (!MACHINE_HAS_NX)
	if (!MACHINE_HAS_NX)
		pte_val(pte) &= ~_PAGE_NOEXEC;
		pte_val(pte) &= ~_PAGE_NOEXEC;
+6 −5
Original line number Original line Diff line number Diff line
@@ -422,25 +422,26 @@ static inline pgdval_t pgd_val(pgd_t pgd)
}
}


#define  __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION
#define  __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION
static inline pte_t ptep_modify_prot_start(struct mm_struct *mm, unsigned long addr,
static inline pte_t ptep_modify_prot_start(struct vm_area_struct *vma, unsigned long addr,
					   pte_t *ptep)
					   pte_t *ptep)
{
{
	pteval_t ret;
	pteval_t ret;


	ret = PVOP_CALL3(pteval_t, mmu.ptep_modify_prot_start, mm, addr, ptep);
	ret = PVOP_CALL3(pteval_t, mmu.ptep_modify_prot_start, vma, addr, ptep);


	return (pte_t) { .pte = ret };
	return (pte_t) { .pte = ret };
}
}


static inline void ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
static inline void ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr,
					   pte_t *ptep, pte_t pte)
					   pte_t *ptep, pte_t pte)
{
{

	if (sizeof(pteval_t) > sizeof(long))
	if (sizeof(pteval_t) > sizeof(long))
		/* 5 arg words */
		/* 5 arg words */
		pv_ops.mmu.ptep_modify_prot_commit(mm, addr, ptep, pte);
		pv_ops.mmu.ptep_modify_prot_commit(vma, addr, ptep, pte);
	else
	else
		PVOP_VCALL4(mmu.ptep_modify_prot_commit,
		PVOP_VCALL4(mmu.ptep_modify_prot_commit,
			    mm, addr, ptep, pte.pte);
			    vma, addr, ptep, pte.pte);
}
}


static inline void set_pte(pte_t *ptep, pte_t pte)
static inline void set_pte(pte_t *ptep, pte_t pte)
+3 −2
Original line number Original line Diff line number Diff line
@@ -55,6 +55,7 @@ struct task_struct;
struct cpumask;
struct cpumask;
struct flush_tlb_info;
struct flush_tlb_info;
struct mmu_gather;
struct mmu_gather;
struct vm_area_struct;


/*
/*
 * Wrapper type for pointers to code which uses the non-standard
 * Wrapper type for pointers to code which uses the non-standard
@@ -254,9 +255,9 @@ struct pv_mmu_ops {
			   pte_t *ptep, pte_t pteval);
			   pte_t *ptep, pte_t pteval);
	void (*set_pmd)(pmd_t *pmdp, pmd_t pmdval);
	void (*set_pmd)(pmd_t *pmdp, pmd_t pmdval);


	pte_t (*ptep_modify_prot_start)(struct mm_struct *mm, unsigned long addr,
	pte_t (*ptep_modify_prot_start)(struct vm_area_struct *vma, unsigned long addr,
					pte_t *ptep);
					pte_t *ptep);
	void (*ptep_modify_prot_commit)(struct mm_struct *mm, unsigned long addr,
	void (*ptep_modify_prot_commit)(struct vm_area_struct *vma, unsigned long addr,
					pte_t *ptep, pte_t pte);
					pte_t *ptep, pte_t pte);


	struct paravirt_callee_save pte_val;
	struct paravirt_callee_save pte_val;
+2 −2
Original line number Original line Diff line number Diff line
@@ -17,8 +17,8 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);


void set_pte_mfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
void set_pte_mfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);


pte_t xen_ptep_modify_prot_start(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
pte_t xen_ptep_modify_prot_start(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep);
void  xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
void  xen_ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr,
				  pte_t *ptep, pte_t pte);
				  pte_t *ptep, pte_t pte);


unsigned long xen_read_cr2_direct(void);
unsigned long xen_read_cr2_direct(void);
Loading