svn commit: r350427 - head/sys/arm64/arm64
Mark Johnston
markj at FreeBSD.org
Mon Jul 29 21:21:54 UTC 2019
Author: markj
Date: Mon Jul 29 21:21:53 2019
New Revision: 350427
URL: https://svnweb.freebsd.org/changeset/base/350427
Log:
Have arm64's pmap_fault() handle WnR faults on dirty PTEs.
If we take a WnR permission fault on a managed, writeable and dirty
PTE, simply return success without calling the main fault handler. This
situation can occur if multiple threads simultaneously access a clean
writeable mapping and trigger WnR faults; losers of the race to mark the
PTE dirty would end up calling the main fault handler, which had no work
to do.
Reported by: alc
Reviewed by: alc
MFC with: r350004
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D21097
Modified:
head/sys/arm64/arm64/pmap.c
Modified: head/sys/arm64/arm64/pmap.c
==============================================================================
--- head/sys/arm64/arm64/pmap.c Mon Jul 29 20:50:26 2019 (r350426)
+++ head/sys/arm64/arm64/pmap.c Mon Jul 29 21:21:53 2019 (r350427)
@@ -5743,7 +5743,7 @@ pmap_sync_icache(pmap_t pmap, vm_offset_t va, vm_size_
int
pmap_fault(pmap_t pmap, uint64_t esr, uint64_t far)
{
- pt_entry_t *pte;
+ pt_entry_t pte, *ptep;
register_t intr;
uint64_t ec, par;
int lvl, rv;
@@ -5767,9 +5767,9 @@ pmap_fault(pmap_t pmap, uint64_t esr, uint64_t far)
case ISS_DATA_DFSC_AFF_L2:
case ISS_DATA_DFSC_AFF_L3:
PMAP_LOCK(pmap);
- pte = pmap_pte(pmap, far, &lvl);
- if (pte != NULL) {
- pmap_set_bits(pte, ATTR_AF);
+ ptep = pmap_pte(pmap, far, &lvl);
+ if (ptep != NULL) {
+ pmap_set_bits(ptep, ATTR_AF);
rv = KERN_SUCCESS;
/*
* XXXMJ as an optimization we could mark the entry
@@ -5785,12 +5785,13 @@ pmap_fault(pmap_t pmap, uint64_t esr, uint64_t far)
(esr & ISS_DATA_WnR) == 0)
return (rv);
PMAP_LOCK(pmap);
- pte = pmap_pte(pmap, far, &lvl);
- if (pte != NULL &&
- (pmap_load(pte) & (ATTR_AP_RW_BIT | ATTR_SW_DBM)) ==
- (ATTR_AP(ATTR_AP_RO) | ATTR_SW_DBM)) {
- pmap_clear_bits(pte, ATTR_AP_RW_BIT);
- pmap_invalidate_page(pmap, far);
+ ptep = pmap_pte(pmap, far, &lvl);
+ if (ptep != NULL &&
+ ((pte = pmap_load(ptep)) & ATTR_SW_DBM) != 0) {
+ if ((pte & ATTR_AP_RW_BIT) == ATTR_AP(ATTR_AP_RO)) {
+ pmap_clear_bits(ptep, ATTR_AP_RW_BIT);
+ pmap_invalidate_page(pmap, far);
+ }
rv = KERN_SUCCESS;
}
PMAP_UNLOCK(pmap);
More information about the svn-src-all
mailing list