Ultrix-3.1/sys/sas/README


	ULTRIX-11 V3.0 changes to stand-alone system.

	Fred Canter 6/20/85

	The 1K file system caused all the stand-alone program to grow a
	bunch. Many of them got too big! This required shrinking libsa.a.
	This was accomplished by changing the NBUF definition in saio.h
	from 4 to 1. This saved 3K bytes in buffers, but limits the max
	size of files the stand-alone system can load to 260 Kbytes, i.e.,
	a single indirect block.

	The #define NO_FIO was also added to SYS.c. This removes all code
	that deals with accessing files thru the file system. NO_FIO is
	used to shrink programs like RABADS that only access physical devices
	and don't need the file I/O support code.

	*note - there are other changes I need to document someday!

	The new boot program size limit is 55552 bytes. This makes sure that
	when the block zero boot program (??uboot) loads the secondary boot
	program (/boot), /boot does not overwrite the block zero boot.
	The following is the memory layout for uboot and boot.

		+---------------+ 0
		| boot		|
		| max size is	|
		| 55552 bytes	|
		|		|
		|		|
		+---------------+ 0154400
		| buf		|
		| 1024 bytes	|
		|		|
		+---------------+
		| stack & data	|
		| 256 bytes	|
		+---------------+ 0157000
		| ??uboot	|
		| 512 bytes	|
		+---------------+ 0160000

		V7M-11 V1.1 NEW STANDALONE PROGRAM FORMAT

		Fred Canter 12/19/83


	PROBLEMS

	1.	Some of the standalone programs, dskinit & restor mainly,
		became so large that they used all of the virtual address
		space available in the PDP-11. The 56 Kbyte program size
		limit prevented the addition of new features to the stand-
		alone programs.

	2.	Because KISA6 was used to map both the stack and program data
		space, there was no way to prevent a stack overflow from
		overwriting the program. This lead to unexplained crashes after
		almost any modification that increased the size of the program.

	SOLUTION

	The standalone programs have been divided into two segments, the program
	segment and the syscall segment. Previously, a standalone program was
	created by linking the program to the standalone library (/lib/libsa.a).
	The standalone library simulated the V7M-11 kernel environment for the
	program. Libsa.a consists of: trap handler, terminal I/O routines, 
	printf, system calls, and device drivers.

	There is a reasonably clean functional separation between the program
	and the standalone library. The linkages between them are mostly via
	the stack and there is very little common code. This provides for a
	clean segmentation of the standalone programs, i.e., the entire program
	need not be permanently mapped into memory at all times.

	CAVEATS

	1.	The syscall segment must be loaded each time a program is
		loaded because there is no way to reinitialize MSCP disk
		controllers (ra_openf). It would speed things up a bit if
		the syscall segment could be loaded with the first program
		only.

	2.	Calls to the routine _stop always cause a trap, this problem
		exists in the old standalone program format as well.

	3.	A standalone program cannot open a file and read from it. A
		program can only open and read physical devices. The getc
		and getw functions must be used to get data from a file in
		the file system. As yet, none of the standalone programs use
		this feature. This restriction does not apply to BOOT.

	4.	Standalone program trap handling has not been completely test
		yet.

	The new virtual address layout of a standalone program is as follows:

		+---------------+
	KISA0	|    PROGRAM	|
		+    SEGMENT	+
	KISA1	|      or	|
		+    SYSCALL	+
	KISA2	|    SEGMENT	|
		+		+
	KISA3	|		|
		+		+
	KISA4	|		|
		+		+
	KISA5	|		|
		+---------------+
	KISA6	|    SYSCALL	|
		|   INTERFACE	|
		|      and	|
		|     STACK	|
		+---------------+
	KISA7	|   UNIBUS I/O	|
		+---------------+

	The first six memory management segmentation registers map the program
	segment or syscall segment into the first 48 Kbytes of virtual address
	space as required. The stack and system call interface code is always
	mapped to virtual address 140000 and is 8 Kbytes in length. This allows
	for a large enough stack space to solve the stack overflow problem.
	The syscall interface is the small amount of code needed to be permently
	mapped, that handles the linkages between the two segments. The last
	segmentation register maps to UNIBUS I/O space.

	The Boot and standalone programs are loaded into physical memory as
	follows:

	     0	+---------------+
		|   srt0.o	|  Startup code for program segment
		+		+
		|   program.o	|  The actual program
		|		|
		+		+
		|   sci.o	|  Program resident syscall interface
		+		+
		|   SYS.o	|  exit, stop, and trap handler from libsa.a
		+		+
		|   prf.o	|  Terminal I/O and printf routines
		+		+
		|   libc.a	|  Routines from C library (-lc)
		+		+
		:		:
		:		:
	  48KB	+---------------+
		|   sci.o	|  System call interface code (relocated)
		|		|
		|   stack	|  Stack expanding downwards
	  56KB  +---------------+
		|   unused	|
		|   memory	|
	  64KB	+---------------+
		|   srt1.o	|  Syscall segment startup code & EMT handler
		+		+
		|   libsa.a	|  System calls and device drivers (-lsa)
		+		+
		|   libc.a	|  Routines form the C library (-lc)
		+		+
		|   I/O buffers	|  General I/O and disk bad block buffers
		+		+
		:		:
		:		:
		+---------------+
		|   unused	|
		|   memory	|
	 128KB	+---------------+
		|   M.o		|  BOOT startup code & trap handler
		+		+
		|   boot.o	|  BOOT program (Boot:)
		+		+
		|   libsa.a	|  Standalone library (with syscalls & drivers)
		+		+
		|   libc.a	|  Routines from the C library
		+		+
		:		:
		:		:
		+---------------+
		|   stack	|  A small (512 byte) stack
		+---------------+

	Standalone programs are loaded and executed by the BOOT program.
	The sequence is as follows:

	1.	The primary boot program (block zero disk or magtape boot)
		loads the BOOT program into low memory and starts it a zero.

	2.	The BOOT sets up memory management, relocates itself to 128KB,
		and starts executing at 128KB in user mode. Then prompts with

			Boot:

	3.	The user types the name of the standalone program. The BOOT
		program loads the standalone program segment and syscall segment
		as shown above. The BOOT program then starts the standalone
		program by executing a TRAP instruction.

	4.	The startup code (srt0.o) initializes the program segment,
		copies the syscall interface code to 140000, and starts the
		program running.

	5.	When the program exits control is returned to BOOT via a
		RTT (return from trap).

	The standalone program functions as before, except when one of the
	following routines (syscalls) is called:

		_lseek, _getc, _getw, _read, _write, _open, _close

	Calls to these routines are intercepted by the syscall interface code.
	This code (see sci.s) remaps to the syscall segment and calls the
	routine. When the routine returns, the syscall interface code remaps
	back to the program segment and returns to it. To the program it
	appears that the call functions as it did before.

	The syscall interface code is implemented in two sections, the first
	is resident with the program segment and the second is at virtual
	address 140000. The second segment is relocated from the program 
	segment to 140000 by the startup code, see srt0.s.

	The system call flow is as follows:

	1.	The program segment calls one of the system call functions.

	SEE sci.s

	2.	The call is intercepted by the syscall interface code, which:

		Sets the EMT code

		Saves the return address

		If the call is to _open, copies the file name string into a
		buffer at 140000 after the syscall interface code.
		The address of this buffer is passed to the actual open routine
		instead of the string address in the program segment because
		the program segment is mapped out while open is executing.

		Jumps to the syscall entry point at 140000+.

	3.	The syscall interface code remaps to the syscall segment.

	4.	If the call is a read or write, sets the I/O segmentation flag
		which tells the drivers where the I/O buffer really is, in
		physical memory.

	5.	The code calls the actual routine in the syscall segment
		by executing an emulator trap (EMT).

	SEE srt1.s

	6.	On the first call to the syscall segment, the startup code
		initializes the syscall segment.

	7.	The EMT code is used to dispatch to the actual system call
		routine.

	8.	The called routine executes, then control is returned to the
		syscall interface code via an RTT (return from trap).

	SEE sci.s

	9.	The syscall interface code remaps back to the program segment
		and returns via the saved return address.

	MODIFIED FILES

	File		Previous Delta
	----		--------------
	SYS.c		1.0
	bads.c		1.0
	boot.c		1.1
	conf.c		1.0
	dskinit.c	1.0
	hk.c		1.0
	hp.c		1.0
	prf.c		1.0
	makefile	1.1
	str0.s		1.0
	srt1.s		new file
	sci.s		new file
	sizchk.c	new file
	/sas/contents.*	not under SCCS control
	/sas/td800.*	"
	/sas/td1600.*	"