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