diff options
author | Alan Cox <alc@FreeBSD.org> | 2021-07-24 08:50:27 +0000 |
---|---|---|
committer | Mark Johnston <markj@FreeBSD.org> | 2021-08-31 19:09:24 +0000 |
commit | 8024a900a4a76f11d972213f108e0cbdeb82564b (patch) | |
tree | 0ea2a07ee16864549403e17b77506251b817a63f | |
parent | 1fe88bc8512b8444a31534f4b196a1d62af7df33 (diff) | |
download | src-8024a900a4a76f11d972213f108e0cbdeb82564b.tar.gz src-8024a900a4a76f11d972213f108e0cbdeb82564b.zip |
amd64: Don't repeat unnecessary tests when cmpset fails
When a cmpset for removing the PG_RW bit in pmap_promote_pde() fails,
there is no need to repeat the alignment, PG_A, and PG_V tests just to
reload the PTE's value. The only bit that we need be concerned with at
this point is PG_M. Use fcmpset instead.
(cherry picked from commit 3687797618b6c978ad733bd206a623e5df47dbe3)
-rw-r--r-- | sys/amd64/amd64/pmap.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index 705bbe712bff..0ac312a95a8c 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -6511,7 +6511,6 @@ pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va, * within a 2MB page. */ firstpte = (pt_entry_t *)PHYS_TO_DMAP(*pde & PG_FRAME); -setpde: newpde = *firstpte; if ((newpde & ((PG_FRAME & PDRMASK) | PG_A | PG_V)) != (PG_A | PG_V) || !pmap_allow_2m_x_page(pmap, pmap_pde_ept_executable(pmap, @@ -6521,12 +6520,13 @@ setpde: " in pmap %p", va, pmap); return; } +setpde: if ((newpde & (PG_M | PG_RW)) == PG_RW) { /* * When PG_M is already clear, PG_RW can be cleared without * a TLB invalidation. */ - if (!atomic_cmpset_long(firstpte, newpde, newpde & ~PG_RW)) + if (!atomic_fcmpset_long(firstpte, &newpde, newpde & ~PG_RW)) goto setpde; newpde &= ~PG_RW; } @@ -6538,7 +6538,6 @@ setpde: */ pa = (newpde & (PG_PS_FRAME | PG_A | PG_V)) + NBPDR - PAGE_SIZE; for (pte = firstpte + NPTEPG - 1; pte > firstpte; pte--) { -setpte: oldpte = *pte; if ((oldpte & (PG_FRAME | PG_A | PG_V)) != pa) { atomic_add_long(&pmap_pde_p_failures, 1); @@ -6546,12 +6545,13 @@ setpte: " in pmap %p", va, pmap); return; } +setpte: if ((oldpte & (PG_M | PG_RW)) == PG_RW) { /* * When PG_M is already clear, PG_RW can be cleared * without a TLB invalidation. */ - if (!atomic_cmpset_long(pte, oldpte, oldpte & ~PG_RW)) + if (!atomic_fcmpset_long(pte, &oldpte, oldpte & ~PG_RW)) goto setpte; oldpte &= ~PG_RW; CTR2(KTR_PMAP, "pmap_promote_pde: protect for va %#lx" |