--- /dev/null
+From ac15bd63bbb24238f763ec5b24ee175ec301e8cd Mon Sep 17 00:00:00 2001
+From: Catalin Marinas <catalin.marinas@arm.com>
+Date: Thu, 7 Jan 2016 16:07:20 +0000
+Subject: arm64: Honour !PTE_WRITE in set_pte_at() for kernel mappings
+
+From: Catalin Marinas <catalin.marinas@arm.com>
+
+commit ac15bd63bbb24238f763ec5b24ee175ec301e8cd upstream.
+
+Currently, set_pte_at() only checks the software PTE_WRITE bit for user
+mappings when it sets or clears the hardware PTE_RDONLY accordingly. The
+kernel ptes are written directly without any modification, relying
+solely on the protection bits in macros like PAGE_KERNEL. However,
+modifying kernel pte attributes via pte_wrprotect() would be ignored by
+set_pte_at(). Since pte_wrprotect() does not set PTE_RDONLY (it only
+clears PTE_WRITE), the new permission is not taken into account.
+
+This patch changes set_pte_at() to adjust the read-only permission for
+kernel ptes as well. As a side effect, existing PROT_* definitions used
+for kernel ioremap*() need to include PTE_DIRTY | PTE_WRITE.
+
+(additionally, white space fix for PTE_KERNEL_ROX)
+
+Acked-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
+Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Reported-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/include/asm/pgtable.h | 21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+--- a/arch/arm64/include/asm/pgtable.h
++++ b/arch/arm64/include/asm/pgtable.h
+@@ -69,11 +69,11 @@ extern void __pgd_error(const char *file
+ #define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED)
+ #define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S)
+
+-#define PROT_DEVICE_nGnRnE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRnE))
+-#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
+-#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL_NC))
+-#define PROT_NORMAL_WT (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL_WT))
+-#define PROT_NORMAL (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL))
++#define PROT_DEVICE_nGnRnE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRnE))
++#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRE))
++#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_NC))
++#define PROT_NORMAL_WT (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_WT))
++#define PROT_NORMAL (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL))
+
+ #define PROT_SECT_DEVICE_nGnRE (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE))
+ #define PROT_SECT_NORMAL (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL))
+@@ -83,7 +83,7 @@ extern void __pgd_error(const char *file
+
+ #define PAGE_KERNEL __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE)
+ #define PAGE_KERNEL_RO __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_RDONLY)
+-#define PAGE_KERNEL_ROX __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_RDONLY)
++#define PAGE_KERNEL_ROX __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_RDONLY)
+ #define PAGE_KERNEL_EXEC __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE)
+ #define PAGE_KERNEL_EXEC_CONT __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_CONT)
+
+@@ -155,6 +155,7 @@ extern struct page *empty_zero_page;
+ #define pte_write(pte) (!!(pte_val(pte) & PTE_WRITE))
+ #define pte_exec(pte) (!(pte_val(pte) & PTE_UXN))
+ #define pte_cont(pte) (!!(pte_val(pte) & PTE_CONT))
++#define pte_user(pte) (!!(pte_val(pte) & PTE_USER))
+
+ #ifdef CONFIG_ARM64_HW_AFDBM
+ #define pte_hw_dirty(pte) (pte_write(pte) && !(pte_val(pte) & PTE_RDONLY))
+@@ -165,8 +166,6 @@ extern struct page *empty_zero_page;
+ #define pte_dirty(pte) (pte_sw_dirty(pte) || pte_hw_dirty(pte))
+
+ #define pte_valid(pte) (!!(pte_val(pte) & PTE_VALID))
+-#define pte_valid_user(pte) \
+- ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER))
+ #define pte_valid_not_user(pte) \
+ ((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID)
+
+@@ -264,13 +263,13 @@ extern void __sync_icache_dcache(pte_t p
+ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte)
+ {
+- if (pte_valid_user(pte)) {
+- if (!pte_special(pte) && pte_exec(pte))
+- __sync_icache_dcache(pte, addr);
++ if (pte_valid(pte)) {
+ if (pte_sw_dirty(pte) && pte_write(pte))
+ pte_val(pte) &= ~PTE_RDONLY;
+ else
+ pte_val(pte) |= PTE_RDONLY;
++ if (pte_user(pte) && pte_exec(pte) && !pte_special(pte))
++ __sync_icache_dcache(pte, addr);
+ }
+
+ /*
--- /dev/null
+From fdc69e7df3cb24f18a93192641786e5b7ecd1dfe Mon Sep 17 00:00:00 2001
+From: Catalin Marinas <catalin.marinas@arm.com>
+Date: Wed, 9 Mar 2016 16:31:29 +0000
+Subject: arm64: Update PTE_RDONLY in set_pte_at() for PROT_NONE permission
+
+From: Catalin Marinas <catalin.marinas@arm.com>
+
+commit fdc69e7df3cb24f18a93192641786e5b7ecd1dfe upstream.
+
+The set_pte_at() function must update the hardware PTE_RDONLY bit
+depending on the state of the PTE_WRITE and PTE_DIRTY bits of the given
+entry value. However, it currently only performs this for pte_valid()
+entries, ignoring PTE_PROT_NONE. The side-effect is that PROT_NONE
+mappings would not have the PTE_RDONLY bit set. Without
+CONFIG_ARM64_HW_AFDBM, this is not an issue since such PROT_NONE pages
+are not accessible anyway.
+
+With commit 2f4b829c625e ("arm64: Add support for hardware updates of
+the access and dirty pte bits"), the ptep_set_wrprotect() function was
+re-written to cope with automatic hardware updates of the dirty state.
+As an optimisation, only PTE_RDONLY is checked to assess the "dirty"
+status. Since set_pte_at() does not set this bit for PROT_NONE mappings,
+such pages may be considered "dirty" as a result of
+ptep_set_wrprotect().
+
+This patch updates the pte_valid() check to pte_present() in
+set_pte_at(). It also adds PTE_PROT_NONE to the swap entry bits comment.
+
+Fixes: 2f4b829c625e ("arm64: Add support for hardware updates of the access and dirty pte bits")
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Reported-by: Ganapatrao Kulkarni <gkulkarni@caviumnetworks.com>
+Tested-by: Ganapatrao Kulkarni <gkulkarni@cavium.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/include/asm/pgtable.h | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/arch/arm64/include/asm/pgtable.h
++++ b/arch/arm64/include/asm/pgtable.h
+@@ -263,7 +263,7 @@ extern void __sync_icache_dcache(pte_t p
+ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte)
+ {
+- if (pte_valid(pte)) {
++ if (pte_present(pte)) {
+ if (pte_sw_dirty(pte) && pte_write(pte))
+ pte_val(pte) &= ~PTE_RDONLY;
+ else
+@@ -640,6 +640,7 @@ extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
+ * bits 0-1: present (must be zero)
+ * bits 2-7: swap type
+ * bits 8-57: swap offset
++ * bit 58: PTE_PROT_NONE (must be zero)
+ */
+ #define __SWP_TYPE_SHIFT 2
+ #define __SWP_TYPE_BITS 6