|
|
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.