|
|
1.1 ! root 1: /* vmproc.c 4.5 81/03/08 */ ! 2: ! 3: #include "sys/param.h" ! 4: #include "sys/systm.h" ! 5: #include "sys/user.h" ! 6: #include "sys/proc.h" ! 7: #include "sys/mtpr.h" ! 8: #include "sys/pte.h" ! 9: #include "sys/map.h" ! 10: #include "sys/cmap.h" ! 11: #include "sys/text.h" ! 12: #include "sys/inode.h" ! 13: #include "sys/vm.h" ! 14: ! 15: struct pte *Forkmap; ! 16: struct user *forkutl; ! 17: ! 18: struct dmap zdmap; /* well, it has to be somewhere */ ! 19: ! 20: /* ! 21: * Get virtual memory resources for a new process. ! 22: * Called after page tables are allocated, but before they ! 23: * are initialized, we initialize the memory management registers, ! 24: * and then expand the page tables for the data and stack segments ! 25: * creating zero fill pte's there. Text pte's are set up elsewhere. ! 26: * ! 27: * SHOULD FREE EXTRA PAGE TABLE PAGES HERE OR SOMEWHERE. ! 28: */ ! 29: vgetvm(ts, ds, ss) ! 30: clicks_t ts, ds, ss; ! 31: { ! 32: ! 33: mtpr(P0LR, ts); ! 34: u.u_pcb.pcb_p0lr = ts | AST_NONE; ! 35: mtpr(P1LR, P1TOP - UPAGES); ! 36: u.u_pcb.pcb_p1lr = P1TOP - UPAGES; ! 37: u.u_procp->p_tsize = ts; ! 38: u.u_tsize = ts; ! 39: expand((int)ss, P1BR); ! 40: expand((int)ds, P0BR); ! 41: } ! 42: ! 43: /* ! 44: * Release the virtual memory resources (memory ! 45: * pages, and swap area) associated with the current process. ! 46: * Caller must not be swappable. Used at exit or execl. ! 47: */ ! 48: vrelvm() ! 49: { ! 50: register struct proc *p = u.u_procp; ! 51: ! 52: /* ! 53: * Release memory; text first, then data and stack pages. ! 54: */ ! 55: xfree(); ! 56: p->p_rssize -= vmemfree(dptopte(p, 0), p->p_dsize); ! 57: p->p_rssize -= vmemfree(sptopte(p, p->p_ssize - 1), p->p_ssize); ! 58: if (p->p_rssize != 0) ! 59: panic("vrelvm rss"); ! 60: /* ! 61: * Wait for all page outs to complete, then ! 62: * release swap space. ! 63: */ ! 64: p->p_swrss = 0; ! 65: while (p->p_poip) ! 66: sleep((caddr_t)&p->p_poip, PSWP+1); ! 67: (void) vsexpand((clicks_t)0, &u.u_dmap, 1); ! 68: (void) vsexpand((clicks_t)0, &u.u_smap, 1); ! 69: p->p_tsize = 0; ! 70: p->p_dsize = 0; ! 71: p->p_ssize = 0; ! 72: u.u_tsize = 0; ! 73: u.u_dsize = 0; ! 74: u.u_ssize = 0; ! 75: } ! 76: ! 77: /* ! 78: * Change the size of the data+stack regions of the process. ! 79: * If the size is shrinking, it's easy-- just release virtual memory. ! 80: * If it's growing, initalize new page table entries as ! 81: * 'zero fill on demand' pages. ! 82: */ ! 83: expand(change, region) ! 84: { ! 85: register struct proc *p; ! 86: register struct pte *base, *p0, *p1; ! 87: struct pte proto; ! 88: int a0, a1; ! 89: ! 90: p = u.u_procp; ! 91: if (change == 0) ! 92: return; ! 93: if (change % CLSIZE) ! 94: panic("expand"); ! 95: #ifdef PGINPROF ! 96: vmsizmon(); ! 97: #endif ! 98: /* ! 99: * Update the sizes to reflect the change. Note that we may ! 100: * swap as a result of a ptexpand, but this will work, because ! 101: * the routines which swap out will get the current text and data ! 102: * sizes from the arguments they are passed, and when the process ! 103: * resumes the lengths in the proc structure are used to ! 104: * build the new page tables. ! 105: */ ! 106: if (region == P0BR) { ! 107: p->p_dsize += change; ! 108: u.u_dsize += change; ! 109: } else { ! 110: p->p_ssize += change; ! 111: u.u_ssize += change; ! 112: } ! 113: /* ! 114: * Compute the end of the text+data regions and the beginning ! 115: * of the stack region in the page tables, ! 116: * and expand the page tables if necessary. ! 117: */ ! 118: p0 = (struct pte *)mfpr(P0BR) + mfpr(P0LR); ! 119: p1 = (struct pte *)mfpr(P1BR) + mfpr(P1LR); ! 120: if (change > p1 - p0) ! 121: ptexpand(clrnd(ctopt(change - (p1 - p0)))); ! 122: /* PTEXPAND SHOULD GIVE BACK EXCESS PAGE TABLE PAGES */ ! 123: /* ! 124: * Compute the base of the allocated/freed region. ! 125: */ ! 126: if (region == P0BR) { ! 127: base = (struct pte *)mfpr(P0BR); ! 128: base += (a0 = mfpr(P0LR)) + (change > 0 ? 0 : change); ! 129: } else { ! 130: base = (struct pte *)mfpr(P1BR); ! 131: base += (a1 = mfpr(P1LR)) - (change > 0 ? change : 0); ! 132: } ! 133: ! 134: /* ! 135: * If we shrunk, give back the virtual memory. ! 136: */ ! 137: if (change < 0) ! 138: p->p_rssize -= vmemfree(base, -change); ! 139: ! 140: /* ! 141: * Update the processor length registers and copies in the pcb. ! 142: */ ! 143: if (region == P0BR) { ! 144: mtpr(P0LR, a0 + change); ! 145: u.u_pcb.pcb_p0lr = a0 + change | (u.u_pcb.pcb_p0lr & AST_CLR); ! 146: } else { ! 147: mtpr(P1LR, a1 - change); ! 148: u.u_pcb.pcb_p1lr = a1 - change; ! 149: } ! 150: *(int *)&proto = PG_UW; ! 151: if (change < 0) ! 152: change = -change; ! 153: else { ! 154: proto.pg_fod = 1; ! 155: ((struct fpte *)&proto)->pg_source = PG_FZERO; ! 156: cnt.v_nzfod += change; ! 157: } ! 158: while (--change >= 0) ! 159: *base++ = proto; ! 160: mtpr(TBIA,0); ! 161: } ! 162: ! 163: /* ! 164: * Create a duplicate copy of the current process ! 165: * in process slot p, which has been partially initialized ! 166: * by newproc(). ! 167: * ! 168: * Could deadlock here if two large proc's get page tables ! 169: * and then each gets part of his UPAGES if they then have ! 170: * consumed all the available memory. This can only happen when ! 171: * USRPTSIZE + UPAGES * NPROC > maxmem ! 172: * which happens only when large procs fork on machines with tiny real memories ! 173: */ ! 174: procdup(p) ! 175: register struct proc *p; ! 176: { ! 177: extern struct map kernelmap[]; ! 178: ! 179: /* ! 180: * allocate page tables and a user block; ! 181: * copy parent's user to child ! 182: */ ! 183: while (vgetpt(p, vmemall) == 0) { ! 184: kmapwnt++; ! 185: sleep((caddr_t)kernelmap, PSWP+4); ! 186: } ! 187: resume(pcbb(u.u_procp)); ! 188: (void) vgetu(p, vmemall, Forkmap, forkutl, &u); ! 189: /* ! 190: * child: return here when scheduled and returns 1 ! 191: */ ! 192: forkutl->u_pcb.pcb_sswap = u.u_ssav; ! 193: if (savectx(forkutl->u_ssav)) ! 194: return (1); ! 195: /* ! 196: * parent: ! 197: * finish setting up child: ! 198: * clear vm counters, attach text, copy data and stack ! 199: * return 0 ! 200: */ ! 201: forkutl->u_vm = zvms; ! 202: forkutl->u_cvm = zvms; ! 203: forkutl->u_dmap = u.u_cdmap; ! 204: forkutl->u_smap = u.u_csmap; ! 205: forkutl->u_outime = 0; ! 206: if (p->p_textp && ((p->p_textp->x_flag&XTRC) == 0 || vmxdup(p))) { ! 207: p->p_textp->x_count++; ! 208: xlink(p); ! 209: } ! 210: vmdup(p, dptopte(p, 0), dptov(p, 0), p->p_dsize, CDATA); ! 211: vmdup(p, sptopte(p, p->p_ssize - 1), sptov(p, p->p_ssize - 1), p->p_ssize, CSTACK); ! 212: return (0); ! 213: } ! 214: ! 215: /* ! 216: * Duplicate text segment (cf. xalloc). ! 217: */ ! 218: vmxdup(p) ! 219: register struct proc *p; ! 220: { ! 221: register struct text *xp, *uxp; ! 222: register clicks_t ts; ! 223: ! 224: if ((uxp = u.u_procp->p_textp) == 0) ! 225: return 0; ! 226: ! 227: for (xp = text; xp < textNTEXT && xp->x_iptr; xp++) ! 228: /* void */ ; ! 229: if (xp >= textNTEXT) ! 230: return 1; ! 231: ! 232: xp->x_flag = XLOCK|XTRC|XLOAD; ! 233: xp->x_size = ts = uxp->x_size; ! 234: if (vsxalloc(xp) == NULL) ! 235: return 1; ! 236: ! 237: xp->x_count = 1; ! 238: xp->x_ccount = 0; ! 239: xp->x_rssize = 0; ! 240: (xp->x_iptr = uxp->x_iptr)->i_count++; ! 241: p->p_textp = xp; ! 242: xlink(p); ! 243: vmdup(p, tptopte(p, 0), tptov(p, 0), ts, CTEXT); ! 244: xp->x_flag |= XWRIT; ! 245: xp->x_flag &= ~XLOAD; ! 246: xunlock(xp); ! 247: ! 248: return 0; ! 249: } ! 250: ! 251: vmdup(p, pte, v, count, type) ! 252: struct proc *p; ! 253: register struct pte *pte; ! 254: register unsigned v; ! 255: register clicks_t count; ! 256: int type; ! 257: { ! 258: register struct pte *opte = vtopte(u.u_procp, v); ! 259: register int i; ! 260: ! 261: while (count != 0) { ! 262: count -= CLSIZE; ! 263: if (opte->pg_fod && type != CTEXT) { ! 264: v += CLSIZE; ! 265: for (i = 0; i < CLSIZE; i++) ! 266: *(int *)pte++ = *(int *)opte++; ! 267: continue; ! 268: } ! 269: opte += CLSIZE; ! 270: (void) vmemall(pte, CLSIZE, p, type); ! 271: if (type == CTEXT) ! 272: p->p_textp->x_rssize += CLSIZE; ! 273: else ! 274: p->p_rssize += CLSIZE; ! 275: for (i = 0; i < CLSIZE; i++) { ! 276: copyseg((caddr_t)ctob(v+i), (pte+i)->pg_pfnum); ! 277: *(int *)(pte+i) |= (type == CTEXT) ? ! 278: ((PG_V|PG_M) + PG_URKR) : ((PG_V|PG_M) + PG_UW); ! 279: } ! 280: v += CLSIZE; ! 281: munlock(pte->pg_pfnum); ! 282: pte += CLSIZE; ! 283: } ! 284: } ! 285: ! 286: /* ! 287: * Check that a process will not be too large. ! 288: */ ! 289: chksize(ts, ds, ss) ! 290: clicks_t ts, ds, ss; ! 291: { ! 292: ! 293: if (ts>maxtsize || ds>maxdsize || ss>maxssize) { ! 294: u.u_error = ENOMEM; ! 295: return(1); ! 296: } ! 297: return (0); ! 298: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.