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