BSD 4 development
authorBill Joy <wnj@ucbvax.Berkeley.EDU>
Sun, 9 Nov 1980 16:07:50 +0000 (08:07 -0800)
committerBill Joy <wnj@ucbvax.Berkeley.EDU>
Sun, 9 Nov 1980 16:07:50 +0000 (08:07 -0800)
Work on file usr/src/sys/sys/vmsubr.c

Synthesized-from: CSRG//cd1/4.0

usr/src/sys/sys/vmsubr.c [new file with mode: 0644]

diff --git a/usr/src/sys/sys/vmsubr.c b/usr/src/sys/sys/vmsubr.c
new file mode 100644 (file)
index 0000000..1acaf5a
--- /dev/null
@@ -0,0 +1,276 @@
+/*     vmsubr.c        4.2     11/9/80 */
+
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/vm.h"
+#include "../h/proc.h"
+#include "../h/mtpr.h"
+#include "../h/pte.h"
+#include "../h/cmap.h"
+#include "../h/inode.h"
+#include "../h/buf.h"
+#include "../h/text.h"
+
+/*
+ * Make uarea of process p addressible at kernel virtual
+ * address uarea through sysmap locations starting at map.
+ */
+uaccess(p, map, uarea)
+       register struct proc *p;
+       struct pte *map;
+       register struct user *uarea;
+{
+       register int i;
+       register struct pte *mp = map;
+
+       for (i = 0; i < UPAGES; i++) {
+               *(int *)mp = 0;
+               mp->pg_pfnum = p->p_addr[i].pg_pfnum;
+               mp++;
+       }
+       vmaccess(map, (caddr_t)uarea, UPAGES);
+}
+
+/*
+ * Validate the kernel map for size ptes which
+ * start at ppte in the sysmap, and which map
+ * kernel virtual addresses starting with vaddr.
+ */
+vmaccess(ppte, vaddr, size)
+       register struct pte *ppte;
+       register caddr_t vaddr;
+       register int size;
+{
+
+       while (size != 0) {
+               *(int *)ppte++ |= PG_V|PG_KW;
+               mtpr(TBIS, vaddr);
+               vaddr += NBPG;
+               --size;
+       }
+}
+
+/* 
+ * Convert a pte pointer to
+ * a virtual page number.
+ */
+ptetov(p, pte)
+       register struct proc *p;
+       register struct pte *pte;
+{
+
+       if (isatpte(p, pte))
+               return (tptov(p, ptetotp(p, pte)));
+       else if (isadpte(p, pte))
+               return (dptov(p, ptetodp(p, pte)));
+       else
+               return (sptov(p, ptetosp(p, pte)));
+}
+
+/*
+ * Convert a virtual page 
+ * number to a pte address.
+ */
+struct pte *
+vtopte(p, v)
+       register struct proc *p;
+       register unsigned v;
+{
+
+       if (isatsv(p, v))
+               return (tptopte(p, vtotp(p, v)));
+       else if (isadsv(p, v))
+               return (dptopte(p, vtodp(p, v)));
+       else 
+               return (sptopte(p, vtosp(p, v)));
+}
+
+struct buf *vbmap();
+/*
+ * Initialize the page tables for paging from an inode,
+ * by scouring up the indirect blocks in order.
+ * Corresponding area of memory should have been vmemfree()d
+ * first or just created.
+ */
+vinifod(pte, fileno, ip, bstart, count)
+       register struct fpte *pte;
+       int fileno;
+       register struct inode *ip;
+       daddr_t bstart;
+       size_t count;
+{
+       register int i, j;
+       struct buf *bp;
+       int indx;
+       register daddr_t *pp;
+
+       while (count > 0) {
+               if (bstart < NADDR - 3) {
+                       ((struct pte *)pte)->pg_vreadm = 0;
+                       pte->pg_fod = 1;
+                       pte->pg_fileno = fileno;
+                       pte->pg_blkno = ip ? ip->i_un.i_addr[bstart] : 0;
+                       if (pte->pg_blkno == 0) {
+                               pte->pg_fileno = PG_FZERO;
+                               pte->pg_blkno = 0;
+                               cnt.v_nzfod += CLSIZE;
+                       } else if (fileno == PG_FTEXT)
+                               cnt.v_nexfod += CLSIZE;
+                       else {
+                               cnt.v_nvrfod += CLSIZE;
+                               u.u_vrpages[fileno] += CLSIZE;
+                       }
+                       for (j = 1; j < CLSIZE; j++)
+                               pte[j] = pte[0];
+                       pte += CLSIZE;
+                       bstart++;
+                       count -= CLSIZE;
+               } else {
+                       mtpr(TBIA, 0);          /* conservative */
+                       bp = vbmap(ip, bstart);
+                       indx = (bstart - (NADDR - 3)) % NINDIR;
+                       i = imin((NINDIR - indx) * CLSIZE, count);
+                       bstart += i / CLSIZE;
+                       count -= i;
+                       if (bp) {
+                               if (fileno == PG_FTEXT)
+                                       cnt.v_nexfod += i;
+                               else {
+                                       cnt.v_nvrfod += i;
+                                       u.u_vrpages[fileno] += i;
+                               }
+                               pp = &bp->b_un.b_daddr[indx];
+                               do {
+                                       ((struct pte *)pte)->pg_vreadm = 0;
+                                       pte->pg_fod = 1;
+                                       pte->pg_blkno = *pp++;
+                                       if (pte->pg_blkno)
+                                               pte->pg_fileno = fileno;
+                                       else {
+                                               pte->pg_fileno = PG_FZERO;
+                                               pte->pg_blkno = 0;
+                                               u.u_vrpages[fileno] -= CLSIZE;
+                                               cnt.v_nvrfod -= CLSIZE;
+                                               cnt.v_nzfod += CLSIZE;
+                                       }
+                                       for (j = 1; j < CLSIZE; j++)
+                                               pte[j] = pte[0];
+                                       pte += CLSIZE;
+                               } while ((i -= CLSIZE) > 0);
+                               brelse(bp);
+                       } else {
+                               cnt.v_nzfod += i;
+                               do {
+                                       ((struct pte *)pte)->pg_vreadm = 0;
+                                       pte->pg_fod = 1;
+                                       pte->pg_fileno = PG_FZERO;
+                                       distcl(pte);
+                                       pte += CLSIZE;
+                               } while ((i -= CLSIZE) > 0);
+                       }
+               }
+       }
+       mtpr(TBIA, 0);          /* necessary! */
+}
+
+/*
+ * Vbmap returns a block full of indirect pointers for a given block offset
+ * in a file.  It returns 0 if a missing address block was encountered,
+ * in which case the pages can be normal zfod pages.
+ */
+struct buf *
+vbmap(ip, bn)
+register struct inode *ip;
+daddr_t bn;
+{
+       register i;
+       struct buf *bp;
+       int j, sh;
+       daddr_t nb;
+       dev_t dev = ip->i_dev;
+
+       if (bn < NADDR-3)
+               panic("vbmap");
+       if (ip == 0)
+               return (0);
+
+       /*
+        * addresses NADDR-3, NADDR-2, and NADDR-1
+        * have single, double, triple indirect blocks.
+        * the first step is to determine
+        * how many levels of indirection.
+        */
+       sh = 0;
+       nb = 1;
+       bn -= NADDR-3;
+       for (j = 3; j > 0; j--) {
+               sh += NSHIFT;
+               nb <<= NSHIFT;
+               if(bn < nb)
+                       break;
+               bn -= nb;
+       }
+       if (j == 0)
+               goto noblk;
+
+       /*
+        * fetch the address from the inode
+        */
+       nb = ip->i_un.i_addr[NADDR-j];
+
+       /*
+        * fetch through the indirect blocks
+        */
+       for (;;) {
+               if (nb == 0)
+                       return (0);
+               bp = bread(dev, nb);
+               if (bp->b_flags & B_ERROR) {
+                       brelse(bp);
+                       goto noblk;
+               }
+               if (j == 3)
+                       break;
+               j++;
+               sh -= NSHIFT;
+               i = (bn>>sh) & NMASK;
+               nb = bp->b_un.b_daddr[i];
+               brelse(bp);
+               if (nb == 0)
+                       goto noblk;
+       }
+       return (bp);
+
+noblk:
+       return ((struct buf *)0);
+}
+
+getmemc(addr)
+       caddr_t addr;
+{
+       register int c;
+       struct pte savemap;
+
+       savemap = mmap[0];
+       *(int *)mmap = PG_V | PG_KR | btop(addr);
+       mtpr(TBIS, vmmap);
+       c = *(char *)&vmmap[(int)addr & PGOFSET];
+       mmap[0] = savemap;
+       mtpr(TBIS, vmmap);
+       return (c & 0377);
+}
+
+putmemc(addr, val)
+       caddr_t addr;
+{
+       struct pte savemap;
+
+       savemap = mmap[0];
+       *(int *)mmap = PG_V | PG_KW | btop(addr);
+       mtpr(TBIS, vmmap);
+       *(char *)&vmmap[(int)addr & PGOFSET] = val;
+       mmap[0] = savemap;
+       mtpr(TBIS, vmmap);
+}