[PATCH v7 13/41] mm: Make pte_mkwrite() take a VMA

Christophe Leroy christophe.leroy at csgroup.eu
Tue Feb 28 23:03:23 PST 2023



Le 27/02/2023 à 23:29, Rick Edgecombe a écrit :
> The x86 Control-flow Enforcement Technology (CET) feature includes a new
> type of memory called shadow stack. This shadow stack memory has some
> unusual properties, which requires some core mm changes to function
> properly.
> 
> One of these unusual properties is that shadow stack memory is writable,
> but only in limited ways. These limits are applied via a specific PTE
> bit combination. Nevertheless, the memory is writable, and core mm code
> will need to apply the writable permissions in the typical paths that
> call pte_mkwrite().
> 
> In addition to VM_WRITE, the shadow stack VMA's will have a flag denoting
> that they are special shadow stack flavor of writable memory. So make
> pte_mkwrite() take a VMA, so that the x86 implementation of it can know to
> create regular writable memory or shadow stack memory.
> 
> Apply the same changes for pmd_mkwrite() and huge_pte_mkwrite().

I'm not sure it is a good idea to add a second argument to 
pte_mkwrite(). All pte_mkxxxx() only take a pte and nothing else.

I think you should do the same as commit d9ed9faac283 ("mm: add new 
arch_make_huge_pte() method for tile support")

Christophe

> 
> No functional change.
> 
> Cc: linux-doc at vger.kernel.org
> Cc: linux-kernel at vger.kernel.org
> Cc: linux-alpha at vger.kernel.org
> Cc: linux-snps-arc at lists.infradead.org
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-csky at vger.kernel.org
> Cc: linux-hexagon at vger.kernel.org
> Cc: linux-ia64 at vger.kernel.org
> Cc: loongarch at lists.linux.dev
> Cc: linux-m68k at lists.linux-m68k.org
> Cc: Michal Simek <monstr at monstr.eu>
> Cc: Dinh Nguyen <dinguyen at kernel.org>
> Cc: linux-mips at vger.kernel.org
> Cc: linux-openrisc at vger.kernel.org
> Cc: linux-parisc at vger.kernel.org
> Cc: linuxppc-dev at lists.ozlabs.org
> Cc: linux-riscv at lists.infradead.org
> Cc: linux-s390 at vger.kernel.org
> Cc: linux-sh at vger.kernel.org
> Cc: sparclinux at vger.kernel.org
> Cc: linux-um at lists.infradead.org
> Cc: xen-devel at lists.xenproject.org
> Cc: linux-arch at vger.kernel.org
> Cc: linux-mm at kvack.org
> Tested-by: Pengfei Xu <pengfei.xu at intel.com>
> Tested-by: John Allen <john.allen at amd.com>
> Tested-by: Kees Cook <keescook at chromium.org>
> Acked-by: Mike Rapoport (IBM) <rppt at kernel.org>
> Acked-by: Michael Ellerman <mpe at ellerman.id.au>
> Acked-by: David Hildenbrand <david at redhat.com>
> Reviewed-by: Kees Cook <keescook at chromium.org>
> Suggested-by: David Hildenbrand <david at redhat.com>
> Signed-off-by: Rick Edgecombe <rick.p.edgecombe at intel.com>
> 
> ---
> Hi Non-x86 Arch’s,
> 
> x86 has a feature that allows for the creation of a special type of
> writable memory (shadow stack) that is only writable in limited specific
> ways. Previously, changes were proposed to core MM code to teach it to
> decide when to create normally writable memory or the special shadow stack
> writable memory, but David Hildenbrand suggested[0] to change
> pXX_mkwrite() to take a VMA, so awareness of shadow stack memory can be
> moved into x86 code.
> 
> Since pXX_mkwrite() is defined in every arch, it requires some tree-wide
> changes. So that is why you are seeing some patches out of a big x86
> series pop up in your arch mailing list. There is no functional change.
> After this refactor, the shadow stack series goes on to use the arch
> helpers to push shadow stack memory details inside arch/x86.
> 
> Testing was just 0-day build testing.
> 
> Hopefully that is enough context. Thanks!
> 
> [0] https://lore.kernel.org/lkml/0e29a2d0-08d8-bcd6-ff26-4bea0e4037b0@redhat.com/#t
> 
> v6:
>   - New patch
> ---
>   Documentation/mm/arch_pgtable_helpers.rst    |  9 ++++++---
>   arch/alpha/include/asm/pgtable.h             |  6 +++++-
>   arch/arc/include/asm/hugepage.h              |  2 +-
>   arch/arc/include/asm/pgtable-bits-arcv2.h    |  7 ++++++-
>   arch/arm/include/asm/pgtable-3level.h        |  7 ++++++-
>   arch/arm/include/asm/pgtable.h               |  2 +-
>   arch/arm64/include/asm/pgtable.h             |  4 ++--
>   arch/csky/include/asm/pgtable.h              |  2 +-
>   arch/hexagon/include/asm/pgtable.h           |  2 +-
>   arch/ia64/include/asm/pgtable.h              |  2 +-
>   arch/loongarch/include/asm/pgtable.h         |  4 ++--
>   arch/m68k/include/asm/mcf_pgtable.h          |  2 +-
>   arch/m68k/include/asm/motorola_pgtable.h     |  6 +++++-
>   arch/m68k/include/asm/sun3_pgtable.h         |  6 +++++-
>   arch/microblaze/include/asm/pgtable.h        |  2 +-
>   arch/mips/include/asm/pgtable.h              |  6 +++---
>   arch/nios2/include/asm/pgtable.h             |  2 +-
>   arch/openrisc/include/asm/pgtable.h          |  2 +-
>   arch/parisc/include/asm/pgtable.h            |  6 +++++-
>   arch/powerpc/include/asm/book3s/32/pgtable.h |  2 +-
>   arch/powerpc/include/asm/book3s/64/pgtable.h |  4 ++--
>   arch/powerpc/include/asm/nohash/32/pgtable.h |  2 +-
>   arch/powerpc/include/asm/nohash/32/pte-8xx.h |  2 +-
>   arch/powerpc/include/asm/nohash/64/pgtable.h |  2 +-
>   arch/riscv/include/asm/pgtable.h             |  6 +++---
>   arch/s390/include/asm/hugetlb.h              |  4 ++--
>   arch/s390/include/asm/pgtable.h              |  4 ++--
>   arch/sh/include/asm/pgtable_32.h             | 10 ++++++++--
>   arch/sparc/include/asm/pgtable_32.h          |  2 +-
>   arch/sparc/include/asm/pgtable_64.h          |  6 +++---
>   arch/um/include/asm/pgtable.h                |  2 +-
>   arch/x86/include/asm/pgtable.h               |  6 ++++--
>   arch/xtensa/include/asm/pgtable.h            |  2 +-
>   include/asm-generic/hugetlb.h                |  4 ++--
>   include/linux/mm.h                           |  2 +-
>   mm/debug_vm_pgtable.c                        | 16 ++++++++--------
>   mm/huge_memory.c                             |  6 +++---
>   mm/hugetlb.c                                 |  4 ++--
>   mm/memory.c                                  |  4 ++--
>   mm/migrate_device.c                          |  2 +-
>   mm/mprotect.c                                |  2 +-
>   mm/userfaultfd.c                             |  2 +-
>   42 files changed, 106 insertions(+), 69 deletions(-)
> 
> diff --git a/Documentation/mm/arch_pgtable_helpers.rst b/Documentation/mm/arch_pgtable_helpers.rst
> index 30d9a09f01f4..78ac3ff2fe1d 100644
> --- a/Documentation/mm/arch_pgtable_helpers.rst
> +++ b/Documentation/mm/arch_pgtable_helpers.rst
> @@ -46,7 +46,8 @@ PTE Page Table Helpers
>   +---------------------------+--------------------------------------------------+
>   | pte_mkclean               | Creates a clean PTE                              |
>   +---------------------------+--------------------------------------------------+
> -| pte_mkwrite               | Creates a writable PTE                           |
> +| pte_mkwrite               | Creates a writable PTE of the type specified by  |
> +|                           | the VMA.                                         |
>   +---------------------------+--------------------------------------------------+
>   | pte_wrprotect             | Creates a write protected PTE                    |
>   +---------------------------+--------------------------------------------------+
> @@ -118,7 +119,8 @@ PMD Page Table Helpers
>   +---------------------------+--------------------------------------------------+
>   | pmd_mkclean               | Creates a clean PMD                              |
>   +---------------------------+--------------------------------------------------+
> -| pmd_mkwrite               | Creates a writable PMD                           |
> +| pmd_mkwrite               | Creates a writable PMD of the type specified by  |
> +|                           | the VMA.                                         |
>   +---------------------------+--------------------------------------------------+
>   | pmd_wrprotect             | Creates a write protected PMD                    |
>   +---------------------------+--------------------------------------------------+
> @@ -222,7 +224,8 @@ HugeTLB Page Table Helpers
>   +---------------------------+--------------------------------------------------+
>   | huge_pte_mkdirty          | Creates a dirty HugeTLB                          |
>   +---------------------------+--------------------------------------------------+
> -| huge_pte_mkwrite          | Creates a writable HugeTLB                       |
> +| huge_pte_mkwrite          | Creates a writable HugeTLB of the type specified |
> +|                           | by the VMA.                                      |
>   +---------------------------+--------------------------------------------------+
>   | huge_pte_wrprotect        | Creates a write protected HugeTLB                |
>   +---------------------------+--------------------------------------------------+
> diff --git a/arch/alpha/include/asm/pgtable.h b/arch/alpha/include/asm/pgtable.h
> index ba43cb841d19..fb5d207c2a89 100644
> --- a/arch/alpha/include/asm/pgtable.h
> +++ b/arch/alpha/include/asm/pgtable.h
> @@ -256,9 +256,13 @@ extern inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED;
>   extern inline pte_t pte_wrprotect(pte_t pte)	{ pte_val(pte) |= _PAGE_FOW; return pte; }
>   extern inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~(__DIRTY_BITS); return pte; }
>   extern inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~(__ACCESS_BITS); return pte; }
> -extern inline pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) &= ~_PAGE_FOW; return pte; }
>   extern inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= __DIRTY_BITS; return pte; }
>   extern inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= __ACCESS_BITS; return pte; }
> +extern inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
> +{
> +	pte_val(pte) &= ~_PAGE_FOW;
> +	return pte;
> +}
>   
>   /*
>    * The smp_rmb() in the following functions are required to order the load of
> diff --git a/arch/arc/include/asm/hugepage.h b/arch/arc/include/asm/hugepage.h
> index 5001b796fb8d..223a96967188 100644
> --- a/arch/arc/include/asm/hugepage.h
> +++ b/arch/arc/include/asm/hugepage.h
> @@ -21,7 +21,7 @@ static inline pmd_t pte_pmd(pte_t pte)
>   }
>   
>   #define pmd_wrprotect(pmd)	pte_pmd(pte_wrprotect(pmd_pte(pmd)))
> -#define pmd_mkwrite(pmd)	pte_pmd(pte_mkwrite(pmd_pte(pmd)))
> +#define pmd_mkwrite(pmd, vma)	pte_pmd(pte_mkwrite(pmd_pte(pmd), (vma)))
>   #define pmd_mkdirty(pmd)	pte_pmd(pte_mkdirty(pmd_pte(pmd)))
>   #define pmd_mkold(pmd)		pte_pmd(pte_mkold(pmd_pte(pmd)))
>   #define pmd_mkyoung(pmd)	pte_pmd(pte_mkyoung(pmd_pte(pmd)))
> diff --git a/arch/arc/include/asm/pgtable-bits-arcv2.h b/arch/arc/include/asm/pgtable-bits-arcv2.h
> index 6e9f8ca6d6a1..a5b8bc955015 100644
> --- a/arch/arc/include/asm/pgtable-bits-arcv2.h
> +++ b/arch/arc/include/asm/pgtable-bits-arcv2.h
> @@ -87,7 +87,6 @@
>   
>   PTE_BIT_FUNC(mknotpresent,     &= ~(_PAGE_PRESENT));
>   PTE_BIT_FUNC(wrprotect,	&= ~(_PAGE_WRITE));
> -PTE_BIT_FUNC(mkwrite,	|= (_PAGE_WRITE));
>   PTE_BIT_FUNC(mkclean,	&= ~(_PAGE_DIRTY));
>   PTE_BIT_FUNC(mkdirty,	|= (_PAGE_DIRTY));
>   PTE_BIT_FUNC(mkold,	&= ~(_PAGE_ACCESSED));
> @@ -95,6 +94,12 @@ PTE_BIT_FUNC(mkyoung,	|= (_PAGE_ACCESSED));
>   PTE_BIT_FUNC(mkspecial,	|= (_PAGE_SPECIAL));
>   PTE_BIT_FUNC(mkhuge,	|= (_PAGE_HW_SZ));
>   
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
> +{
> +	pte_val(pte) |= (_PAGE_WRITE);
> +	return pte;
> +}
> +
>   static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
>   {
>   	return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
> diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
> index 106049791500..df071a807610 100644
> --- a/arch/arm/include/asm/pgtable-3level.h
> +++ b/arch/arm/include/asm/pgtable-3level.h
> @@ -202,11 +202,16 @@ static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
>   
>   PMD_BIT_FUNC(wrprotect,	|= L_PMD_SECT_RDONLY);
>   PMD_BIT_FUNC(mkold,	&= ~PMD_SECT_AF);
> -PMD_BIT_FUNC(mkwrite,   &= ~L_PMD_SECT_RDONLY);
>   PMD_BIT_FUNC(mkdirty,   |= L_PMD_SECT_DIRTY);
>   PMD_BIT_FUNC(mkclean,   &= ~L_PMD_SECT_DIRTY);
>   PMD_BIT_FUNC(mkyoung,   |= PMD_SECT_AF);
>   
> +static inline pmd_t pmd_mkwrite(pmd_t pmd, struct vm_area_struct *vma)
> +{
> +	pmd_val(pmd) |= L_PMD_SECT_RDONLY;
> +	return pmd;
> +}
> +
>   #define pmd_mkhuge(pmd)		(__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))
>   
>   #define pmd_pfn(pmd)		(((pmd_val(pmd) & PMD_MASK) & PHYS_MASK) >> PAGE_SHIFT)
> diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
> index a58ccbb406ad..39ad1ae1308d 100644
> --- a/arch/arm/include/asm/pgtable.h
> +++ b/arch/arm/include/asm/pgtable.h
> @@ -227,7 +227,7 @@ static inline pte_t pte_wrprotect(pte_t pte)
>   	return set_pte_bit(pte, __pgprot(L_PTE_RDONLY));
>   }
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	return clear_pte_bit(pte, __pgprot(L_PTE_RDONLY));
>   }
> diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
> index cccf8885792e..913bf370f74a 100644
> --- a/arch/arm64/include/asm/pgtable.h
> +++ b/arch/arm64/include/asm/pgtable.h
> @@ -187,7 +187,7 @@ static inline pte_t pte_mkwrite_kernel(pte_t pte)
>   	return pte;
>   }
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	return pte_mkwrite_kernel(pte);
>   }
> @@ -492,7 +492,7 @@ static inline int pmd_trans_huge(pmd_t pmd)
>   #define pmd_cont(pmd)		pte_cont(pmd_pte(pmd))
>   #define pmd_wrprotect(pmd)	pte_pmd(pte_wrprotect(pmd_pte(pmd)))
>   #define pmd_mkold(pmd)		pte_pmd(pte_mkold(pmd_pte(pmd)))
> -#define pmd_mkwrite(pmd)	pte_pmd(pte_mkwrite(pmd_pte(pmd)))
> +#define pmd_mkwrite(pmd, vma)	pte_pmd(pte_mkwrite(pmd_pte(pmd), (vma)))
>   #define pmd_mkclean(pmd)	pte_pmd(pte_mkclean(pmd_pte(pmd)))
>   #define pmd_mkdirty(pmd)	pte_pmd(pte_mkdirty(pmd_pte(pmd)))
>   #define pmd_mkyoung(pmd)	pte_pmd(pte_mkyoung(pmd_pte(pmd)))
> diff --git a/arch/csky/include/asm/pgtable.h b/arch/csky/include/asm/pgtable.h
> index d4042495febc..c2f92c991e37 100644
> --- a/arch/csky/include/asm/pgtable.h
> +++ b/arch/csky/include/asm/pgtable.h
> @@ -176,7 +176,7 @@ static inline pte_t pte_mkold(pte_t pte)
>   	return pte;
>   }
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	pte_val(pte) |= _PAGE_WRITE;
>   	if (pte_val(pte) & _PAGE_MODIFIED)
> diff --git a/arch/hexagon/include/asm/pgtable.h b/arch/hexagon/include/asm/pgtable.h
> index 59393613d086..14ab9c789c0e 100644
> --- a/arch/hexagon/include/asm/pgtable.h
> +++ b/arch/hexagon/include/asm/pgtable.h
> @@ -300,7 +300,7 @@ static inline pte_t pte_wrprotect(pte_t pte)
>   }
>   
>   /* pte_mkwrite - mark page as writable */
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	pte_val(pte) |= _PAGE_WRITE;
>   	return pte;
> diff --git a/arch/ia64/include/asm/pgtable.h b/arch/ia64/include/asm/pgtable.h
> index 21c97e31a28a..f879dd626da6 100644
> --- a/arch/ia64/include/asm/pgtable.h
> +++ b/arch/ia64/include/asm/pgtable.h
> @@ -268,7 +268,7 @@ ia64_phys_addr_valid (unsigned long addr)
>    * access rights:
>    */
>   #define pte_wrprotect(pte)	(__pte(pte_val(pte) & ~_PAGE_AR_RW))
> -#define pte_mkwrite(pte)	(__pte(pte_val(pte) | _PAGE_AR_RW))
> +#define pte_mkwrite(pte, vma)	(__pte(pte_val(pte) | _PAGE_AR_RW))
>   #define pte_mkold(pte)		(__pte(pte_val(pte) & ~_PAGE_A))
>   #define pte_mkyoung(pte)	(__pte(pte_val(pte) | _PAGE_A))
>   #define pte_mkclean(pte)	(__pte(pte_val(pte) & ~_PAGE_D))
> diff --git a/arch/loongarch/include/asm/pgtable.h b/arch/loongarch/include/asm/pgtable.h
> index d28fb9dbec59..ebf645f40298 100644
> --- a/arch/loongarch/include/asm/pgtable.h
> +++ b/arch/loongarch/include/asm/pgtable.h
> @@ -390,7 +390,7 @@ static inline pte_t pte_mkdirty(pte_t pte)
>   	return pte;
>   }
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	pte_val(pte) |= _PAGE_WRITE;
>   	if (pte_val(pte) & _PAGE_MODIFIED)
> @@ -490,7 +490,7 @@ static inline int pmd_write(pmd_t pmd)
>   	return !!(pmd_val(pmd) & _PAGE_WRITE);
>   }
>   
> -static inline pmd_t pmd_mkwrite(pmd_t pmd)
> +static inline pmd_t pmd_mkwrite(pmd_t pmd, struct vm_area_struct *vma)
>   {
>   	pmd_val(pmd) |= _PAGE_WRITE;
>   	if (pmd_val(pmd) & _PAGE_MODIFIED)
> diff --git a/arch/m68k/include/asm/mcf_pgtable.h b/arch/m68k/include/asm/mcf_pgtable.h
> index 13741c1245e1..37d77e055016 100644
> --- a/arch/m68k/include/asm/mcf_pgtable.h
> +++ b/arch/m68k/include/asm/mcf_pgtable.h
> @@ -211,7 +211,7 @@ static inline pte_t pte_mkold(pte_t pte)
>   	return pte;
>   }
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	pte_val(pte) |= CF_PAGE_WRITABLE;
>   	return pte;
> diff --git a/arch/m68k/include/asm/motorola_pgtable.h b/arch/m68k/include/asm/motorola_pgtable.h
> index ec0dc19ab834..c4e8eb76286d 100644
> --- a/arch/m68k/include/asm/motorola_pgtable.h
> +++ b/arch/m68k/include/asm/motorola_pgtable.h
> @@ -155,7 +155,6 @@ static inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED;
>   static inline pte_t pte_wrprotect(pte_t pte)	{ pte_val(pte) |= _PAGE_RONLY; return pte; }
>   static inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
>   static inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
> -static inline pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) &= ~_PAGE_RONLY; return pte; }
>   static inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
>   static inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
>   static inline pte_t pte_mknocache(pte_t pte)
> @@ -168,6 +167,11 @@ static inline pte_t pte_mkcache(pte_t pte)
>   	pte_val(pte) = (pte_val(pte) & _CACHEMASK040) | m68k_supervisor_cachemode;
>   	return pte;
>   }
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
> +{
> +	pte_val(pte) &= ~_PAGE_RONLY;
> +	return pte;
> +}
>   
>   #define swapper_pg_dir kernel_pg_dir
>   extern pgd_t kernel_pg_dir[128];
> diff --git a/arch/m68k/include/asm/sun3_pgtable.h b/arch/m68k/include/asm/sun3_pgtable.h
> index e582b0484a55..2a06bea51a1e 100644
> --- a/arch/m68k/include/asm/sun3_pgtable.h
> +++ b/arch/m68k/include/asm/sun3_pgtable.h
> @@ -143,10 +143,14 @@ static inline int pte_young(pte_t pte)		{ return pte_val(pte) & SUN3_PAGE_ACCESS
>   static inline pte_t pte_wrprotect(pte_t pte)	{ pte_val(pte) &= ~SUN3_PAGE_WRITEABLE; return pte; }
>   static inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~SUN3_PAGE_MODIFIED; return pte; }
>   static inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~SUN3_PAGE_ACCESSED; return pte; }
> -static inline pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) |= SUN3_PAGE_WRITEABLE; return pte; }
>   static inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= SUN3_PAGE_MODIFIED; return pte; }
>   static inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= SUN3_PAGE_ACCESSED; return pte; }
>   static inline pte_t pte_mknocache(pte_t pte)	{ pte_val(pte) |= SUN3_PAGE_NOCACHE; return pte; }
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
> +{
> +	pte_val(pte) |= SUN3_PAGE_WRITEABLE;
> +	return pte;
> +}
>   // use this version when caches work...
>   //static inline pte_t pte_mkcache(pte_t pte)	{ pte_val(pte) &= SUN3_PAGE_NOCACHE; return pte; }
>   // until then, use:
> diff --git a/arch/microblaze/include/asm/pgtable.h b/arch/microblaze/include/asm/pgtable.h
> index d1b8272abcd9..5b83e82f8d7e 100644
> --- a/arch/microblaze/include/asm/pgtable.h
> +++ b/arch/microblaze/include/asm/pgtable.h
> @@ -266,7 +266,7 @@ static inline pte_t pte_mkread(pte_t pte) \
>   	{ pte_val(pte) |= _PAGE_USER; return pte; }
>   static inline pte_t pte_mkexec(pte_t pte) \
>   	{ pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; }
> -static inline pte_t pte_mkwrite(pte_t pte) \
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma) \
>   	{ pte_val(pte) |= _PAGE_RW; return pte; }
>   static inline pte_t pte_mkdirty(pte_t pte) \
>   	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
> diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
> index 791389bf3c12..06efd567144a 100644
> --- a/arch/mips/include/asm/pgtable.h
> +++ b/arch/mips/include/asm/pgtable.h
> @@ -309,7 +309,7 @@ static inline pte_t pte_mkold(pte_t pte)
>   	return pte;
>   }
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	pte.pte_low |= _PAGE_WRITE;
>   	if (pte.pte_low & _PAGE_MODIFIED) {
> @@ -364,7 +364,7 @@ static inline pte_t pte_mkold(pte_t pte)
>   	return pte;
>   }
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	pte_val(pte) |= _PAGE_WRITE;
>   	if (pte_val(pte) & _PAGE_MODIFIED)
> @@ -626,7 +626,7 @@ static inline pmd_t pmd_wrprotect(pmd_t pmd)
>   	return pmd;
>   }
>   
> -static inline pmd_t pmd_mkwrite(pmd_t pmd)
> +static inline pmd_t pmd_mkwrite(pmd_t pmd, struct vm_area_struct *vma)
>   {
>   	pmd_val(pmd) |= _PAGE_WRITE;
>   	if (pmd_val(pmd) & _PAGE_MODIFIED)
> diff --git a/arch/nios2/include/asm/pgtable.h b/arch/nios2/include/asm/pgtable.h
> index 0f5c2564e9f5..edd458518e0e 100644
> --- a/arch/nios2/include/asm/pgtable.h
> +++ b/arch/nios2/include/asm/pgtable.h
> @@ -129,7 +129,7 @@ static inline pte_t pte_mkold(pte_t pte)
>   	return pte;
>   }
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	pte_val(pte) |= _PAGE_WRITE;
>   	return pte;
> diff --git a/arch/openrisc/include/asm/pgtable.h b/arch/openrisc/include/asm/pgtable.h
> index 3eb9b9555d0d..fd40aec189d1 100644
> --- a/arch/openrisc/include/asm/pgtable.h
> +++ b/arch/openrisc/include/asm/pgtable.h
> @@ -250,7 +250,7 @@ static inline pte_t pte_mkold(pte_t pte)
>   	return pte;
>   }
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	pte_val(pte) |= _PAGE_WRITE;
>   	return pte;
> diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h
> index e2950f5db7c9..89f62137e67f 100644
> --- a/arch/parisc/include/asm/pgtable.h
> +++ b/arch/parisc/include/asm/pgtable.h
> @@ -331,8 +331,12 @@ static inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~_PAGE_ACCESSED; retu
>   static inline pte_t pte_wrprotect(pte_t pte)	{ pte_val(pte) &= ~_PAGE_WRITE; return pte; }
>   static inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
>   static inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
> -static inline pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) |= _PAGE_WRITE; return pte; }
>   static inline pte_t pte_mkspecial(pte_t pte)	{ pte_val(pte) |= _PAGE_SPECIAL; return pte; }
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
> +{
> +	pte_val(pte) |= _PAGE_WRITE;
> +	return pte;
> +}
>   
>   /*
>    * Huge pte definitions.
> diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h
> index 7bf1fe7297c6..10d9a1d2aca9 100644
> --- a/arch/powerpc/include/asm/book3s/32/pgtable.h
> +++ b/arch/powerpc/include/asm/book3s/32/pgtable.h
> @@ -498,7 +498,7 @@ static inline pte_t pte_mkpte(pte_t pte)
>   	return pte;
>   }
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	return __pte(pte_val(pte) | _PAGE_RW);
>   }
> diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h
> index 4acc9690f599..be0636522d36 100644
> --- a/arch/powerpc/include/asm/book3s/64/pgtable.h
> +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
> @@ -600,7 +600,7 @@ static inline pte_t pte_mkexec(pte_t pte)
>   	return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_EXEC));
>   }
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	/*
>   	 * write implies read, hence set both
> @@ -1071,7 +1071,7 @@ static inline pte_t *pmdp_ptep(pmd_t *pmd)
>   #define pmd_mkdirty(pmd)	pte_pmd(pte_mkdirty(pmd_pte(pmd)))
>   #define pmd_mkclean(pmd)	pte_pmd(pte_mkclean(pmd_pte(pmd)))
>   #define pmd_mkyoung(pmd)	pte_pmd(pte_mkyoung(pmd_pte(pmd)))
> -#define pmd_mkwrite(pmd)	pte_pmd(pte_mkwrite(pmd_pte(pmd)))
> +#define pmd_mkwrite(pmd, vma)	pte_pmd(pte_mkwrite(pmd_pte(pmd), (vma)))
>   
>   #ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY
>   #define pmd_soft_dirty(pmd)    pte_soft_dirty(pmd_pte(pmd))
> diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h
> index fec56d965f00..7bfbcb9ba55b 100644
> --- a/arch/powerpc/include/asm/nohash/32/pgtable.h
> +++ b/arch/powerpc/include/asm/nohash/32/pgtable.h
> @@ -171,7 +171,7 @@ void unmap_kernel_page(unsigned long va);
>   	do { pte_update(mm, addr, ptep, ~0, 0, 0); } while (0)
>   
>   #ifndef pte_mkwrite
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	return __pte(pte_val(pte) | _PAGE_RW);
>   }
> diff --git a/arch/powerpc/include/asm/nohash/32/pte-8xx.h b/arch/powerpc/include/asm/nohash/32/pte-8xx.h
> index 1a89ebdc3acc..f32450eb270a 100644
> --- a/arch/powerpc/include/asm/nohash/32/pte-8xx.h
> +++ b/arch/powerpc/include/asm/nohash/32/pte-8xx.h
> @@ -101,7 +101,7 @@ static inline int pte_write(pte_t pte)
>   
>   #define pte_write pte_write
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	return __pte(pte_val(pte) & ~_PAGE_RO);
>   }
> diff --git a/arch/powerpc/include/asm/nohash/64/pgtable.h b/arch/powerpc/include/asm/nohash/64/pgtable.h
> index 287e25864ffa..589009555877 100644
> --- a/arch/powerpc/include/asm/nohash/64/pgtable.h
> +++ b/arch/powerpc/include/asm/nohash/64/pgtable.h
> @@ -85,7 +85,7 @@
>   #ifndef __ASSEMBLY__
>   /* pte_clear moved to later in this file */
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	return __pte(pte_val(pte) | _PAGE_RW);
>   }
> diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> index d8d8de0ded99..fed1b81fbe07 100644
> --- a/arch/riscv/include/asm/pgtable.h
> +++ b/arch/riscv/include/asm/pgtable.h
> @@ -338,7 +338,7 @@ static inline pte_t pte_wrprotect(pte_t pte)
>   
>   /* static inline pte_t pte_mkread(pte_t pte) */
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	return __pte(pte_val(pte) | _PAGE_WRITE);
>   }
> @@ -624,9 +624,9 @@ static inline pmd_t pmd_mkyoung(pmd_t pmd)
>   	return pte_pmd(pte_mkyoung(pmd_pte(pmd)));
>   }
>   
> -static inline pmd_t pmd_mkwrite(pmd_t pmd)
> +static inline pmd_t pmd_mkwrite(pmd_t pmd, struct vm_area_struct *vma)
>   {
> -	return pte_pmd(pte_mkwrite(pmd_pte(pmd)));
> +	return pte_pmd(pte_mkwrite(pmd_pte(pmd), vma));
>   }
>   
>   static inline pmd_t pmd_wrprotect(pmd_t pmd)
> diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h
> index ccdbccfde148..558f7eef9c4d 100644
> --- a/arch/s390/include/asm/hugetlb.h
> +++ b/arch/s390/include/asm/hugetlb.h
> @@ -102,9 +102,9 @@ static inline int huge_pte_dirty(pte_t pte)
>   	return pte_dirty(pte);
>   }
>   
> -static inline pte_t huge_pte_mkwrite(pte_t pte)
> +static inline pte_t huge_pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
> -	return pte_mkwrite(pte);
> +	return pte_mkwrite(pte, vma);
>   }
>   
>   static inline pte_t huge_pte_mkdirty(pte_t pte)
> diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
> index deeb918cae1d..8f2c743da0eb 100644
> --- a/arch/s390/include/asm/pgtable.h
> +++ b/arch/s390/include/asm/pgtable.h
> @@ -1013,7 +1013,7 @@ static inline pte_t pte_mkwrite_kernel(pte_t pte)
>   	return pte;
>   }
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	return pte_mkwrite_kernel(pte);
>   }
> @@ -1499,7 +1499,7 @@ static inline pmd_t pmd_mkwrite_kernel(pmd_t pmd)
>   	return pmd;
>   }
>   
> -static inline pmd_t pmd_mkwrite(pmd_t pmd)
> +static inline pmd_t pmd_mkwrite(pmd_t pmd, struct vm_area_struct *vma)
>   {
>   	return pmd_mkwrite_kernel(pmd);
>   }
> diff --git a/arch/sh/include/asm/pgtable_32.h b/arch/sh/include/asm/pgtable_32.h
> index 21952b094650..9f2dcb9eafc8 100644
> --- a/arch/sh/include/asm/pgtable_32.h
> +++ b/arch/sh/include/asm/pgtable_32.h
> @@ -351,6 +351,12 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
>   
>   #define PTE_BIT_FUNC(h,fn,op) \
>   static inline pte_t pte_##fn(pte_t pte) { pte.pte_##h op; return pte; }
> +#define PTE_BIT_FUNC_VMA(h,fn,op) \
> +static inline pte_t pte_##fn(pte_t pte, struct vm_area_struct *vma) \
> +{ \
> +	pte.pte_##h op; \
> +	return pte; \
> +}
>   
>   #ifdef CONFIG_X2TLB
>   /*
> @@ -359,11 +365,11 @@ static inline pte_t pte_##fn(pte_t pte) { pte.pte_##h op; return pte; }
>    * kernel permissions), we attempt to couple them a bit more sanely here.
>    */
>   PTE_BIT_FUNC(high, wrprotect, &= ~(_PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE));
> -PTE_BIT_FUNC(high, mkwrite, |= _PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE);
> +PTE_BIT_FUNC_VMA(high, mkwrite, |= _PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE);
>   PTE_BIT_FUNC(high, mkhuge, |= _PAGE_SZHUGE);
>   #else
>   PTE_BIT_FUNC(low, wrprotect, &= ~_PAGE_RW);
> -PTE_BIT_FUNC(low, mkwrite, |= _PAGE_RW);
> +PTE_BIT_FUNC_VMA(low, mkwrite, |= _PAGE_RW);
>   PTE_BIT_FUNC(low, mkhuge, |= _PAGE_SZHUGE);
>   #endif
>   
> diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h
> index d4330e3c57a6..3e8836179456 100644
> --- a/arch/sparc/include/asm/pgtable_32.h
> +++ b/arch/sparc/include/asm/pgtable_32.h
> @@ -241,7 +241,7 @@ static inline pte_t pte_mkold(pte_t pte)
>   	return __pte(pte_val(pte) & ~SRMMU_REF);
>   }
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	return __pte(pte_val(pte) | SRMMU_WRITE);
>   }
> diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
> index 2dc8d4641734..c5cd5c03f557 100644
> --- a/arch/sparc/include/asm/pgtable_64.h
> +++ b/arch/sparc/include/asm/pgtable_64.h
> @@ -466,7 +466,7 @@ static inline pte_t pte_mkclean(pte_t pte)
>   	return __pte(val);
>   }
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	unsigned long val = pte_val(pte), mask;
>   
> @@ -756,11 +756,11 @@ static inline pmd_t pmd_mkyoung(pmd_t pmd)
>   	return __pmd(pte_val(pte));
>   }
>   
> -static inline pmd_t pmd_mkwrite(pmd_t pmd)
> +static inline pmd_t pmd_mkwrite(pmd_t pmd, struct vm_area_struct *vma)
>   {
>   	pte_t pte = __pte(pmd_val(pmd));
>   
> -	pte = pte_mkwrite(pte);
> +	pte = pte_mkwrite(pte, vma);
>   
>   	return __pmd(pte_val(pte));
>   }
> diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h
> index a70d1618eb35..963479c133b7 100644
> --- a/arch/um/include/asm/pgtable.h
> +++ b/arch/um/include/asm/pgtable.h
> @@ -207,7 +207,7 @@ static inline pte_t pte_mkyoung(pte_t pte)
>   	return(pte);
>   }
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	if (unlikely(pte_get_bits(pte,  _PAGE_RW)))
>   		return pte;
> diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
> index 3607f2572f9e..66c514808276 100644
> --- a/arch/x86/include/asm/pgtable.h
> +++ b/arch/x86/include/asm/pgtable.h
> @@ -369,7 +369,9 @@ static inline pte_t pte_mkwrite_kernel(pte_t pte)
>   	return pte_set_flags(pte, _PAGE_RW);
>   }
>   
> -static inline pte_t pte_mkwrite(pte_t pte)
> +struct vm_area_struct;
> +
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	return pte_mkwrite_kernel(pte);
>   }
> @@ -470,7 +472,7 @@ static inline pmd_t pmd_mkyoung(pmd_t pmd)
>   	return pmd_set_flags(pmd, _PAGE_ACCESSED);
>   }
>   
> -static inline pmd_t pmd_mkwrite(pmd_t pmd)
> +static inline pmd_t pmd_mkwrite(pmd_t pmd, struct vm_area_struct *vma)
>   {
>   	return pmd_set_flags(pmd, _PAGE_RW);
>   }
> diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h
> index fc7a14884c6c..d72632d9c53c 100644
> --- a/arch/xtensa/include/asm/pgtable.h
> +++ b/arch/xtensa/include/asm/pgtable.h
> @@ -262,7 +262,7 @@ static inline pte_t pte_mkdirty(pte_t pte)
>   	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
>   static inline pte_t pte_mkyoung(pte_t pte)
>   	{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
> -static inline pte_t pte_mkwrite(pte_t pte)
> +static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   	{ pte_val(pte) |= _PAGE_WRITABLE; return pte; }
>   
>   #define pgprot_noncached(prot) \
> diff --git a/include/asm-generic/hugetlb.h b/include/asm-generic/hugetlb.h
> index d7f6335d3999..e86c830728de 100644
> --- a/include/asm-generic/hugetlb.h
> +++ b/include/asm-generic/hugetlb.h
> @@ -20,9 +20,9 @@ static inline unsigned long huge_pte_dirty(pte_t pte)
>   	return pte_dirty(pte);
>   }
>   
> -static inline pte_t huge_pte_mkwrite(pte_t pte)
> +static inline pte_t huge_pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
> -	return pte_mkwrite(pte);
> +	return pte_mkwrite(pte, vma);
>   }
>   
>   #ifndef __HAVE_ARCH_HUGE_PTE_WRPROTECT
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 1f79667824eb..af652444fbba 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -1163,7 +1163,7 @@ void free_compound_page(struct page *page);
>   static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
>   {
>   	if (likely(vma->vm_flags & VM_WRITE))
> -		pte = pte_mkwrite(pte);
> +		pte = pte_mkwrite(pte, vma);
>   	return pte;
>   }
>   
> diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c
> index af59cc7bd307..7bc5592900bc 100644
> --- a/mm/debug_vm_pgtable.c
> +++ b/mm/debug_vm_pgtable.c
> @@ -109,10 +109,10 @@ static void __init pte_basic_tests(struct pgtable_debug_args *args, int idx)
>   	WARN_ON(!pte_same(pte, pte));
>   	WARN_ON(!pte_young(pte_mkyoung(pte_mkold(pte))));
>   	WARN_ON(!pte_dirty(pte_mkdirty(pte_mkclean(pte))));
> -	WARN_ON(!pte_write(pte_mkwrite(pte_wrprotect(pte))));
> +	WARN_ON(!pte_write(pte_mkwrite(pte_wrprotect(pte), args->vma)));
>   	WARN_ON(pte_young(pte_mkold(pte_mkyoung(pte))));
>   	WARN_ON(pte_dirty(pte_mkclean(pte_mkdirty(pte))));
> -	WARN_ON(pte_write(pte_wrprotect(pte_mkwrite(pte))));
> +	WARN_ON(pte_write(pte_wrprotect(pte_mkwrite(pte, args->vma))));
>   	WARN_ON(pte_dirty(pte_wrprotect(pte_mkclean(pte))));
>   	WARN_ON(!pte_dirty(pte_wrprotect(pte_mkdirty(pte))));
>   }
> @@ -153,7 +153,7 @@ static void __init pte_advanced_tests(struct pgtable_debug_args *args)
>   	pte = pte_mkclean(pte);
>   	set_pte_at(args->mm, args->vaddr, args->ptep, pte);
>   	flush_dcache_page(page);
> -	pte = pte_mkwrite(pte);
> +	pte = pte_mkwrite(pte, args->vma);
>   	pte = pte_mkdirty(pte);
>   	ptep_set_access_flags(args->vma, args->vaddr, args->ptep, pte, 1);
>   	pte = ptep_get(args->ptep);
> @@ -199,10 +199,10 @@ static void __init pmd_basic_tests(struct pgtable_debug_args *args, int idx)
>   	WARN_ON(!pmd_same(pmd, pmd));
>   	WARN_ON(!pmd_young(pmd_mkyoung(pmd_mkold(pmd))));
>   	WARN_ON(!pmd_dirty(pmd_mkdirty(pmd_mkclean(pmd))));
> -	WARN_ON(!pmd_write(pmd_mkwrite(pmd_wrprotect(pmd))));
> +	WARN_ON(!pmd_write(pmd_mkwrite(pmd_wrprotect(pmd), args->vma)));
>   	WARN_ON(pmd_young(pmd_mkold(pmd_mkyoung(pmd))));
>   	WARN_ON(pmd_dirty(pmd_mkclean(pmd_mkdirty(pmd))));
> -	WARN_ON(pmd_write(pmd_wrprotect(pmd_mkwrite(pmd))));
> +	WARN_ON(pmd_write(pmd_wrprotect(pmd_mkwrite(pmd, args->vma))));
>   	WARN_ON(pmd_dirty(pmd_wrprotect(pmd_mkclean(pmd))));
>   	WARN_ON(!pmd_dirty(pmd_wrprotect(pmd_mkdirty(pmd))));
>   	/*
> @@ -253,7 +253,7 @@ static void __init pmd_advanced_tests(struct pgtable_debug_args *args)
>   	pmd = pmd_mkclean(pmd);
>   	set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
>   	flush_dcache_page(page);
> -	pmd = pmd_mkwrite(pmd);
> +	pmd = pmd_mkwrite(pmd, args->vma);
>   	pmd = pmd_mkdirty(pmd);
>   	pmdp_set_access_flags(args->vma, vaddr, args->pmdp, pmd, 1);
>   	pmd = READ_ONCE(*args->pmdp);
> @@ -928,8 +928,8 @@ static void __init hugetlb_basic_tests(struct pgtable_debug_args *args)
>   	pte = mk_huge_pte(page, args->page_prot);
>   
>   	WARN_ON(!huge_pte_dirty(huge_pte_mkdirty(pte)));
> -	WARN_ON(!huge_pte_write(huge_pte_mkwrite(huge_pte_wrprotect(pte))));
> -	WARN_ON(huge_pte_write(huge_pte_wrprotect(huge_pte_mkwrite(pte))));
> +	WARN_ON(!huge_pte_write(huge_pte_mkwrite(huge_pte_wrprotect(pte), args->vma)));
> +	WARN_ON(huge_pte_write(huge_pte_wrprotect(huge_pte_mkwrite(pte, args->vma))));
>   
>   #ifdef CONFIG_ARCH_WANT_GENERAL_HUGETLB
>   	pte = pfn_pte(args->fixed_pmd_pfn, args->page_prot);
> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> index 4fc43859e59a..aaf815838144 100644
> --- a/mm/huge_memory.c
> +++ b/mm/huge_memory.c
> @@ -555,7 +555,7 @@ __setup("transparent_hugepage=", setup_transparent_hugepage);
>   pmd_t maybe_pmd_mkwrite(pmd_t pmd, struct vm_area_struct *vma)
>   {
>   	if (likely(vma->vm_flags & VM_WRITE))
> -		pmd = pmd_mkwrite(pmd);
> +		pmd = pmd_mkwrite(pmd, vma);
>   	return pmd;
>   }
>   
> @@ -1580,7 +1580,7 @@ vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf)
>   	pmd = pmd_modify(oldpmd, vma->vm_page_prot);
>   	pmd = pmd_mkyoung(pmd);
>   	if (writable)
> -		pmd = pmd_mkwrite(pmd);
> +		pmd = pmd_mkwrite(pmd, vma);
>   	set_pmd_at(vma->vm_mm, haddr, vmf->pmd, pmd);
>   	update_mmu_cache_pmd(vma, vmf->address, vmf->pmd);
>   	spin_unlock(vmf->ptl);
> @@ -1926,7 +1926,7 @@ int change_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
>   	/* See change_pte_range(). */
>   	if ((cp_flags & MM_CP_TRY_CHANGE_WRITABLE) && !pmd_write(entry) &&
>   	    can_change_pmd_writable(vma, addr, entry))
> -		entry = pmd_mkwrite(entry);
> +		entry = pmd_mkwrite(entry, vma);
>   
>   	ret = HPAGE_PMD_NR;
>   	set_pmd_at(mm, addr, pmd, entry);
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index 07abcb6eb203..6af471bdcff8 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
> @@ -4900,7 +4900,7 @@ static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page,
>   
>   	if (writable) {
>   		entry = huge_pte_mkwrite(huge_pte_mkdirty(mk_huge_pte(page,
> -					 vma->vm_page_prot)));
> +					 vma->vm_page_prot)), vma);
>   	} else {
>   		entry = huge_pte_wrprotect(mk_huge_pte(page,
>   					   vma->vm_page_prot));
> @@ -4916,7 +4916,7 @@ static void set_huge_ptep_writable(struct vm_area_struct *vma,
>   {
>   	pte_t entry;
>   
> -	entry = huge_pte_mkwrite(huge_pte_mkdirty(huge_ptep_get(ptep)));
> +	entry = huge_pte_mkwrite(huge_pte_mkdirty(huge_ptep_get(ptep)), vma);
>   	if (huge_ptep_set_access_flags(vma, address, ptep, entry, 1))
>   		update_mmu_cache(vma, address, ptep);
>   }
> diff --git a/mm/memory.c b/mm/memory.c
> index f456f3b5049c..d0972d2d6f36 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -4067,7 +4067,7 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf)
>   	entry = mk_pte(&folio->page, vma->vm_page_prot);
>   	entry = pte_sw_mkyoung(entry);
>   	if (vma->vm_flags & VM_WRITE)
> -		entry = pte_mkwrite(pte_mkdirty(entry));
> +		entry = pte_mkwrite(pte_mkdirty(entry), vma);
>   
>   	vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, vmf->address,
>   			&vmf->ptl);
> @@ -4755,7 +4755,7 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf)
>   	pte = pte_modify(old_pte, vma->vm_page_prot);
>   	pte = pte_mkyoung(pte);
>   	if (writable)
> -		pte = pte_mkwrite(pte);
> +		pte = pte_mkwrite(pte, vma);
>   	ptep_modify_prot_commit(vma, vmf->address, vmf->pte, old_pte, pte);
>   	update_mmu_cache(vma, vmf->address, vmf->pte);
>   	pte_unmap_unlock(vmf->pte, vmf->ptl);
> diff --git a/mm/migrate_device.c b/mm/migrate_device.c
> index d30c9de60b0d..df3f5e9d5f76 100644
> --- a/mm/migrate_device.c
> +++ b/mm/migrate_device.c
> @@ -646,7 +646,7 @@ static void migrate_vma_insert_page(struct migrate_vma *migrate,
>   		}
>   		entry = mk_pte(page, vma->vm_page_prot);
>   		if (vma->vm_flags & VM_WRITE)
> -			entry = pte_mkwrite(pte_mkdirty(entry));
> +			entry = pte_mkwrite(pte_mkdirty(entry), vma);
>   	}
>   
>   	ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl);
> diff --git a/mm/mprotect.c b/mm/mprotect.c
> index 1d4843c97c2a..381163a41e88 100644
> --- a/mm/mprotect.c
> +++ b/mm/mprotect.c
> @@ -198,7 +198,7 @@ static long change_pte_range(struct mmu_gather *tlb,
>   			if ((cp_flags & MM_CP_TRY_CHANGE_WRITABLE) &&
>   			    !pte_write(ptent) &&
>   			    can_change_pte_writable(vma, addr, ptent))
> -				ptent = pte_mkwrite(ptent);
> +				ptent = pte_mkwrite(ptent, vma);
>   
>   			ptep_modify_prot_commit(vma, addr, pte, oldpte, ptent);
>   			if (pte_needs_flush(oldpte, ptent))
> diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
> index 53c3d916ff66..3db6f87c0aca 100644
> --- a/mm/userfaultfd.c
> +++ b/mm/userfaultfd.c
> @@ -75,7 +75,7 @@ int mfill_atomic_install_pte(struct mm_struct *dst_mm, pmd_t *dst_pmd,
>   	if (page_in_cache && !vm_shared)
>   		writable = false;
>   	if (writable)
> -		_dst_pte = pte_mkwrite(_dst_pte);
> +		_dst_pte = pte_mkwrite(_dst_pte, dst_vma);
>   	if (wp_copy)
>   		_dst_pte = pte_mkuffd_wp(_dst_pte);
>   


More information about the linux-riscv mailing list