|
|
1.1 root 1: /*
2: * Copyright (c) 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Computer Consoles Inc.
7: *
8: * Redistribution is only permitted until one year after the first shipment
9: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
10: * binary forms are permitted provided that: (1) source distributions retain
11: * this entire copyright notice and comment, and (2) distributions including
12: * binaries display the following acknowledgement: This product includes
13: * software developed by the University of California, Berkeley and its
14: * contributors'' in the documentation or other materials provided with the
15: * distribution and in all advertising materials mentioning features or use
16: * of this software. Neither the name of the University nor the names of
17: * its contributors may be used to endorse or promote products derived from
18: * this software without specific prior written permission.
19: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22: *
23: * @(#)vm_machdep.c 7.8 (Berkeley) 6/28/90
24: */
25:
26: #include "param.h"
27: #include "systm.h"
28: #include "user.h"
29: #include "proc.h"
30: #include "cmap.h"
31: #include "vm.h"
32: #include "text.h"
33: #include "kernel.h"
34:
35: #include "pte.h"
36: #include "cpu.h"
37: #include "mtpr.h"
38:
39: /*
40: * Set a red zone in the kernel stack after the u. area.
41: */
42: setredzone(pte, vaddr)
43: register struct pte *pte;
44: caddr_t vaddr;
45: {
46:
47: pte += (sizeof (struct user) + NBPG - 1) / NBPG;
48: *(int *)pte &= ~PG_PROT;
49: *(int *)pte |= PG_URKR;
50: if (vaddr)
51: mtpr(TBIS, vaddr + sizeof (struct user) + NBPG - 1);
52: }
53:
54: /*
55: * Check for valid program size
56: * NB - Check data and data growth separately as they may overflow
57: * when summed together.
58: */
59: chksize(ts, ids, uds, ss)
60: register unsigned ts, ids, uds, ss;
61: {
62: extern unsigned maxtsize;
63:
64: if (ctob(ts) > maxtsize ||
65: ctob(ids) > u.u_rlimit[RLIMIT_DATA].rlim_cur ||
66: ctob(uds) > u.u_rlimit[RLIMIT_DATA].rlim_cur ||
67: ctob(ids + uds) > u.u_rlimit[RLIMIT_DATA].rlim_cur ||
68: ctob(ss) > u.u_rlimit[RLIMIT_STACK].rlim_cur) {
69: return (ENOMEM);
70: }
71: return (0);
72: }
73:
74: /*ARGSUSED*/
75: newptes(pte, v, size)
76: register struct pte *pte;
77: u_int v;
78: register int size;
79: {
80: register caddr_t a = ptob(v);
81:
82: #ifdef lint
83: pte = pte;
84: #endif
85: if (size >= 8) {
86: mtpr(TBIA, 0);
87: return;
88: }
89: while (size > 0) {
90: mtpr(TBIS, a);
91: a += NBPG;
92: size--;
93: }
94: }
95:
96: /*
97: * Change protection codes of text segment.
98: * Have to flush translation buffer since this
99: * affect virtual memory mapping of current process.
100: */
101: chgprot(addr, tprot)
102: caddr_t addr;
103: long tprot;
104: {
105: unsigned v;
106: int tp;
107: register struct pte *pte;
108: register struct cmap *c;
109:
110: v = clbase(btop(addr));
111: if (!isatsv(u.u_procp, v))
112: return (EFAULT);
113: tp = vtotp(u.u_procp, v);
114: pte = tptopte(u.u_procp, tp);
115: if (pte->pg_fod == 0 && pte->pg_pfnum) {
116: c = &cmap[pgtocm(pte->pg_pfnum)];
117: if (c->c_blkno)
118: munhash(c->c_vp, (daddr_t)(u_long)c->c_blkno);
119: }
120: *(int *)pte &= ~PG_PROT;
121: *(int *)pte |= tprot;
122: distcl(pte);
123: tbiscl(v);
124: return (0);
125: }
126:
127: settprot(tprot)
128: long tprot;
129: {
130: register int *ptaddr, i;
131:
132: ptaddr = (int *)mfpr(P0BR);
133: for (i = 0; i < u.u_tsize; i++) {
134: ptaddr[i] &= ~PG_PROT;
135: ptaddr[i] |= tprot;
136: }
137: mtpr(TBIA, 0);
138: }
139:
140: #ifdef notdef
141: /*
142: * Rest are machine-dependent
143: */
144: getmemc(addr)
145: caddr_t addr;
146: {
147: register int c;
148: struct pte savemap;
149:
150: savemap = mmap[0];
151: *(int *)mmap = PG_V | PG_KR | btop(addr);
152: mtpr(TBIS, vmmap);
153: uncache(&vmmap[(int)addr & PGOFSET]);
154: c = *(char *)&vmmap[(int)addr & PGOFSET];
155: mmap[0] = savemap;
156: mtpr(TBIS, vmmap);
157: return (c & 0377);
158: }
159:
160: putmemc(addr, val)
161: caddr_t addr;
162: {
163: struct pte savemap;
164:
165: savemap = mmap[0];
166: *(int *)mmap = PG_V | PG_KW | btop(addr);
167: mtpr(TBIS, vmmap);
168: *(char *)&vmmap[(int)addr & PGOFSET] = val;
169:
170: mtpr(PADC, 0);
171: mtpr(PACC, 0);
172:
173: mmap[0] = savemap;
174: mtpr(TBIS, vmmap);
175: }
176: #endif
177:
178: /*
179: * Move pages from one kernel virtual address to another.
180: * Both addresses are assumed to reside in the Sysmap,
181: * and size must be a multiple of CLSIZE.
182: */
183: pagemove(from, to, size)
184: register caddr_t from, to;
185: int size;
186: {
187: register struct pte *fpte, *tpte;
188:
189: if (size % CLBYTES)
190: panic("pagemove");
191: fpte = kvtopte(from);
192: tpte = kvtopte(to);
193: while (size > 0) {
194: *tpte++ = *fpte;
195: *(int *)fpte++ = 0;
196: mtpr(TBIS, from);
197: mtpr(TBIS, to);
198: mtpr(P1DC, to); /* purge !! */
199: from += NBPG;
200: to += NBPG;
201: size -= NBPG;
202: }
203: }
204:
205: /*
206: * Code and data key management routines.
207: *
208: * The array ckey_cnt maintains the count of processes currently
209: * sharing each code key. The array ckey_cache maintains a record
210: * of all code keys used since the last flush of the code cache.
211: * Such keys may not be reused, even if unreferenced, until
212: * the cache is flushed. The data cache key handling is analogous.
213: * The arrays ckey_cnt and ckey_cache are allways kept in such a way
214: * that the following invariant holds:
215: * ckey_cnt > 0 =>'s ckey_cache == 1
216: * meaning as long as a code key is used by at least one process, it's
217: * marked as being 'in the cache'. Of course, the following invariant
218: * also holds:
219: * ckey_cache == 0 =>'s ckey_cnt == 0
220: * which is just the reciprocal of the 1'st invariant.
221: * Equivalent invariants hold for the data key arrays.
222: */
223: struct keystats ckeystats = { NCKEY - 1 };
224: struct keystats dkeystats = { NDKEY - 1 };
225:
226: /*
227: * Release a code key.
228: */
229: ckeyrelease(key)
230: int key;
231: {
232: register int s;
233:
234: s = spl8();
235: if (--ckey_cnt[key] < 0) {
236: printf("ckeyrelease: key = %d\n", key);
237: ckey_cnt[key] = 0;
238: }
239: if (ckey_cnt[key] == 0)
240: ckeystats.ks_dirty++;
241: splx(s);
242: }
243:
244: /*
245: * Release a data key.
246: */
247: dkeyrelease(key)
248: int key;
249: {
250: register int s;
251:
252: s = spl8();
253: if (--dkey_cnt[key] != 0) {
254: printf("dkeyrelease: key = %d\n", key);
255: dkey_cnt[key] = 0;
256: }
257: splx(s);
258: dkeystats.ks_dirty++;
259: }
260:
261: /*
262: * Invalidate the data cache for a process
263: * by exchanging cache keys.
264: */
265: dkeyinval(p)
266: register struct proc *p;
267: {
268: int s;
269:
270: dkeystats.ks_inval++;
271: s = spl8();
272: if (--dkey_cnt[p->p_dkey] != 0)
273: dkey_cnt[p->p_dkey] = 0;
274: if (p == u.u_procp && !noproc) {
275: p->p_dkey = getdatakey();
276: mtpr(DCK, p->p_dkey);
277: } else
278: p->p_dkey = 0;
279: splx(s);
280: }
281:
282: /*
283: * Get a code key.
284: * Strategy: try each of the following in turn
285: * until a key is allocated.
286: *
287: * 1) Find an unreferenced key not yet in the cache.
288: * If this fails, a code cache purge will be necessary.
289: * 2) Find an unreferenced key. Mark all unreferenced keys
290: * as available and purge the cache.
291: * 3) Free the keys from all processes not sharing keys.
292: * 4) Free the keys from all processes.
293: */
294: getcodekey()
295: {
296: register int i, s, freekey;
297: register struct proc *p;
298: int desparate = 0;
299: static int lastkey = MAXCKEY;
300:
301: ckeystats.ks_allocs++;
302: s = spl8();
303: freekey = 0;
304: for (i = lastkey + 1; ; i++) {
305: if (i > MAXCKEY)
306: i = 1;
307: if ((int)ckey_cache[i] == 0) { /* free key, take it */
308: ckey_cache[i] = 1, ckey_cnt[i] = 1;
309: splx(s);
310: ckeystats.ks_allocfree++;
311: ckeystats.ks_avail--;
312: lastkey = i;
313: return (i);
314: }
315: if (ckey_cnt[i] == 0) /* save for potential use */
316: freekey = i;
317: if (i == lastkey)
318: break;
319: }
320: /*
321: * All code keys were marked as being in cache.
322: * If a key was in the cache, but not in use, grab it.
323: */
324: if (freekey != 0) {
325: purge:
326: /*
327: * If we've run out of free keys,
328: * try and free up some other keys to avoid
329: * future cache purges.
330: */
331: ckey_cnt[freekey] = 1, ckey_cache[freekey] = 1;
332: for (i = 1; i <= MAXCKEY; i++)
333: if (ckey_cnt[i] == 0) {
334: ckey_cache[i] = 0;
335: ckeystats.ks_avail++;
336: }
337: mtpr(PACC, 0);
338: splx(s);
339: ckeystats.ks_dirty = 0;
340: ckeystats.ks_norefs++;
341: return (freekey);
342: }
343:
344: /*
345: * All keys are marked as in the cache and in use.
346: * Release all unshared keys, or, on second pass,
347: * release all keys.
348: */
349: steal:
350: for (p = allproc; p; p = p->p_nxt)
351: if (p->p_ckey != 0 && (p->p_flag & SSYS) == 0) {
352: i = p->p_ckey;
353: if (ckey_cnt[i] == 1 || desparate) {
354: p->p_ckey = 0;
355: if (--ckey_cnt[i] == 0) {
356: freekey = i;
357: if (p->p_textp)
358: p->p_textp->x_ckey = 0;
359: }
360: }
361: }
362:
363: if (freekey) {
364: ckeystats.ks_taken++;
365: goto purge;
366: } else {
367: desparate++;
368: goto steal;
369: }
370: }
371:
372: /*
373: * Get a data key.
374: *
375: * General strategy:
376: * 1) Try to find a data key that isn't in the cache. Allocate it.
377: * 2) If all data keys are in the cache, find one which isn't
378: * allocated. Mark all unallocated keys as not in cache,
379: * purge the cache, and allocate this one.
380: * 3) If all of them are allocated, free all process' keys
381: * and let them reclaim then as they run.
382: */
383: getdatakey()
384: {
385: register int i, freekey;
386: register struct proc *p;
387: int s;
388: static int lastkey = MAXDKEY;
389:
390: dkeystats.ks_allocs++;
391: s = spl8();
392: freekey = 0;
393: for (i = lastkey + 1; ; i++) {
394: if (i > MAXDKEY)
395: i = 1;
396: if ((int)dkey_cache[i] == 0) { /* free key, take it */
397: dkey_cache[i] = 1, dkey_cnt[i] = 1;
398: splx(s);
399: dkeystats.ks_allocfree++;
400: dkeystats.ks_avail--;
401: lastkey = i;
402: return (i);
403: }
404: if (dkey_cnt[i] == 0)
405: freekey = i;
406: if (i == lastkey)
407: break;
408: }
409: purge:
410: if (freekey) {
411: /*
412: * Try and free up some more keys to avoid
413: * future allocations causing a cache purge.
414: */
415: dkey_cnt[freekey] = 1, dkey_cache[freekey] = 1;
416: for (i = 1; i <= MAXDKEY; i++)
417: if (dkey_cnt[i] == 0) {
418: dkey_cache[i] = 0;
419: dkeystats.ks_avail++;
420: }
421: mtpr(PADC, 0);
422: splx(s);
423: dkeystats.ks_norefs++;
424: dkeystats.ks_dirty = 0;
425: return (freekey);
426: }
427:
428: /*
429: * Now, we have to take a key from someone.
430: * May as well take them all, so we get them
431: * from all of the idle procs.
432: */
433: for (p = allproc; p; p = p->p_nxt)
434: if (p->p_dkey != 0 && (p->p_flag & SSYS) == 0) {
435: freekey = p->p_dkey;
436: dkey_cnt[freekey] = 0;
437: p->p_dkey = 0;
438: }
439: dkeystats.ks_taken++;
440: goto purge;
441: }
442:
443: /*VARGARGS1*/
444: vtoph(p, v)
445: register struct proc *p;
446: unsigned v;
447: {
448: register struct pte *pte;
449: register unsigned pg;
450:
451: pg = btop(v);
452: if (pg >= BTOPKERNBASE)
453: pte = &Sysmap[pg - BTOPKERNBASE];
454: else
455: pte = vtopte(p, pg);
456: return ((pte->pg_pfnum << PGSHIFT) + (v & PGOFSET));
457: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.