|
|
1.1 root 1: /* vmsubr.c 4.6 81/05/28 */
2:
3: #include "sys/param.h"
4: #include "sys/systm.h"
5: #include "sys/user.h"
6: #include "sys/vm.h"
7: #include "sys/proc.h"
8: #include "sys/mtpr.h"
9: #include "sys/pte.h"
10: #include "sys/cmap.h"
11: #include "sys/inode.h"
12: #include "sys/buf.h"
13: #include "sys/text.h"
14:
15: /*
16: * Make uarea of process p addressible at kernel virtual
17: * address uarea through sysmap locations starting at map.
18: */
19: uaccess(p, map, uarea)
20: register struct proc *p;
21: struct pte *map;
22: register struct user *uarea;
23: {
24: register int i;
25: register struct pte *mp = map;
26:
27: for (i = 0; i < UPAGES; i++) {
28: *(int *)mp = 0;
29: mp->pg_pfnum = p->p_addr[i].pg_pfnum;
30: mp++;
31: }
32: vmaccess(map, (caddr_t)uarea, UPAGES);
33: }
34:
35: /*
36: * Validate the kernel map for size ptes which
37: * start at ppte in the sysmap, and which map
38: * kernel virtual addresses starting with vaddr.
39: */
40: vmaccess(ppte, vaddr, size)
41: register struct pte *ppte;
42: register caddr_t vaddr;
43: register int size;
44: {
45:
46: while (size != 0) {
47: *(int *)ppte++ |= PG_V|PG_KW;
48: mtpr(TBIS, vaddr);
49: vaddr += NBPG;
50: --size;
51: }
52: }
53:
54: /*
55: * Convert a pte pointer to
56: * a virtual page number.
57: */
58: ptetov(p, pte)
59: register struct proc *p;
60: register struct pte *pte;
61: {
62:
63: if (isatpte(p, pte))
64: return (tptov(p, ptetotp(p, pte)));
65: else if (isadpte(p, pte))
66: return (dptov(p, ptetodp(p, pte)));
67: else
68: return (sptov(p, ptetosp(p, pte)));
69: }
70:
71: /*
72: * Convert a virtual page
73: * number to a pte address.
74: */
75: struct pte *
76: vtopte(p, v)
77: register struct proc *p;
78: register unsigned v;
79: {
80:
81: if (isatsv(p, v))
82: return (tptopte(p, vtotp(p, v)));
83: else if (isadsv(p, v))
84: return (dptopte(p, vtodp(p, v)));
85: else
86: return (sptopte(p, vtosp(p, v)));
87: }
88:
89: /*
90: * convert a buffer to a pte address
91: * this knows about pageout conventions,
92: * swapping conventions, and physio.
93: */
94:
95: struct pte *
96: btopte(bp)
97: register struct buf *bp;
98: {
99: struct proc *rp;
100:
101: if (bp->b_flags & B_DIRTY)
102: rp = &proc[2]; /* ugh */
103: else
104: rp = bp->b_proc;
105: if ((bp->b_flags & B_PHYS) == 0)
106: return(&Sysmap[btop(((int)bp->b_un.b_addr)&~KSTART)]);
107: else if (bp->b_flags & B_UAREA)
108: return(&rp->p_addr[btop(bp->b_un.b_addr)]);
109: else if (bp->b_flags & B_PAGET)
110: return(&Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]);
111: else
112: return(vtopte(rp, btop(bp->b_un.b_addr)));
113: }
114:
115: struct buf *vbmap();
116: /*
117: * Initialize the page tables for paging from an inode,
118: * by scouring up the indirect blocks in order.
119: * Corresponding area of memory should have been vmemfree()d
120: * first or just created.
121: */
122: vinifod(pte, fileno, ip, bstart, count)
123: register struct fpte *pte;
124: int fileno;
125: register struct inode *ip;
126: daddr_t bstart;
127: clicks_t count;
128: {
129: register int i, j;
130: struct buf *bp;
131: int indx;
132: register daddr_t *pp;
133:
134: if(ip->i_fstyp)
135: panic("vinifod, fstyp");
136: if(fileno < PG_FMIN)
137: panic("vinifod, fileno");
138: while (count > 0) {
139: if (bstart < NADDR - 3) {
140: ((struct pte *)pte)->pg_vreadm = 0;
141: pte->pg_fod = 1;
142: pte->pg_source = fileno - PG_FMIN;
143: pte->pg_blkno = ip ? ip->i_un.i_addr[bstart] : 0;
144: if (pte->pg_blkno == 0) {
145: pte->pg_source = PG_FZERO - PG_FMIN;
146: pte->pg_blkno = 0;
147: cnt.v_nzfod += CLSIZE;
148: } else if (fileno == PG_FTEXT)
149: cnt.v_nexfod += CLSIZE;
150: else
151: panic("vinifod, vrpages set");
152: for (j = 1; j < CLSIZE; j++)
153: pte[j] = pte[0];
154: pte += CLSIZE;
155: bstart++;
156: count -= CLSIZE;
157: } else {
158: mtpr(TBIA, 0); /* conservative */
159: bp = vbmap(ip, bstart);
160: indx = (bstart - (NADDR - 3)) % NINDIR(ip->i_dev);
161: i = imin((NINDIR(ip->i_dev) - indx) * CLSIZE, count);
162: bstart += i / CLSIZE;
163: count -= i;
164: if (bp) {
165: pp = &bp->b_un.b_daddr[indx];
166: do {
167: ((struct pte *)pte)->pg_vreadm = 0;
168: pte->pg_fod = 1;
169: pte->pg_blkno = *pp++;
170: if (pte->pg_blkno) {
171: pte->pg_source = fileno - PG_FMIN;
172: if (fileno == PG_FTEXT)
173: cnt.v_nexfod += CLSIZE;
174: else
175: panic("vinifod, vrpages set");
176: } else {
177: pte->pg_source = PG_FZERO - PG_FMIN;
178: pte->pg_blkno = 0;
179: cnt.v_nzfod += CLSIZE;
180: }
181: for (j = 1; j < CLSIZE; j++)
182: pte[j] = pte[0];
183: pte += CLSIZE;
184: } while ((i -= CLSIZE) > 0);
185: brelse(bp);
186: } else {
187: cnt.v_nzfod += i;
188: do {
189: ((struct pte *)pte)->pg_vreadm = 0;
190: pte->pg_fod = 1;
191: pte->pg_source = PG_FZERO - PG_FMIN;
192: distcl(pte);
193: pte += CLSIZE;
194: } while ((i -= CLSIZE) > 0);
195: }
196: }
197: }
198: mtpr(TBIA, 0); /* necessary! */
199: }
200:
201: /*
202: * Vbmap returns a block full of indirect pointers for a given block offset
203: * in a file. It returns 0 if a missing address block was encountered,
204: * in which case the pages can be normal zfod pages.
205: */
206: struct buf *
207: vbmap(ip, bn)
208: register struct inode *ip;
209: daddr_t bn;
210: {
211: register i;
212: struct buf *bp;
213: int j, sh;
214: daddr_t nb;
215: dev_t dev = ip->i_dev;
216:
217: if (bn < NADDR-3)
218: panic("vbmap");
219: if (ip == 0)
220: return (0);
221:
222: /*
223: * addresses NADDR-3, NADDR-2, and NADDR-1
224: * have single, double, triple indirect blocks.
225: * the first step is to determine
226: * how many levels of indirection.
227: */
228: sh = 0;
229: nb = 1;
230: bn -= NADDR-3;
231: for (j = 3; j > 0; j--) {
232: sh += NSHIFT(dev);
233: nb <<= NSHIFT(dev);
234: if(bn < nb)
235: break;
236: bn -= nb;
237: }
238: if (j == 0)
239: goto noblk;
240:
241: /*
242: * fetch the address from the inode
243: */
244: nb = ip->i_un.i_addr[NADDR-j];
245:
246: /*
247: * fetch through the indirect blocks
248: */
249: for (;;) {
250: if (nb == 0)
251: return (0);
252: bp = bread(dev, nb);
253: if (bp->b_flags & B_ERROR) {
254: brelse(bp);
255: goto noblk;
256: }
257: if (j == 3)
258: break;
259: j++;
260: sh -= NSHIFT(dev);
261: i = (bn>>sh) & NMASK(dev);
262: nb = bp->b_un.b_daddr[i];
263: brelse(bp);
264: if (nb == 0)
265: goto noblk;
266: }
267: return (bp);
268:
269: noblk:
270: return ((struct buf *)0);
271: }
272:
273: /*
274: * Set a red zone in the kernel stack after the u. area.
275: */
276: setredzone(pte, vaddr)
277: register struct pte *pte;
278: caddr_t vaddr;
279: {
280:
281: pte += (sizeof (struct user) + NBPG - 1) / NBPG;
282: *(int *)pte &= ~PG_PROT;
283: *(int *)pte |= PG_URKR;
284: if (vaddr)
285: mtpr(TBIS, vaddr + sizeof (struct user));
286: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.