|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)vm_machdep.c 1.1 86/02/03 Copyr 1985 Sun Micro"; ! 3: #endif ! 4: ! 5: /* ! 6: * Copyright (c) 1985 by Sun Microsystems, Inc. ! 7: */ ! 8: ! 9: /* ! 10: * Machine dependent virtual memory support. ! 11: * Context and segment and page map support for the Sun-3. ! 12: */ ! 13: ! 14: #include "../h/param.h" ! 15: #include "../h/systm.h" ! 16: #include "../h/buf.h" ! 17: #include "../h/dir.h" ! 18: #include "../h/user.h" ! 19: #include "../h/proc.h" ! 20: #include "../h/vm.h" ! 21: #include "../h/cmap.h" ! 22: #include "../h/text.h" ! 23: #include "../h/mount.h" ! 24: ! 25: #include "../machine/pte.h" ! 26: #include "../machine/mmu.h" ! 27: #include "../machine/cpu.h" ! 28: #include "../machine/reg.h" ! 29: #include "../machine/buserr.h" ! 30: #include "../machine/scb.h" ! 31: #include "../machine/mbvar.h" ! 32: ! 33: u_char getsegmap(); ! 34: long getpgmap(); ! 35: ! 36: struct context context[NCONTEXT]; /* contexts */ ! 37: int ctxtime = 0; /* pseudo-time for ctx lru */ ! 38: ! 39: struct pmeg pmeg[NPMEG]; /* all the pmegs in the world */ ! 40: struct pmeg pmeghead; /* pmeg free list */ ! 41: ! 42: int kernpmeg = 0; /* how many pmegs the kernel has */ ! 43: ! 44: /* ! 45: * Initialize pmeg allocation list. ! 46: */ ! 47: pmeginit() ! 48: { ! 49: register int i; ! 50: ! 51: pmeghead.pm_forw = pmeghead.pm_back = &pmeghead; ! 52: for (i = 0; i < NPMEG; i++) /* add all entries to queue */ ! 53: insque(&pmeg[i], &pmeghead); ! 54: } ! 55: ! 56: /* ! 57: * Take care of common pmeg release code for pmegalloc() and pmegallocres(), ! 58: * called only when pmp->pm_procp is non-zero. ! 59: */ ! 60: pmegrelease(pmp) ! 61: register struct pmeg *pmp; ! 62: { ! 63: register struct context *cp; ! 64: int ctx; ! 65: ! 66: pmegunload(pmp); ! 67: cp = pmp->pm_procp->p_ctx; ! 68: cp->ctx_pmeg[pmp->pm_seg] = 0; ! 69: ctx = getcontext(); ! 70: setcontext((int)cp->ctx_context); ! 71: setsegmap((u_int)pmp->pm_seg, (u_char)SEGINV); ! 72: setcontext(ctx); ! 73: } ! 74: ! 75: /* ! 76: * Allocate a page map entry group. ! 77: */ ! 78: u_char ! 79: pmegalloc(p) ! 80: register struct proc *p; /* process to allocate it for */ ! 81: { ! 82: register struct pmeg *pmp; ! 83: extern int potime; ! 84: ! 85: pmp = pmeghead.pm_forw; /* get pmeg off head of chain */ ! 86: if (pmp->pm_procp) ! 87: pmegrelease(pmp); ! 88: remque(pmp); ! 89: pmp->pm_procp = p; /* set process pointer */ ! 90: pmp->pm_count = 0; /* no valid pages yet */ ! 91: pmp->pm_seg = -1; /* no segments yet */ ! 92: pmp->pm_time = potime - 1; /* reset time */ ! 93: if (p) ! 94: insque(pmp, pmeghead.pm_back); /* put back on queue */ ! 95: else ! 96: pmp->pm_forw = pmp->pm_back = 0;/* wanted by kernel */ ! 97: ! 98: return ((u_char)(pmp - pmeg)); /* return index to pmeg in pmeg list */ ! 99: } ! 100: ! 101: /* ! 102: * Free a pmeg. ! 103: */ ! 104: pmegfree(pmx) ! 105: u_char pmx; /* index of pmeg in pmeg list */ ! 106: { ! 107: register struct pmeg *pmp = &pmeg[pmx]; ! 108: ! 109: if (pmp->pm_procp) /* is there a process with this one? */ ! 110: remque(pmp); /* take if off the queue its on */ ! 111: pmp->pm_procp = 0; /* reset process number */ ! 112: insque(pmp, &pmeghead); /* put back on free list */ ! 113: } ! 114: ! 115: /* ! 116: * Reserve named pmeg for use by kernel and monitor. ! 117: */ ! 118: pmegreserve(n) ! 119: u_char n; ! 120: { ! 121: register struct pmeg *pmp = &pmeg[n]; ! 122: ! 123: remque(pmp); ! 124: pmp->pm_forw = pmp->pm_back = 0; ! 125: pmp->pm_count = NPAGSEG; ! 126: pmp->pm_procp = (struct proc *)0; ! 127: pmp->pm_seg = 0; ! 128: kernpmeg++; ! 129: } ! 130: ! 131: /* ! 132: * Allocate and reserve kernel pmeg ! 133: */ ! 134: u_char ! 135: pmegallocres() ! 136: { ! 137: struct pmeg *pmp; ! 138: u_char pm; ! 139: ! 140: pmp = pmeghead.pm_forw; ! 141: if (pmp->pm_procp) ! 142: pmegrelease(pmp); ! 143: pm = (u_char)(pmp - pmeg); ! 144: pmegreserve(pm); ! 145: return (pm); ! 146: } ! 147: ! 148: /* ! 149: * Load all hardware page map entries for the specified ! 150: * pmeg from the software page table entries. ! 151: */ ! 152: pmegload(seg, need) ! 153: int seg; /* segment we are loading */ ! 154: int need; /* need a segment */ ! 155: { ! 156: register struct pte *pte; ! 157: register struct pmeg *pmp; ! 158: register int v, num, k, new = 0; ! 159: register int i; ! 160: register struct proc *p = u.u_procp; ! 161: int pm, last, tse, dse, sss; ! 162: struct context *cp = p->p_ctx; /* process context number */ ! 163: u_char *pmxp = &cp->ctx_pmeg[seg]; /* which segments pmeg */ ! 164: int s = splimp(); ! 165: ! 166: if (getcontext() == KCONTEXT) { ! 167: printf("NO CONTEXT IN PMEGLOAD\n"); ! 168: (void) splx(s); ! 169: return; ! 170: } ! 171: if (*pmxp == 0) { /* is there a pmeg already */ ! 172: if (!need) { ! 173: setsegmap((u_int)seg, (u_char)SEGINV); ! 174: (void) splx(s); ! 175: return; ! 176: } ! 177: *pmxp = pmegalloc(p); /* get one */ ! 178: pmeg[*pmxp].pm_seg = seg; /* assign it in context */ ! 179: new = 1; ! 180: } ! 181: pmp = &pmeg[*pmxp]; /* get pointer to pmeg */ ! 182: if (pmp->pm_procp != p) /* better be same process */ ! 183: panic("dup alloc pmeg"); ! 184: if (pmp->pm_seg != seg) /* better be same segment */ ! 185: panic("pmeg changed seg"); ! 186: pm = pmp - pmeg; /* make pmeg index based on pmeg addr */ ! 187: v = seg * NPAGSEG; /* make index based on segment number */ ! 188: /* ! 189: * Decide which of the text|data|stack ! 190: * segments the virtual segment seg is in. ! 191: * ! 192: * Lots of assumptions about the layout ! 193: * of virtual memory here. Should be ! 194: * more parameterized. ! 195: */ ! 196: last = ptos(btop(USRSTACK)); /* find bottom of user stack seg */ ! 197: /* find end of text segment */ ! 198: tse = p->p_tsize ? ptos(tptov(p, 0) + p->p_tsize - 1) : 0; ! 199: /* find end of data segment */ ! 200: dse = ptos(dptov(p, 0) + p->p_dsize - 1); ! 201: /* compute start of stack segment */ ! 202: sss = last - ptos(p->p_ssize + NPAGSEG - 1); ! 203: ! 204: setsegmap((u_int)seg, (u_char)pm); /* set the seg map */ ! 205: if (seg <= tse) { ! 206: if (seg == 0) { ! 207: setpgmap((caddr_t)0, (long)0);/* first page invalid */ ! 208: v = LOWPAGES; /* set addr in map */ ! 209: num = MIN((p->p_tsize ? p->p_tsize : p->p_dsize), ! 210: NPAGSEG - LOWPAGES); ! 211: i = 0; ! 212: } else { ! 213: i = v - tptov(p, 0); /* compute index in text */ ! 214: num = MIN(p->p_tsize - i, NPAGSEG); ! 215: } ! 216: pte = tptopte(p, i); /* get pointer ptes */ ! 217: pmp->pm_pte = pte; ! 218: pmp->pm_count = num; ! 219: for (k = num; k--; v++, pte++) ! 220: loadpgmap((u_int)v, pte, new); ! 221: for (k = NPAGSEG - num - ((seg == 0)? LOWPAGES : 0); k--; v++) ! 222: setpgmap((caddr_t)ctob(v), (long)0); ! 223: if (seg > cp->ctx_tdmax) ! 224: cp->ctx_tdmax = seg; ! 225: } else if (seg > tse && seg <= dse) { ! 226: i = v - dptov(p, 0); /* compute index in data */ ! 227: pte = dptopte(p, i); /* get pointer ptes */ ! 228: num = MIN(p->p_dsize - i, NPAGSEG); ! 229: pmp->pm_pte = pte; ! 230: pmp->pm_count = num; ! 231: for (k = num; k--; v++, pte++) ! 232: loadpgmap((u_int)v, pte, new); ! 233: for (k = NPAGSEG - num; k--; v++) ! 234: setpgmap((caddr_t)ctob(v), (long)0); ! 235: if (seg > cp->ctx_tdmax) ! 236: cp->ctx_tdmax = seg; ! 237: } else if (seg >= sss && seg < last) { ! 238: i = btop(USRSTACK)-NPAGSEG - v; /* compute index in stack */ ! 239: pte = sptopte(p, i); /* get pointer ptes */ ! 240: num = MIN(p->p_ssize - i, NPAGSEG); ! 241: pte -= num - 1; ! 242: pmp->pm_pte = pte; ! 243: pmp->pm_count = -num; ! 244: for (k = NPAGSEG - num; k--; v++) ! 245: setpgmap((caddr_t)ctob(v), (long)0); ! 246: for (k = num; k--; v++, pte++) ! 247: loadpgmap((u_int)v, pte, new); ! 248: if (seg < cp->ctx_smin) ! 249: cp->ctx_smin = seg; ! 250: } else { ! 251: if (need) ! 252: panic("need pmeg in hole"); ! 253: pmegfree(*pmxp); ! 254: *pmxp = 0; ! 255: setsegmap((u_int)seg, (u_char)SEGINV); ! 256: } ! 257: (void) splx(s); ! 258: } ! 259: ! 260: /* ! 261: * Unload bits for specified pmeg. ! 262: */ ! 263: pmegunload(pmp) ! 264: register struct pmeg *pmp; /* pointer to pmeg */ ! 265: { ! 266: register struct pte *pte; ! 267: register int num, k, v; ! 268: ! 269: if (pmp->pm_procp == 0) ! 270: panic("pmegunload"); ! 271: setsegmap(CSEG, (u_char)(pmp - pmeg)); ! 272: v = NPAGSEG * CSEG; ! 273: num = pmp->pm_count; ! 274: pte = pmp->pm_pte; ! 275: if (num < 0) { ! 276: num = -num; ! 277: v += NPAGSEG - num; ! 278: } ! 279: if (pmp->pm_seg == 0) /* special case seg zero */ ! 280: v += LOWPAGES; ! 281: for (k = num; k--; v++, pte++) ! 282: unloadpgmap((u_int)v, pte); ! 283: setsegmap(CSEG, (u_char)SEGINV); ! 284: } ! 285: ! 286: /* ! 287: * Get referenced and modified bits for ! 288: * the pmeg containing page v. Called ! 289: * only by pageout. ! 290: */ ! 291: ptesync(p, v) ! 292: register struct proc *p; ! 293: register unsigned v; ! 294: { ! 295: register struct context *cp; ! 296: register struct pmeg *pmp; ! 297: register int pm, s; ! 298: ! 299: s = splimp(); ! 300: if ((cp = p->p_ctx) == NULL) ! 301: goto out; ! 302: if ((pm = cp->ctx_pmeg[ptos(v)]) == 0) ! 303: goto out; ! 304: pmp = &pmeg[pm]; ! 305: if (pmp->pm_procp != p) ! 306: panic("ptesync procp"); ! 307: if (pmp->pm_time != potime) { /* check mod time, done? */ ! 308: pmegunload(pmp); ! 309: pmp->pm_time = potime; ! 310: } ! 311: out: ! 312: (void) splx(s); ! 313: } ! 314: ! 315: /* ! 316: * get a kernel page map entry given an address ! 317: */ ! 318: getkpgmap(addr) ! 319: caddr_t addr; ! 320: { ! 321: ! 322: return ((int)getpgmap(addr)); ! 323: } ! 324: ! 325: /* ! 326: * Initialize the context structures. ! 327: */ ! 328: ctxinit() ! 329: { ! 330: register int i; ! 331: ! 332: for (i = 0; i < NCONTEXT; i++) { ! 333: if (i == KCONTEXT) ! 334: continue; ! 335: context[i].ctx_context = i; ! 336: } ! 337: } ! 338: ! 339: /* ! 340: * Allocate a context and corresponding ! 341: * page map entries for the current process. ! 342: * If no free context must take one away ! 343: * from someone. ! 344: */ ! 345: ctxalloc() ! 346: { ! 347: register struct proc *p = u.u_procp; /* process this is for */ ! 348: register struct context *cp, *scp = 0; ! 349: register int ct, i; ! 350: ! 351: /* find a free context or an old one */ ! 352: for (cp = context; cp < &context[NCONTEXT]; cp++) { ! 353: if (cp == &context[KCONTEXT]) ! 354: continue; ! 355: if (cp->ctx_procp == 0) /* if no process use this one */ ! 356: goto found; ! 357: if (scp == 0) { /* otherwise find the oldest */ ! 358: scp = cp; ! 359: ct = cp->ctx_time; ! 360: } else if (cp->ctx_time <= ct) { ! 361: scp = cp; ! 362: ct = cp->ctx_time; ! 363: } ! 364: } ! 365: cp = scp; /* reset pointer to save context pointer */ ! 366: if (cp->ctx_procp) /* if in use free it up before using */ ! 367: ctxfree(cp->ctx_procp); ! 368: found: ! 369: p->p_ctx = cp; /* set context pointer in proc entry */ ! 370: cp->ctx_procp = p; /* set proc pointer in context table */ ! 371: cp->ctx_time = ctxtime++; ! 372: setcontext((int)cp->ctx_context); ! 373: for (i = 0; i <= cp->ctx_tdmax; i++) ! 374: setsegmap((u_int)i, (u_char)SEGINV); ! 375: for (i = cp->ctx_smin; i < ptos(btop(USRSTACK)); i++) ! 376: setsegmap((u_int)i, (u_char)SEGINV); ! 377: cp->ctx_tdmax = 0; ! 378: cp->ctx_smin = (ptos(btop(USRSTACK))); ! 379: p->p_flag &= ~SPTECHG; ! 380: } ! 381: ! 382: /* ! 383: * Free the context and page map entries ! 384: * of the specified process. ! 385: */ ! 386: ctxfree(p) ! 387: register struct proc *p; ! 388: { ! 389: register struct context *cp; ! 390: register u_char *pmxp; ! 391: register int s; ! 392: ! 393: if ((cp = p->p_ctx) == 0) /* no context */ ! 394: return; ! 395: if (p != cp->ctx_procp) /* not the same process */ ! 396: panic("ctxfree"); ! 397: if ((p->p_flag&SWEXIT) == 0) /* don't bother if dieing */ ! 398: ctxunload(p); ! 399: s = splimp(); ! 400: ! 401: /* free the pmegs for this context */ ! 402: for (pmxp = cp->ctx_pmeg; pmxp < &cp->ctx_pmeg[ptos(btop(USRSTACK))]; ! 403: pmxp++) { ! 404: if (*pmxp) { /* is there a pmeg for this segment */ ! 405: pmegfree(*pmxp); ! 406: *pmxp = 0; ! 407: } ! 408: } ! 409: (void) splx(s); /* back to normal */ ! 410: setcontext(KCONTEXT); /* paranoid */ ! 411: cp->ctx_procp = 0; /* reset proc pointer */ ! 412: p->p_ctx = 0; /* reset context pointer */ ! 413: } ! 414: ! 415: /* ! 416: * Set up the segment and page map entries for ! 417: * the current process. ! 418: */ ! 419: ctxsetup() ! 420: { ! 421: register int i; ! 422: register int last = ptos(btop(USRSTACK)); /* last segment */ ! 423: register struct context *cp = u.u_procp->p_ctx; ! 424: ! 425: /* ! 426: * Initialize all segments. ! 427: */ ! 428: for (i = 0; i <= cp->ctx_tdmax; i++) /* load pmegs for text/data */ ! 429: pmegload(i, 0); ! 430: for (i = cp->ctx_smin; i < last; i++) /* load pmegs for stack */ ! 431: pmegload(i, 0); ! 432: ! 433: u.u_procp->p_flag &= ~SPTECHG; ! 434: } ! 435: ! 436: /* ! 437: * Unload the referenced and modified bits ! 438: * for the specified process. ! 439: */ ! 440: ctxunload(p) ! 441: struct proc *p; ! 442: { ! 443: register int last = ptos(btop(USRSTACK)); /* last segment */ ! 444: register int i, s = splimp(); ! 445: register u_char *pmxp; ! 446: ! 447: /* ! 448: * Unload bits from all allocated pmegs. ! 449: */ ! 450: pmxp = p->p_ctx->ctx_pmeg; /* get pointer to pte's */ ! 451: for (i = 0; i < last; i++, pmxp++) ! 452: if (*pmxp) /* is it set */ ! 453: pmegunload(&pmeg[*pmxp]); ! 454: (void) splx(s); ! 455: } ! 456: ! 457: /* ! 458: * Pass all resources associated with a context ! 459: * from process p to process q. Used by vfork. ! 460: */ ! 461: ctxpass(p, q) ! 462: register struct proc *p, *q; ! 463: { ! 464: register struct context *cp = p->p_ctx; ! 465: register u_char *pmxp; ! 466: register int last = ptos(btop(USRSTACK)); /* last segment */ ! 467: register int i; ! 468: ! 469: if (cp == 0) ! 470: return; ! 471: /* ! 472: * Pass the context from p to q. ! 473: */ ! 474: q->p_ctx = cp; /* q gets p's context */ ! 475: p->p_ctx = 0; /* p loses the context */ ! 476: cp->ctx_procp = q; /* context get q's proc id */ ! 477: q->p_flag |= SPTECHG; /* conservative */ ! 478: setcontext(KCONTEXT); /* paranoid */ ! 479: ! 480: /* ! 481: * Change all pmegs to refer to q. ! 482: */ ! 483: pmxp = cp->ctx_pmeg; ! 484: for (i = 0; i < last; i++, pmxp++) ! 485: if (*pmxp) ! 486: pmeg[*pmxp].pm_procp = q; ! 487: } ! 488: ! 489: /* ! 490: * Handle a page fault on a 68020. ! 491: */ ! 492: pagefault(accaddr) ! 493: register int accaddr; ! 494: { ! 495: register struct proc *p = u.u_procp; ! 496: register int v = btop(accaddr); ! 497: struct pte *addrtopte(); ! 498: int i, seg; ! 499: int s; ! 500: ! 501: /* ! 502: * If user has no context, allocate one for him. ! 503: */ ! 504: if (getcontext() == KCONTEXT) { ! 505: usetup(); ! 506: return (1); ! 507: } ! 508: ! 509: if (addrtopte((caddr_t)accaddr, 1) == NULL) ! 510: return (0); ! 511: ! 512: seg = ptos(v); ! 513: if (p->p_ctx->ctx_pmeg[seg]) { ! 514: if (getpgmap((caddr_t)accaddr) & PG_V) ! 515: return (0); ! 516: i = u.u_error; ! 517: pagein((u_int)accaddr, &u, 0); ! 518: u.u_error = i; ! 519: } ! 520: s = splimp(); ! 521: if (p->p_ctx && p->p_ctx->ctx_pmeg[seg] == 0) ! 522: pmegload(seg, 1); ! 523: (void) splx(s); ! 524: return (1); ! 525: } ! 526: ! 527: /* ! 528: * Set up everything the user program might need. ! 529: * If we need a context, allocate it. If we need ! 530: * to set up hardware segment and page maps, do it. ! 531: */ ! 532: usetup() ! 533: { ! 534: register struct proc *p = u.u_procp; ! 535: ! 536: if (p->p_ctx == 0) /* do we need a context */ ! 537: ctxalloc(); ! 538: else { ! 539: p->p_ctx->ctx_time = ctxtime++; /* update time */ ! 540: setcontext((int)p->p_ctx->ctx_context); /* set to user */ ! 541: if (p->p_flag & SPTECHG) /* are we changing? */ ! 542: ctxsetup(); ! 543: } ! 544: } ! 545: ! 546: /* ! 547: * Set a red zone below the kernel stack. ! 548: * NO LONGER USED, startup() SETS THE REDZONE. ! 549: */ ! 550: /*ARGSUSED*/ ! 551: setredzone(pte, vaddr) ! 552: struct pte *pte; ! 553: caddr_t vaddr; ! 554: { ! 555: } ! 556: ! 557: /* ! 558: * Map a physical address range into kernel virtual addresses. ! 559: * Since the kernel appears in all contexts any new pmegs are ! 560: * mapped in all contexts. ! 561: */ ! 562: mapin(ppte, v, paddr, size, access) ! 563: register struct pte *ppte; /* pointer to pte's */ ! 564: u_int v; /* page number to map in */ ! 565: register u_int paddr; /* physical address */ ! 566: register int size, access; /* size in pages and access rights */ ! 567: { ! 568: register caddr_t vaddr = (caddr_t)ctob(v); ! 569: register u_char pm; ! 570: register int c, i; ! 571: int s = splimp(); ! 572: ! 573: while (size--) { ! 574: if ((pm = getsegmap((u_int)ptos(v))) == SEGINV) { ! 575: caddr_t va, vs; ! 576: ! 577: pm = pmegalloc((struct proc *)0); ! 578: kernpmeg++; ! 579: c = getcontext(); ! 580: /* need to map in new seg across all contexts */ ! 581: for (i = 0; i < NCONTEXT; i++) { ! 582: setcontext(i); ! 583: setsegmap(ptos(v), pm); ! 584: } ! 585: setcontext(c); ! 586: vs = (caddr_t)(ptos(v)<<SGSHIFT); ! 587: for (va = vs; va < vs + NBSG; va += NBPG) ! 588: setpgmap(va, (long)0); ! 589: } ! 590: /* ! 591: * Increment count of number of pme's used in this pmeg. ! 592: * Allow it to go one past the number of pme's in a pmeg; ! 593: * this indicates someone is doing a mapin without ! 594: * corresponding mapout's and will be noticed in mapout ! 595: * who will prevent the reference count from changing. ! 596: */ ! 597: if (pmeg[pm].pm_count <= NPAGSEG) ! 598: pmeg[pm].pm_count++; ! 599: *((int *)ppte) = (paddr & PG_PFNUM) | access; ! 600: setpgmap(vaddr, *(long *)ppte); ! 601: ppte++; ! 602: paddr++; ! 603: v++; ! 604: vaddr += NBPG; ! 605: } ! 606: (void) splx(s); ! 607: } ! 608: ! 609: /* ! 610: * Release mapping for kernel. ! 611: * This frees pmegs, which are the most critical resource. ! 612: * Since the kernel appears in all contexts the pmeg has to be mapped ! 613: * out for all contexts. Assumes that ppte is a pointer ! 614: * to a pte within Sysmap. ! 615: */ ! 616: mapout(ppte, size) ! 617: register struct pte *ppte; ! 618: { ! 619: register int vaddr = ctob(ppte - Sysmap) + KERNELBASE; ! 620: register u_char pm; ! 621: register int c, i; ! 622: int s = splimp(); ! 623: ! 624: while (size--) { ! 625: if (!ppte->pg_v) ! 626: panic("mapout: invalid pte"); ! 627: ppte->pg_v = 0; ! 628: if ((pm = getsegmap((u_int)ptos(btop(vaddr)))) == SEGINV) ! 629: panic("mapout: invalid segment"); ! 630: if ((getpgmap((caddr_t)vaddr)&PG_V) == 0) ! 631: panic("mapout: invalid page"); ! 632: if (pmeg[pm].pm_count <= 0) ! 633: panic("mapout: pmeg count"); ! 634: setpgmap((caddr_t)vaddr, (long)0); ! 635: if (pmeg[pm].pm_count <= NPAGSEG) ! 636: if (--pmeg[pm].pm_count == 0) { /* done with all ptes */ ! 637: c = getcontext(); ! 638: /* need to map out seg across all contexts */ ! 639: for (i = 0; i < NCONTEXT; i++) { ! 640: setcontext(i); ! 641: setsegmap((u_int)ptos(btop(vaddr)), ! 642: (u_char)SEGINV); ! 643: } ! 644: setcontext(c); /* reset context */ ! 645: pmegfree(pm); ! 646: kernpmeg--; ! 647: } ! 648: ppte++; /* do next pte */ ! 649: vaddr += NBPG; ! 650: } ! 651: (void) splx(s); ! 652: } ! 653: ! 654: /* ! 655: * Check user accessibility to a given address. ! 656: */ ! 657: useracc(vaddr, count, access) ! 658: caddr_t vaddr; ! 659: u_int count; ! 660: int access; ! 661: { ! 662: register struct pte *pte; ! 663: struct pte *addrtopte(); ! 664: ! 665: pte = addrtopte(vaddr, count); ! 666: if (pte == NULL) ! 667: return (0); ! 668: ! 669: count = btop((int)(vaddr + count - 1)) - btop((int)vaddr) + 1; ! 670: access = access == B_READ ? 0 : PG_W; ! 671: while (count--) { ! 672: if (((*(int *)pte) & PG_S) || ! 673: (((*(int *)pte) & PG_W)) < access) ! 674: return (0); ! 675: pte++; ! 676: } ! 677: return (1); ! 678: } ! 679: ! 680: /* ! 681: * Check kernel accessibility to a given address. ! 682: * Unlike the vax, vaddr is checked against the range of Sysmap only! ! 683: */ ! 684: kernacc(vaddr, count, access) ! 685: caddr_t vaddr; ! 686: u_int count; ! 687: int access; ! 688: { ! 689: register struct pte *ppte = &Sysmap[btop((int)vaddr - KERNELBASE)]; ! 690: extern struct pte ESysmap[]; ! 691: ! 692: count = btoc((int)vaddr + count) - btop(vaddr); ! 693: if (ppte + count > ESysmap || ppte < Sysmap) ! 694: return (0); ! 695: access = access == B_READ ? 0 : PG_W; ! 696: while (count--) { ! 697: if (!ppte->pg_v || ((((*(int *)ppte) & PG_W)) < access)) ! 698: return (0); ! 699: ppte++; ! 700: } ! 701: return (1); ! 702: } ! 703: ! 704: /* ! 705: * Check for valid program size ! 706: */ ! 707: chksize(ts, ds, ss) ! 708: unsigned ts, ds, ss; ! 709: { ! 710: static int maxdmap = 0; ! 711: ! 712: if (ts > MAXTSIZ || ds > MAXDSIZ || ss > MAXSSIZ) { ! 713: u.u_error = ENOMEM; ! 714: return (1); ! 715: } ! 716: /* check for swap map overflow */ ! 717: if (maxdmap == 0) { ! 718: register int i, blk; ! 719: ! 720: blk = DMMIN; ! 721: for (i = 0; i < NDMAP; i++) { ! 722: maxdmap += blk; ! 723: if (blk < DMMAX) ! 724: blk *= 2; ! 725: } ! 726: } ! 727: if (ctod(ts) > NXDAD*DMTEXT || ! 728: ctod(ds) > maxdmap || ctod(ss) > maxdmap) { ! 729: u.u_error = ENOMEM; ! 730: return (1); ! 731: } ! 732: /* ! 733: * Make sure the process isn't bigger than our ! 734: * virtual memory limit. ! 735: * ! 736: * THERE SHOULD BE A CONSTANT FOR THIS. ! 737: */ ! 738: if (ctos(ts + LOWPAGES) + ctos(ds) + ctos(ss + HIGHPAGES) > ! 739: ctos(btop(USRSTACK))) { ! 740: u.u_error = ENOMEM; ! 741: return (1); ! 742: } ! 743: return (0); ! 744: } ! 745: ! 746: /* ! 747: * Change the translation for the current proc ! 748: * to reflect the change made in software ptes ! 749: * starting at ppte for size ptes. ! 750: */ ! 751: newptes(ppte, v, size) ! 752: register struct pte *ppte; ! 753: u_int v; ! 754: int size; ! 755: { ! 756: register int i, fs, ls, need; ! 757: ! 758: if (getcontext() == KCONTEXT) { ! 759: if (u.u_procp->p_ctx) ! 760: usetup(); ! 761: else ! 762: return; ! 763: } ! 764: fs = ptos(v); /* convert page pointer for 1st seg */ ! 765: ls = ptos(v + size - 1); /* convert page pointer for last seg */ ! 766: need = ppte->pg_v; ! 767: for (i = fs; i <= ls; i++) /* go through list and set ptes */ ! 768: pmegload(i, need); ! 769: } ! 770: ! 771: /* ! 772: * Move pages from one kernel virtual address to another. ! 773: * Both addresses are assumed to reside in the Sysmap, ! 774: * and size must be a multiple of CLSIZE. ! 775: */ ! 776: pagemove(from, to, size) ! 777: register caddr_t from, to; ! 778: int size; ! 779: { ! 780: register struct pte *fpte, *tpte; ! 781: ! 782: if (size % CLBYTES) ! 783: panic("pagemove"); ! 784: fpte = &Sysmap[btop((int)from - KERNELBASE)]; ! 785: tpte = &Sysmap[btop((int)to - KERNELBASE)]; ! 786: while (size > 0) { ! 787: *tpte++ = *fpte; ! 788: setpgmap(to, *(long *)fpte); ! 789: *(int *)fpte++ = 0; ! 790: setpgmap(from, (long)0); ! 791: from += NBPG; ! 792: to += NBPG; ! 793: size -= NBPG; ! 794: } ! 795: } ! 796: ! 797: /* ! 798: * Check the validity of a user address range and return NULL ! 799: * on error or a pointer to the first pte for these addresses. ! 800: */ ! 801: struct pte * ! 802: addrtopte(vaddr, count) ! 803: caddr_t vaddr; ! 804: u_int count; ! 805: { ! 806: register struct proc *p = u.u_procp; ! 807: register int fv, lv; ! 808: int tss, dss, sss; ! 809: ! 810: fv = btop((int)vaddr); ! 811: lv = btop((int)(vaddr + count - 1)); ! 812: ! 813: if (lv < fv || fv < btop(USRTEXT) || lv >= btop(USRSTACK)) ! 814: return (NULL); ! 815: ! 816: /* ! 817: * Check that the request was within the ! 818: * user's valid address space. Can't use ! 819: * isa[tds]sv because they don't check the holes. ! 820: */ ! 821: tss = tptov(p, 0); ! 822: dss = dptov(p, 0); ! 823: sss = sptov(p, p->p_ssize - 1); ! 824: ! 825: if (fv >= tss && lv < tss + p->p_tsize) ! 826: return (tptopte(p, vtotp(p, fv))); ! 827: else if (fv >= dss && lv < dss + p->p_dsize) ! 828: return (dptopte(p, vtodp(p, fv))); ! 829: else if (fv >= sss && lv < sss + p->p_ssize) ! 830: return (sptopte(p, vtosp(p, fv))); ! 831: ! 832: return (NULL); ! 833: } ! 834: ! 835: #define ONBPG 2048 /* old page size */ ! 836: #define ONBSG 32768 /* old segment size */ ! 837: ! 838: /* ! 839: * Routine used to check to see if an a.out can be executed ! 840: * by the current machine/architecture. ! 841: */ ! 842: chkaout() ! 843: { ! 844: ! 845: if ((u.u_exdata.ux_mach == M_68010) || ! 846: (u.u_exdata.ux_mach == M_68020)) ! 847: return (0); ! 848: else ! 849: return (ENOEXEC); ! 850: } ! 851: ! 852: /* ! 853: * The following functions return information about an a.out ! 854: * which is used when a program is executed. ! 855: */ ! 856: ! 857: /* ! 858: * Return the size of the text segment adjusted for the type of a.out. ! 859: */ ! 860: size_t ! 861: getts() ! 862: { ! 863: return (clrnd(btoc(u.u_exdata.ux_tsize))); ! 864: } ! 865: ! 866: /* ! 867: * Return the size of the data segment depending on the type of a.out. ! 868: * For the case of an old a.out we need to allow for the old segment ! 869: * alignment and the fact that the text segment starts at 32k and not 8k. ! 870: * To do this we calculate the size of the text segment and round ! 871: * it to the next old Sun-2 segment boundary. ! 872: */ ! 873: size_t ! 874: getds() ! 875: { ! 876: ! 877: return (clrnd(btoc(u.u_exdata.ux_dsize + u.u_exdata.ux_bsize))); ! 878: } ! 879: ! 880: /* ! 881: * Return the load memory address for the data segment. ! 882: */ ! 883: caddr_t ! 884: getdmem() ! 885: { ! 886: ! 887: return ((caddr_t)ctob(dptov(u.u_procp, 0))); ! 888: } ! 889: ! 890: /* ! 891: * Return the starting disk address for the data segment. ! 892: */ ! 893: getdfile() ! 894: { ! 895: ! 896: if (u.u_exdata.ux_mag == ZMAGIC) ! 897: return (u.u_exdata.ux_tsize); ! 898: else ! 899: return (sizeof (u.u_exdata) + u.u_exdata.ux_tsize); ! 900: } ! 901: ! 902: /* ! 903: * Return the load memory address for the text segment. ! 904: */ ! 905: caddr_t ! 906: gettmem() ! 907: { ! 908: ! 909: return ((caddr_t)USRTEXT); ! 910: } ! 911: ! 912: /* ! 913: * Return the file byte offset for the text segment. ! 914: */ ! 915: gettfile() ! 916: { ! 917: ! 918: if (u.u_exdata.ux_mag == ZMAGIC) ! 919: return (0); ! 920: else ! 921: return (sizeof (u.u_exdata)); ! 922: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.