1. 7

  2. 3

    My very first *nix job was as a sysadmin for a xenix installation. And my very first task was to figure out how to make Wyse 60 terminals work correctly with it. We were using ProgressDB and needed the line drawing characters to work correctly. The solution involved hacking/fiddling with termcap.

    Ignoring my nostalgia, however, it was really amazing how a 286/386 based machine could hold up work for a handful of people on terminals (vs the 1 to 1 computer to user ratio that the DOS model was driving).

    1. 1

      There was a Xenix port to the 8086, with no MMU or paging. From what I understand, it was fairly usable for a single user workstation.

      1. 2

        If you’re willing to limit yourself to at most 64 KiB per process, the 8086’s segmentation let you do some ad-hoc memory protection. DOS COM binaries worked like this. They promised not to modify the segment descriptor registers and so could be dynamically relocated. They could even have a brk-like interface, which let them request more memory and dynamically grow up to the 64 KiB limit (though the limit wasn’t enforced, so out-of-bounds accesses could clobber another segment). If you were willing to give up on storing stack pointers on the heap, you could make the stack and data segments separate, giving you 64 KiB of code, 64 KiB of stack, and 64 KiB of globals + heap per process. I seem to remember that PL/M had a model that fitted with this, with different types for heap, global, and stack pointers so that you could store all of these in separate segments. You could also implement shared libraries if your calling convention for them used a far call instruction (which pushed cs and ip to the stack and popped them both on return, jumping to a new code segment and address).

        Once the 286 came along, anything that used an ABI with this kind of model could retrofit memory safety quite easily. Now the segment registers were extended from 16-bit addresses (left-shifted by 4 to give the world’s worst 20-bit address space design) to 16-bit entries into one of two 15-bit tables, so you could just define the four segments as bounded ranges and move things around as necessary.

        Minix made a lot of use of this. Minix 2 had a configuration that ran on 8086 and 80286 machines.