|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution is only permitted until one year after the first shipment ! 6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 7: * binary forms are permitted provided that: (1) source distributions retain ! 8: * this entire copyright notice and comment, and (2) distributions including ! 9: * binaries display the following acknowledgement: This product includes ! 10: * software developed by the University of California, Berkeley and its ! 11: * contributors'' in the documentation or other materials provided with the ! 12: * distribution and in all advertising materials mentioning features or use ! 13: * of this software. Neither the name of the University nor the names of ! 14: * its contributors may be used to endorse or promote products derived from ! 15: * this software without specific prior written permission. ! 16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 19: * ! 20: * @(#)kern_mman.c 7.18 (Berkeley) 6/30/90 ! 21: */ ! 22: ! 23: #include "param.h" ! 24: #include "systm.h" ! 25: #include "map.h" ! 26: #include "user.h" ! 27: #include "proc.h" ! 28: #include "buf.h" ! 29: #include "vnode.h" ! 30: #include "specdev.h" ! 31: #include "seg.h" ! 32: #include "acct.h" ! 33: #include "wait.h" ! 34: #include "vm.h" ! 35: #include "text.h" ! 36: #include "file.h" ! 37: #include "vadvise.h" ! 38: #include "cmap.h" ! 39: #include "trace.h" ! 40: #include "mman.h" ! 41: #include "mapmem.h" ! 42: #include "malloc.h" ! 43: #include "conf.h" ! 44: ! 45: #include "machine/cpu.h" ! 46: #include "machine/reg.h" ! 47: #include "machine/psl.h" ! 48: #include "machine/pte.h" ! 49: #include "machine/mtpr.h" ! 50: ! 51: /* ! 52: * The MMAP code here is temporary; it provides support ! 53: * only for mmaping devices such as frame buffers. ! 54: * All to be different next time... ! 55: */ ! 56: #ifndef MAPMEM ! 57: #undef MMAP /* XXX */ ! 58: #endif ! 59: ! 60: #ifdef MMAP ! 61: struct mapmemops mmapops = { ! 62: (int (*)())0, (int (*)())0, (int (*)())0, (int (*)())0 ! 63: }; ! 64: #endif ! 65: ! 66: /* ARGSUSED */ ! 67: sbrk(p, uap, retval) ! 68: struct proc *p; ! 69: struct args { ! 70: int incr; ! 71: } *uap; ! 72: int *retval; ! 73: { ! 74: ! 75: /* Not yet implemented */ ! 76: return (EOPNOTSUPP); ! 77: } ! 78: ! 79: /* ARGSUSED */ ! 80: sstk(p, uap, retval) ! 81: struct proc *p; ! 82: struct args { ! 83: int incr; ! 84: } *uap; ! 85: int *retval; ! 86: { ! 87: ! 88: /* Not yet implemented */ ! 89: return (EOPNOTSUPP); ! 90: } ! 91: ! 92: /* ARGSUSED */ ! 93: getpagesize(p, uap, retval) ! 94: struct proc *p; ! 95: struct args *uap; ! 96: int *retval; ! 97: { ! 98: ! 99: *retval = NBPG * CLSIZE; ! 100: return (0); ! 101: } ! 102: ! 103: /* ARGSUSED */ ! 104: smmap(p, uap, retval) ! 105: register struct proc *p; ! 106: register struct args { ! 107: caddr_t addr; ! 108: int len; ! 109: int prot; ! 110: int share; ! 111: int fd; ! 112: off_t pos; ! 113: } *uap; ! 114: int *retval; ! 115: { ! 116: #ifndef MMAP ! 117: return (EOPNOTSUPP); ! 118: #else ! 119: register struct file *fp; ! 120: struct mapmem *mp; ! 121: struct vnode *vp; ! 122: register struct pte *pte; ! 123: struct pte *dpte; ! 124: register int off; ! 125: int error, fv, lv, pm, (*mapfun)(); ! 126: dev_t dev; ! 127: ! 128: if (error = getvnode(u.u_ofile, uap->fd, &fp)) ! 129: return (error); ! 130: vp = (struct vnode *)fp->f_data; ! 131: if (vp->v_type != VCHR) ! 132: return (EINVAL); ! 133: dev = vp->v_rdev; ! 134: mapfun = cdevsw[major(dev)].d_mmap; ! 135: if (mapfun == NULL) ! 136: return (EINVAL); ! 137: if (((int)uap->addr & CLOFSET) || (uap->pos & CLOFSET) || ! 138: uap->len <= 0 || (uap->len & CLOFSET)) ! 139: return (EINVAL); ! 140: if ((uap->prot & PROT_WRITE) && (fp->f_flag&FWRITE) == 0) ! 141: return (EINVAL); ! 142: if ((uap->prot & PROT_READ) && (fp->f_flag&FREAD) == 0) ! 143: return (EINVAL); ! 144: if (uap->share != MAP_SHARED) ! 145: return (EINVAL); ! 146: for (off = 0; off < uap->len; off += NBPG) ! 147: if ((*mapfun)(dev, uap->pos+off, uap->prot) == -1) ! 148: return (EINVAL); /* Needs translation */ ! 149: /* ! 150: * Allocate a descriptor for this region and expand page ! 151: * table to accomodate. ! 152: */ ! 153: if (uap->prot & PROT_WRITE) { ! 154: pm = PG_UW|PG_FOD|PG_V; ! 155: off = MM_RW; ! 156: } else { ! 157: pm = PG_URKR|PG_FOD|PG_V; ! 158: off = MM_RO; ! 159: } ! 160: #if defined(hp300) ! 161: pm |= PG_CI; ! 162: off |= MM_CI; ! 163: #endif ! 164: error = mmalloc(p, uap->fd, &uap->addr, uap->len, off, &mmapops, &mp); ! 165: if (error) ! 166: return (error); ! 167: /* ! 168: * Now map it in. ! 169: * Can't use mmmapin() because of args to map function. ! 170: */ ! 171: fv = btop(uap->addr); ! 172: pte = vtopte(p, fv); ! 173: dpte = dptopte(p, u.u_dsize); ! 174: for (off = 0; off < uap->len; off += NBPG) { ! 175: if ((off&CLOFSET) == 0 && pte < dpte) ! 176: p->p_rssize -= vmemfree(pte, CLSIZE); ! 177: *(int *)pte = pm; ! 178: pte->pg_pfnum = (*mapfun)(dev, uap->pos+off, uap->prot); ! 179: pte++; ! 180: } ! 181: newptes(vtopte(p, fv), fv, btoc(uap->len)); ! 182: u.u_pofile[uap->fd] |= UF_MAPPED; ! 183: return (0); ! 184: #endif /* MMAP */ ! 185: } ! 186: ! 187: /* ARGSUSED */ ! 188: msync(p, uap, retval) ! 189: struct proc *p; ! 190: struct args { ! 191: char *addr; ! 192: int len; ! 193: } *uap; ! 194: int *retval; ! 195: { ! 196: ! 197: /* Not yet implemented */ ! 198: return (EOPNOTSUPP); ! 199: } ! 200: ! 201: /* ARGSUSED */ ! 202: munmap(p, uap, retval) ! 203: register struct proc *p; ! 204: register struct args { ! 205: caddr_t addr; ! 206: int len; ! 207: } *uap; ! 208: int *retval; ! 209: { ! 210: #ifndef MMAP ! 211: return (EOPNOTSUPP); ! 212: #else ! 213: register struct mapmem *mp; ! 214: register int fd; ! 215: caddr_t eaddr; ! 216: int error; ! 217: ! 218: if (((int)uap->addr & CLOFSET) || ! 219: uap->len <= 0 || (uap->len & CLOFSET)) ! 220: return (EINVAL); ! 221: /* ! 222: * Locate region mapping this range. If found, unmap it. ! 223: */ ! 224: eaddr = uap->addr + uap->len - 1; ! 225: for (mp = u.u_mmap; mp; mp = mp->mm_next) ! 226: if (mp->mm_ops == &mmapops && ! 227: uap->addr >= mp->mm_uva && eaddr < mp->mm_uva+mp->mm_size) ! 228: break; ! 229: if (mp == MMNIL) ! 230: return (EINVAL); ! 231: fd = mp->mm_id; ! 232: mmmapout(p, mp); ! 233: error = mmfree(mp); ! 234: /* ! 235: * If no other range has this descriptor mapped, mark it as unmapped. ! 236: */ ! 237: for (mp = u.u_mmap; mp; mp = mp->mm_next) ! 238: if (mp->mm_id == fd) ! 239: break; ! 240: if (mp == MMNIL) ! 241: u.u_pofile[fd] &= ~UF_MAPPED; ! 242: return (error); ! 243: #endif /* MMAP */ ! 244: } ! 245: ! 246: munmapfd(fd) ! 247: int fd; ! 248: { ! 249: int error = 0; ! 250: #ifdef MMAP ! 251: struct proc *p = u.u_procp; /* XXX */ ! 252: register struct mapmem *mp, **mpp; ! 253: ! 254: if (p->p_flag & SVFORK) ! 255: return (0); ! 256: mpp = &u.u_mmap; ! 257: for (mp = *mpp; mp; mp = *mpp) { ! 258: if (mp->mm_ops == &mmapops && mp->mm_id == fd) { ! 259: mmmapout(p, mp); ! 260: error = mmfree(mp); ! 261: } else ! 262: mpp = &mp->mm_next; ! 263: } ! 264: #endif ! 265: u.u_pofile[fd] &= ~UF_MAPPED; ! 266: return (error); ! 267: } ! 268: ! 269: /* ARGSUSED */ ! 270: mprotect(p, uap, retval) ! 271: struct proc *p; ! 272: struct args { ! 273: char *addr; ! 274: int len; ! 275: int prot; ! 276: } *uap; ! 277: int *retval; ! 278: { ! 279: ! 280: /* Not yet implemented */ ! 281: return (EOPNOTSUPP); ! 282: } ! 283: ! 284: /* ARGSUSED */ ! 285: madvise(p, uap, retval) ! 286: struct proc *p; ! 287: struct args { ! 288: char *addr; ! 289: int len; ! 290: int behav; ! 291: } *uap; ! 292: int *retval; ! 293: { ! 294: ! 295: /* Not yet implemented */ ! 296: return (EOPNOTSUPP); ! 297: } ! 298: ! 299: /* ARGSUSED */ ! 300: mincore(p, uap, retval) ! 301: struct proc *p; ! 302: struct args { ! 303: char *addr; ! 304: int len; ! 305: char *vec; ! 306: } *uap; ! 307: int *retval; ! 308: { ! 309: ! 310: /* Not yet implemented */ ! 311: return (EOPNOTSUPP); ! 312: } ! 313: ! 314: /* BEGIN DEFUNCT */ ! 315: /* ARGSUSED */ ! 316: obreak(p, uap, retval) ! 317: struct proc *p; ! 318: struct args { ! 319: char *nsiz; ! 320: } *uap; ! 321: int *retval; ! 322: { ! 323: register segsz_t n, d, ds; ! 324: int error; ! 325: ! 326: /* ! 327: * set n to new data size ! 328: */ ! 329: n = btoc(uap->nsiz) - dptov(p, 0); ! 330: if (n < 0) ! 331: n = 0; ! 332: /* ! 333: * since we can't pass a -ve argument for the difference to chksize, ! 334: * if d is negative, make ds equal to the final value and clear d. ! 335: * keep the real difference in n for later use in expand. ! 336: */ ! 337: ds = u.u_dsize; ! 338: if ((n = d = clrnd(n - u.u_dsize)) < 0) { ! 339: ds += d; ! 340: d = 0; ! 341: } ! 342: if (ctob(ds + d) > u.u_rlimit[RLIMIT_DATA].rlim_cur) ! 343: return (ENOMEM); ! 344: if (error = ! 345: chksize((u_int)u.u_tsize, (u_int)ds, (u_int)d, (u_int)u.u_ssize)) ! 346: return (error); ! 347: #ifdef MAPMEM ! 348: /* ! 349: * If change would conflict with any mapped memory segment ! 350: * return ENOMEM. ! 351: */ ! 352: if (u.u_mmap && n != 0) { ! 353: caddr_t low, high; ! 354: ! 355: low = (caddr_t) ctob(dptov(p, ds)); ! 356: high = low + ctob((n < 0) ? -n : n); ! 357: if (mmclash(u.u_mmap, low, high)) ! 358: return (ENOMEM); ! 359: } ! 360: #endif ! 361: if (error = swpexpand(ds + d, u.u_ssize, &u.u_dmap, &u.u_smap)) ! 362: return (error); ! 363: if (p->p_mmsize && (p->p_mmsize -= n) < 0) ! 364: p->p_mmsize = 0; ! 365: expand((int)n, 0); ! 366: return (0); ! 367: } ! 368: ! 369: /* ! 370: * Macros for clearing a page's reference bits. ! 371: */ ! 372: #ifdef REFBIT ! 373: #if !defined(tahoe) ! 374: #define uncache(pte) /* XXX */ ! 375: #endif ! 376: ! 377: #define CLRREF(pte, c, p, i) { \ ! 378: if (!isatpte(p, pte)) \ ! 379: uncache(pte); \ ! 380: if (pte->pg_u) { \ ! 381: c = &cmap[pgtocm(pte->pg_pfnum)]; \ ! 382: if (c->c_lock) \ ! 383: continue; \ ! 384: pte->pg_u = 0; \ ! 385: if (anycl(pte, pg_m)) \ ! 386: pte->pg_m = 1; \ ! 387: distcl(pte); \ ! 388: if (isatpte(p, pte)) \ ! 389: distpte(p->p_textp, i, pte); \ ! 390: } \ ! 391: } ! 392: #else ! 393: #define CLRREF(pte, c, p, i) { \ ! 394: c = &cmap[pgtocm(pte->pg_pfnum)]; \ ! 395: if (c->c_lock) \ ! 396: continue; \ ! 397: pte->pg_v = 0; \ ! 398: if (anycl(pte, pg_m)) \ ! 399: pte->pg_m = 1; \ ! 400: distcl(pte); \ ! 401: if (isatpte(p, pte)) \ ! 402: distpte(p->p_textp, i, pte); \ ! 403: } ! 404: #endif ! 405: ! 406: /* ARGSUSED */ ! 407: ovadvise(rp, uap, retval) ! 408: register struct proc *rp; ! 409: struct args { ! 410: int anom; ! 411: } *uap; ! 412: int *retval; ! 413: { ! 414: int oanom = rp->p_flag & SUANOM; ! 415: register struct pte *pte; ! 416: register struct cmap *c; ! 417: register unsigned i; ! 418: ! 419: trace(TR_VADVISE, uap->anom, rp->p_pid); ! 420: rp->p_flag &= ~(SSEQL|SUANOM); ! 421: switch (uap->anom) { ! 422: ! 423: case VA_ANOM: ! 424: rp->p_flag |= SUANOM; ! 425: break; ! 426: ! 427: case VA_SEQL: ! 428: rp->p_flag |= SSEQL; ! 429: break; ! 430: } ! 431: if ((oanom && (rp->p_flag & SUANOM) == 0) || uap->anom == VA_FLUSH) { ! 432: for (i = 0; i < rp->p_dsize; i += CLSIZE) { ! 433: pte = dptopte(rp, i); ! 434: #ifdef MAPMEM ! 435: /* don't do mmap pages */ ! 436: if (pte->pg_v && !pte->pg_fod) ! 437: #else ! 438: if (pte->pg_v) ! 439: #endif ! 440: CLRREF(pte, c, rp, i); ! 441: } ! 442: } ! 443: if (uap->anom == VA_FLUSH) { /* invalidate all pages */ ! 444: for (i = 1; i < rp->p_ssize; i += CLSIZE) { ! 445: pte = sptopte(rp, i); ! 446: if (pte->pg_v) ! 447: CLRREF(pte, c, rp, i); ! 448: } ! 449: for (i = 0; i < rp->p_tsize; i += CLSIZE) { ! 450: pte = tptopte(rp, i); ! 451: if (pte->pg_v) ! 452: CLRREF(pte, c, rp, i); ! 453: } ! 454: } ! 455: #if defined(vax) || defined(tahoe) ! 456: mtpr(TBIA, 0); ! 457: #endif ! 458: #if defined(hp300) ! 459: TBIAU(); ! 460: #endif ! 461: #if defined(i386) ! 462: tlbflush(); ! 463: #endif ! 464: return (0); ! 465: } ! 466: /* END DEFUNCT */ ! 467: ! 468: /* ! 469: * Grow the stack to include the SP; true return if successful. ! 470: * Clients do not care about the cause of the error. ! 471: */ ! 472: grow(sp) ! 473: unsigned sp; ! 474: { ! 475: int si, error; ! 476: ! 477: if (sp >= USRSTACK-ctob(u.u_ssize)) ! 478: return (0); ! 479: si = clrnd(btoc((USRSTACK-sp)) - u.u_ssize + SINCR); ! 480: if (ctob(si) > u.u_rlimit[RLIMIT_STACK].rlim_cur) ! 481: return (0); ! 482: if (error = chksize((u_int)u.u_tsize, (u_int)u.u_dsize, (u_int)0, ! 483: (u_int)u.u_ssize+si)) ! 484: return (0); ! 485: if (error = swpexpand(u.u_dsize, u.u_ssize + si, &u.u_dmap, &u.u_smap)) ! 486: return (0); ! 487: expand(si, 1); ! 488: return (1); ! 489: } ! 490: ! 491: #ifdef MAPMEM ! 492: ! 493: /* ! 494: * Called from vpassvm() after full context has been passed from fup to tup. ! 495: * Always called in the context of the parent. NOTE: routines should NOT ! 496: * destroy regions. ! 497: */ ! 498: mmvfork(fup, tup) ! 499: struct user *fup, *tup; ! 500: { ! 501: register struct mapmem *mp; ! 502: ! 503: tup->u_mmap = fup->u_mmap; ! 504: fup->u_mmap = (struct mapmem *) 0; ! 505: for (mp = tup->u_mmap; mp; mp = mp->mm_next) ! 506: if (mp->mm_ops->mm_vfork) ! 507: (*mp->mm_ops->mm_vfork)(mp, fup, tup); ! 508: } ! 509: ! 510: /* ! 511: * Called from procdup() for both parent and child. If in parent ! 512: * we need to duplicate mapped memory regions. In both parent and ! 513: * child, we call object specific routine. ! 514: */ ! 515: mmfork(pup, cup) ! 516: struct user *pup, *cup; ! 517: { ! 518: register struct mapmem *mp, **mpp; ! 519: int error = 0; ! 520: ! 521: if (pup) { ! 522: mmdup(pup, cup); ! 523: for (mp = pup->u_mmap; mp; mp = mp->mm_next) ! 524: if (mp->mm_ops->mm_fork) ! 525: (*mp->mm_ops->mm_fork)(mp, 0); ! 526: } else { ! 527: mpp = &u.u_mmap; ! 528: for (mp = *mpp; mp; mp = *mpp) { ! 529: if (mp->mm_ops->mm_fork) ! 530: (*mp->mm_ops->mm_fork)(mp, 1); ! 531: if (*mpp == mp) ! 532: mpp = &mp->mm_next; ! 533: } ! 534: error = mmexpand(u.u_procp); ! 535: } ! 536: return (error); ! 537: } ! 538: ! 539: /* ! 540: * Its not clear that having a seperate exec routine is useful since ! 541: * exec frees the address space immediately afterwards. We probably ! 542: * need a post-exec hook to reestablish any mappings that persist ! 543: * across execs. ! 544: */ ! 545: mmexec(p) ! 546: struct proc *p; ! 547: { ! 548: register struct mapmem *mp, **mpp; ! 549: int error1, error = 0; ! 550: ! 551: mpp = &u.u_mmap; ! 552: for (mp = *mpp; mp; mp = *mpp) { ! 553: if (mp->mm_ops->mm_exec) ! 554: error = (*mp->mm_ops->mm_exec)(mp); ! 555: if (*mpp == mp) { ! 556: *mpp = mp->mm_next; ! 557: MMFREE(mp); ! 558: } ! 559: } ! 560: if (error1 = mmexpand(p)) ! 561: return (error1); ! 562: if (p->p_mmsize) ! 563: panic("mmexec"); ! 564: return (error); ! 565: } ! 566: ! 567: /* ! 568: * Called from exit just before releasing address space. ! 569: * We always reclaim resources regardless of what the object routine does. ! 570: */ ! 571: mmexit(p) ! 572: struct proc *p; ! 573: { ! 574: register struct mapmem *mp, **mpp; ! 575: int error1, error = 0; ! 576: ! 577: mpp = &u.u_mmap; ! 578: for (mp = *mpp; mp; mp = *mpp) { ! 579: if (mp->mm_ops->mm_exit) ! 580: error = (*mp->mm_ops->mm_exit)(mp); ! 581: if (*mpp == mp) { ! 582: *mpp = mp->mm_next; ! 583: MMFREE(mp); ! 584: } ! 585: } ! 586: if (error1 = mmexpand(p)) ! 587: return (error1); ! 588: if (p->p_mmsize) ! 589: panic("mmexit"); ! 590: return (error); ! 591: } ! 592: ! 593: /* ! 594: * Called from core just before dumping process image to core file. ! 595: * Used to unmap regions which cannot be dumped; e.g. a region mapping ! 596: * hardware registers which are write-only or must be accessed as bytes. ! 597: */ ! 598: mmcore(p) ! 599: struct proc *p; ! 600: { ! 601: register struct mapmem *mp, **mpp; ! 602: int error = 0, error1, changed = 0; ! 603: ! 604: mpp = &u.u_mmap; ! 605: for (mp = *mpp; mp; mp = *mpp) { ! 606: if ((mp->mm_prot & MM_NOCORE) == 0) { ! 607: mpp = &mp->mm_next; ! 608: continue; ! 609: } ! 610: if (mp->mm_ops->mm_exit) ! 611: error = (*mp->mm_ops->mm_exit)(mp); ! 612: if (*mpp == mp) { ! 613: *mpp = mp->mm_next; ! 614: MMFREE(mp); ! 615: } ! 616: changed++; ! 617: } ! 618: if (changed && (error1 = mmexpand(p))) ! 619: return (error1); ! 620: return (error); ! 621: } ! 622: ! 623: /* ! 624: * Duplicate mapped memory regions in a forked process. ! 625: * XXX child may wind up short a few regions if not enough resources. ! 626: */ ! 627: mmdup(pu, cu) ! 628: struct user *pu, *cu; ! 629: { ! 630: register struct mapmem *pmp, *cmp; ! 631: register struct pte *ppte, *cpte; ! 632: register segsz_t count; ! 633: ! 634: /* ! 635: * First duplicate the mmap chain ! 636: */ ! 637: MMALLOC(cu->u_mmap); ! 638: pmp = pu->u_mmap; ! 639: cmp = cu->u_mmap; ! 640: while (pmp && cmp) { ! 641: *cmp = *pmp; ! 642: if (pmp->mm_next) ! 643: MMALLOC(cmp->mm_next); ! 644: pmp = pmp->mm_next; ! 645: cmp = cmp->mm_next; ! 646: } ! 647: /* ! 648: * Now duplicate user address space that vmdup() won't do ! 649: * i.e. mapped regions outside of data segment. ! 650: */ ! 651: ppte = dptopte(pu->u_procp, pu->u_procp->p_dsize); ! 652: cpte = dptopte(cu->u_procp, cu->u_procp->p_dsize); ! 653: for (count = pu->u_procp->p_mmsize; count; count--) { ! 654: if (ppte->pg_fod && ppte->pg_v) ! 655: *(int *)cpte = *(int *)ppte; ! 656: ppte++, cpte++; ! 657: } ! 658: cu->u_procp->p_flag |= SPTECHG; ! 659: } ! 660: ! 661: mmalloc(p, id, uvap, size, prot, ops, mpp) ! 662: struct proc *p; ! 663: caddr_t *uvap; ! 664: segsz_t size; ! 665: struct mapmemops *ops; ! 666: struct mapmem **mpp; ! 667: { ! 668: register struct mapmem *mp; ! 669: register u_int uva; ! 670: int error; ! 671: ! 672: /* ! 673: * Validate size first ! 674: */ ! 675: if (size <= 0 || (size & CLOFSET)) ! 676: return(EINVAL); ! 677: /* ! 678: * A uva of zero means to map at our discretion. ! 679: * Our strategy is to place the segment at the max of: ! 680: * - the current data + mapped memory size ! 681: * - the default data size limit ! 682: * (if it will fit within the MAXDSIZ limit) ! 683: * If this is the first mapped memory region beyond the data ! 684: * segment we round to a MMSEG boundary to allow for data ! 685: * segment growth. ! 686: */ ! 687: uva = (u_int) *uvap; ! 688: if (uva == 0) { ! 689: register u_int uva2; ! 690: ! 691: uva = ctob(dptov(p, u.u_dsize + p->p_mmsize)); ! 692: uva2 = ctob(dptov(p, btoc(DFLDSIZ))); ! 693: uva2 = ((uva2 + (MMSEG-1)) & ~(MMSEG-1)); ! 694: if (uva < uva2 && ! 695: uva2 + size < ctob(dptov(p, btoc(MAXDSIZ)))) ! 696: uva = uva2; ! 697: else if (p->p_mmsize == 0) ! 698: uva = ((uva + (MMSEG-1)) & ~(MMSEG-1)); ! 699: } ! 700: /* ! 701: * Impose necessary constraints on address. ! 702: */ ! 703: if ((uva & CLOFSET) || uva < ctob(dptov(p, 0)) || ! 704: uva+size >= ctob(sptov(p, u.u_ssize))) ! 705: return (EINVAL); ! 706: if (mmclash(u.u_mmap, (caddr_t)uva, (caddr_t)uva+size)) ! 707: return (EINVAL); ! 708: /* ! 709: * Finally, allocate and initialize descriptor and expand ! 710: * user address space as necessary. ! 711: */ ! 712: MMALLOC(mp); ! 713: if (mp == MMNIL) ! 714: return (ENOMEM); ! 715: mp->mm_next = u.u_mmap; ! 716: mp->mm_id = id; ! 717: mp->mm_uva = (caddr_t) uva; ! 718: mp->mm_size = size; ! 719: mp->mm_prot = prot; ! 720: mp->mm_ops = ops; ! 721: u.u_mmap = mp; ! 722: if (error = mmexpand(p)) { ! 723: u.u_mmap = mp->mm_next; ! 724: MMFREE(mp); ! 725: return(error); ! 726: } ! 727: *uvap = (caddr_t) uva; ! 728: *mpp = mp; ! 729: return(0); ! 730: } ! 731: ! 732: mmfree(p, mp) ! 733: struct proc *p; ! 734: register struct mapmem *mp; ! 735: { ! 736: register struct mapmem *cmp, **mpp; ! 737: ! 738: /* ! 739: * Remove region from chain ! 740: */ ! 741: mpp = &u.u_mmap; ! 742: for (cmp = *mpp; cmp; cmp = *mpp) { ! 743: if (cmp == mp) ! 744: break; ! 745: mpp = &cmp->mm_next; ! 746: } ! 747: if (cmp == MMNIL) ! 748: panic("mmfree"); ! 749: *mpp = mp->mm_next; ! 750: MMFREE(mp); ! 751: return (mmexpand(p)); ! 752: } ! 753: ! 754: mmmapin(p, mp, mapfunc) ! 755: register struct proc *p; ! 756: register struct mapmem *mp; ! 757: int (*mapfunc)(); ! 758: { ! 759: register struct pte *pte; ! 760: register int off; ! 761: struct pte *dpte; ! 762: int pm, fv, lv; ! 763: ! 764: /* ! 765: * Verify that range can be mapped ! 766: */ ! 767: for (off = 0; off < mp->mm_size; off += NBPG) ! 768: if ((*mapfunc)(mp, off) == -1) ! 769: return (EINVAL); ! 770: /* ! 771: * Now verify that region is in range ! 772: */ ! 773: fv = btop(mp->mm_uva); ! 774: lv = btop(mp->mm_uva + mp->mm_size - 1); ! 775: if (fv < dptov(p, 0) || ! 776: lv >= dptov(p, u.u_dsize + p->p_mmsize)) ! 777: return (ENOMEM); ! 778: /* ! 779: * Finally, do the mapping. ! 780: */ ! 781: if (mp->mm_prot & MM_RO) ! 782: pm = PG_URKR|PG_FOD|PG_V; ! 783: else ! 784: pm = PG_UW|PG_FOD|PG_V; ! 785: #if defined(hp300) ! 786: if (mp->mm_prot & MM_CI) ! 787: pm |= PG_CI; ! 788: #endif ! 789: pte = vtopte(p, fv); ! 790: dpte = dptopte(p, u.u_dsize); ! 791: for (off = 0; off < mp->mm_size; off += NBPG) { ! 792: if ((off&CLOFSET) == 0 && pte < dpte) ! 793: p->p_rssize -= vmemfree(pte, CLSIZE); ! 794: *(int *)pte = pm; ! 795: pte->pg_pfnum = (*mapfunc)(mp, off); ! 796: pte++; ! 797: } ! 798: newptes(vtopte(p, fv), (u_int)fv, (int)btoc(mp->mm_size)); ! 799: return (0); ! 800: } ! 801: ! 802: mmmapout(p, mp) ! 803: register struct proc *p; ! 804: register struct mapmem *mp; ! 805: { ! 806: register struct pte *pte; ! 807: register int off; ! 808: struct pte *dpte; ! 809: int fv, lv; ! 810: ! 811: fv = btop(mp->mm_uva); ! 812: lv = btop(mp->mm_uva + mp->mm_size - 1); ! 813: if (fv < dptov(p, 0) || ! 814: lv >= dptov(p, u.u_dsize + p->p_mmsize)) ! 815: panic("mmmapout"); ! 816: pte = vtopte(p, fv); ! 817: dpte = dptopte(p, u.u_dsize); ! 818: for (off = 0; off < mp->mm_size; off += NBPG) { ! 819: if (pte < dpte) { ! 820: if ((off & CLOFSET) == 0) ! 821: p->p_rssize -= vmemfree(pte, CLSIZE); ! 822: *(int *)pte = (PG_UW|PG_FOD); ! 823: ((struct fpte *)pte)->pg_fileno = PG_FZERO; ! 824: } else ! 825: *(int *)pte = 0; ! 826: pte++; ! 827: } ! 828: newptes(vtopte(p, fv), (u_int)fv, (int)btoc(mp->mm_size)); ! 829: } ! 830: ! 831: mmexpand(p) ! 832: struct proc *p; ! 833: { ! 834: register int szpt, change; ! 835: caddr_t high; ! 836: segsz_t nsize, oms; ! 837: ! 838: oms = p->p_mmsize; ! 839: /* ! 840: * Get new mmsize based on existing regions and use ! 841: * that to calculate change in page table size. ! 842: */ ! 843: if (u.u_mmap) { ! 844: mmrange(u.u_mmap, (caddr_t *)0, &high); ! 845: nsize = btop(high) - dptov(p, u.u_dsize) + 1; ! 846: if (nsize < 0) ! 847: nsize = 0; ! 848: } else ! 849: nsize = 0; ! 850: change = nsize - oms; ! 851: if (change == 0) ! 852: return(0); ! 853: ! 854: /* ! 855: * Ensure data + mapped memory fits within maximum data limit. ! 856: * This is possibly a little restrictive, but it helps keep ! 857: * page table sizes down. ! 858: */ ! 859: if (change > 0 && ! 860: (ctob(oms+change) > u.u_rlimit[RLIMIT_DATA].rlim_max || ! 861: ctob(u.u_dsize+oms+change) > u.u_rlimit[RLIMIT_DATA].rlim_max)) ! 862: return(ENOMEM); ! 863: /* ! 864: * Expand page table if necessary. ! 865: * Note that ptexpand takes care of flushing the translation buffer. ! 866: */ ! 867: p->p_mmsize += change; ! 868: #if defined(hp300) || defined(i386) ! 869: szpt = ptsize(p) - u.u_pcb.pcb_szpt; ! 870: if (szpt > 0) ! 871: ptexpand(szpt, u.u_dsize, oms, u.u_ssize); ! 872: setp0lr(u.u_pcb.pcb_p0lr + change); ! 873: #endif ! 874: #if defined(vax) || defined(tahoe) ! 875: #if defined(vax) ! 876: szpt = (u.u_pcb.pcb_p1br + (u.u_pcb.pcb_p1lr&~PME_CLR)) - ! 877: (u.u_pcb.pcb_p0br + (u.u_pcb.pcb_p0lr&~AST_CLR)); ! 878: #else ! 879: szpt = (u.u_pcb.pcb_p2br + u.u_pcb.pcb_p2lr) - ! 880: (u.u_pcb.pcb_p0br + u.u_pcb.pcb_p0lr); ! 881: #endif ! 882: if (change > szpt) ! 883: ptexpand(clrnd(ctopt(change - szpt)), u.u_dsize, oms, u.u_ssize); ! 884: /* ! 885: * Clear new ptes. ! 886: * We need to do this because there may be bogus (yet technically ! 887: * valid) ptes above the old p0lr value. This can happen if the ! 888: * data segment has shrunk in the past leaving such ptes behind. ! 889: * There is no need to invalidate such ptes at that time since the ! 890: * length register will prevent their use. We are safe on the HPs ! 891: * because we do invalidate old ptes in setp0lr() when shrinking. ! 892: */ ! 893: if (change > 0) { ! 894: struct pte *bpte; ! 895: ! 896: #if defined(vax) ! 897: bpte = u.u_pcb.pcb_p0br + (u.u_pcb.pcb_p0lr&~AST_CLR); ! 898: #else ! 899: bpte = u.u_pcb.pcb_p0br + u.u_pcb.pcb_p0lr; ! 900: #endif ! 901: bzero((caddr_t)bpte, change * sizeof(struct pte)); ! 902: mtpr(TBIA, 0); ! 903: } ! 904: /* avoid side-effects of setp0lr */ ! 905: #if defined(vax) ! 906: change += u.u_pcb.pcb_p0lr &~ AST_CLR; ! 907: #else ! 908: change += u.u_pcb.pcb_p0lr; ! 909: #endif ! 910: setp0lr(change); ! 911: #endif ! 912: return(0); ! 913: } ! 914: ! 915: mmrange(mp, lap, hap) ! 916: register struct mapmem *mp; ! 917: caddr_t *lap, *hap; ! 918: { ! 919: register caddr_t low, high, top; ! 920: ! 921: low = high = 0; ! 922: while (mp) { ! 923: if (low == 0 || mp->mm_uva < low) ! 924: low = mp->mm_uva; ! 925: top = mp->mm_uva + mp->mm_size - 1; ! 926: if (high == 0 || top > high) ! 927: high = top; ! 928: mp = mp->mm_next; ! 929: } ! 930: if (lap) ! 931: *lap = low; ! 932: if (hap) ! 933: *hap = high; ! 934: } ! 935: ! 936: mmclash(mp, la, ha) ! 937: register struct mapmem *mp; ! 938: caddr_t la, ha; ! 939: { ! 940: while (mp) { ! 941: if (ha > mp->mm_uva && la < mp->mm_uva + mp->mm_size) ! 942: return(1); ! 943: mp = mp->mm_next; ! 944: } ! 945: return(0); ! 946: } ! 947: ! 948: #endif /* MAPMEM */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.