|
|
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
1.1.1.2 ! root 906: gettmem(up)
! 907: struct user *up;
1.1 root 908: {
909:
910: return ((caddr_t)USRTEXT);
911: }
912:
913: /*
914: * Return the file byte offset for the text segment.
915: */
1.1.1.2 ! root 916: gettfile(up)
! 917: struct user *up;
1.1 root 918: {
919:
1.1.1.2 ! root 920: if (up->u_exdata.ux_mag == ZMAGIC)
1.1 root 921: return (0);
922: else
923: return (sizeof (u.u_exdata));
924: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.