From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 22-NOV-1990 17:21:11.74
To:	MRGATE::"ARISIA::EVERHART"
CC:	
Subj:	The RIGHT version of RAMDRIVER, part 4 of 5

Received:  by crdgw1.ge.com (5.57/GE 1.78)
	 id AA04697; Thu, 22 Nov 90 16:57:07 EST
Received: From UCBVAX.BERKELEY.EDU by CRVAX.SRI.COM with TCP; Thu, 22 NOV 90 07:34:46 PST
Received: by ucbvax.Berkeley.EDU (5.63/1.42)
	id AA06336; Thu, 22 Nov 90 07:21:52 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 21 Nov 90 00:38:31 GMT
From: gkn@ucsd.edu  (Gerard K. Newman)
Organization: San Diego Supercomputer Center
Subject: The RIGHT version of RAMDRIVER, part 4 of 5
Message-Id: <23375@ucsd.Edu>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com


-+-+-+-+-+-+-+-+ START OF PART 4 -+-+-+-+-+-+-+-+
X10$:`009MOVL`009(R0)+,R3`009`009      ;Fetch the next PTE
X`009JSB`009G`094IOC$PTETOPFN`009`009      ;Extract the PFN from it.
X`009BICL3`009#`094c<PTE$M_PFN>,R3,(R1)`009      ;Map the page
X`009BISL`009#<PTE$M_VALID!PTE$C_KW>,(R1)+ ;Make it valid
X`009SOBGTR`009R2,10$`009`009`009      ;Loop.
X`009POPL`009R3`009`009`009      ;Restore the IRP address
X`009RSB`009`009`009`009      ;Done.
X
X; Here when we can't get enough page table entries to map the I/O buffer.
X; Post the I/O request complete now (status is SS$_INSFPTES).
X
X20$:`009TSTL`009(SP)+`009`009`009 ;Remove the caller's address from the stac
Vk
X`009JSB`009G`094IOC$REQCOM`009`009 ;Post the request complete (& look for mo
Vre work)
X`009FORKUNLOCK LOCK=UCB$B_FLCK(R5),- ;Release the
X`009`009NEWIPL=(SP)+,-`009`009 ; fork lock
X`009`009PRESERVE=YES`009`009 ;`009...
X`009RSB`009`009`009`009 ;Done
X
X`009.Page
X`009.Subtitle`009RAMD_FREE_SPTES`009- Release SPTEs
X
X;+
X;
X; ----- RAMD_FREE_SPTES:  Release SPTEs
X;
X;
X; This routine is called to release the  system page table entries used
X; to  overmap the user's  buffer when satisfying a page read operation.
X; We must invalidate the translation buffer on all CPUs for the virtual
X; addresses involved.
X;
X; Environment:
X;
X;`009IPL$_SYNCH, fork context.
X;
X; Inputs:
X;
X;`009R5`009- UCB address
X;`009R3`009- IRP address
X;
X; Outputs:
X;
X;`009Page table entries invalidated and freed.
X;
X;-
X
XRAMD_FREE_SPTES:`009`009`009;Release SPTEs
X
X`009PUSHR`009#`094m<R0,R1,R2,R4>`009;Save some registers
X`009MOVL`009IRP$L_PAGE_VA(R3),R4`009;Fetch the starting virtual address
X`009MOVL`009IRP$L_NSPTES(R3),R1`009;Fetch the number of SPTEs
X`009BEQL`00920$`009`009`009;If EQL not much to do (bug!)
X`009MOVL`009IRP$L_SPTE(R3),R0`009;Fetch the first SPTE
X
X10$:`009MOVL`009R4,R2`009`009`009;Here's a virtual address
X`009INVALIDATE_TB R2,INST1=-`009;Flush the
X`009<CLRL`009(R0)+>`009`009`009; translation buffer
X`009MOVAB`009512(R4),R4`009`009;Next page, please
X`009SOBGTR`009R1,10$`009`009`009;Loop.
X`009MOVL`009IRP$L_SPTE(R3),R1`009;Fetch the starting SPTE
X`009MOVL`009IRP$L_NSPTES(R3),R2`009;Deallocate this many
X`009JSB`009G`094LDR$DEALLOC_PT`009;Return the PTEs
X
X20$:`009POPR`009#`094m<R0,R1,R2,R4>`009;Restore some registers
X`009RSB`009`009`009`009;Done
X
X`009.Page
X`009.Subtitle`009RAMD_END`009- End of the driver (for SYSGEN)
X
XRAMD_END:`009`009`009`009;Mark the end of the driver for SYSGEN
X
X
X
X
X`009.End
$ CALL UNPACK RAMDRIVER.MAR;63 168728024
$ create/nolog 'f'
X`009.Title`009InitVD`009- Initialize a virtual disk
X`009.Ident`009/V01.000/
X`009.Enable`009SUP
X`009.Default Displacement,Word
X`009.Subtitle`009Introduction
X
X;+
X;
X; ----- InitVD:  Initialize a virtual disk
X;
X;
X; Facility:
X;
X;`009PDDRIVER.
X;
X; Abstract:
X;
X;`009This program will control the size of a virtual disk connected
X;`009to the PDDRIVER.  The "disk" is a  ram-based disk, with  pages
X;`009allocated from non-paged pool comprising the "blocks".
X;
X; Environment:
X;
X;`009VAX/VMS V4.1 or later, PHY_IO privilege (CMKRNL to load the driver).
X;
X;
X; Version:`009V01.000
X; Date:`009`00923-Nov-1985
X;
X; Gerard K. Newman`00923-Nov-1985
X; Science Applications International
X; 800 Oak Ridge Turnpike
X; Oak Ridge, TN  37830
X; (615) 482-9031
X;
X;
X; Modifications:
X;
X;
X;-
X
X`009.Page
X`009.Subtitle`009Local definitions
X
X`009.NoCross`009`009`009;Save a tree
X
X`009$IODEF`009`009`009`009;I/O function codes
X`009$SSDEF`009`009`009`009;System service codes
X`009$TPADEF`009`009`009`009;TPARSE definitions
X
X`009.Cross`009`009`009`009;Turn CREF back on
X
X`009.Page
X`009.Subtitle`009TPARSE state table
X
X`009$INIT_STATE`009VD_STATES,VD_KEYS`009;Initialize the state table
X
X`009$STATE`009`009`009`009`009;First state
X
X`009$TRAN`009TPA$_SYMBOL,,,,DEV_DESC`009`009;Get the device name
X
X`009$STATE`009`009`009`009`009;Dummy state to swallow a trailing :
X
X`009$TRAN`009':'`009`009`009`009;Swallow the ":"
X`009$TRAN`009TPA$_LAMBDA`009`009`009; if it's there
X
X`009$STATE`009`009`009`009`009;State to pick up the number of pages to alloc
Vate
X
X`009$TRAN`009TPA$_DECIMAL,TPA$_EXIT,GROW_DISK ;Grab a decimal # and grow the
V disk
X
X`009$END_STATE`009`009`009`009;End of the state table
X
X`009.Subtitle`009Storage, pure & impure
X
X`009.Psect`009DATA`009NOEXE,RD,WRT,PIC,NOSHR,PAGE
X
X
XTPARSE_BLOCK:`009.Long`009TPA$K_COUNT0`009;Length of the TPARSE argument blo
Vck
X`009`009.Long`0090`009`009;Option flags (none which matter)
X`009`009.Long`009128`009`009;Input buffer
X`009`009.Address IN_BUFF`009; descriptor
X`009`009.Blkb`009TPA$K_LENGTH0-<4*4> ;Allocate the rest of the block
X
XIOSB:`009`009.Blkq`009`009`009;I/O status block
XDEV_DESC:`009.Blkq`009`009`009;Descriptor of the device name
XDEV_CHAN:`009.Blkw`009`009`009;Channel to the "disk"
XIN_BUFF:`009.Blkb`009128`009`009;Input buffer
X
XPROMPT:`009`009.Ascid`009"Init-VD> "`009;Our prompt
X
X`009.Page
X`009.Subtitle`009Entry point
X
X`009.Psect`009CODE`009`009EXE,RD,NOWRT,PIC,SHR,PAGE
X
X`009.Entry`009START,`094M<>`009`009;Entry here
X
X`009MOVAL`009TPARSE_BLOCK,R11`009;Address our TPARSE parameter block
X`009PUSHAW`009TPA$L_STRINGCNT(R11)`009;Return the length here
X`009PUSHAQ`009PROMPT`009`009`009;Here's our prompt
X`009PUSHAQ`009TPA$L_STRINGCNT(R11)`009;Here's the input buffer
X`009CALLS`009#3,G`094LIB$GET_FOREIGN`009;Get a command line
X`009BLBC`009R0,10$`009`009`009;Probably EOF
X`009PUSHAB`009VD_KEYS`009`009`009;Stack the keyword table address
X`009PUSHAB`009VD_STATES`009`009;Stack the state table address
X`009PUSHL`009R11`009`009`009;Stack the TPARSE parameter block address
X`009CALLS`009#3,G`094LIB$TPARSE`009`009;Go parse & execute the command
X
X10$:`009CMPL`009#RMS$_EOF,R0`009`009;EOF (`094Z) on input?
X`009BNEQ`00920$`009`009`009;If NEQ no, onward
X`009MOVL`009#SS$_NORMAL,R0`009`009;Else not an error
X
X20$:`009RET`009`009`009`009;Bye
X
X`009.Page
X`009.Subtitle`009GROW_DISK`009- Grow (or shrink) the disk
X
X;+
X;
X; ----- GROW_DISK:  Grow (or shrink) the disk
X;
X;
X; This routine will grow or shrink the specified virtual disk.
X;
X; Do NOT try to use this routine on a real disk.
X;
X; You have been warned.
X;
X; Inputs:
X;
X;`009DEV_DESC`009 - A descriptor of the virtual disk name
X;`009TPA$L_NUMBER(AP) - Size to make the disk in pages (blocks)
X;
X; Outputs:
X;
X;`009Whatever $QIOW returns from the IO$_FORMAT request.
X;
X;-
X
XGROW_DISK: .Word `094M<>`009`009`009;Here to grow the disk
X
X`009$ASSIGN_S DEVNAM=DEV_DESC,-`009;Assign a channel
X`009`009CHAN=DEV_CHAN`009`009; to the virtual disk
X`009BLBC`009R0,10$`009`009`009;Branch if error
X`009$QIOW_S`009CHAN=DEV_CHAN,-`009`009;Issue the
X`009`009FUNC=#IO$_FORMAT,-`009; format request
X`009`009IOSB=IOSB,-`009`009;`009...
X`009`009P1=@TPA$L_NUMBER(AP)`009;Extra level of indirection is to pass P1 by
V value
X`009BLBC`009R0,10$`009`009`009;Sigh.
X`009MOVZWL`009IOSB,R0`009`009`009;Get the return status
X
X10$:`009RET`009`009`009`009;Back to TPARSE
X
X
X`009.End`009START
$ CALL UNPACK INITVD.MAR;1 1813055953
$ create/nolog 'f'
X
XHere's a new version of the RAMDRIVER I wrote a while ago with lots better
Xperformance than DEC's PDDRIVER.  This version has a fix in it for executing
Xcertain images off of a "disk" controlled by the RAMDRIVER:  in the previous
Xversion, a pathological case existed where a process incurring a page fault
Xexecuting at IPL$_ASTDEL would hang waiting for the RAMDRIVER to satisfy the
Xpage fault read, since RAMDRIVER queues ASTs to processes.  This is a classi
Vc
Xdeadlock.  This showed up during image activation a lot.  Additionally, if
Xthe process in question owned a MUTEX, then slowly but surely the whole syst
Vem
Xwould hang waiting for the deadlocked process to release the MUTEX.  This al
Vso
Xhappened a lot during image activation :-(
X
XThe new version doesn't suffer from this problem -- it bypasses queueing the
XAST for page fault reads (or writes, for that matter, though why anyone woul
Vd
Xset up a pagefile on a ramdisk is a bit beyond me), thus preventing the hang
Vs.
X
XThe driver source, a program to set the size of the ramdisk, this text, the
Xtext from my original Info-VAX posting from April 1988 and a command procedu
Vre
Xto build everything follows in VMS_SHARE format in 5 parts.
X
XThis version runs on VMS V5.x systems only.  If you're still running on V4.x
Xyou're out of luck (you'll have to invent LDR$ALLOC_PT and LDR$DEALLOC_PT as
Xwell as undo the spin lock stuff).
X
XThe last time I posted this I was deluged with questions about how to use it
V,
Xetc.  To short circuit that process this time, one uses the MAKE.COM procedu
Vre
Xto build it, and from a privileged account one does the following:
X
X`009$ Run SYS$SYSTEM:SYSGEN
X`009SYSGEN>  LOAD dev:`091dir`093RAMDRIVER
X`009SYSGEN>  CONNECT RDA0/NOADAPTER/DRIVER=RAMDRIVER
X`009SYSGEN>  `094Z
X`009$ Run INITVD
X`009Init-VD> RDA0: size-in-blocks
X`009$ Initialize RDA0: your-favorite-volume-label
X`009$ Mount RDA0: your-favorite-volume-label
X
Xand treat it just like any other disk.  The "blocks" for this disk come from
Xnon-paged pool, and therefore you should ensure that you have enough non-pag
Ved
Xpool to accomodate the desired ramdisk.  Also, the RAMDRIVER uses system pag
Ve
Xtable entries to double-map I/O buffers for page fault reads -- this comes f
Vrom
Xthe SYSGEN parameter SPTREQ.  If there aren't enough free SPTEs then RAMDRIV
VER
Xwill return error indications for page fault reads, rendering the process
Xincurring the page fault (and probably you, too) very unhappy.  I run the
XVAXen here at SDSC with a fair amount of extra system address space (`126100
V0
Xpages - but I have lots of spare memory) so this isn't a problem for me.
X
XThe upshot of this is:
X
X`0091.  Ensure you have enough non-paged pool.
X`0092.  Ensure you have enough SPTREQ.
X
Xbefore using RAMDRIVER.
X
XI apologize for taking so long to fix this problem -- I've been aware of it
Xfor quite some time.  RAMDRIVER is a spare-time project for me, and lately
Xmy spare time has been measured in small integer numbers of micro-fortnights
V ...
X
X
XAs before, no warranty, expressed or implied.  Use at your own risk (I do).
X
XComments, fixes, etc.  welcome as always.
X
$ CALL UNPACK NEW-RAMD-BLURB.TXT;5 723596821
$ create/nolog 'f'
X`091This is the text of the message I posted to Info-VAX in late April of 19
V88.
X It's included here for historical perspective about the motivation behind
X RAMDRIVER.`093
X
X
X
X
X
X----------------------------------------------------------------------------
V----
XFolks,
X
XBefore I get started let me apologize about the length -- it's long.  To
Xthose of you without in depth knowledge of VMS internals let me also apologi
Vze
Xfor the amount of VMS internal mumbo-jumbo this contains.  For those of you
Xwith lots of in depth knowledge of VMS internals let me apologize for glossi
Vng
Xover a few points.
X
XHere's some background on what I've been wasting my "spare" time with lately
V...
XA while ago a friend and I got to talking about DEC's PDDRIVER, which is
Xessentially a RAM disk driver for VMS.  It was being used for a demo to help
Xspeed up the login process by putting popular files (LOGINOUT, DCLTABLES,
XSYLOGIN, etc.) on it.  We theorized that perhaps PDDRIVER wasn't significant
Vly
Xfaster than a real disk in certain circumstances.
X
XDEC wrote PDDRIVER as a way to get standalone backup booted from TK50s in
Xorder to boot VMS.  The reason for this you might have to accept on faith ..
V.
XVMS requires a random access device as the system disk, and TK50s are not
Xrandom access devices.  So, if you set bit 18 (%x20000) in R5 when you're
Xbooting a VAX, VMB will set things up such that the system disk and load
Xdevice are different -- the stuff will be loaded from TK50s, and the system
Xdisk will be PDA0 - using DEC's PDDRIVER.
X
XPDDRIVER differs from standard disk drivers in a few interesting ways.  The
XIO$_FORMAT I/O function is used to cause the driver to assign non-paged pool
Xto be the "blocks" which comprise the "disk".  Normal disk type I/O function
Xcodes go thru the standard ACP FDT routines in SYSACPFDT, and are queued to
Xthe driver's start I/O routine.  The start I/O routine uses two VMS routines
V,
XIOC$MOVFRUSER and IOC$MOVTOUSER, to accomplish "writes" and "reads".  Those
Xtwo routines operate by double-mapping the user's buffer a page at a time
Xin system virtual address space and moving data a byte a time, remapping the
Xone page window when the buffer crosses a page boundary.  All of this occurs
Xat driver fork IPL, which happens to match IPL$_SYNCH.  This double-mapping
Xis necessary because fork processes do not have process context, and therefo
Vre
Xuser page tables are not current.
X
XSo, when PDDRIVER is copying data all other driver fork activity stops, your
Xscheduler stops, software timers stop, cluster lock management stops, etc.
Xsince you're spending perhaps significant amounts of time at IPL$_SYNCH.
X
XIt's because of this that response time (e.g. - elapsed time for I/O) may
Xactually be slower for PDDRIVER than it is for a real disk.  A real disk
Xdriver sets up a DMA transfer and then places itself in a wait state, waitin
Vg
Xfor the device to interrupt.  When the device interrupts a fork process is
Xqueued, which is used to do device-dependent post-processing and eventually
Xhand the IRP off to IOC$IOPOST for device-independent post-processing.  Whil
Ve
Xthe driver is waiting for the interrupt your system is doing other things,
Xlike dealing with other driver fork processes, processing the software timer
Xinterrupts, doing cluster lock management, and processing scheduler interrup
Vts.
X
XIn theory a RAM disk *ought* to be faster than a real disk, since there's no
Xrotational latency and memory is faster than spinning an oxide plow.  One
Xobvious way to make a faster RAM disk is to use a MOVC3 instruction rather
Xthan moving data a byte at a time.  The other obvious way to improve respons
Ve
Xis to not spend so much time at IPL$_SYNCH.
X
XVMS device drivers operate at a variety of IPLs in order to synchronize thei
Vr
Xactivity at various phases of processing an I/O request.  One of those phase
Vs,
XFDT processing, happens at IPL$_ASTDEL (2).  Response time could be improved
Xif we could do the data transfer in the FDT routines and avoid the start I/O
+-+-+-+-+-+-+-+-  END  OF PART 4 +-+-+-+-+-+-+-+-
-- 
gkn	Gerard K. Newman		gkn@sds.sdsc.edu	619.534.5076
	San Diego Supercomputer Center	gkn@sdsc.bitnet		619.534.5152 FAX
	PO Box 85608			sdsc::gkn (27.1/span)
	San Diego, CA  92186-9784	ucsd!gkn

