mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-19 15:33:56 +00:00
Avoid a lock order reversal in pmap_extract_and_hold() from relocking
the page. This PMAP requires an additional lock besides the PMAP lock in pmap_extract_and_hold(), which vm_page_pa_tryrelock() did not release. Suggested by: kib MFC after: 4 days
This commit is contained in:
parent
6f1d6967f2
commit
0b852c03eb
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=234576
@ -1333,6 +1333,37 @@ moea64_extract(mmu_t mmu, pmap_t pm, vm_offset_t va)
|
||||
* pmap and virtual address pair if that mapping permits the given
|
||||
* protection.
|
||||
*/
|
||||
|
||||
extern int pa_tryrelock_restart;
|
||||
|
||||
static int
|
||||
vm_page_pa_tryrelock_moea64(pmap_t pmap, vm_paddr_t pa, vm_paddr_t *locked)
|
||||
{
|
||||
/*
|
||||
* This is a duplicate of vm_page_pa_tryrelock(), but with proper
|
||||
* handling of the table lock
|
||||
*/
|
||||
vm_paddr_t lockpa;
|
||||
|
||||
lockpa = *locked;
|
||||
*locked = pa;
|
||||
if (lockpa) {
|
||||
PA_LOCK_ASSERT(lockpa, MA_OWNED);
|
||||
if (PA_LOCKPTR(pa) == PA_LOCKPTR(lockpa))
|
||||
return (0);
|
||||
PA_UNLOCK(lockpa);
|
||||
}
|
||||
if (PA_TRYLOCK(pa))
|
||||
return (0);
|
||||
UNLOCK_TABLE_RD();
|
||||
PMAP_UNLOCK(pmap);
|
||||
atomic_add_int(&pa_tryrelock_restart, 1);
|
||||
PA_LOCK(pa);
|
||||
LOCK_TABLE_RD();
|
||||
PMAP_LOCK(pmap);
|
||||
return (EAGAIN);
|
||||
}
|
||||
|
||||
vm_page_t
|
||||
moea64_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_prot_t prot)
|
||||
{
|
||||
@ -1349,7 +1380,7 @@ moea64_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_prot_t prot)
|
||||
if (pvo != NULL && (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) &&
|
||||
((pvo->pvo_pte.lpte.pte_lo & LPTE_PP) == LPTE_RW ||
|
||||
(prot & VM_PROT_WRITE) == 0)) {
|
||||
if (vm_page_pa_tryrelock(pmap,
|
||||
if (vm_page_pa_tryrelock_moea64(pmap,
|
||||
pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN, &pa))
|
||||
goto retry;
|
||||
m = PHYS_TO_VM_PAGE(pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN);
|
||||
|
@ -131,7 +131,7 @@ TUNABLE_INT("vm.boot_pages", &boot_pages);
|
||||
SYSCTL_INT(_vm, OID_AUTO, boot_pages, CTLFLAG_RD, &boot_pages, 0,
|
||||
"number of pages allocated for bootstrapping the VM system");
|
||||
|
||||
static int pa_tryrelock_restart;
|
||||
int pa_tryrelock_restart;
|
||||
SYSCTL_INT(_vm, OID_AUTO, tryrelock_restart, CTLFLAG_RD,
|
||||
&pa_tryrelock_restart, 0, "Number of tryrelock restarts");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user