|
|
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: * @(#)vm_pt.c 7.14 (Berkeley) 6/30/90 ! 21: */ ! 22: #include "machine/pte.h" ! 23: #include "machine/mtpr.h" ! 24: ! 25: #include "param.h" ! 26: #include "systm.h" ! 27: #include "user.h" ! 28: #include "proc.h" ! 29: #include "map.h" ! 30: #include "cmap.h" ! 31: #include "vm.h" ! 32: #include "buf.h" ! 33: #include "text.h" ! 34: #include "vnode.h" ! 35: #include "kernel.h" ! 36: ! 37: /* ! 38: * Get page tables for process p. Allocator ! 39: * for memory is argument; process must be locked ! 40: * from swapping if vmemall is used; if memall is ! 41: * used, call will return w/o waiting for memory. ! 42: * In any case an error return results if no user ! 43: * page table space is available. ! 44: */ ! 45: vgetpt(p, pmemall) ! 46: register struct proc *p; ! 47: int (*pmemall)(); ! 48: { ! 49: register long a; ! 50: register int szpt = p->p_szpt; ! 51: ! 52: if (szpt == 0) ! 53: panic("vgetpt"); ! 54: #if defined(hp300) || defined(i386) ! 55: /* ! 56: * Allocate a single page segment/paage directory table as well ! 57: * as page tables. ! 58: */ ! 59: szpt++; ! 60: #endif ! 61: /* ! 62: * Allocate space in the kernel map for this process. ! 63: * Then allocate page table pages, and initialize the ! 64: * process' p0br and addr pointer to be the kernel ! 65: * virtual addresses of the base of the page tables and ! 66: * the pte for the process pcb (at the base of the u.). ! 67: */ ! 68: a = rmalloc(kernelmap, (long)szpt); ! 69: if (a == 0) ! 70: return (0); ! 71: if ((*pmemall)(&Usrptmap[a], szpt, p, CSYS) == 0) { ! 72: rmfree(kernelmap, (long)szpt, a); ! 73: return (0); ! 74: } ! 75: p->p_p0br = kmxtob(a); ! 76: p->p_addr = uaddr(p); ! 77: /* ! 78: * Now validate the system page table entries for the ! 79: * user page table pages, flushing old translations ! 80: * for these kernel virtual addresses. Clear the new ! 81: * page table pages for clean post-mortems. ! 82: */ ! 83: vmaccess(&Usrptmap[a], (caddr_t)p->p_p0br, szpt); ! 84: bzero((caddr_t) p->p_p0br, (unsigned) (szpt * NBPG)); ! 85: #if defined(hp300) ! 86: /* cache inhibit page tables pages so HW set bits are always valid */ ! 87: for (szpt = a + szpt - 1; szpt >= a; --szpt) ! 88: Usrptmap[szpt].pg_ci = 1; ! 89: initsegt(p); ! 90: #endif ! 91: #if defined(i386) ! 92: initpdt(p); ! 93: #endif ! 94: return (1); ! 95: } ! 96: ! 97: /* ! 98: * Initialize text portion of page table. ! 99: */ ! 100: vinitpt(p) ! 101: struct proc *p; ! 102: { ! 103: register struct text *xp; ! 104: register struct proc *q; ! 105: register struct pte *pte; ! 106: register int i; ! 107: struct pte proto; ! 108: ! 109: xp = p->p_textp; ! 110: if (xp == 0) ! 111: return; ! 112: pte = tptopte(p, 0); ! 113: /* ! 114: * If there is another instance of same text in core ! 115: * then just copy page tables from other process. ! 116: */ ! 117: if (q = xp->x_caddr) { ! 118: bcopy((caddr_t)tptopte(q, 0), (caddr_t)pte, ! 119: (unsigned) (sizeof(struct pte) * xp->x_size)); ! 120: goto done; ! 121: } ! 122: if (xp->x_flag & XLOAD || (xp->x_flag & XPAGV) == 0) { ! 123: /* ! 124: * Initialize text page tables, zfod if we are loading ! 125: * the text now; unless the process is demand loaded, ! 126: * this will suffice as the text will henceforth either be ! 127: * read from a file or demand paged in. ! 128: */ ! 129: *(int *)&proto = PG_URKR; ! 130: if (xp->x_flag & XLOAD) { ! 131: proto.pg_fod = 1; ! 132: ((struct fpte *)&proto)->pg_fileno = PG_FZERO; ! 133: } ! 134: for (i = 0; i < xp->x_size; i++) ! 135: *pte++ = proto; ! 136: if ((xp->x_flag & XPAGV) == 0) ! 137: goto done; ! 138: } ! 139: /* ! 140: * Text is demand loaded. If process is not loaded (i.e. being ! 141: * swapped in) then retrieve page tables from swap area. Otherwise ! 142: * this is the first time and we must initialize the page tables ! 143: * from the blocks in the file system. ! 144: */ ! 145: if (xp->x_flag & XLOAD) ! 146: vinifod(p, (struct fpte *)tptopte(p, 0), PG_FTEXT, xp->x_vptr, ! 147: (daddr_t)1, xp->x_size); ! 148: else ! 149: (void) swap(p, xp->x_ptdaddr, (caddr_t)tptopte(p, 0), ! 150: (int)(xp->x_size * sizeof (struct pte)), B_READ, ! 151: B_PAGET, swapdev_vp, 0); ! 152: done: ! 153: /* ! 154: * In the case where we are overlaying ourself with new page ! 155: * table entries, old user-space translations should be flushed. ! 156: */ ! 157: if (p == u.u_procp) ! 158: newptes(tptopte(p, 0), tptov(p, 0), (int)xp->x_size); ! 159: else ! 160: p->p_flag |= SPTECHG; ! 161: } ! 162: ! 163: /* ! 164: * Update the page tables of all processes linked ! 165: * to a particular text segment, by distributing ! 166: * dpte to the the text page at virtual frame v. ! 167: * ! 168: * Note that invalidation in the translation buffer for ! 169: * the current process is the responsibility of the caller. ! 170: */ ! 171: distpte(xp, tp, dpte) ! 172: struct text *xp; ! 173: register unsigned tp; ! 174: register struct pte *dpte; ! 175: { ! 176: register struct proc *p; ! 177: register struct pte *pte; ! 178: register int i; ! 179: ! 180: for (p = xp->x_caddr; p; p = p->p_xlink) { ! 181: pte = tptopte(p, tp); ! 182: p->p_flag |= SPTECHG; ! 183: if (pte != dpte) ! 184: for (i = 0; i < CLSIZE; i++) ! 185: pte[i] = dpte[i]; ! 186: } ! 187: } ! 188: ! 189: /* ! 190: * Release page tables of process p. ! 191: */ ! 192: vrelpt(p) ! 193: register struct proc *p; ! 194: { ! 195: register int a; ! 196: register int szpt = p->p_szpt; ! 197: ! 198: if (szpt == 0) ! 199: return; ! 200: a = btokmx(p->p_p0br); ! 201: #if defined(hp300) ! 202: flushustp(initustp(p)); ! 203: /* don't forget the segment table */ ! 204: szpt++; ! 205: #endif ! 206: #if defined(i386) ! 207: /* don't forget the page directory table */ ! 208: szpt++; ! 209: #endif ! 210: (void) vmemfree(&Usrptmap[a], szpt); ! 211: rmfree(kernelmap, (long)szpt, (long)a); ! 212: } ! 213: ! 214: #define Xu(a) t = up->u_pcb.a; up->u_pcb.a = uq ->u_pcb.a; uq->u_pcb.a = t; ! 215: #define Xup(a) tp = up->u_pcb.a; up->u_pcb.a = uq ->u_pcb.a; uq->u_pcb.a = tp; ! 216: #define Xp(a) t = p->a; p->a = q->a; q->a = t; ! 217: #define Xpp(a) tp = p->a; p->a = q->a; q->a = tp; ! 218: ! 219: /* ! 220: * Pass the page tables of process p to process q. ! 221: * Used during vfork(). P and q are not symmetric; ! 222: * p is the giver and q the receiver; after calling vpasspt ! 223: * p will be ``cleaned out''. Thus before vfork() we call vpasspt ! 224: * with the child as q and give it our resources; after vfork() we ! 225: * call vpasspt with the child as p to steal our resources back. ! 226: * We are cognizant of whether we are p or q because we have to ! 227: * be careful to keep our u. area and restore the other u. area from ! 228: * umap after we temporarily put our u. area in both p and q's page tables. ! 229: */ ! 230: vpasspt(p, q, up, uq, umap) ! 231: register struct proc *p, *q; ! 232: register struct user *up, *uq; ! 233: struct pte *umap; ! 234: { ! 235: int t; ! 236: int s; ! 237: struct pte *tp; ! 238: register int i; ! 239: ! 240: s = splhigh(); /* conservative, and slightly paranoid */ ! 241: Xu(pcb_szpt); Xu(pcb_p0lr); Xu(pcb_p1lr); ! 242: #if defined(tahoe) ! 243: Xu(pcb_p2lr); ! 244: #endif ! 245: Xup(pcb_p0br); Xup(pcb_p1br); ! 246: #if defined(tahoe) ! 247: Xup(pcb_p2br); ! 248: #endif ! 249: #if defined(hp300) ! 250: Xu(pcb_ustp); Xu(pcb_flags); ! 251: #endif ! 252: #if defined(i386) ! 253: Xu(pcb_cr3); Xu(pcb_flags); ! 254: #endif ! 255: ! 256: /* ! 257: * The u. area is contained in the process' p1 region. ! 258: * Thus we map the current u. area into the process virtual space ! 259: * of both sets of page tables we will deal with so that it ! 260: * will stay with us as we rearrange memory management. ! 261: */ ! 262: for (i = 0; i < UPAGES; i++) ! 263: if (up == &u) ! 264: q->p_addr[i] = p->p_addr[i]; ! 265: else ! 266: p->p_addr[i] = q->p_addr[i]; ! 267: #if defined(vax) || defined(tahoe) ! 268: mtpr(TBIA, 0); ! 269: #endif ! 270: /* ! 271: * Now have u. double mapped, and have flushed ! 272: * any stale translations to new u. area. ! 273: * Switch the page tables. ! 274: */ ! 275: Xpp(p_p0br); Xp(p_szpt); Xpp(p_addr); ! 276: #if defined(vax) || defined(tahoe) ! 277: mtpr(P0BR, u.u_pcb.pcb_p0br); ! 278: #if defined(vax) ! 279: mtpr(P0LR, u.u_pcb.pcb_p0lr &~ AST_CLR); ! 280: #else ! 281: mtpr(P0LR, u.u_pcb.pcb_p0lr); ! 282: #endif ! 283: mtpr(P1BR, u.u_pcb.pcb_p1br); ! 284: mtpr(P1LR, u.u_pcb.pcb_p1lr); ! 285: #if defined(tahoe) ! 286: mtpr(P2BR, u.u_pcb.pcb_p2br); ! 287: mtpr(P2LR, u.u_pcb.pcb_p2lr); ! 288: #endif ! 289: #endif ! 290: #if defined(hp300) ! 291: loadustp(u.u_pcb.pcb_ustp); ! 292: #endif ! 293: #if defined(i386) ! 294: load_cr3(u.u_pcb.pcb_cr3); ! 295: #endif ! 296: /* ! 297: * Now running on the ``other'' set of page tables. ! 298: * Flush translation to insure that we get correct u. ! 299: * Resurrect the u. for the other process in the other ! 300: * (our old) set of page tables. Thus the other u. has moved ! 301: * from its old (our current) set of page tables to our old ! 302: * (its current) set of page tables, while we have kept our ! 303: * u. by mapping it into the other page table and then keeping ! 304: * the other page table. ! 305: */ ! 306: #if defined(vax) || defined(tahoe) ! 307: mtpr(TBIA, 0); ! 308: #endif ! 309: for (i = 0; i < UPAGES; i++) { ! 310: int pf; ! 311: struct pte *pte; ! 312: if (up == &u) { ! 313: pf = umap[i].pg_pfnum; ! 314: pte = &q->p_addr[i]; ! 315: pte->pg_pfnum = pf; ! 316: } else { ! 317: pf = umap[i].pg_pfnum; ! 318: pte = &p->p_addr[i]; ! 319: pte->pg_pfnum = pf; ! 320: } ! 321: } ! 322: #if defined(vax) || defined(tahoe) ! 323: mtpr(TBIA, 0); ! 324: #endif ! 325: #if defined(hp300) ! 326: TBIA(); ! 327: #endif ! 328: #if defined(i386) ! 329: tlbflush(); ! 330: #endif ! 331: splx(s); ! 332: } ! 333: ! 334: /* ! 335: * Compute number of pages to be allocated to the u. area ! 336: * and data and stack area page tables, which are stored on the ! 337: * disk immediately after the u. area. ! 338: */ ! 339: /*ARGSUSED*/ ! 340: vusize(p, utl) ! 341: register struct proc *p; ! 342: struct user *utl; ! 343: { ! 344: register int tsz = p->p_tsize / NPTEPG; ! 345: ! 346: /* ! 347: * We do not need page table space on the disk for page ! 348: * table pages wholly containing text. This is well ! 349: * understood in the code in vmswap.c. ! 350: */ ! 351: return (clrnd(UPAGES + ptsize(p) - tsz)); ! 352: } ! 353: ! 354: /* ! 355: * Get u area for process p. If a old u area is given, ! 356: * then copy the new area from the old, else ! 357: * swap in as specified in the proc structure. ! 358: * ! 359: * Since argument map/newu is potentially shared ! 360: * when an old u. is provided we have to be careful not ! 361: * to block after beginning to use them in this case. ! 362: * (This is not true when called from swapin() with no old u.) ! 363: */ ! 364: vgetu(p, palloc, map, newu, oldu) ! 365: register struct proc *p; ! 366: int (*palloc)(); ! 367: register struct pte *map; ! 368: register struct user *newu; ! 369: struct user *oldu; ! 370: { ! 371: register int i; ! 372: ! 373: if ((*palloc)(p->p_addr, clrnd(UPAGES), p, CSYS) == 0) ! 374: return (0); ! 375: /* ! 376: * New u. pages are to be accessible in map/newu as well ! 377: * as in process p's virtual memory. ! 378: */ ! 379: for (i = 0; i < UPAGES; i++) { ! 380: map[i] = p->p_addr[i]; ! 381: *(int *)(p->p_addr + i) |= PG_URKW | PG_V; ! 382: } ! 383: setredzone(p->p_addr, (caddr_t)0); ! 384: vmaccess(map, (caddr_t)newu, UPAGES); ! 385: /* ! 386: * New u.'s come from forking or inswap. ! 387: */ ! 388: if (oldu) { ! 389: bcopy((caddr_t)oldu, (caddr_t)newu, (unsigned) UPAGES * NBPG); ! 390: newu->u_procp = p; ! 391: } else { ! 392: #if defined(vax) || defined(hp300) || defined(i386) ! 393: (void) swap(p, p->p_swaddr, (caddr_t)0, ctob(UPAGES), ! 394: #else ! 395: (void) swap(p, p->p_swaddr, (caddr_t)&u, ctob(UPAGES), ! 396: #endif ! 397: B_READ, B_UAREA, swapdev_vp, 0); ! 398: if ( ! 399: #if defined(vax) ! 400: newu->u_pcb.pcb_ssp != -1 || newu->u_pcb.pcb_esp != -1 || ! 401: #endif ! 402: newu->u_tsize != p->p_tsize || newu->u_dsize != p->p_dsize || ! 403: newu->u_ssize != p->p_ssize || newu->u_procp != p) ! 404: panic("vgetu"); ! 405: } ! 406: /* ! 407: * Initialize the pcb copies of the p0 and p1 region bases and ! 408: * software page table size from the information in the proc structure. ! 409: */ ! 410: newu->u_pcb.pcb_p0br = p->p_p0br; ! 411: #if defined(vax) ! 412: newu->u_pcb.pcb_p1br = initp1br(p->p_p0br + p->p_szpt * NPTEPG); ! 413: #endif ! 414: #if defined(tahoe) ! 415: newu->u_pcb.pcb_p2br = initp2br(p->p_p0br + p->p_szpt * NPTEPG); ! 416: #endif ! 417: #if defined(hp300) ! 418: newu->u_pcb.pcb_p1br = initp1br(p->p_p0br + p->p_szpt * NPTEPG); ! 419: newu->u_pcb.pcb_ustp = initustp(p); ! 420: #endif ! 421: #if defined(i386) ! 422: newu->u_pcb.pcb_p1br = initp1br(p->p_p0br + p->p_szpt * NPTEPG); ! 423: newu->u_pcb.pcb_cr3 = initpdt(p); ! 424: #endif ! 425: newu->u_pcb.pcb_szpt = p->p_szpt; ! 426: return (1); ! 427: } ! 428: ! 429: /* ! 430: * Release swap space for a u. area. ! 431: */ ! 432: vrelswu(p, utl) ! 433: struct proc *p; ! 434: struct user *utl; ! 435: { ! 436: ! 437: rmfree(swapmap, (long)ctod(vusize(p, utl)), p->p_swaddr); ! 438: /* p->p_swaddr = 0; */ /* leave for post-mortems */ ! 439: } ! 440: ! 441: /* ! 442: * Get swap space for a u. area. ! 443: */ ! 444: vgetswu(p, utl) ! 445: struct proc *p; ! 446: struct user *utl; ! 447: { ! 448: ! 449: p->p_swaddr = rmalloc(swapmap, (long)ctod(vusize(p, utl))); ! 450: return (p->p_swaddr); ! 451: } ! 452: ! 453: /* ! 454: * Release u. area, swapping it out if desired. ! 455: */ ! 456: vrelu(p, swapu) ! 457: register struct proc *p; ! 458: { ! 459: register int i; ! 460: struct pte uu[UPAGES]; ! 461: ! 462: if (swapu) ! 463: #if defined(vax) || defined(hp300) || defined(i386) ! 464: (void) swap(p, p->p_swaddr, (caddr_t)0, ctob(UPAGES), ! 465: #else ! 466: (void) swap(p, p->p_swaddr, (caddr_t)&u, ctob(UPAGES), ! 467: #endif ! 468: B_WRITE, B_UAREA, swapdev_vp, 0); ! 469: for (i = 0; i < UPAGES; i++) ! 470: uu[i] = p->p_addr[i]; ! 471: /* ! 472: * If freeing the user structure and kernel stack ! 473: * for the current process, have to run a bit longer ! 474: * using the pages which have already been freed... ! 475: * block memory allocation from the network by raising ipl. ! 476: */ ! 477: if (p == u.u_procp) ! 478: (void) splimp(); /* XXX */ ! 479: (void) vmemfree(uu, clrnd(UPAGES)); ! 480: } ! 481: ! 482: #ifdef DIAGNOSTIC ! 483: int ptforceswap; ! 484: #endif ! 485: /* ! 486: * Expand a page table, assigning new kernel virtual ! 487: * space and copying the page table entries over both ! 488: * in the system map and as necessary in the user page table space. ! 489: * IMPORTANT NOTE: ! 490: * ! 491: * On the HPs, excess PTEs will *always* be zero. This is critical ! 492: * since we don't have length registers. We guarentee this for ! 493: * expansion here by zeroing new PT pages, and for shrinking in ! 494: * setptlr() which zeroes excess PTEs. ! 495: * ! 496: * On the VAX and TAHOE, the state of excess PTEs is less important ! 497: * as the length registers dictate the actual bounds. As a result ! 498: * the state of these PTEs is random. New pages are zeroed unless ! 499: * they come about due to a PT expansion swap in which case they ! 500: * have garbage. Page table splitting (either here or as part of ! 501: * an expansion swap) can lead to duplicate PTEs. When shrinking, ! 502: * expand() sets excess PTEs to PG_UW (not zero). ! 503: */ ! 504: ptexpand(change, ods, omms, oss) ! 505: register int change; ! 506: segsz_t ods, omms, oss; ! 507: { ! 508: register struct pte *p1, *p2; ! 509: register int i; ! 510: #if defined(vax) || defined(hp300) || defined(i386) ! 511: register int spages, ss = P1PAGES - u.u_pcb.pcb_p1lr; ! 512: #endif ! 513: #if defined(tahoe) ! 514: register int spages, ss = P2PAGES - u.u_pcb.pcb_p2lr; ! 515: #endif ! 516: register int kold = btokmx(u.u_pcb.pcb_p0br); ! 517: int knew, tdpages; ! 518: int szpt = u.u_pcb.pcb_szpt; ! 519: caddr_t a; ! 520: int s; ! 521: ! 522: if (change <= 0 || change % CLSIZE) ! 523: panic("ptexpand"); ! 524: #if defined(hp300) || defined(i386) ! 525: /* ! 526: * ++ to account for segment/page directory table. We reallocate ! 527: * a segment table PTE so that it is virtually contiguous with ! 528: * the page tables. ! 529: * This way we can locate it relative to p_p0br (see initustp()). ! 530: * Reallocation also reduces fragmentation of Usrptmap. ! 531: */ ! 532: szpt++; ! 533: #endif ! 534: /* ! 535: * Change is the number of new page table pages needed. ! 536: * Kold is the old index in the kernelmap of the page tables. ! 537: * Allocate a new kernel map segment of size szpt+change for ! 538: * the page tables, and the new page table pages in the ! 539: * middle of this new region. ! 540: */ ! 541: top: ! 542: #if defined(hp300) || defined(i386) ! 543: /* ! 544: * Consider segment/page directory table as part of stack ptes ! 545: * Note we use ctopt() since we don't pack page tables ! 546: */ ! 547: spages = ctopt(ss) + 1; ! 548: #else ! 549: spages = ss/NPTEPG; ! 550: #endif ! 551: tdpages = szpt - spages; ! 552: #ifdef DIAGNOSTIC ! 553: if (ptforceswap) ! 554: goto bad; ! 555: #endif ! 556: if ((knew=rmalloc(kernelmap, (long)(szpt+change))) == 0) ! 557: goto bad; ! 558: if (memall(&Usrptmap[knew+tdpages], change, u.u_procp, CSYS) == 0) { ! 559: rmfree(kernelmap, (long)(szpt+change), (long)knew); ! 560: goto bad; ! 561: } ! 562: ! 563: /* ! 564: * Spages pages of u.+stack page tables go over unchanged. ! 565: * Tdpages of text+data page table may contain a few stack ! 566: * pages which need to go in one of the newly allocated pages; ! 567: * this is a rough cut. ! 568: * ! 569: * NOTE: The last statement is not true on HPs, text/data and ! 570: * stack are seperate page tables. We really cannot "pack" page ! 571: * tables since we have no length register, and packing would ! 572: * result in some pages being accessible at two different addrs. ! 573: */ ! 574: kmcopy(knew, kold, tdpages); ! 575: kmcopy(knew+tdpages+change, kold+tdpages, spages); ! 576: ! 577: /* ! 578: * Validate and clear the newly allocated page table pages in the ! 579: * center of the new region of the kernelmap. ! 580: */ ! 581: i = knew + tdpages; ! 582: p1 = &Usrptmap[i]; ! 583: a = (caddr_t) kmxtob(i); ! 584: p2 = p1 + change; ! 585: while (p1 < p2) { ! 586: #if defined(hp300) ! 587: /* mapin is overkill */ ! 588: *(u_int *)p1 |= PG_V|PG_KW|PG_CI; ! 589: #else ! 590: mapin(p1, (u_int) a, p1->pg_pfnum, (int)(PG_V|PG_KW)); ! 591: #endif ! 592: bzero(a, NBPG); ! 593: a += NBPG; ! 594: p1++; ! 595: } ! 596: ! 597: #if !defined(hp300) && !defined(i386) ! 598: /* ! 599: * Move the stack and u. pte's which are before the newly ! 600: * allocated pages into the last of the newly allocated pages. ! 601: * They are taken from the end of the current p1 region, ! 602: * and moved to the end of the new p1 region. ! 603: */ ! 604: #if defined(vax) ! 605: p1 = u.u_pcb.pcb_p1br + u.u_pcb.pcb_p1lr; ! 606: p2 = initp1br(kmxtob(knew+szpt+change)) + u.u_pcb.pcb_p1lr; ! 607: #endif ! 608: #if defined(tahoe) ! 609: p1 = u.u_pcb.pcb_p2br + u.u_pcb.pcb_p2lr; ! 610: p2 = initp2br(kmxtob(knew+szpt+change)) + u.u_pcb.pcb_p2lr; ! 611: #endif ! 612: bcopy((caddr_t) p1, (caddr_t) p2, ! 613: (unsigned)((caddr_t)kmxtob(kold + tdpages) - (caddr_t)p1)); ! 614: #endif ! 615: ! 616: /* ! 617: * Now switch to the new page tables. ! 618: */ ! 619: s = splhigh(); /* conservative */ ! 620: u.u_procp->p_p0br = kmxtob(knew); ! 621: setp0br(u.u_procp->p_p0br); ! 622: #if defined(vax) ! 623: u.u_pcb.pcb_p1br = initp1br(kmxtob(knew+szpt+change)); ! 624: setp1br(u.u_pcb.pcb_p1br); ! 625: #endif ! 626: #if defined(tahoe) ! 627: u.u_pcb.pcb_p1br = kmxtob(knew); ! 628: setp1br(u.u_pcb.pcb_p1br); ! 629: u.u_pcb.pcb_p2br = initp2br(kmxtob(knew+szpt+change)); ! 630: setp2br(u.u_pcb.pcb_p2br); ! 631: #endif ! 632: #if defined(hp300) || defined(i386) ! 633: u.u_pcb.pcb_p1br = initp1br(kmxtob(knew+szpt-1+change)); ! 634: setp1br(u.u_pcb.pcb_p1br); ! 635: #endif ! 636: u.u_pcb.pcb_szpt += change; ! 637: u.u_procp->p_szpt += change; ! 638: u.u_procp->p_addr = uaddr(u.u_procp); ! 639: #if defined(vax) || defined(tahoe) ! 640: mtpr(TBIA, 0); ! 641: #endif ! 642: #if defined(hp300) ! 643: u.u_pcb.pcb_ustp = initustp(u.u_procp); ! 644: initsegt(u.u_procp); ! 645: TBIA(); ! 646: #endif ! 647: #if defined(i386) ! 648: u.u_pcb.pcb_cr3 = initpdt(u.u_procp); ! 649: tlbflush(); ! 650: #endif ! 651: splx(s); ! 652: ! 653: /* ! 654: * Finally, free old kernelmap. ! 655: */ ! 656: if (szpt) ! 657: rmfree(kernelmap, (long)szpt, (long)kold); ! 658: return; ! 659: ! 660: bad: ! 661: /* ! 662: * Swap out the process so that the unavailable ! 663: * resource will be allocated upon swapin. ! 664: * ! 665: * When resume is executed for the process, ! 666: * here is where it will resume. ! 667: */ ! 668: resume(pcbb(u.u_procp)); ! 669: if (savectx(&u.u_ssave)) { ! 670: #if defined(hp300) || defined(i386) ! 671: /* ! 672: * New page table pages will contain garbage since ! 673: * the page table was expanded on disk without the ! 674: * new pages being zeroed. ! 675: */ ! 676: bzero((caddr_t)u.u_procp->p_p0br+tdpages*NBPG, change*NBPG); ! 677: #endif ! 678: return; ! 679: } ! 680: if (swapout(u.u_procp, ods, omms, oss) == 0) { ! 681: /* ! 682: * No space to swap... it is inconvenient to try ! 683: * to exit, so just wait a bit and hope something ! 684: * turns up. Could deadlock here. ! 685: * ! 686: * SOMEDAY REFLECT ERROR BACK THROUGH expand TO CALLERS ! 687: * (grow, sbreak) SO CAN'T DEADLOCK HERE. ! 688: */ ! 689: sleep((caddr_t)&lbolt, PRIBIO); ! 690: goto top; ! 691: } ! 692: /* ! 693: * Set SSWAP bit, so that when process is swapped back in ! 694: * swapin will set u.u_pcb.pcb_sswap to u_sswap and force a ! 695: * return from the savectx() above. ! 696: */ ! 697: u.u_procp->p_flag |= SSWAP; ! 698: swtch(); ! 699: /* NOTREACHED */ ! 700: } ! 701: ! 702: kmcopy(to, from, count) ! 703: int to; ! 704: int from; ! 705: register int count; ! 706: { ! 707: register struct pte *tp = &Usrptmap[to]; ! 708: register struct pte *fp = &Usrptmap[from]; ! 709: u_int a; ! 710: ! 711: a = (u_int) kmxtob(to); ! 712: while (count != 0) { ! 713: #if defined(hp300) ! 714: mapin(tp, a, fp->pg_pfnum, ! 715: (int)(*((int *)fp) & (PG_V|PG_PROT|PG_CI))); ! 716: #else ! 717: mapin(tp, a, fp->pg_pfnum, ! 718: (int)(*((int *)fp) & (PG_V|PG_PROT))); ! 719: #endif ! 720: #if defined(tahoe) ! 721: mtpr(P1DC, a); ! 722: #endif ! 723: tp++; ! 724: fp++; ! 725: a += NBPG; ! 726: count--; ! 727: } ! 728: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.