|
|
1.1 root 1: /* vmpt.c 4.11 81/04/15 */
2:
3: #include "sys/param.h"
4: #include "sys/systm.h"
5: #include "sys/user.h"
6: #include "sys/proc.h"
7: #include "sys/map.h"
8: #include "sys/mtpr.h"
9: #include "sys/pte.h"
10: #include "sys/cmap.h"
11: #include "sys/vm.h"
12: #include "sys/buf.h"
13: #include "sys/text.h"
14:
15: extern struct map kernelmap[], swapmap[];
16:
17: /*
18: * Get page tables for process p. Allocator
19: * for memory is argument; process must be locked
20: * from swapping if vmemall is used; if memall is
21: * used, call will return w/o waiting for memory.
22: * In any case an error return results if no user
23: * page table space is available.
24: */
25: vgetpt(p, pmemall)
26: register struct proc *p;
27: int (*pmemall)();
28: {
29: register int a;
30: register int i;
31:
32: if (p->p_szpt == 0)
33: panic("vgetpt");
34: /*
35: * Allocate space in the kernel map for this process.
36: * Then allocate page table pages, and initialize the
37: * process' p0br and addr pointer to be the kernel
38: * virtual addresses of the base of the page tables and
39: * the pte for the process pcb (at the base of the u.).
40: */
41: a = rmalloc(kernelmap, p->p_szpt);
42: if (a == 0)
43: return (0);
44: if ((*pmemall)(&Usrptmap[a], p->p_szpt, p, CSYS) == 0) {
45: kmfree(p->p_szpt, a);
46: return (0);
47: }
48: p->p_p0br = kmxtob(a);
49: p->p_addr = uaddr(p);
50: /*
51: * Now validate the system page table entries for the
52: * user page table pages, flushing old translations
53: * for these kernel virtual addresses. Clear the new
54: * page table pages for clean post-mortems.
55: */
56: vmaccess(&Usrptmap[a], (caddr_t)p->p_p0br, p->p_szpt);
57: for (i = 0; i < p->p_szpt; i++)
58: clearseg(Usrptmap[a + i].pg_pfnum);
59: return (1);
60: }
61:
62: /*
63: * Initialize text portion of page table.
64: */
65: vinitpt(p)
66: struct proc *p;
67: {
68: register struct text *xp;
69: register struct proc *q;
70: register struct pte *pte;
71: register int i;
72: struct pte proto;
73:
74: xp = p->p_textp;
75: if (xp == 0)
76: return;
77: pte = tptopte(p, 0);
78: /*
79: * If there is another instance of same text in core
80: * then just copy page tables from other process.
81: */
82: if (q = xp->x_caddr) {
83: bcopy((caddr_t)tptopte(q, 0), (caddr_t)pte,
84: (unsigned) (sizeof(struct pte) * xp->x_size));
85: goto done;
86: }
87: /*
88: * Initialize text page tables, zfod if we are loading
89: * the text now; unless the process is demand loaded,
90: * this will suffice as the text will henceforth either be
91: * read from a file or demand paged in.
92: */
93: *(int *)&proto = PG_URKR;
94: if (xp->x_flag & XLOAD) {
95: proto.pg_fod = 1;
96: ((struct fpte *)&proto)->pg_source = PG_FZERO;
97: }
98: for (i = 0; i < xp->x_size; i++)
99: *pte++ = proto;
100: if ((xp->x_flag & XPAGI) == 0)
101: goto done;
102: /*
103: * Text is demand loaded. If process is not loaded (i.e. being
104: * swapped in) then retrieve page tables from swap area. Otherwise
105: * this is the first time and we must initialize the page tables
106: * from the blocks in the file system.
107: */
108: if (xp->x_flag & XLOAD)
109: vinifod((struct fpte *)tptopte(p, 0), xp->x_iptr,
110: (daddr_t)1, xp->x_size);
111: else
112: swap(p, xp->x_ptdaddr, (caddr_t)tptopte(p, 0),
113: xp->x_size * sizeof (struct pte), B_READ,
114: B_PAGET, swapdev, 0);
115: done:
116: /*
117: * In the case where we are overlaying ourself with new page
118: * table entries, old user-space translations should be flushed.
119: */
120: if (p == u.u_procp)
121: mtpr(TBIA, 0);
122: }
123:
124: /*
125: * Update the page tables of all processes linked
126: * to a particular text segment, by distributing
127: * dpte to the the text page at virtual frame v.
128: *
129: * Note that invalidation in the translation buffer for
130: * the current process is the responsibility of the caller.
131: */
132: distpte(xp, tp, dpte)
133: struct text *xp;
134: register clicks_t tp;
135: register struct pte *dpte;
136: {
137: register struct proc *p;
138: register struct pte *pte;
139: register int i;
140:
141: for (p = xp->x_caddr; p; p = p->p_xlink) {
142: pte = tptopte(p, tp);
143: if (pte != dpte)
144: for (i = 0; i < CLSIZE; i++)
145: pte[i] = dpte[i];
146: }
147: }
148:
149: /*
150: * Release page tables of process p.
151: */
152: vrelpt(p)
153: register struct proc *p;
154: {
155: register int a;
156:
157: if (p->p_szpt == 0)
158: return;
159: a = btokmx(p->p_p0br);
160: (void) vmemfree(&Usrptmap[a], p->p_szpt);
161: kmfree(p->p_szpt, a);
162: }
163:
164: /*
165: * Compute number of pages to be allocated to the u. area
166: * and data and stack area page tables, which are stored on the
167: * disk immediately after the u. area.
168: */
169: vusize(p)
170: register struct proc *p;
171: {
172: register int tsz = p->p_tsize / NPTEPG;
173:
174: /*
175: * We do not need page table space on the disk for page
176: * table pages wholly containing text. This is well
177: * understood in the code in vmswap.c.
178: */
179: return (clrnd(UPAGES +
180: clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES)) - tsz));
181: }
182:
183: /*
184: * Get u area for process p. If a old u area is given,
185: * then copy the new area from the old, else
186: * swap in as specified in the proc structure.
187: *
188: * Since argument map/newu is potentially shared
189: * when an old u. is provided we have to be careful not
190: * to block after beginning to use them in this case.
191: * (This is not true when called from swapin() with no old u.)
192: */
193: vgetu(p, palloc, map, newu, oldu)
194: register struct proc *p;
195: int (*palloc)();
196: register struct pte *map;
197: register struct user *newu;
198: struct user *oldu;
199: {
200: register int i;
201:
202: if ((*palloc)(p->p_addr, clrnd(UPAGES), p, CSYS) == 0)
203: return (0);
204: /*
205: * New u. pages are to be accessible in map/newu as well
206: * as in process p's virtual memory.
207: */
208: for (i = 0; i < UPAGES; i++) {
209: map[i] = p->p_addr[i];
210: *(int *)(p->p_addr + i) |= PG_URKW | PG_V;
211: }
212: setredzone(p->p_addr, (caddr_t)0);
213: vmaccess(map, (caddr_t)newu, UPAGES);
214: /*
215: * New u.'s come from forking or inswap.
216: */
217: if (oldu) {
218: bcopy((caddr_t)oldu, (caddr_t)newu, UPAGES * NBPG);
219: newu->u_procp = p;
220: } else { int tf = 0;
221: swap(p, p->p_swaddr, (caddr_t)0, ctob(UPAGES),
222: B_READ, B_UAREA, swapdev, 0);
223: /*if (newu->u_pcb.pcb_ssp != -1 || newu->u_pcb.pcb_esp != -1 ||
224: newu->u_tsize != p->p_tsize || newu->u_dsize != p->p_dsize ||
225: newu->u_ssize != p->p_ssize || newu->u_procp != p)
226: panic("vgetu");*/
227: if(newu->u_pcb.pcb_ssp != -1) tf |= 1;
228: if(newu->u_pcb.pcb_esp != -1) tf |= 2;
229: if(newu->u_tsize != p->p_tsize) tf |= 4;
230: if(newu->u_dsize != p->p_dsize) tf |= 8;
231: if(newu->u_ssize != p->p_ssize) tf |= 16;
232: if(newu->u_procp != p) tf |= 32;
233: if(tf) {
234: printf("vgetu %d ", tf);
235: panic("vgetu");
236: }
237: }
238: /*
239: * Initialize the pcb copies of the p0 and p1 region bases and
240: * software page table size from the information in the proc structure.
241: */
242: newu->u_pcb.pcb_p0br = p->p_p0br;
243: newu->u_pcb.pcb_p1br = p->p_p0br + p->p_szpt * NPTEPG - P1TOP;
244: newu->u_pcb.pcb_szpt = p->p_szpt;
245: return (1);
246: }
247:
248: /*
249: * Release swap space for a u. area.
250: */
251: vrelswu(p)
252: struct proc *p;
253: {
254:
255: rmfree(swapmap, ctod(vusize(p)), p->p_swaddr);
256: /* p->p_swaddr = 0; */ /* leave for post-mortems */
257: }
258:
259: /*
260: * Get swap space for a u. area.
261: */
262: vgetswu(p)
263: struct proc *p;
264: {
265:
266: p->p_swaddr = srmalloc(swapmap, ctod(vusize(p)));
267: return (p->p_swaddr);
268: }
269:
270: /*
271: * Release u. area, swapping it out if desired.
272: *
273: * Note: we run on the old u. after it is released into swtch(),
274: * and are safe because nothing can happen at interrupt time.
275: */
276: vrelu(p, swapu)
277: register struct proc *p;
278: {
279: register int i;
280: struct pte uu[UPAGES];
281:
282: if (swapu)
283: swap(p, p->p_swaddr, (caddr_t)0, ctob(UPAGES),
284: B_WRITE, B_UAREA, swapdev, 0);
285: for (i = 0; i < UPAGES; i++)
286: uu[i] = p->p_addr[i];
287: (void) vmemfree(uu, clrnd(UPAGES));
288: }
289:
290: #ifdef unneeded
291: int ptforceswap;
292: #endif
293: /*
294: * Expand a page table, assigning new kernel virtual
295: * space and copying the page table entries over both
296: * in the system map and as necessary in the user page table space.
297: */
298: ptexpand(change)
299: register int change;
300: {
301: register struct pte *p1, *p2;
302: register int i;
303: register int spages, ss = P1TOP - mfpr(P1LR);
304: register int kold = btokmx((struct pte *)mfpr(P0BR));
305: int knew, tdpages;
306: int szpt = u.u_pcb.pcb_szpt;
307: int s;
308:
309: if (change <= 0 || change % CLSIZE)
310: panic("ptexpand 1");
311: /*
312: * Change is the number of new page table pages needed.
313: * Kold is the old index in the kernelmap of the page tables.
314: * Allocate a new kernel map segment of size szpt+change for
315: * the page tables, and the new page table pages in the
316: * middle of this new region.
317: */
318: top:
319: if ((knew=rmalloc(kernelmap, szpt+change)) == 0)
320: goto bad;
321: spages = ss/NPTEPG;
322: tdpages = szpt - spages;
323: if (memall(&Usrptmap[knew+tdpages], change, u.u_procp, CSYS) == 0) {
324: kmfree(szpt+change, knew);
325: goto bad;
326: }
327: /*
328: * Spages pages of u.+stack page tables go over unchanged.
329: * Tdpages of text+data page table may contain a few stack
330: * pages which need to go in one of the newly allocated pages;
331: * this is a rough cut.
332: */
333: kmcopy(knew, kold, tdpages);
334: kmcopy(knew+tdpages+change, kold+tdpages, spages);
335:
336: /*
337: * Validate and clear the newly allocated page table pages in the
338: * center of the new region of the kernelmap.
339: * Then flush translation since we changed
340: * the kernel page tables.
341: */
342: i = knew + tdpages;
343: p1 = &Usrptmap[i];
344: p2 = p1 + change;
345: while (p1 < p2) {
346: *(int *)p1 |= PG_V | PG_KW;
347: clearseg(p1->pg_pfnum);
348: p1++;
349: i++;
350: }
351: mtpr(TBIA, 0);
352:
353: /*
354: * Move the stack or u. pte's which are before the newly
355: * allocated pages into the last of the newly allocated pages.
356: * They are taken from the end of the current p1 region,
357: * and moved to the end of the new p1 region. There are
358: * ss % NPTEPG such pte's.
359: */
360: p1 = (struct pte *)mfpr(P1BR) + mfpr(P1LR);
361: p2 = kmxtob(knew+szpt+change) - ss;
362: for (i = ss - NPTEPG*spages; i != 0; i--)
363: *p2++ = *p1++;
364:
365: /*
366: * Now switch to the new page tables.
367: */
368: mtpr(TBIA, 0); /* paranoid */
369: s = spl7(); /* conservative */
370: u.u_procp->p_p0br = kmxtob(knew);
371: u.u_pcb.pcb_p0br = kmxtob(knew);
372: u.u_pcb.pcb_p1br = kmxtob(knew+szpt+change) - P1TOP;
373: u.u_pcb.pcb_szpt += change;
374: u.u_procp->p_szpt += change;
375: u.u_procp->p_addr = uaddr(u.u_procp);
376: mtpr(P0BR, u.u_procp->p_p0br);
377: mtpr(P1BR, u.u_pcb.pcb_p1br);
378: mtpr(TBIA, 0);
379: splx(s);
380:
381: /*
382: * Finally, free old kernelmap.
383: */
384: if (szpt)
385: kmfree(szpt, kold);
386: return;
387:
388: bad:
389: /*
390: * Swap out the process so that the unavailable
391: * resource will be allocated upon swapin.
392: *
393: * When resume is executed for the process,
394: * here is where it will resume.
395: */
396: resume(pcbb(u.u_procp));
397: if (savectx(u.u_ssav))
398: return;
399: if (swapout(u.u_procp, (clicks_t)(mfpr(P0LR) - u.u_tsize), ss - UPAGES) == 0) {
400: /*
401: * No space to swap... it is inconvenient to try
402: * to exit, so just wait a bit and hope something
403: * turns up. Could deadlock here.
404: *
405: * SOMEDAY REFLECT ERROR BACK THROUGH expand TO CALLERS
406: * (grow, sbreak) SO CAN'T DEADLOCK HERE.
407: */
408: printf(":");
409: sleep((caddr_t)&lbolt, PRIBIO);
410: goto top;
411: }
412: /*
413: * Set SSWAP bit, so that when process is swapped back in
414: * swapin will set u.u_pcb.pcb_sswap to u_sswap and force a
415: * return from the setjmp() above.
416: */
417: u.u_procp->p_flag |= SSWAP;
418: swtch();
419: /* no return */
420: }
421:
422: kmcopy(to, from, count)
423: register int to;
424: int from;
425: register int count;
426: {
427: register struct pte *tp = &Usrptmap[to];
428: register struct pte *fp = &Usrptmap[from];
429:
430: while (count != 0) {
431: *tp++ = *fp++;
432: to++;
433: count--;
434: }
435: }
436:
437: kmfree(addr, size)
438: int addr, size;
439: {
440: rmfree(kernelmap, addr, size);
441: if (kmapwnt) {
442: kmapwnt = 0;
443: wakeup((caddr_t)kernelmap);
444: }
445: }
446:
447: #if NOTDEF
448: /* who calls this?? */
449: /*
450: * Change protection codes of text segment.
451: * Have to flush translation buffer since this
452: * affect virtual memory mapping of current process.
453: */
454: chgprot(p, addr, tprot)
455: struct proc *p;
456: caddr_t addr;
457: long tprot;
458: {
459: unsigned v;
460: int tp;
461: register struct pte *pte;
462: register struct cmap *c;
463:
464: v = clbase(btop(addr));
465: if (!isatsv(p, v)) {
466: u.u_error = EFAULT;
467: return (0);
468: }
469: tp = vtotp(p, v);
470: pte = tptopte(p, tp);
471: if (pte->pg_fod == 0 && pte->pg_pfnum) {
472: c = &cmap[pgtocm(pte->pg_pfnum)];
473: if (c->c_blkno && c->c_mdev != MSWAPX)
474: munhash(c->c_mdev, (daddr_t)c->c_blkno);
475: }
476: *(int *)pte &= ~PG_PROT;
477: *(int *)pte |= tprot;
478: distcl(pte);
479: tbiscl(v);
480: return (1);
481: }
482: #endif
483:
484: settprot(okwrit)
485: int okwrit;
486: {
487: register int *ptaddr, i, prot;
488:
489: prot = okwrit ? PG_UW : PG_URKR;
490: ptaddr = (int *)mfpr(P0BR);
491: for (i = 0; i < u.u_tsize; i++) {
492: ptaddr[i] &= ~PG_PROT;
493: ptaddr[i] |= prot;
494: }
495: mtpr(TBIA, 0);
496: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.