[comp.sources.misc] memdisk

mouse@mcgill-vision.UUCP (der Mouse ) (07/07/87)

A while back I posted a silicon disk driver here.  Recently I posted a
patch to it.  Well, 'tis time for another patch.
This one allows you to execute binaries residing on the silicon disk.
Unfortunately, it works this way only on VAXen.  I would have fixed it
for Suns too, except that I don't know the Sun memory management well
enough to wing it and SunOS doesn't come with source, unlike civilized
operating systems (even *VMS* had it on microfiche, mutter grumble...).

The reason you couldn't execute off the silicon disk in the first place
is that Berserkeley did something that stunningly violates the
principle of least astonishment: user text space is readonly to the
kernel as well as user!  Worse, when paging it in from disk, the page
table entry is not marked valid until *after* the disk I/O is complete,
meaning it doesn't work to just settprot(RW) before and settprot(RO)
after!!  Sigh.  This way is a hack, but it does work.

*** /sys/local/memdisk.c-	Fri Jun 19 19:12:54 1987
--- memdisk.c	Sun Jul  5 04:23:07 1987
***************
*** 34,42 ****
  #include "../h/ioctl.h"
  #include "../h/buf.h"
  #include "../h/conf.h"
- #include "../h/time.h"
- #include "../h/kernel.h"
  #include "../h/errno.h"
  #ifdef UFS_UFSMOUNT
  #include "../ufs/ufsmount.h"
  #define MOUNTTABLE mounttab
--- 34,49 ----
  #include "../h/ioctl.h"
  #include "../h/buf.h"
  #include "../h/conf.h"
  #include "../h/errno.h"
+ #include "../h/dir.h"
+ #include "../h/user.h"
+ #include "../h/proc.h"
+ #include "../h/kernel.h"
+ #include "../h/seg.h"
+ #include "../h/vmmac.h"
+ #ifdef vax
+ #include "../vax/mtpr.h"
+ #endif
  #ifdef UFS_UFSMOUNT
  #include "../ufs/ufsmount.h"
  #define MOUNTTABLE mounttab
***************
*** 50,55 ****
--- 57,64 ----
  #define MOUNTTABLE mounttab
  #endif
  
+ #include "../machine/pte.h"
+ 
  int max_md_size = (2048+512) * 1024; /* 2.5Mb */
  
  static struct memdiskinfo {
***************
*** 124,130 ****
      return;
    }
   if (bp->b_flags & B_READ)
!   { bcopy(mdi->data+off,bp->b_un.b_addr,bp->b_bcount);
    }
   else
    { bcopy(bp->b_un.b_addr,mdi->data+off,bp->b_bcount);
--- 133,189 ----
      return;
    }
   if (bp->b_flags & B_READ)
!   {
! /* Berserkeley did something really stunning here.  User text is	 */
! /*  read-only to the kernel, which means we can't just bcopy(), or you	 */
! /*  can't run a binary residing on the silicon disk.  We double-map the	 */
! /*  physical memory to a known r/w page to do the copy.  Unfortunately,	 */
! /*  I don't know enough about Sun memory management to fix this for	 */
! /*  Suns as well.							 */
! #ifdef vax
!     if ( !(0x80000000&(int)bp->b_un.b_addr) &&
! 	 isatsv(u.u_procp,btop(bp->b_un.b_addr)) )
!      { static char kbuf[1024];
!        static caddr_t kptr = 0;
!        int nb;
!        int bwp;
!        int tocopy;
!        caddr_t uva;
!        struct pte *upte;
!        struct pte *kpte;
!        int kpfn;
!        caddr_t daddr;
!        if (kptr == 0)
! 	{ kptr = (caddr_t) (((int)&kbuf[511])&~511);
! 	}
!        kpte = (struct pte *) (0x80000000+mfpr(SBR)+(((0x7fffffff&(int)kptr)>>9)<<2));
!        kpfn = kpte->pg_pfnum;
!        nb = bp->b_bcount;
!        uva = (caddr_t) bp->b_un.b_addr;
!        daddr = mdi->data + off;
!        while (nb > 0)
! 	{ bwp = 511 & (int)uva;
! 	  tocopy = 512 - bwp;
! 	  if (tocopy > nb)
! 	   { tocopy = nb;
! 	   }
! 	  upte = tptopte(u.u_procp,btop(uva));
! 	  kpte->pg_pfnum = upte->pg_pfnum;
! 	  mtpr(TBIS,(int)kptr);
! 	  bcopy(daddr,kptr+bwp,tocopy);
! 	  uva += tocopy;
! 	  daddr += tocopy;
! 	  nb -= tocopy;
! 	}
!        kpte->pg_pfnum = kpfn;
!        mtpr(TBIS,(int)kptr);
!      }
!     else
!      { bcopy(mdi->data+off,bp->b_un.b_addr,bp->b_bcount);
!      }
! #else
!     bcopy(mdi->data+off,bp->b_un.b_addr,bp->b_bcount);
! #endif
    }
   else
    { bcopy(bp->b_un.b_addr,mdi->data+off,bp->b_bcount);

					der Mouse

				(mouse@mcgill-vision.uucp)