On Wed, 10 Oct 2018 at 21:40, Ethan Gardener <eekee57@fastmail.fm> wrote:
>
> Not sure I would agree with that. The 20 bit addressing of the 8086 and 8088 did not change their 16 bit nature. They were still 16 bit program counter, with segmentation to provide access to a larger memory - similar in principle to the PDP11 with MMU. 

That's not at all the same as being constrained to 64KB memory.  Are we communicating at cross purposes here?  If we're not, if I haven't misunderstood you, you might want to read up on creating .exe files for MS-DOS. 

Agreed, but the PDP11/70 was not constrained to 64KB memory either. 

I do recall the MS-DOS small/large/medium etc models that used the segmentation in various ways to mitigate the limitations of being a 16 bit computer. Similar techniques were possible on the PDP11, for example Modula-2/VRS under RT-11 used the MMU to transparently support 4MB programs back in 1984 (it used trap instructions to implement subroutine calls). 

It wasn't possible under Unix, of course, because there were no system calls for manipulating the mmu. Understandable, as it would have complicated the security model in a multi-tasking system. Something neither MS-DOS or RT-11 had to deal with.

Address space manipulation was more convenient with Intel segmentation because the instruction set included procedure call/return instructions that manipulated the segmentation registers, but the situation was not fundamentally different.  They were both 16 bit machines with hacks to give access to a larger than 64K physical memory.

The OS9 operating system allowed some control of application memory maps in a unix like environement by supporting dynamic (but explicit) link and unlink of subroutine and data modules - which would be added and removed from your 64K address space as required.So more analogous to memory based overlays.


> I went Commodore Amiga at about that time - because it at least supported some form of multi-tasking out out the box, and I spent many happy hours getting OS9 running on it.. An interesting architecture, capable of some impressive graphics, but subject to quite severe limitations which made general purpose graphics difficult. (Commodore later released SVR4 Unix for the A3000, but limited X11 to monochrome when using the inbuilt graphics).

It does sound like fun. :)  I'm not surprised by the monochrome graphics limitation after my calculations.  Still, X11 or any other window system which lacks a backing store may do better in low-memory environments than Plan 9's present draw device.  It's a shame, a backing store is a great simplification for programmers.

X11 does, of course, support the concept of a backing store. It just doesn't mandate it. It was an expensive thing to provide back when X11 was young, so pretty rare. I remember finding the need to be able to re-create windows on demand rather annoying when I first learned to program in Xlib, but once you get used to it I find it can lead to benefits when you have to retain a knowledge of how an image is created, not just the end result.
 
> But being 32 bit didn't give it a huge advantage over the 16 bit x86 systems for tinkering with operating system, because the 68000 had no MMU.  It was easier to get a Unix like system going with 16 bit segmentation than a 32 bit linear space and no hardware support for run time relocation.
> (OS9 used position independent code throughout to work without an MMU, but didn't try to implement fork() semantics).

I'm sometimes tempted to think that fork() is freakishly high-level crazy stuff. :)  Still, like backing store, it's very nice to have.

I agree. Very elegant when you compare it to the hoops you have to jump through to initialize the child process environment in systems with the more common combined 'forkexec' semantics, but a real sticking point for low end hardware.
 
> It wasn't till the 68030 based Amiga 3000 came out in 1990 that it really did everything I wanted. The 68020 with an optional MMU was equivalent, but not so common in consumer machines.
>
> Hardware progress seems to have been rather uninteresting since then. Sure, hardware is *much* faster and *much* bigger, but fundamentally the same architecture. Intel had a brief flirtation with a novel architecture with the iAPX 432 in 81, but obviously found that was more profitable making the familiar architecture bigger and faster .

I rather agree.  Multi-core and hyperthreading don't bring in much from an operating system designer's perspective, and I think all the interesting things about caches are means of working around their problems.

I don't think anyone would bother with multiple cores or caches if that same performance could be achieved without them.  They just buy a bit more performance at the cost of additional software complexity.

I would very much like to get my hands on a ga144 to see what sort of operating system structure would work well on 144 processors with 64KW RAM each. :)  There's 64KW ROM per processor too, a lot of stock code could go in that.  Both the RAM and ROM operate at the full speed of the processor, no caches to worry about.

