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