Skip to content

Commit ff1712f

Browse files
committed
arm64: pgtable: Ensure dirty bit is preserved across pte_wrprotect()
With hardware dirty bit management, calling pte_wrprotect() on a writable, dirty PTE will lose the dirty state and return a read-only, clean entry. Move the logic from ptep_set_wrprotect() into pte_wrprotect() to ensure that the dirty bit is preserved for writable entries, as this is required for soft-dirty bit management if we enable it in the future. Cc: <[email protected]> Fixes: 2f4b829 ("arm64: Add support for hardware updates of the access and dirty pte bits") Reviewed-by: Catalin Marinas <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 07509e1 commit ff1712f

File tree

1 file changed

+14
-13
lines changed

1 file changed

+14
-13
lines changed

arch/arm64/include/asm/pgtable.h

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,6 @@ static inline pmd_t set_pmd_bit(pmd_t pmd, pgprot_t prot)
165165
return pmd;
166166
}
167167

168-
static inline pte_t pte_wrprotect(pte_t pte)
169-
{
170-
pte = clear_pte_bit(pte, __pgprot(PTE_WRITE));
171-
pte = set_pte_bit(pte, __pgprot(PTE_RDONLY));
172-
return pte;
173-
}
174-
175168
static inline pte_t pte_mkwrite(pte_t pte)
176169
{
177170
pte = set_pte_bit(pte, __pgprot(PTE_WRITE));
@@ -197,6 +190,20 @@ static inline pte_t pte_mkdirty(pte_t pte)
197190
return pte;
198191
}
199192

193+
static inline pte_t pte_wrprotect(pte_t pte)
194+
{
195+
/*
196+
* If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY
197+
* clear), set the PTE_DIRTY bit.
198+
*/
199+
if (pte_hw_dirty(pte))
200+
pte = pte_mkdirty(pte);
201+
202+
pte = clear_pte_bit(pte, __pgprot(PTE_WRITE));
203+
pte = set_pte_bit(pte, __pgprot(PTE_RDONLY));
204+
return pte;
205+
}
206+
200207
static inline pte_t pte_mkold(pte_t pte)
201208
{
202209
return clear_pte_bit(pte, __pgprot(PTE_AF));
@@ -846,12 +853,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
846853
pte = READ_ONCE(*ptep);
847854
do {
848855
old_pte = pte;
849-
/*
850-
* If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY
851-
* clear), set the PTE_DIRTY bit.
852-
*/
853-
if (pte_hw_dirty(pte))
854-
pte = pte_mkdirty(pte);
855856
pte = pte_wrprotect(pte);
856857
pte_val(pte) = cmpxchg_relaxed(&pte_val(*ptep),
857858
pte_val(old_pte), pte_val(pte));

0 commit comments

Comments
 (0)