Interesting. I hadn't come across those before....
 
A little rant about MMUs, sort-of saying "unix and C are not without complexifying nonsense":  I'm sure the MMU itself is uninteresting or even harmful to many who prefer other languages and system designs.  Just look at that other discussion about the penalties of copying versus the cache penalties of page flipping.  If that doesn't devolve into "heavy negativity," it'll only be because those who know don't write much, or those who write much don't want to provide actual figures or references to argue about.

I think if you are going to postulate about this, we need to refine our terms a bit. The term MMU encompasses too many quite different concepts. For example:
1. run time relocation 
2. virtual address space expansion (use more memory than can be directly addressed)
3. virtual memory expansion (appear to use more memory than you physically have)
4. process interference protection
5. process privacy protection
 
I'm sure there are more. For example, on the 68K processors, OS-9/68K had no support for the first three - virtual and physical addresses were always the same. For Unix style timesharing it required all compilers to generate position independent code. There was no swapping or virtual memory. It did use an MMU via a module called SPU - the 'System Protection Unit', which mapped all of your program code as read only, your data as read/write, and made everything else inaccessible. That sort of functionality is invaluable while developing, because you don't want faulty programs to change the kernel or other programs, and trapping attempts to do so makes it easier to identify faults.
However with suitable privileges, any process can request that arbitrary memory addresses be made readable or writable, and if desired, the SPU could be omitted from the system, either removing an MMU  performance penalty or allowing the application to run on cheaper, non-mmu equipped hardware.

The executables were re-entrant and position independent, but one an instance started executing it could not be moved (calculated pointers stored in data etc). So this software solution would not have been enough to support efficient swapping or paging. It was ok in this case, because it was intended as a real-time system and you don't do swapping in that situation.

What about all those languages which don't even give the programmer access to pointers in the first place.  Many have run directly on hardware in the past, some can now.  Do they need MMUs? 
 
Then there's Forth, which relies on pointers even more than C does.  I haven't read *anything* about MMUs in relation to Forth, and yet Forth is in practice as much an operating system as a language.  It runs directly on hardware.  I'm not sure of some details yet, but it looks like many operating system features either "fall out of" the language design (to use a phrase from Ken Thompson & co.), or are trivial to implement. 

There were multitasking Forth systems in the 70s.  No MMU.  The full power of pointers *at the prompt*.  Potential for stack under- and over-runs too.  And yet these were working systems, and the language hasn't been consigned to the graveyard of computing history.  My big project includes exploring how this is possible. :)  A likely possibility is the power to redefine words (functions) without affecting previous definitions.  Pointer store and fetch can trivially be redefined to check bounds.  Check your code doesn't go out of bounds, then "empty", and load it without the bounds-checking store and fetch. 

MMU's are probably more important in multi-user than just multi-tasking systems. The Amiga's, as I mentioned, were multi-tasking without the need for an MMU. The result was a very fast system, resulting in some of the impressive graphics and games. But also the need for frequent reboots when developing.

But you are right, if you try hard enough, you can replace hardware memory management with software - a sandboxed environment with program development tools with strong typing and no low level access. Look, for example, and the old Burroughs B6700 which had a security paradigm based on making it impossible for unprivileged users to generate machine code. Compilers had to blessed with trusted status, and only code generated by trusted compilers would be executed.. I don't recall many details, other than it had an interesting tagged architecture. 

An extreme example would be an emulator - sandboxing users without any actual hardware protection, albeit at significant performance cost.

Forth, Basic and all the other common development environments common on person computers before the MMU availability were fine because there was generally only one user, the language provided a lot or protection/restriction (and was often interpreted), and if you managed to crash it, it was generally quick to restart.
 
So I still tend to feel that MMUs were a valuable advance in computer architecture that I would hate to have to live without..