The former ran on machines such as the PDP-11/05 and similar machines, and the latter was intended for the PDP-11/03, which used the LSI-11 procesor. MINI-UNIX was the more capable of the two; its kernel was less cut-down than LSX's, and it could support multiple simultaneous users. (LSX was intended for systems with the absolute minimum amount of main memory; a real concern with early LSI-11's, which often came with limited amounts of expensive core memory.)
In the classic computer world, LSI-11's are still relatively easy to find, and not expensive, and people who have them would like to run an early Unix. Although MINI-UNIX is the more capable, it does not run on LSI-11's 'out of the box'. However, there are no major fundamental differences between the LSI-11 and the models MINI-UNIX was intended for. MINI-UNIX was actually historically moved to the LSI-11; however, that version is apparently now lost. It has recently been moved to the LSI-11 again; this page provides the code needed to run it on the LSI-11 (either real hardware, or a simulator), and explains how to do it.
A pre-built -11/03 MINI-UNIX is not made available (although it would be possible to do so); instead, you'll have to build it yourself. The advantage of this approach is that it will teach you a lot about MINI-UNIX in the process. It's not hard, so it's not a major imposition.
Note that LSI-11's only work with Q18 memory, so most 256KB boards (both DEC and off-brand), which are Q22, won't work with an LSI-11.
It is also recommended that LSI-11's have the KEV11 EIS chip (either an -A or the rumoured -B); this will allow the build to omit the EIS emulator code, and save memory. (This obviously applies to simulated systems as well as real ones.)
(It is possible to increase the amount of space for the kernel, but this requires re-linking every single user command, including the shell and 'init'. Not recommended.)
Note: DON'T just follow this document blindly; it may be out of date. Instead, read it to get an idea of how the whole process works, and then look to see what you've actually got on disk, and then go from there.
This site also contains much useful information, including this collection of documents.
Unix kernels consists of a number of smallish relocatable binary modules which statically linked into a large object code image; during booting, that image is loaded into memory and started. After the usual initialization, the '0th' process (which in V6 has the task of swapping processes in and out) is hand-crafted; if then 'forks' into two, using the standard Unix fork() system call (which creates a 'clone' of the existing process).
The second process then runs a tiny program (the binary for which is built into the kernel) which does an 'exec()' system call, to read in and run "/etc/init". That process/command then does another fork(), and the child process from that exec()'s the shell (command interpreter, in "/bin/sh").
"/usr/sys" is where new kernel loads are built; two shell command files are relevent. "shld" contains the command to actually build a kernel image. "run" is a longish commad file which builds a number of different kernel images for different disk devices.
"/usr/sys/mxsys" is where the main sources for the kernel are found. They
are all in
C,
except for two files in
assembly language:
"mch.s", which contains things like a number of low-level operations
inaccessible from C, low-level initialization code, etc; and "low.s", which
contains
interrupt vectors.
"/usr/sys/dev" contains the sources for the low-level device drivers - the
parts which talk to the actual device hardware. Two higher-level modules
of device code, "bio.c" (which deals with the block-structure mass storage
devices which hold the file system(s)) and "tty.c" (which deals with the
serial lines through which users interact with the system) are in "mxsys".
The MINI-UNIX linker, which normally creates binaries starting at 060000, can
do kernels (which start at 0); there's a special flag, '-a', to say 'link at
0'.
Instructions on how to bring up V6, including how build a new version of its
kernel (very similar to the procedure for MINI-UNIX, so a good learning
experience) are available
here
and
here.
The one exception to the above observations about the dual applicability of
the V6 tool-chain is that MINI-UNIX requires user commands to be linked to
run at a high address (usually 060000, but see below), instead of at 0 as on
standard V6. This is a result of the lack of memory management in systems
that run MINI-UNIX; the kernel and user commands share a single PDP-11
address space,
with the kernel in low memory, and user commands (as processes,
one at a time) in high memory.
So, while operating system images can be built with the standard V6 linker
('ld'), building user command binaries requires a special version of the
linker. This is a lightly edited version of the standard V6 linker; it is
trivial to copy the source over (avilable once a MINI-UNIX disk pack is
mounted), and compile it under V6 to produce
binary
of a MINI-UNIX linker which runs under V6.
That can be used to create, on V6, MINI-UNIX versions of commands, e.g. a
version of the shell which uses 'cd' instead of 'chdir'. (Note that un-linked
relocatable binaries for most commands, etc are the same for both V6 and
MINI-UNIX; they are also the same for all the PDP-11 CPU models on which V6
and MINI-UNIX run. Only one kernel module (mch.o) differs from model to
model.)
One additional issue is that MINI-UNIX uses the 'new' archive format, not
the 'old' one of stock V6; this includes in the linker. There are a number
of ways around this: the so-called
'Shoppa disks'
include a V6 binary for the new archive command ('nar'); MINI-UNIX also
includes the source for it, and like the linker, it can be copied over and
compiled. Dealing with existing libraries (liba.a and libc.a) is left as an
exercise for the reader (hint; the V6 libraries seem to work for MINI-UNIX).
Building MINI-UNIX under MINI-UNIX
Unless you happen to have a working PDP-11/05 with RK drives, the best way
to work with them is to bring a MINI-UNIX system up under a simulator.
Building MINI-UNIX under V6
V6 is an incredibly good system to use as a host because MINI-UNIX uses the
V6
file system,
so one can mount MINI-UNIX disk packs and work on them with standard V6
tools. MINI-UNIX also uses more-or-less the standard V6 tool-chain
(assembler, C
compiler,
and
linker),
so both the MINI-UNIX system, and user commands, can be built using the V6
tools.
Details about Changes Needed for the -11/03
There are three areas where the LSI-11 version needs work, over the
original /05 version:
For the first two, the needed changes are identical to the ones needed to run
the full V6 on the
PDP-11/23,
detailed
here.
(These had all been tested on the /23.) Rather than have anyone make the
exact same changes independently, modified versions of the MiniUnix files for
them
(low.s,
main.c and
param.h)
are available here. (It is also necessary to re-compile sys4.c, once the
new param.h has been down-loaded.)
For the third, I have a modified version of mch.s which has the required changes for the LSI-11, along with a conditional assembly flag.
In addition, there are also really minor edits to bio.c, clock.c, slp.c, and tty.c, to remove in-line accesses to the PS. The DH driver had a similar issue; a fixed version is here.
To avoid having to edit source files to turn configuration conditional assembly flags on and off, those have been moved to separate header files, available here and here. The former goes with low.s (this version provides an RK11 disk controller, and requires the EIS, and so allows the elimination of the EIS emulation package normally included in MINI-UNIX); the latter goes with mch.s. To use them, one says:
as 03mch.s mch.setc. I recommand following that with something like:
mv a.out 03mch.o(most V6 commands do not have the -o flag).
I advise against trying to use 'mkconf'; it is only used to create new conf.c and low.s files, and the existing ones should be good. (In fact, low.s has some needed changes, which mkconf can't generate. So I recommend not using it, since it will trash the low.s with the needed custom changes.)
I also advise running 'nm -ng' on the resulting image, and making sure that the end of the kernel's BSS is less than 056000 (the location of the 'user' structure, unless you've changed the system's layout). If the kernel's data overlays that, the system will die in a horrible and un-predictable way when you start it. (I am adding an automatic check for this on start-up, but I'm having some issues getting it to work properly; the V6 linker is not setting '_end' correctly.)
ld -a -x -r *.o mv a.out syso ar r ../lib1 syso emuloso the constituents (including main.o) don't exist any more as individual files in lib1, so that your build can't use the existing version of un-modified files, but the new versions of the modified ones, with a link command like:
ld -x lowrkne.o conf.o mxsys/03mch.o mxsys/xmain.o mxsys/xsys1.o lib1o lib2o
The linker will try to pull in the monolithic 'syso' (since it contains some missing symbols) and then you'll get a 'multiply defined symbol' error (because it contains old copies of things you have new ones of). Hence the need to create a new lib1, with the individual files in it.
I'm not sure if the files in the library have to be in any particular order (with that early Unix linker, if a module X in a library has an un-resolved external which is met by a different module Y, they have to be in the library in order X,Y since libraries are only searched once).
The order in my lib1o is:
Which library manager version you will have to use to build the new 'lib1' will depend on whether you are doing your build under V6 or MINI-UNIX; i.e. which version of the linker you are using.
That division as to which library bio.o, tty.o, etc is kind of arbitary, though; personal taste as much as anything. Historically, in V6, all the I/O files went in lib2.
Having cone all that, a MINI-UNIX kernel can be created with a very simple command:
ld -x lowrkne.o mxsys/03mch.o conf.o lib1 lib2 mv a.out /03rkmxmostly doing demand loading from the libraries (which is how the distributed V6 was normally built).
I added it to my MINI-UNIX to make it easier to debug the system when I was bringing it up on the LSI-11. It is not required to run MINI-UNIX, though. If you want to include it, here is a copy. (If you leave out the EIS emulator there's plenty of room for it.
I have added a small assembler kernel 'prs()' so the kernel can print things; main() currently calls it for messages about the clock (on hardware -11/03's, the LTC MUST be turned off while booting; so a message pops up once it's safe to turn it on). In the latest version of mch.s; prs() has beeen fixed to save and restore the console CSR.
The 'low.s' (above) can support the RL, but you will need to conditionally assemble support for it; here is a header file for 'low.s', 'lowrkrlne.s', which does that; 'conf.c will also need to have a line added to support the RL block device: here is a copy which has the RL line added.
The RL driver calls several routines which are not normally present in MINI-UNIX (such as 'deverror()'), so this has those. (I suppose I could have diked the calls, but I like to see printout when something goes wrong.)
You'll also need to "mknod /dev/rl0 b 1 0", to provide access to the device from command level; the OS itself doesn't need that special file. Note: the driver probably produces EIS instructions when compiled, so it won't run on a machine without EIS or simulator.
The real problem is that MINI-UNIX looks like it supports switching
around the devices used for the 'root' file system, and for
swapping:
but it doesn't - at least, not easily.
Confusingly, there are ROOTDEV and SWAPDEV constants, set in param.h, but
neither ROOTDEV nor SWAPDEV is used anywhere in the code that I could find!
Instead, there are 'rootdev' and 'swapdev' variables, which is what the code
uses, but they aren't statically initialized:
Note that SWPLO and NSWAP are also set in param.h as constants, so to switch
from one type of drive to another, since they will generally have their swap
partitions in different places, one would have to edit it param.h, and then
re-compile 'the appropriate modules'.
Probably the best solution, overall, it to move them all back info conf.c
as variables, the way V6 had them:
int rootdev; /* dev of root see conf.c */
int swapdev; /* dev of swap see conf.c */
and nothing in the code initializes them (i.e. no 'rootdev = ROOTDEV'). Since
they are in BSS (which is cleared on startup), they are both '0'. So one
could edit param.h all one likes and nothing will happen. So whatever device
is set up in conf.c as block device 0, that's what MINI-UNIX will be trying
to boot/swap off of.
int rootdev {(1 << 8) | 0};
int swapdev {(0 << 8) | 0};
int swplo 4000; /* cannot be zero */
int nswap 800;
so you can have diffenent ones for different configurations (e.g. rkconf.c,
rlconf.c, etc - actually I'd probably have {bd}{ad0}..{adn}conf.c, so
rkrlconf.c would be a system that uses the RK as root, but also has the RL
driver; rlconf.c would be booting off the RL, with no other disk drivers)
without having to re-compile chunks of the system to switch to a different
configuration. This will take almost no extra room (a couple of words,
is all) so seems like the optimal choice. The one given above is allegedly
set to use the 0th disk of major type 1 (hopefully an RL) as the root,
and the back end of 0/0 (hopefully an RK) for swapping. Adjust as needed.
Back to JNC's home page
© Copyright 2020, 2022 by J. Noel Chiappa
Last updated: 14/June/2022