Annotation of src/sys/uvm/uvm_loan.c, Revision 1.67
1.67 ! ad 1: /* $NetBSD: uvm_loan.c,v 1.66 2007/07/21 19:21:54 ad Exp $ */
1.1 mrg 2:
3: /*
4: *
5: * Copyright (c) 1997 Charles D. Cranor and Washington University.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by Charles D. Cranor and
19: * Washington University.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.4 mrg 33: *
34: * from: Id: uvm_loan.c,v 1.1.6.4 1998/02/06 05:08:43 chs Exp
1.1 mrg 35: */
36:
37: /*
38: * uvm_loan.c: page loanout handler
39: */
1.35 lukem 40:
41: #include <sys/cdefs.h>
1.67 ! ad 42: __KERNEL_RCSID(0, "$NetBSD: uvm_loan.c,v 1.66 2007/07/21 19:21:54 ad Exp $");
1.1 mrg 43:
44: #include <sys/param.h>
45: #include <sys/systm.h>
46: #include <sys/kernel.h>
47: #include <sys/proc.h>
48: #include <sys/malloc.h>
49: #include <sys/mman.h>
50:
51: #include <uvm/uvm.h>
52:
53: /*
1.29 chs 54: * "loaned" pages are pages which are (read-only, copy-on-write) loaned
1.1 mrg 55: * from the VM system to other parts of the kernel. this allows page
56: * copying to be avoided (e.g. you can loan pages from objs/anons to
57: * the mbuf system).
58: *
59: * there are 3 types of loans possible:
60: * O->K uvm_object page to wired kernel page (e.g. mbuf data area)
1.16 thorpej 61: * A->K anon page to wired kernel page (e.g. mbuf data area)
1.1 mrg 62: * O->A uvm_object to anon loan (e.g. vnode page to an anon)
63: * note that it possible to have an O page loaned to both an A and K
64: * at the same time.
65: *
66: * loans are tracked by pg->loan_count. an O->A page will have both
67: * a uvm_object and a vm_anon, but PQ_ANON will not be set. this sort
68: * of page is considered "owned" by the uvm_object (not the anon).
69: *
1.16 thorpej 70: * each loan of a page to the kernel bumps the pg->wire_count. the
71: * kernel mappings for these pages will be read-only and wired. since
72: * the page will also be wired, it will not be a candidate for pageout,
73: * and thus will never be pmap_page_protect()'d with VM_PROT_NONE. a
74: * write fault in the kernel to one of these pages will not cause
75: * copy-on-write. instead, the page fault is considered fatal. this
76: * is because the kernel mapping will have no way to look up the
77: * object/anon which the page is owned by. this is a good side-effect,
78: * since a kernel write to a loaned page is an error.
1.1 mrg 79: *
1.29 chs 80: * owners that want to free their pages and discover that they are
1.1 mrg 81: * loaned out simply "disown" them (the page becomes an orphan). these
82: * pages should be freed when the last loan is dropped. in some cases
83: * an anon may "adopt" an orphaned page.
84: *
85: * locking: to read pg->loan_count either the owner or the page queues
86: * must be locked. to modify pg->loan_count, both the owner of the page
87: * and the PQs must be locked. pg->flags is (as always) locked by
88: * the owner of the page.
89: *
90: * note that locking from the "loaned" side is tricky since the object
91: * getting the loaned page has no reference to the page's owner and thus
92: * the owner could "die" at any time. in order to prevent the owner
93: * from dying the page queues should be locked. this forces us to sometimes
94: * use "try" locking.
95: *
96: * loans are typically broken by the following events:
1.29 chs 97: * 1. user-level xwrite fault to a loaned page
1.1 mrg 98: * 2. pageout of clean+inactive O->A loaned page
99: * 3. owner frees page (e.g. pager flush)
100: *
101: * note that loaning a page causes all mappings of the page to become
102: * read-only (via pmap_page_protect). this could have an unexpected
1.16 thorpej 103: * effect on normal "wired" pages if one is not careful (XXX).
1.1 mrg 104: */
105:
106: /*
107: * local prototypes
108: */
109:
1.50 junyoung 110: static int uvm_loananon(struct uvm_faultinfo *, void ***,
111: int, struct vm_anon *);
112: static int uvm_loanuobj(struct uvm_faultinfo *, void ***,
113: int, vaddr_t);
114: static int uvm_loanzero(struct uvm_faultinfo *, void ***, int);
115: static void uvm_unloananon(struct vm_anon **, int);
116: static void uvm_unloanpage(struct vm_page **, int);
1.51 yamt 117: static int uvm_loanpage(struct vm_page **, int);
1.33 jdolecek 118:
1.1 mrg 119:
120: /*
121: * inlines
122: */
123:
124: /*
125: * uvm_loanentry: loan out pages in a map entry (helper fn for uvm_loan())
126: *
127: * => "ufi" is the result of a successful map lookup (meaning that
1.31 chuck 128: * on entry the map is locked by the caller)
1.28 chuck 129: * => we may unlock and then relock the map if needed (for I/O)
1.1 mrg 130: * => we put our output result in "output"
1.31 chuck 131: * => we always return with the map unlocked
1.28 chuck 132: * => possible return values:
133: * -1 == error, map is unlocked
134: * 0 == map relock error (try again!), map is unlocked
1.31 chuck 135: * >0 == number of pages we loaned, map is unlocked
1.55 thorpej 136: *
137: * NOTE: We can live with this being an inline, because it is only called
138: * from one place.
1.1 mrg 139: */
140:
1.57 perry 141: static inline int
1.54 thorpej 142: uvm_loanentry(struct uvm_faultinfo *ufi, void ***output, int flags)
1.1 mrg 143: {
1.10 chuck 144: vaddr_t curaddr = ufi->orig_rvaddr;
1.9 eeh 145: vsize_t togo = ufi->size;
1.6 mrg 146: struct vm_aref *aref = &ufi->entry->aref;
147: struct uvm_object *uobj = ufi->entry->object.uvm_obj;
148: struct vm_anon *anon;
149: int rv, result = 0;
150:
1.52 yamt 151: UVMHIST_FUNC(__func__); UVMHIST_CALLED(loanhist);
152:
1.6 mrg 153: /*
1.28 chuck 154: * lock us the rest of the way down (we unlock before return)
1.6 mrg 155: */
156: if (aref->ar_amap)
1.13 chuck 157: amap_lock(aref->ar_amap);
1.6 mrg 158:
159: /*
160: * loop until done
161: */
162: while (togo) {
163:
164: /*
165: * find the page we want. check the anon layer first.
166: */
167:
168: if (aref->ar_amap) {
169: anon = amap_lookup(aref, curaddr - ufi->entry->start);
170: } else {
171: anon = NULL;
172: }
173:
1.28 chuck 174: /* locked: map, amap, uobj */
1.6 mrg 175: if (anon) {
176: rv = uvm_loananon(ufi, output, flags, anon);
177: } else if (uobj) {
178: rv = uvm_loanuobj(ufi, output, flags, curaddr);
179: } else if (UVM_ET_ISCOPYONWRITE(ufi->entry)) {
180: rv = uvm_loanzero(ufi, output, flags);
181: } else {
1.47 yamt 182: uvmfault_unlockall(ufi, aref->ar_amap, uobj, NULL);
1.34 chs 183: rv = -1;
1.6 mrg 184: }
1.31 chuck 185: /* locked: if (rv > 0) => map, amap, uobj [o.w. unlocked] */
1.66 ad 186: KASSERT(rv > 0 || aref->ar_amap == NULL ||
187: !mutex_owned(&aref->ar_amap->am_l));
1.6 mrg 188:
189: /* total failure */
1.52 yamt 190: if (rv < 0) {
191: UVMHIST_LOG(loanhist, "failure %d", rv, 0,0,0);
1.34 chs 192: return (-1);
1.52 yamt 193: }
1.6 mrg 194:
195: /* relock failed, need to do another lookup */
1.52 yamt 196: if (rv == 0) {
197: UVMHIST_LOG(loanhist, "relock failure %d", result
198: ,0,0,0);
1.34 chs 199: return (result);
1.52 yamt 200: }
1.6 mrg 201:
202: /*
203: * got it... advance to next page
204: */
1.34 chs 205:
1.6 mrg 206: result++;
207: togo -= PAGE_SIZE;
208: curaddr += PAGE_SIZE;
209: }
210:
211: /*
1.31 chuck 212: * unlock what we locked, unlock the maps and return
1.6 mrg 213: */
1.34 chs 214:
1.28 chuck 215: if (aref->ar_amap)
216: amap_unlock(aref->ar_amap);
1.65 thorpej 217: uvmfault_unlockmaps(ufi, false);
1.52 yamt 218: UVMHIST_LOG(loanhist, "done %d", result, 0,0,0);
1.34 chs 219: return (result);
1.1 mrg 220: }
221:
222: /*
223: * normal functions
224: */
225:
226: /*
1.28 chuck 227: * uvm_loan: loan pages in a map out to anons or to the kernel
1.29 chs 228: *
1.1 mrg 229: * => map should be unlocked
230: * => start and len should be multiples of PAGE_SIZE
231: * => result is either an array of anon's or vm_pages (depending on flags)
232: * => flag values: UVM_LOAN_TOANON - loan to anons
233: * UVM_LOAN_TOPAGE - loan to wired kernel page
234: * one and only one of these flags must be set!
1.28 chuck 235: * => returns 0 (success), or an appropriate error number
1.1 mrg 236: */
237:
1.6 mrg 238: int
1.54 thorpej 239: uvm_loan(struct vm_map *map, vaddr_t start, vsize_t len, void *v, int flags)
1.1 mrg 240: {
1.6 mrg 241: struct uvm_faultinfo ufi;
1.34 chs 242: void **result, **output;
1.25 chs 243: int rv, error;
1.6 mrg 244:
1.52 yamt 245: UVMHIST_FUNC(__func__); UVMHIST_CALLED(loanhist);
246:
1.6 mrg 247: /*
248: * ensure that one and only one of the flags is set
249: */
250:
1.25 chs 251: KASSERT(((flags & UVM_LOAN_TOANON) == 0) ^
252: ((flags & UVM_LOAN_TOPAGE) == 0));
253: KASSERT((map->flags & VM_MAP_INTRSAFE) == 0);
1.6 mrg 254:
255: /*
1.34 chs 256: * "output" is a pointer to the current place to put the loaned page.
1.6 mrg 257: */
258:
1.34 chs 259: result = v;
1.6 mrg 260: output = &result[0]; /* start at the beginning ... */
261:
262: /*
263: * while we've got pages to do
264: */
265:
266: while (len > 0) {
267:
268: /*
269: * fill in params for a call to uvmfault_lookup
270: */
271:
272: ufi.orig_map = map;
273: ufi.orig_rvaddr = start;
274: ufi.orig_size = len;
1.29 chs 275:
1.6 mrg 276: /*
277: * do the lookup, the only time this will fail is if we hit on
278: * an unmapped region (an error)
279: */
280:
1.65 thorpej 281: if (!uvmfault_lookup(&ufi, false)) {
1.25 chs 282: error = ENOENT;
1.6 mrg 283: goto fail;
1.25 chs 284: }
1.6 mrg 285:
286: /*
1.28 chuck 287: * map now locked. now do the loanout...
1.6 mrg 288: */
1.34 chs 289:
1.6 mrg 290: rv = uvm_loanentry(&ufi, &output, flags);
1.25 chs 291: if (rv < 0) {
1.28 chuck 292: /* all unlocked due to error */
1.25 chs 293: error = EINVAL;
1.6 mrg 294: goto fail;
1.25 chs 295: }
1.6 mrg 296:
297: /*
1.31 chuck 298: * done! the map is unlocked. advance, if possible.
1.28 chuck 299: *
1.50 junyoung 300: * XXXCDC: could be recoded to hold the map lock with
301: * smarter code (but it only happens on map entry
1.31 chuck 302: * boundaries, so it isn't that bad).
1.6 mrg 303: */
1.34 chs 304:
1.28 chuck 305: if (rv) {
306: rv <<= PAGE_SHIFT;
307: len -= rv;
308: start += rv;
309: }
1.6 mrg 310: }
1.52 yamt 311: UVMHIST_LOG(loanhist, "success", 0,0,0,0);
1.25 chs 312: return 0;
1.1 mrg 313:
314: fail:
1.6 mrg 315: /*
1.34 chs 316: * failed to complete loans. drop any loans and return failure code.
1.28 chuck 317: * map is already unlocked.
1.6 mrg 318: */
1.34 chs 319:
1.6 mrg 320: if (output - result) {
1.34 chs 321: if (flags & UVM_LOAN_TOANON) {
1.6 mrg 322: uvm_unloananon((struct vm_anon **)result,
1.34 chs 323: output - result);
324: } else {
1.6 mrg 325: uvm_unloanpage((struct vm_page **)result,
1.34 chs 326: output - result);
327: }
1.6 mrg 328: }
1.52 yamt 329: UVMHIST_LOG(loanhist, "error %d", error,0,0,0);
1.26 jdolecek 330: return (error);
1.1 mrg 331: }
332:
333: /*
334: * uvm_loananon: loan a page from an anon out
1.29 chs 335: *
1.28 chuck 336: * => called with map, amap, uobj locked
1.1 mrg 337: * => return value:
338: * -1 = fatal error, everything is unlocked, abort.
339: * 0 = lookup in ufi went stale, everything unlocked, relookup and
340: * try again
341: * 1 = got it, everything still locked
342: */
343:
1.6 mrg 344: int
1.54 thorpej 345: uvm_loananon(struct uvm_faultinfo *ufi, void ***output, int flags,
346: struct vm_anon *anon)
1.1 mrg 347: {
1.6 mrg 348: struct vm_page *pg;
1.34 chs 349: int error;
1.1 mrg 350:
1.52 yamt 351: UVMHIST_FUNC(__func__); UVMHIST_CALLED(loanhist);
352:
1.6 mrg 353: /*
1.28 chuck 354: * if we are loaning to "another" anon then it is easy, we just
1.6 mrg 355: * bump the reference count on the current anon and return a
1.28 chuck 356: * pointer to it (it becomes copy-on-write shared).
1.6 mrg 357: */
1.34 chs 358:
1.6 mrg 359: if (flags & UVM_LOAN_TOANON) {
360: simple_lock(&anon->an_lock);
1.53 yamt 361: pg = anon->an_page;
1.34 chs 362: if (pg && (pg->pqflags & PQ_ANON) != 0 && anon->an_ref == 1) {
1.51 yamt 363: if (pg->wire_count > 0) {
1.52 yamt 364: UVMHIST_LOG(loanhist, "->A wired %p", pg,0,0,0);
1.51 yamt 365: uvmfault_unlockall(ufi,
366: ufi->entry->aref.ar_amap,
367: ufi->entry->object.uvm_obj, anon);
368: return (-1);
369: }
1.19 chs 370: pmap_page_protect(pg, VM_PROT_READ);
1.34 chs 371: }
1.6 mrg 372: anon->an_ref++;
373: **output = anon;
1.34 chs 374: (*output)++;
1.6 mrg 375: simple_unlock(&anon->an_lock);
1.52 yamt 376: UVMHIST_LOG(loanhist, "->A done", 0,0,0,0);
1.34 chs 377: return (1);
1.6 mrg 378: }
379:
380: /*
381: * we are loaning to a kernel-page. we need to get the page
382: * resident so we can wire it. uvmfault_anonget will handle
383: * this for us.
384: */
385:
386: simple_lock(&anon->an_lock);
1.34 chs 387: error = uvmfault_anonget(ufi, ufi->entry->aref.ar_amap, anon);
1.6 mrg 388:
389: /*
390: * if we were unable to get the anon, then uvmfault_anonget has
391: * unlocked everything and returned an error code.
392: */
1.34 chs 393:
394: if (error) {
1.52 yamt 395: UVMHIST_LOG(loanhist, "error %d", error,0,0,0);
1.6 mrg 396:
397: /* need to refault (i.e. refresh our lookup) ? */
1.34 chs 398: if (error == ERESTART) {
399: return (0);
400: }
1.6 mrg 401:
402: /* "try again"? sleep a bit and retry ... */
1.34 chs 403: if (error == EAGAIN) {
1.24 chs 404: tsleep(&lbolt, PVM, "loanagain", 0);
1.34 chs 405: return (0);
1.6 mrg 406: }
407:
408: /* otherwise flag it as an error */
1.34 chs 409: return (-1);
1.6 mrg 410: }
411:
412: /*
413: * we have the page and its owner locked: do the loan now.
414: */
415:
1.53 yamt 416: pg = anon->an_page;
1.6 mrg 417: uvm_lock_pageq();
1.51 yamt 418: if (pg->wire_count > 0) {
419: uvm_unlock_pageq();
1.52 yamt 420: UVMHIST_LOG(loanhist, "->K wired %p", pg,0,0,0);
1.51 yamt 421: KASSERT(pg->uobject == NULL);
422: uvmfault_unlockall(ufi, ufi->entry->aref.ar_amap,
1.58 yamt 423: NULL, anon);
1.51 yamt 424: return (-1);
425: }
1.34 chs 426: if (pg->loan_count == 0) {
1.19 chs 427: pmap_page_protect(pg, VM_PROT_READ);
1.34 chs 428: }
1.6 mrg 429: pg->loan_count++;
1.63 yamt 430: uvm_pageactivate(pg);
1.6 mrg 431: uvm_unlock_pageq();
432: **output = pg;
1.34 chs 433: (*output)++;
1.6 mrg 434:
435: /* unlock anon and return success */
1.58 yamt 436: if (pg->uobject)
1.6 mrg 437: simple_unlock(&pg->uobject->vmobjlock);
438: simple_unlock(&anon->an_lock);
1.52 yamt 439: UVMHIST_LOG(loanhist, "->K done", 0,0,0,0);
1.34 chs 440: return (1);
1.1 mrg 441: }
442:
443: /*
1.45 yamt 444: * uvm_loanpage: loan out pages to kernel (->K)
1.42 yamt 445: *
1.51 yamt 446: * => pages should be object-owned and the object should be locked.
447: * => in the case of error, the object might be unlocked and relocked.
448: * => caller should busy the pages beforehand.
449: * => pages will be unbusied.
450: * => fail with EBUSY if meet a wired page.
1.42 yamt 451: */
1.51 yamt 452: static int
1.54 thorpej 453: uvm_loanpage(struct vm_page **pgpp, int npages)
1.42 yamt 454: {
455: int i;
1.51 yamt 456: int error = 0;
1.42 yamt 457:
1.52 yamt 458: UVMHIST_FUNC(__func__); UVMHIST_CALLED(loanhist);
459:
1.42 yamt 460: for (i = 0; i < npages; i++) {
461: struct vm_page *pg = pgpp[i];
462:
463: KASSERT(pg->uobject != NULL);
1.51 yamt 464: KASSERT(pg->uobject == pgpp[0]->uobject);
1.42 yamt 465: KASSERT(!(pg->flags & (PG_RELEASED|PG_PAGEOUT)));
466: LOCK_ASSERT(simple_lock_held(&pg->uobject->vmobjlock));
467: KASSERT(pg->flags & PG_BUSY);
468:
469: uvm_lock_pageq();
1.51 yamt 470: if (pg->wire_count > 0) {
471: uvm_unlock_pageq();
1.52 yamt 472: UVMHIST_LOG(loanhist, "wired %p", pg,0,0,0);
1.51 yamt 473: error = EBUSY;
474: break;
475: }
1.42 yamt 476: if (pg->loan_count == 0) {
477: pmap_page_protect(pg, VM_PROT_READ);
478: }
479: pg->loan_count++;
1.63 yamt 480: uvm_pageactivate(pg);
1.42 yamt 481: uvm_unlock_pageq();
482: }
1.51 yamt 483:
484: uvm_page_unbusy(pgpp, npages);
485:
486: if (error) {
487: /*
488: * backout what we've done
489: */
490: struct simplelock *slock = &pgpp[0]->uobject->vmobjlock;
491:
492: simple_unlock(slock);
493: uvm_unloan(pgpp, i, UVM_LOAN_TOPAGE);
494: simple_lock(slock);
495: }
496:
1.52 yamt 497: UVMHIST_LOG(loanhist, "done %d", error,0,0,0);
1.51 yamt 498: return error;
1.42 yamt 499: }
500:
501: /*
1.45 yamt 502: * XXX UBC temp limit
503: * number of pages to get at once.
504: * should be <= MAX_READ_AHEAD in genfs_vnops.c
505: */
506: #define UVM_LOAN_GET_CHUNK 16
507:
508: /*
1.46 yamt 509: * uvm_loanuobjpages: loan pages from a uobj out (O->K)
1.45 yamt 510: *
1.46 yamt 511: * => uobj shouldn't be locked. (we'll lock it)
1.51 yamt 512: * => fail with EBUSY if we meet a wired page.
1.45 yamt 513: */
514: int
1.54 thorpej 515: uvm_loanuobjpages(struct uvm_object *uobj, voff_t pgoff, int orignpages,
516: struct vm_page **origpgpp)
1.45 yamt 517: {
1.51 yamt 518: int ndone; /* # of pages loaned out */
1.45 yamt 519: struct vm_page **pgpp;
520: int error;
521: int i;
522: struct simplelock *slock;
523:
524: pgpp = origpgpp;
525: for (ndone = 0; ndone < orignpages; ) {
526: int npages;
1.51 yamt 527: /* npendloan: # of pages busied but not loand out yet. */
1.45 yamt 528: int npendloan = 0xdead; /* XXX gcc */
529: reget:
530: npages = MIN(UVM_LOAN_GET_CHUNK, orignpages - ndone);
531: simple_lock(&uobj->vmobjlock);
532: error = (*uobj->pgops->pgo_get)(uobj,
533: pgoff + (ndone << PAGE_SHIFT), pgpp, &npages, 0,
534: VM_PROT_READ, 0, PGO_SYNCIO);
535: if (error == EAGAIN) {
536: tsleep(&lbolt, PVM, "nfsread", 0);
537: continue;
538: }
1.51 yamt 539: if (error)
540: goto fail;
1.45 yamt 541:
542: KASSERT(npages > 0);
1.50 junyoung 543:
1.45 yamt 544: /* loan and unbusy pages */
545: slock = NULL;
546: for (i = 0; i < npages; i++) {
547: struct simplelock *nextslock; /* slock for next page */
548: struct vm_page *pg = *pgpp;
549:
550: /* XXX assuming that the page is owned by uobj */
551: KASSERT(pg->uobject != NULL);
552: nextslock = &pg->uobject->vmobjlock;
553:
554: if (slock != nextslock) {
555: if (slock) {
556: KASSERT(npendloan > 0);
1.51 yamt 557: error = uvm_loanpage(pgpp - npendloan,
1.45 yamt 558: npendloan);
559: simple_unlock(slock);
1.51 yamt 560: if (error)
561: goto fail;
562: ndone += npendloan;
563: KASSERT(origpgpp + ndone == pgpp);
1.45 yamt 564: }
565: slock = nextslock;
1.51 yamt 566: npendloan = 0;
1.45 yamt 567: simple_lock(slock);
568: }
569:
1.51 yamt 570: if ((pg->flags & PG_RELEASED) != 0) {
1.45 yamt 571: /*
572: * release pages and try again.
573: */
574: simple_unlock(slock);
575: for (; i < npages; i++) {
576: pg = pgpp[i];
577: slock = &pg->uobject->vmobjlock;
578:
579: simple_lock(slock);
580: uvm_lock_pageq();
581: uvm_page_unbusy(&pg, 1);
582: uvm_unlock_pageq();
583: simple_unlock(slock);
584: }
585: goto reget;
586: }
587:
588: npendloan++;
589: pgpp++;
1.51 yamt 590: KASSERT(origpgpp + ndone + npendloan == pgpp);
1.45 yamt 591: }
592: KASSERT(slock != NULL);
593: KASSERT(npendloan > 0);
1.51 yamt 594: error = uvm_loanpage(pgpp - npendloan, npendloan);
1.45 yamt 595: simple_unlock(slock);
1.51 yamt 596: if (error)
597: goto fail;
598: ndone += npendloan;
599: KASSERT(origpgpp + ndone == pgpp);
1.45 yamt 600: }
601:
602: return 0;
1.51 yamt 603:
604: fail:
605: uvm_unloan(origpgpp, ndone, UVM_LOAN_TOPAGE);
606:
607: return error;
1.45 yamt 608: }
609:
610: /*
1.1 mrg 611: * uvm_loanuobj: loan a page from a uobj out
612: *
1.28 chuck 613: * => called with map, amap, uobj locked
1.1 mrg 614: * => return value:
615: * -1 = fatal error, everything is unlocked, abort.
616: * 0 = lookup in ufi went stale, everything unlocked, relookup and
617: * try again
618: * 1 = got it, everything still locked
619: */
620:
1.33 jdolecek 621: static int
1.54 thorpej 622: uvm_loanuobj(struct uvm_faultinfo *ufi, void ***output, int flags, vaddr_t va)
1.1 mrg 623: {
1.6 mrg 624: struct vm_amap *amap = ufi->entry->aref.ar_amap;
625: struct uvm_object *uobj = ufi->entry->object.uvm_obj;
626: struct vm_page *pg;
627: struct vm_anon *anon;
1.34 chs 628: int error, npages;
1.64 thorpej 629: bool locked;
1.6 mrg 630:
1.52 yamt 631: UVMHIST_FUNC(__func__); UVMHIST_CALLED(loanhist);
632:
1.6 mrg 633: /*
634: * first we must make sure the page is resident.
635: *
636: * XXXCDC: duplicate code with uvm_fault().
637: */
638:
1.58 yamt 639: simple_lock(&uobj->vmobjlock);
1.28 chuck 640: if (uobj->pgops->pgo_get) { /* try locked pgo_get */
1.6 mrg 641: npages = 1;
642: pg = NULL;
1.37 enami 643: error = (*uobj->pgops->pgo_get)(uobj,
644: va - ufi->entry->start + ufi->entry->offset,
1.6 mrg 645: &pg, &npages, 0, VM_PROT_READ, MADV_NORMAL, PGO_LOCKED);
646: } else {
1.34 chs 647: error = EIO; /* must have pgo_get op */
1.6 mrg 648: }
649:
650: /*
651: * check the result of the locked pgo_get. if there is a problem,
652: * then we fail the loan.
653: */
654:
1.34 chs 655: if (error && error != EBUSY) {
1.6 mrg 656: uvmfault_unlockall(ufi, amap, uobj, NULL);
1.34 chs 657: return (-1);
1.6 mrg 658: }
659:
660: /*
661: * if we need to unlock for I/O, do so now.
662: */
663:
1.34 chs 664: if (error == EBUSY) {
1.6 mrg 665: uvmfault_unlockall(ufi, amap, NULL, NULL);
1.34 chs 666:
667: /* locked: uobj */
1.6 mrg 668: npages = 1;
1.37 enami 669: error = (*uobj->pgops->pgo_get)(uobj,
670: va - ufi->entry->start + ufi->entry->offset,
1.30 chs 671: &pg, &npages, 0, VM_PROT_READ, MADV_NORMAL, PGO_SYNCIO);
1.6 mrg 672: /* locked: <nothing> */
1.29 chs 673:
1.34 chs 674: if (error) {
1.43 yamt 675: if (error == EAGAIN) {
1.24 chs 676: tsleep(&lbolt, PVM, "fltagain2", 0);
1.34 chs 677: return (0);
1.29 chs 678: }
1.34 chs 679: return (-1);
1.6 mrg 680: }
681:
682: /*
683: * pgo_get was a success. attempt to relock everything.
684: */
685:
686: locked = uvmfault_relock(ufi);
687: if (locked && amap)
1.13 chuck 688: amap_lock(amap);
1.58 yamt 689: uobj = pg->uobject;
1.6 mrg 690: simple_lock(&uobj->vmobjlock);
691:
692: /*
693: * verify that the page has not be released and re-verify
694: * that amap slot is still free. if there is a problem we
695: * drop our lock (thus force a lookup refresh/retry).
696: */
1.29 chs 697:
1.6 mrg 698: if ((pg->flags & PG_RELEASED) != 0 ||
699: (locked && amap && amap_lookup(&ufi->entry->aref,
1.10 chuck 700: ufi->orig_rvaddr - ufi->entry->start))) {
1.6 mrg 701: if (locked)
702: uvmfault_unlockall(ufi, amap, NULL, NULL);
1.65 thorpej 703: locked = false;
1.29 chs 704: }
1.6 mrg 705:
706: /*
707: * didn't get the lock? release the page and retry.
708: */
709:
1.65 thorpej 710: if (locked == false) {
1.32 chs 711: if (pg->flags & PG_WANTED) {
1.18 thorpej 712: wakeup(pg);
1.32 chs 713: }
1.6 mrg 714: if (pg->flags & PG_RELEASED) {
1.38 enami 715: uvm_lock_pageq();
1.32 chs 716: uvm_pagefree(pg);
1.38 enami 717: uvm_unlock_pageq();
1.58 yamt 718: simple_unlock(&uobj->vmobjlock);
1.6 mrg 719: return (0);
720: }
721: uvm_lock_pageq();
1.32 chs 722: uvm_pageactivate(pg);
1.6 mrg 723: uvm_unlock_pageq();
724: pg->flags &= ~(PG_BUSY|PG_WANTED);
725: UVM_PAGE_OWN(pg, NULL);
726: simple_unlock(&uobj->vmobjlock);
727: return (0);
728: }
729: }
730:
1.58 yamt 731: KASSERT(uobj == pg->uobject);
732:
1.6 mrg 733: /*
734: * at this point we have the page we want ("pg") marked PG_BUSY for us
1.34 chs 735: * and we have all data structures locked. do the loanout. page can
1.6 mrg 736: * not be PG_RELEASED (we caught this above).
737: */
738:
1.34 chs 739: if ((flags & UVM_LOAN_TOANON) == 0) {
1.51 yamt 740: if (uvm_loanpage(&pg, 1)) {
741: uvmfault_unlockall(ufi, amap, uobj, NULL);
742: return (-1);
743: }
1.58 yamt 744: simple_unlock(&uobj->vmobjlock);
1.34 chs 745: **output = pg;
746: (*output)++;
747: return (1);
1.6 mrg 748: }
749:
750: /*
751: * must be a loan to an anon. check to see if there is already
752: * an anon associated with this page. if so, then just return
1.29 chs 753: * a reference to this object. the page should already be
1.6 mrg 754: * mapped read-only because it is already on loan.
755: */
756:
757: if (pg->uanon) {
758: anon = pg->uanon;
759: simple_lock(&anon->an_lock);
760: anon->an_ref++;
761: simple_unlock(&anon->an_lock);
1.34 chs 762: if (pg->flags & PG_WANTED) {
1.18 thorpej 763: wakeup(pg);
1.34 chs 764: }
1.6 mrg 765: pg->flags &= ~(PG_WANTED|PG_BUSY);
766: UVM_PAGE_OWN(pg, NULL);
1.58 yamt 767: simple_unlock(&uobj->vmobjlock);
1.34 chs 768: **output = anon;
769: (*output)++;
770: return (1);
1.6 mrg 771: }
1.29 chs 772:
1.6 mrg 773: /*
774: * need to allocate a new anon
775: */
776:
777: anon = uvm_analloc();
1.34 chs 778: if (anon == NULL) {
1.51 yamt 779: goto fail;
1.6 mrg 780: }
1.53 yamt 781: anon->an_page = pg;
1.6 mrg 782: pg->uanon = anon;
783: uvm_lock_pageq();
1.51 yamt 784: if (pg->wire_count > 0) {
785: uvm_unlock_pageq();
1.52 yamt 786: UVMHIST_LOG(loanhist, "wired %p", pg,0,0,0);
1.51 yamt 787: pg->uanon = NULL;
1.53 yamt 788: anon->an_page = NULL;
1.51 yamt 789: anon->an_ref--;
790: simple_unlock(&anon->an_lock);
791: uvm_anfree(anon);
792: goto fail;
793: }
1.34 chs 794: if (pg->loan_count == 0) {
1.19 chs 795: pmap_page_protect(pg, VM_PROT_READ);
1.34 chs 796: }
1.6 mrg 797: pg->loan_count++;
798: uvm_pageactivate(pg);
799: uvm_unlock_pageq();
1.34 chs 800: if (pg->flags & PG_WANTED) {
1.18 thorpej 801: wakeup(pg);
1.34 chs 802: }
1.6 mrg 803: pg->flags &= ~(PG_WANTED|PG_BUSY);
804: UVM_PAGE_OWN(pg, NULL);
1.58 yamt 805: simple_unlock(&uobj->vmobjlock);
1.23 thorpej 806: simple_unlock(&anon->an_lock);
1.34 chs 807: **output = anon;
808: (*output)++;
809: return (1);
1.51 yamt 810:
811: fail:
1.52 yamt 812: UVMHIST_LOG(loanhist, "fail", 0,0,0,0);
1.51 yamt 813: /*
814: * unlock everything and bail out.
815: */
816: if (pg->flags & PG_WANTED) {
817: wakeup(pg);
818: }
819: pg->flags &= ~(PG_WANTED|PG_BUSY);
820: UVM_PAGE_OWN(pg, NULL);
821: uvmfault_unlockall(ufi, amap, uobj, NULL);
822: return (-1);
1.1 mrg 823: }
824:
825: /*
1.40 thorpej 826: * uvm_loanzero: loan a zero-fill page out
1.1 mrg 827: *
1.28 chuck 828: * => called with map, amap, uobj locked
1.1 mrg 829: * => return value:
830: * -1 = fatal error, everything is unlocked, abort.
831: * 0 = lookup in ufi went stale, everything unlocked, relookup and
832: * try again
833: * 1 = got it, everything still locked
834: */
835:
1.40 thorpej 836: static struct uvm_object uvm_loanzero_object;
837:
1.33 jdolecek 838: static int
1.54 thorpej 839: uvm_loanzero(struct uvm_faultinfo *ufi, void ***output, int flags)
1.1 mrg 840: {
1.6 mrg 841: struct vm_anon *anon;
842: struct vm_page *pg;
1.34 chs 843: struct vm_amap *amap = ufi->entry->aref.ar_amap;
1.1 mrg 844:
1.52 yamt 845: UVMHIST_FUNC(__func__); UVMHIST_CALLED(loanhist);
1.44 yamt 846: again:
1.40 thorpej 847: simple_lock(&uvm_loanzero_object.vmobjlock);
848:
849: /*
850: * first, get ahold of our single zero page.
851: */
852:
853: if (__predict_false((pg =
854: TAILQ_FIRST(&uvm_loanzero_object.memq)) == NULL)) {
855: while ((pg = uvm_pagealloc(&uvm_loanzero_object, 0, NULL,
856: UVM_PGA_ZERO)) == NULL) {
857: simple_unlock(&uvm_loanzero_object.vmobjlock);
1.58 yamt 858: uvmfault_unlockall(ufi, amap, NULL, NULL);
1.40 thorpej 859: uvm_wait("loanzero");
1.34 chs 860: if (!uvmfault_relock(ufi)) {
861: return (0);
862: }
863: if (amap) {
864: amap_lock(amap);
865: }
1.44 yamt 866: goto again;
1.6 mrg 867: }
1.29 chs 868:
1.40 thorpej 869: /* got a zero'd page. */
870: pg->flags &= ~(PG_WANTED|PG_BUSY|PG_FAKE);
871: pg->flags |= PG_RDONLY;
1.44 yamt 872: uvm_lock_pageq();
873: uvm_pageactivate(pg);
874: uvm_unlock_pageq();
1.6 mrg 875: UVM_PAGE_OWN(pg, NULL);
1.40 thorpej 876: }
877:
878: if ((flags & UVM_LOAN_TOANON) == 0) { /* loaning to kernel-page */
879: uvm_lock_pageq();
880: pg->loan_count++;
881: uvm_unlock_pageq();
882: simple_unlock(&uvm_loanzero_object.vmobjlock);
1.6 mrg 883: **output = pg;
1.34 chs 884: (*output)++;
885: return (1);
1.6 mrg 886: }
887:
1.40 thorpej 888: /*
889: * loaning to an anon. check to see if there is already an anon
890: * associated with this page. if so, then just return a reference
891: * to this object.
892: */
1.23 thorpej 893:
1.40 thorpej 894: if (pg->uanon) {
895: anon = pg->uanon;
896: simple_lock(&anon->an_lock);
897: anon->an_ref++;
898: simple_unlock(&anon->an_lock);
899: simple_unlock(&uvm_loanzero_object.vmobjlock);
900: **output = anon;
901: (*output)++;
902: return (1);
903: }
1.23 thorpej 904:
1.40 thorpej 905: /*
906: * need to allocate a new anon
907: */
1.34 chs 908:
1.40 thorpej 909: anon = uvm_analloc();
910: if (anon == NULL) {
911: /* out of swap causes us to fail */
912: simple_unlock(&uvm_loanzero_object.vmobjlock);
1.58 yamt 913: uvmfault_unlockall(ufi, amap, NULL, NULL);
1.40 thorpej 914: return (-1);
1.6 mrg 915: }
1.53 yamt 916: anon->an_page = pg;
1.40 thorpej 917: pg->uanon = anon;
1.6 mrg 918: uvm_lock_pageq();
1.40 thorpej 919: pg->loan_count++;
1.6 mrg 920: uvm_pageactivate(pg);
921: uvm_unlock_pageq();
1.59 yamt 922: simple_unlock(&anon->an_lock);
1.40 thorpej 923: simple_unlock(&uvm_loanzero_object.vmobjlock);
1.6 mrg 924: **output = anon;
1.34 chs 925: (*output)++;
926: return (1);
1.1 mrg 927: }
928:
929:
930: /*
931: * uvm_unloananon: kill loans on anons (basically a normal ref drop)
932: *
933: * => we expect all our resources to be unlocked
934: */
935:
1.33 jdolecek 936: static void
1.54 thorpej 937: uvm_unloananon(struct vm_anon **aloans, int nanons)
1.1 mrg 938: {
1.6 mrg 939: struct vm_anon *anon;
1.1 mrg 940:
1.6 mrg 941: while (nanons-- > 0) {
1.12 chs 942: int refs;
1.1 mrg 943:
1.6 mrg 944: anon = *aloans++;
945: simple_lock(&anon->an_lock);
1.12 chs 946: refs = --anon->an_ref;
947: simple_unlock(&anon->an_lock);
1.1 mrg 948:
1.12 chs 949: if (refs == 0) {
1.34 chs 950: uvm_anfree(anon);
1.6 mrg 951: }
952: }
1.1 mrg 953: }
954:
955: /*
956: * uvm_unloanpage: kill loans on pages loaned out to the kernel
957: *
958: * => we expect all our resources to be unlocked
959: */
960:
1.33 jdolecek 961: static void
1.54 thorpej 962: uvm_unloanpage(struct vm_page **ploans, int npages)
1.1 mrg 963: {
1.6 mrg 964: struct vm_page *pg;
1.36 chs 965: struct simplelock *slock;
1.1 mrg 966:
1.6 mrg 967: uvm_lock_pageq();
968: while (npages-- > 0) {
969: pg = *ploans++;
1.1 mrg 970:
1.6 mrg 971: /*
1.36 chs 972: * do a little dance to acquire the object or anon lock
973: * as appropriate. we are locking in the wrong order,
974: * so we have to do a try-lock here.
975: */
976:
977: slock = NULL;
978: while (pg->uobject != NULL || pg->uanon != NULL) {
979: if (pg->uobject != NULL) {
980: slock = &pg->uobject->vmobjlock;
981: } else {
982: slock = &pg->uanon->an_lock;
983: }
984: if (simple_lock_try(slock)) {
985: break;
986: }
987: uvm_unlock_pageq();
988: uvm_lock_pageq();
989: slock = NULL;
990: }
991:
992: /*
993: * drop our loan. if page is owned by an anon but
994: * PQ_ANON is not set, the page was loaned to the anon
995: * from an object which dropped ownership, so resolve
996: * this by turning the anon's loan into real ownership
997: * (ie. decrement loan_count again and set PQ_ANON).
998: * after all this, if there are no loans left, put the
999: * page back a paging queue (if the page is owned by
1000: * an anon) or free it (if the page is now unowned).
1.6 mrg 1001: */
1.1 mrg 1002:
1.34 chs 1003: KASSERT(pg->loan_count > 0);
1004: pg->loan_count--;
1.36 chs 1005: if (pg->uobject == NULL && pg->uanon != NULL &&
1006: (pg->pqflags & PQ_ANON) == 0) {
1007: KASSERT(pg->loan_count > 0);
1008: pg->loan_count--;
1009: pg->pqflags |= PQ_ANON;
1010: }
1.63 yamt 1011: if (pg->loan_count == 0 && pg->uobject == NULL &&
1012: pg->uanon == NULL) {
1013: KASSERT((pg->flags & PG_BUSY) == 0);
1014: uvm_pagefree(pg);
1.36 chs 1015: }
1016: if (slock != NULL) {
1017: simple_unlock(slock);
1.6 mrg 1018: }
1019: }
1020: uvm_unlock_pageq();
1.1 mrg 1021: }
1022:
1.33 jdolecek 1023: /*
1.34 chs 1024: * uvm_unloan: kill loans on pages or anons.
1.33 jdolecek 1025: */
1.34 chs 1026:
1.33 jdolecek 1027: void
1.34 chs 1028: uvm_unloan(void *v, int npages, int flags)
1.33 jdolecek 1029: {
1.34 chs 1030: if (flags & UVM_LOAN_TOANON) {
1031: uvm_unloananon(v, npages);
1032: } else {
1033: uvm_unloanpage(v, npages);
1034: }
1.40 thorpej 1035: }
1036:
1037: /*
1.41 thorpej 1038: * Minimal pager for uvm_loanzero_object. We need to provide a "put"
1039: * method, because the page can end up on a paging queue, and the
1040: * page daemon will want to call pgo_put when it encounters the page
1041: * on the inactive list.
1042: */
1043:
1044: static int
1.62 yamt 1045: ulz_put(struct uvm_object *uobj, voff_t start, voff_t stop, int flags)
1.41 thorpej 1046: {
1047: struct vm_page *pg;
1048:
1049: KDASSERT(uobj == &uvm_loanzero_object);
1050:
1051: /*
1052: * Don't need to do any work here if we're not freeing pages.
1053: */
1054:
1055: if ((flags & PGO_FREE) == 0) {
1056: simple_unlock(&uobj->vmobjlock);
1057: return 0;
1058: }
1059:
1060: /*
1061: * we don't actually want to ever free the uvm_loanzero_page, so
1062: * just reactivate or dequeue it.
1063: */
1064:
1065: pg = TAILQ_FIRST(&uobj->memq);
1066: KASSERT(pg != NULL);
1067: KASSERT(TAILQ_NEXT(pg, listq) == NULL);
1068:
1069: uvm_lock_pageq();
1070: if (pg->uanon)
1071: uvm_pageactivate(pg);
1072: else
1073: uvm_pagedequeue(pg);
1074: uvm_unlock_pageq();
1075:
1076: simple_unlock(&uobj->vmobjlock);
1077: return 0;
1078: }
1079:
1080: static struct uvm_pagerops ulz_pager = {
1081: NULL, /* init */
1082: NULL, /* reference */
1083: NULL, /* detach */
1084: NULL, /* fault */
1085: NULL, /* get */
1086: ulz_put, /* put */
1087: };
1088:
1089: /*
1.40 thorpej 1090: * uvm_loan_init(): initialize the uvm_loan() facility.
1091: */
1092:
1093: void
1094: uvm_loan_init(void)
1095: {
1096:
1097: simple_lock_init(&uvm_loanzero_object.vmobjlock);
1098: TAILQ_INIT(&uvm_loanzero_object.memq);
1.41 thorpej 1099: uvm_loanzero_object.pgops = &ulz_pager;
1.52 yamt 1100:
1101: UVMHIST_INIT(loanhist, 300);
1.42 yamt 1102: }
1103:
1104: /*
1105: * uvm_loanbreak: break loan on a uobj page
1106: *
1107: * => called with uobj locked
1108: * => the page should be busy
1109: * => return value:
1110: * newly allocated page if succeeded
1111: */
1112: struct vm_page *
1113: uvm_loanbreak(struct vm_page *uobjpage)
1114: {
1115: struct vm_page *pg;
1.49 drochner 1116: #ifdef DIAGNOSTIC
1.42 yamt 1117: struct uvm_object *uobj = uobjpage->uobject;
1.49 drochner 1118: #endif
1.42 yamt 1119:
1120: KASSERT(uobj != NULL);
1121: LOCK_ASSERT(simple_lock_held(&uobj->vmobjlock));
1122: KASSERT(uobjpage->flags & PG_BUSY);
1123:
1124: /* alloc new un-owned page */
1125: pg = uvm_pagealloc(NULL, 0, NULL, 0);
1126: if (pg == NULL)
1127: return NULL;
1128:
1129: /*
1130: * copy the data from the old page to the new
1.61 yamt 1131: * one and clear the fake flags on the new page (keep it busy).
1132: * force a reload of the old page by clearing it from all
1133: * pmaps.
1134: * transfer dirtiness of the old page to the new page.
1135: * then lock the page queues to rename the pages.
1.42 yamt 1136: */
1137:
1138: uvm_pagecopy(uobjpage, pg); /* old -> new */
1.61 yamt 1139: pg->flags &= ~PG_FAKE;
1.42 yamt 1140: pmap_page_protect(uobjpage, VM_PROT_NONE);
1.61 yamt 1141: if ((uobjpage->flags & PG_CLEAN) != 0 && !pmap_clear_modify(uobjpage)) {
1142: pmap_clear_modify(pg);
1143: pg->flags |= PG_CLEAN;
1144: } else {
1145: /* uvm_pagecopy marked it dirty */
1146: KASSERT((pg->flags & PG_CLEAN) == 0);
1147: /* a object with a dirty page should be dirty. */
1148: KASSERT(!UVM_OBJ_IS_CLEAN(uobj));
1149: }
1.42 yamt 1150: if (uobjpage->flags & PG_WANTED)
1151: wakeup(uobjpage);
1152: /* uobj still locked */
1153: uobjpage->flags &= ~(PG_WANTED|PG_BUSY);
1154: UVM_PAGE_OWN(uobjpage, NULL);
1155:
1156: uvm_lock_pageq();
1.48 yamt 1157:
1158: /*
1159: * replace uobjpage with new page.
1160: */
1161:
1162: uvm_pagereplace(uobjpage, pg);
1.42 yamt 1163:
1164: /*
1165: * if the page is no longer referenced by
1166: * an anon (i.e. we are breaking an O->K
1167: * loan), then remove it from any pageq's.
1168: */
1169: if (uobjpage->uanon == NULL)
1170: uvm_pagedequeue(uobjpage);
1171:
1172: /*
1173: * at this point we have absolutely no
1174: * control over uobjpage
1175: */
1176:
1177: /* install new page */
1178: uvm_pageactivate(pg);
1179: uvm_unlock_pageq();
1180:
1181: /*
1182: * done! loan is broken and "pg" is
1183: * PG_BUSY. it can now replace uobjpage.
1184: */
1185:
1186: return pg;
1.33 jdolecek 1187: }
CVSweb <webmaster@jp.NetBSD.org>