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
This commit is contained in:
parent
0367bca479
commit
1587dc37fa
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=350427
@ -5743,7 +5743,7 @@ pmap_sync_icache(pmap_t pmap, vm_offset_t va, vm_size_t sz)
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user