arm64: Ignore hardware dirty bit updates in ptep_set_wrprotect()
ptep_set_wrprotect() is only called on CoW mappings which are private (!VM_SHARED) with the pte either read-only (!PTE_WRITE && PTE_RDONLY) or writable and software-dirty (PTE_WRITE && !PTE_RDONLY && PTE_DIRTY). There is no race with the hardware update of the dirty state: clearing of PTE_RDONLY when PTE_WRITE (a.k.a. PTE_DBM) is set. This patch removes the code setting the software PTE_DIRTY bit in ptep_set_wrprotect() as superfluous. A VM_WARN_ONCE is introduced in case the above logic is wrong or the core mm code changes its use of ptep_set_wrprotect(). Reviewed-by: Will Deacon <will.deacon@arm.com> Acked-by: Steve Capper <steve.capper@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
This commit is contained in:
parent
73e86cb03c
commit
64c26841b3
1 changed files with 13 additions and 8 deletions
|
@ -634,23 +634,28 @@ static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
|
||||||
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ptep_set_wrprotect - mark read-only while trasferring potential hardware
|
* ptep_set_wrprotect - mark read-only while preserving the hardware update of
|
||||||
* dirty status (PTE_DBM && !PTE_RDONLY) to the software PTE_DIRTY bit.
|
* the Access Flag.
|
||||||
*/
|
*/
|
||||||
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
|
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
|
||||||
static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long address, pte_t *ptep)
|
static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long address, pte_t *ptep)
|
||||||
{
|
{
|
||||||
pte_t old_pte, pte;
|
pte_t old_pte, pte;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ptep_set_wrprotect() is only called on CoW mappings which are
|
||||||
|
* private (!VM_SHARED) with the pte either read-only (!PTE_WRITE &&
|
||||||
|
* PTE_RDONLY) or writable and software-dirty (PTE_WRITE &&
|
||||||
|
* !PTE_RDONLY && PTE_DIRTY); see is_cow_mapping() and
|
||||||
|
* protection_map[]. There is no race with the hardware update of the
|
||||||
|
* dirty state: clearing of PTE_RDONLY when PTE_WRITE (a.k.a. PTE_DBM)
|
||||||
|
* is set.
|
||||||
|
*/
|
||||||
|
VM_WARN_ONCE(pte_write(*ptep) && !pte_dirty(*ptep),
|
||||||
|
"%s: potential race with hardware DBM", __func__);
|
||||||
pte = READ_ONCE(*ptep);
|
pte = READ_ONCE(*ptep);
|
||||||
do {
|
do {
|
||||||
old_pte = pte;
|
old_pte = pte;
|
||||||
/*
|
|
||||||
* If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY
|
|
||||||
* clear), set the PTE_DIRTY bit.
|
|
||||||
*/
|
|
||||||
if (pte_hw_dirty(pte))
|
|
||||||
pte = pte_mkdirty(pte);
|
|
||||||
pte = pte_wrprotect(pte);
|
pte = pte_wrprotect(pte);
|
||||||
pte_val(pte) = cmpxchg_relaxed(&pte_val(*ptep),
|
pte_val(pte) = cmpxchg_relaxed(&pte_val(*ptep),
|
||||||
pte_val(old_pte), pte_val(pte));
|
pte_val(old_pte), pte_val(pte));
|
||||||
|
|
Loading…
Reference in a new issue