revert uvm_fault.c 1.104 for now. see PR/28372, PR/32665.
This commit is contained in:
parent
ed1116428c
commit
7fcddedf0b
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: uvm_fault.c,v 1.104 2006/01/21 13:13:07 yamt Exp $ */
|
||||
/* $NetBSD: uvm_fault.c,v 1.105 2006/01/30 11:50:17 yamt Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
@ -39,7 +39,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: uvm_fault.c,v 1.104 2006/01/21 13:13:07 yamt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: uvm_fault.c,v 1.105 2006/01/30 11:50:17 yamt Exp $");
|
||||
|
||||
#include "opt_uvmhist.h"
|
||||
|
||||
@ -535,143 +535,6 @@ released:
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* uvmfault_promote: promote data to a new anon. used for 1B and 2B.
|
||||
*
|
||||
* 1. allocate an anon and a page.
|
||||
* 2. fill its contents.
|
||||
* 3. put it into amap.
|
||||
*
|
||||
* => if we fail (result != 0) we unlock everything.
|
||||
* => on success, return a new locked anon via 'nanon'.
|
||||
* (*nanon)->an_page will be a resident, locked, dirty page.
|
||||
*/
|
||||
|
||||
static int
|
||||
uvmfault_promote(struct uvm_faultinfo *ufi,
|
||||
struct vm_anon *oanon,
|
||||
struct vm_page *uobjpage,
|
||||
struct vm_anon **nanon, /* OUT: allocated anon */
|
||||
struct vm_anon **spare)
|
||||
{
|
||||
struct vm_amap *amap = ufi->entry->aref.ar_amap;
|
||||
struct uvm_object *uobj;
|
||||
struct vm_anon *anon;
|
||||
struct vm_page *pg;
|
||||
struct vm_page *opg;
|
||||
int error;
|
||||
UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist);
|
||||
|
||||
if (oanon) {
|
||||
/* anon COW */
|
||||
opg = oanon->an_page;
|
||||
KASSERT(opg != NULL);
|
||||
KASSERT(opg->uobject == NULL || opg->loan_count > 0);
|
||||
} else if (uobjpage != PGO_DONTCARE) {
|
||||
/* object-backed COW */
|
||||
opg = uobjpage;
|
||||
KASSERT(opg->uobject == ufi->entry->object.uvm_obj);
|
||||
} else {
|
||||
/* ZFOD */
|
||||
opg = NULL;
|
||||
}
|
||||
if (opg != NULL) {
|
||||
uobj = opg->uobject;
|
||||
} else {
|
||||
uobj = NULL;
|
||||
}
|
||||
|
||||
KASSERT(amap != NULL);
|
||||
KASSERT(uobjpage != NULL);
|
||||
KASSERT(uobjpage == PGO_DONTCARE || (uobjpage->flags & PG_BUSY) != 0);
|
||||
LOCK_ASSERT(simple_lock_held(&amap->am_l));
|
||||
LOCK_ASSERT(oanon == NULL || simple_lock_held(&oanon->an_lock));
|
||||
LOCK_ASSERT(uobj == NULL || simple_lock_held(&uobj->vmobjlock));
|
||||
LOCK_ASSERT(*spare == NULL || !simple_lock_held(&(*spare)->an_lock));
|
||||
|
||||
if (*spare != NULL) {
|
||||
anon = *spare;
|
||||
*spare = NULL;
|
||||
simple_lock(&anon->an_lock);
|
||||
} else if (ufi->map != kernel_map) {
|
||||
anon = uvm_analloc();
|
||||
} else {
|
||||
UVMHIST_LOG(maphist, "kernel_map, unlock and retry", 0,0,0,0);
|
||||
|
||||
/*
|
||||
* we can't allocate anons with kernel_map locked.
|
||||
*/
|
||||
|
||||
uvm_page_unbusy(&uobjpage, 1);
|
||||
uvmfault_unlockall(ufi, amap, uobj, oanon);
|
||||
|
||||
*spare = uvm_analloc();
|
||||
if (*spare == NULL) {
|
||||
goto nomem;
|
||||
}
|
||||
simple_unlock(&(*spare)->an_lock);
|
||||
error = ERESTART;
|
||||
goto done;
|
||||
}
|
||||
if (anon) {
|
||||
|
||||
/*
|
||||
* The new anon is locked.
|
||||
*
|
||||
* if opg == NULL, we want a zero'd, dirty page,
|
||||
* so have uvm_pagealloc() do that for us.
|
||||
*/
|
||||
|
||||
pg = uvm_pagealloc(NULL, 0, anon,
|
||||
(opg == NULL) ? UVM_PGA_ZERO : 0);
|
||||
} else {
|
||||
pg = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* out of memory resources?
|
||||
*/
|
||||
|
||||
if (pg == NULL) {
|
||||
/* save anon for the next try. */
|
||||
if (anon != NULL) {
|
||||
simple_unlock(&anon->an_lock);
|
||||
*spare = anon;
|
||||
}
|
||||
|
||||
/* unlock and fail ... */
|
||||
uvm_page_unbusy(&uobjpage, 1);
|
||||
uvmfault_unlockall(ufi, amap, uobj, oanon);
|
||||
nomem:
|
||||
if (!uvm_reclaimable()) {
|
||||
UVMHIST_LOG(maphist, "out of VM", 0,0,0,0);
|
||||
uvmexp.fltnoanon++;
|
||||
error = ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
UVMHIST_LOG(maphist, "out of RAM, waiting for more", 0,0,0,0);
|
||||
uvmexp.fltnoram++;
|
||||
uvm_wait("flt_noram5");
|
||||
error = ERESTART;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* copy page [pg now dirty] */
|
||||
if (opg) {
|
||||
uvm_pagecopy(opg, pg);
|
||||
}
|
||||
|
||||
amap_add(&ufi->entry->aref, ufi->orig_rvaddr - ufi->entry->start, anon,
|
||||
oanon != NULL);
|
||||
|
||||
*nanon = anon;
|
||||
error = 0;
|
||||
done:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* F A U L T - m a i n e n t r y p o i n t
|
||||
*/
|
||||
@ -704,14 +567,13 @@ uvm_fault(struct vm_map *orig_map, vaddr_t vaddr, vm_fault_t fault_type,
|
||||
struct vm_amap *amap;
|
||||
struct uvm_object *uobj;
|
||||
struct vm_anon *anons_store[UVM_MAXRANGE], **anons, *anon, *oanon;
|
||||
struct vm_anon *anon_spare;
|
||||
struct vm_page *pages[UVM_MAXRANGE], *pg, *uobjpage;
|
||||
UVMHIST_FUNC("uvm_fault"); UVMHIST_CALLED(maphist);
|
||||
|
||||
UVMHIST_LOG(maphist, "(map=0x%x, vaddr=0x%x, ft=%d, at=%d)",
|
||||
orig_map, vaddr, fault_type, access_type);
|
||||
|
||||
anon = anon_spare = NULL;
|
||||
anon = NULL;
|
||||
pg = NULL;
|
||||
|
||||
uvmexp.faults++; /* XXX: locking? */
|
||||
@ -742,8 +604,7 @@ ReFault:
|
||||
|
||||
if (uvmfault_lookup(&ufi, FALSE) == FALSE) {
|
||||
UVMHIST_LOG(maphist, "<- no mapping @ 0x%x", vaddr, 0,0,0);
|
||||
error = EFAULT;
|
||||
goto done;
|
||||
return (EFAULT);
|
||||
}
|
||||
/* locked: maps(read) */
|
||||
|
||||
@ -768,8 +629,7 @@ ReFault:
|
||||
"<- protection failure (prot=0x%x, access=0x%x)",
|
||||
ufi.entry->protection, access_type, 0, 0);
|
||||
uvmfault_unlockmaps(&ufi, FALSE);
|
||||
error = EACCES;
|
||||
goto done;
|
||||
return EACCES;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -832,8 +692,7 @@ ReFault:
|
||||
if (amap == NULL && uobj == NULL) {
|
||||
uvmfault_unlockmaps(&ufi, FALSE);
|
||||
UVMHIST_LOG(maphist,"<- no backing store, no overlay",0,0,0,0);
|
||||
error = EFAULT;
|
||||
goto done;
|
||||
return (EFAULT);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1027,7 +886,7 @@ ReFault:
|
||||
/*
|
||||
* object fault routine responsible for pmap_update().
|
||||
*/
|
||||
goto done;
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1205,7 +1064,7 @@ ReFault:
|
||||
goto ReFault;
|
||||
|
||||
default:
|
||||
goto done;
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1321,24 +1180,41 @@ ReFault:
|
||||
UVMHIST_LOG(maphist, " case 1B: COW fault",0,0,0,0);
|
||||
uvmexp.flt_acow++;
|
||||
oanon = anon; /* oanon = old, locked anon */
|
||||
|
||||
error = uvmfault_promote(&ufi, oanon, PGO_DONTCARE,
|
||||
&anon, &anon_spare);
|
||||
switch (error) {
|
||||
case 0:
|
||||
break;
|
||||
case ERESTART:
|
||||
goto ReFault;
|
||||
default:
|
||||
goto done;
|
||||
anon = uvm_analloc();
|
||||
if (anon) {
|
||||
/* new anon is locked! */
|
||||
pg = uvm_pagealloc(NULL, 0, anon, 0);
|
||||
}
|
||||
|
||||
pg = anon->an_page;
|
||||
/* check for out of RAM */
|
||||
if (anon == NULL || pg == NULL) {
|
||||
if (anon) {
|
||||
anon->an_ref--;
|
||||
simple_unlock(&anon->an_lock);
|
||||
uvm_anfree(anon);
|
||||
}
|
||||
uvmfault_unlockall(&ufi, amap, uobj, oanon);
|
||||
if (!uvm_reclaimable()) {
|
||||
UVMHIST_LOG(maphist,
|
||||
"<- failed. out of VM",0,0,0,0);
|
||||
uvmexp.fltnoanon++;
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
uvmexp.fltnoram++;
|
||||
uvm_wait("flt_noram3"); /* out of RAM, wait for more */
|
||||
goto ReFault;
|
||||
}
|
||||
|
||||
/* got all resources, replace anon with nanon */
|
||||
uvm_pagecopy(oanon->an_page, pg);
|
||||
uvm_lock_pageq();
|
||||
uvm_pageactivate(pg);
|
||||
uvm_unlock_pageq();
|
||||
pg->flags &= ~(PG_BUSY|PG_FAKE);
|
||||
uvm_unlock_pageq();
|
||||
UVM_PAGE_OWN(pg, NULL);
|
||||
amap_add(&ufi.entry->aref, ufi.orig_rvaddr - ufi.entry->start,
|
||||
anon, TRUE);
|
||||
|
||||
/* deref: can not drop to zero here by defn! */
|
||||
oanon->an_ref--;
|
||||
@ -1386,8 +1262,7 @@ ReFault:
|
||||
UVMHIST_LOG(maphist,
|
||||
"<- failed. out of VM",0,0,0,0);
|
||||
/* XXX instrumentation */
|
||||
error = ENOMEM;
|
||||
goto done;
|
||||
return ENOMEM;
|
||||
}
|
||||
/* XXX instrumentation */
|
||||
uvm_wait("flt_pmfail1");
|
||||
@ -1424,8 +1299,7 @@ ReFault:
|
||||
simple_unlock(&anon->an_lock);
|
||||
uvmfault_unlockall(&ufi, amap, uobj, oanon);
|
||||
pmap_update(ufi.orig_map->pmap);
|
||||
error = 0;
|
||||
goto done;
|
||||
return 0;
|
||||
|
||||
Case2:
|
||||
/*
|
||||
@ -1496,7 +1370,7 @@ Case2:
|
||||
|
||||
UVMHIST_LOG(maphist, "<- pgo_get failed (code %d)",
|
||||
error, 0,0,0);
|
||||
goto done;
|
||||
return error;
|
||||
}
|
||||
|
||||
/* locked: uobjpage */
|
||||
@ -1648,18 +1522,62 @@ Case2:
|
||||
if (amap == NULL)
|
||||
panic("uvm_fault: want to promote data, but no anon");
|
||||
#endif
|
||||
error = uvmfault_promote(&ufi, NULL, uobjpage,
|
||||
&anon, &anon_spare);
|
||||
switch (error) {
|
||||
case 0:
|
||||
break;
|
||||
case ERESTART:
|
||||
goto ReFault;
|
||||
default:
|
||||
goto done;
|
||||
|
||||
anon = uvm_analloc();
|
||||
if (anon) {
|
||||
|
||||
/*
|
||||
* The new anon is locked.
|
||||
*
|
||||
* In `Fill in data...' below, if
|
||||
* uobjpage == PGO_DONTCARE, we want
|
||||
* a zero'd, dirty page, so have
|
||||
* uvm_pagealloc() do that for us.
|
||||
*/
|
||||
|
||||
pg = uvm_pagealloc(NULL, 0, anon,
|
||||
(uobjpage == PGO_DONTCARE) ? UVM_PGA_ZERO : 0);
|
||||
}
|
||||
|
||||
pg = anon->an_page;
|
||||
/*
|
||||
* out of memory resources?
|
||||
*/
|
||||
|
||||
if (anon == NULL || pg == NULL) {
|
||||
if (anon != NULL) {
|
||||
anon->an_ref--;
|
||||
simple_unlock(&anon->an_lock);
|
||||
uvm_anfree(anon);
|
||||
}
|
||||
|
||||
/*
|
||||
* arg! must unbusy our page and fail or sleep.
|
||||
*/
|
||||
|
||||
if (uobjpage != PGO_DONTCARE) {
|
||||
if (uobjpage->flags & PG_WANTED)
|
||||
/* still holding object lock */
|
||||
wakeup(uobjpage);
|
||||
|
||||
uobjpage->flags &= ~(PG_BUSY|PG_WANTED);
|
||||
UVM_PAGE_OWN(uobjpage, NULL);
|
||||
}
|
||||
|
||||
/* unlock and fail ... */
|
||||
uvmfault_unlockall(&ufi, amap, uobj, NULL);
|
||||
if (!uvm_reclaimable()) {
|
||||
UVMHIST_LOG(maphist, " promote: out of VM",
|
||||
0,0,0,0);
|
||||
uvmexp.fltnoanon++;
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
UVMHIST_LOG(maphist, " out of RAM, waiting for more",
|
||||
0,0,0,0);
|
||||
uvmexp.fltnoram++;
|
||||
uvm_wait("flt_noram5");
|
||||
goto ReFault;
|
||||
}
|
||||
|
||||
/*
|
||||
* fill in the data
|
||||
@ -1667,6 +1585,8 @@ Case2:
|
||||
|
||||
if (uobjpage != PGO_DONTCARE) {
|
||||
uvmexp.flt_prcopy++;
|
||||
/* copy page [pg now dirty] */
|
||||
uvm_pagecopy(uobjpage, pg);
|
||||
|
||||
/*
|
||||
* promote to shared amap? make sure all sharing
|
||||
@ -1702,13 +1622,15 @@ Case2:
|
||||
uvmexp.flt_przero++;
|
||||
|
||||
/*
|
||||
* Page is zero'd and marked dirty by
|
||||
* uvmfault_promote().
|
||||
* Page is zero'd and marked dirty by uvm_pagealloc()
|
||||
* above.
|
||||
*/
|
||||
|
||||
UVMHIST_LOG(maphist," zero fill anon/page 0x%x/0%x",
|
||||
anon, pg, 0, 0);
|
||||
}
|
||||
amap_add(&ufi.entry->aref, ufi.orig_rvaddr - ufi.entry->start,
|
||||
anon, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1756,8 +1678,7 @@ Case2:
|
||||
UVMHIST_LOG(maphist,
|
||||
"<- failed. out of VM",0,0,0,0);
|
||||
/* XXX instrumentation */
|
||||
error = ENOMEM;
|
||||
goto done;
|
||||
return ENOMEM;
|
||||
}
|
||||
/* XXX instrumentation */
|
||||
uvm_wait("flt_pmfail2");
|
||||
@ -1796,13 +1717,7 @@ Case2:
|
||||
uvmfault_unlockall(&ufi, amap, uobj, anon);
|
||||
pmap_update(ufi.orig_map->pmap);
|
||||
UVMHIST_LOG(maphist, "<- done (SUCCESS!)",0,0,0,0);
|
||||
error = 0;
|
||||
done:
|
||||
if (anon_spare != NULL) {
|
||||
anon_spare->an_ref--;
|
||||
uvm_anfree(anon_spare);
|
||||
}
|
||||
return error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user