1
0
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:
Nathan Whitehorn 2012-04-22 17:58:30 +00:00
parent 6f1d6967f2
commit 0b852c03eb
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=234576
2 changed files with 33 additions and 2 deletions

View File

@ -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);

View File

@ -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");