|
|
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, ip, bstart, count)
123: register struct fpte *pte;
124: register struct inode *ip;
125: daddr_t bstart;
126: clicks_t count;
127: {
128: register int i, j;
129: struct buf *bp;
130: int indx;
131: register daddr_t *pp;
132:
133: if(ip->i_fstyp)
134: panic("vinifod, fstyp");
135: while (count > 0) {
136: if (bstart < NADDR - 3) {
137: pte->pg_fod = 1;
138: pte->pg_source = PG_FTEXT;
139: pte->pg_blkno = ip ? ip->i_un.i_addr[bstart] : 0;
140: if (pte->pg_blkno == 0) {
141: pte->pg_source = PG_FZERO;
142: pte->pg_blkno = 0;
143: cnt.v_nzfod += CLSIZE;
144: }
145: cnt.v_nexfod += CLSIZE;
146: for (j = 1; j < CLSIZE; j++)
147: pte[j] = pte[0];
148: pte += CLSIZE;
149: bstart++;
150: count -= CLSIZE;
151: } else {
152: mtpr(TBIA, 0); /* conservative */
153: bp = vbmap(ip, bstart);
154: indx = (bstart - (NADDR - 3)) % NINDIR(ip->i_dev);
155: i = imin((NINDIR(ip->i_dev) - indx) * CLSIZE, count);
156: bstart += i / CLSIZE;
157: count -= i;
158: if (bp) {
159: pp = &bp->b_un.b_daddr[indx];
160: do {
161: pte->pg_fod = 1;
162: pte->pg_blkno = *pp++;
163: if (pte->pg_blkno) {
164: pte->pg_source = PG_FTEXT;
165: cnt.v_nexfod += CLSIZE;
166: } else {
167: pte->pg_source = PG_FZERO;
168: pte->pg_blkno = 0;
169: cnt.v_nzfod += CLSIZE;
170: }
171: for (j = 1; j < CLSIZE; j++)
172: pte[j] = pte[0];
173: pte += CLSIZE;
174: } while ((i -= CLSIZE) > 0);
175: brelse(bp);
176: } else {
177: cnt.v_nzfod += i;
178: do {
179: pte->pg_fod = 1;
180: pte->pg_source = PG_FZERO;
181: distcl(pte);
182: pte += CLSIZE;
183: } while ((i -= CLSIZE) > 0);
184: }
185: }
186: }
187: mtpr(TBIA, 0); /* necessary! */
188: }
189:
190: /*
191: * Vbmap returns a block full of indirect pointers for a given block offset
192: * in a file. It returns 0 if a missing address block was encountered,
193: * in which case the pages can be normal zfod pages.
194: */
195: struct buf *
196: vbmap(ip, bn)
197: register struct inode *ip;
198: daddr_t bn;
199: {
200: register i;
201: struct buf *bp;
202: int j, sh;
203: daddr_t nb;
204: dev_t dev = ip->i_dev;
205:
206: if (bn < NADDR-3)
207: panic("vbmap");
208: if (ip == 0)
209: return (0);
210:
211: /*
212: * addresses NADDR-3, NADDR-2, and NADDR-1
213: * have single, double, triple indirect blocks.
214: * the first step is to determine
215: * how many levels of indirection.
216: */
217: sh = 0;
218: nb = 1;
219: bn -= NADDR-3;
220: for (j = 3; j > 0; j--) {
221: sh += NSHIFT(dev);
222: nb <<= NSHIFT(dev);
223: if(bn < nb)
224: break;
225: bn -= nb;
226: }
227: if (j == 0)
228: goto noblk;
229:
230: /*
231: * fetch the address from the inode
232: */
233: nb = ip->i_un.i_addr[NADDR-j];
234:
235: /*
236: * fetch through the indirect blocks
237: */
238: for (;;) {
239: if (nb == 0)
240: return (0);
241: bp = bread(dev, nb);
242: if (bp->b_flags & B_ERROR) {
243: brelse(bp);
244: goto noblk;
245: }
246: if (j == 3)
247: break;
248: j++;
249: sh -= NSHIFT(dev);
250: i = (bn>>sh) & NMASK(dev);
251: nb = bp->b_un.b_daddr[i];
252: brelse(bp);
253: if (nb == 0)
254: goto noblk;
255: }
256: return (bp);
257:
258: noblk:
259: return ((struct buf *)0);
260: }
261:
262: /*
263: * Set a red zone in the kernel stack after the u. area.
264: */
265: setredzone(pte, vaddr)
266: register struct pte *pte;
267: caddr_t vaddr;
268: {
269:
270: pte += (sizeof (struct user) + NBPG - 1) / NBPG;
271: *(int *)pte &= ~PG_PROT;
272: *(int *)pte |= PG_URKR;
273: if (vaddr)
274: mtpr(TBIS, vaddr + sizeof (struct user));
275: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.