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