|
|
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.