[comp.os.minix] Virtual addresses

dave@csis.dit.csiro.au (David Campbell) (05/09/91)

Can somebody please elaborate on the role of virtual addresses in Minix
running under a 680x0 architecture with an MMU.  What sort of remapping
of the address space is performed by the MMU in ports to this
architecture?  Do processes see their memory starting at 0 or what?

I'm doing some severe hacking inside a 68000 version of Minix and I'm
looking towards future compatiblity.  I'm not familiar with the MMU
(yet).

Thanks.
Dave Campbell
dave@csis.dit.csiro.au
-- 
dave campbell

HBO043%DJUKFA11.BITNET@cunyvm.cuny.edu (Christoph van Wuellen) (05/11/91)

I do not know what exactly has been done around -- but:

Future versions of 68K MINIX with MMU have the following features:
- all processes have virtual addresses starting at zero (or, near zero.
  It is sensible to leave the first 8K or so unused to trace NIL pointer
  dereferences)

- there will be memory protection

This does not change the layout of the system binaries, for example.
These are actually relocated for use at address zero, but there is
relocation info that allows MM to relocate it. In 68K-MMU-MINIX, you can
use the same binaries and just ignore the relocation info.

How it is done in practise is under discussion. Opinions go from
- integrating MM in the kernel
to
- leaving MM as it is, but expanding the MM-Kernel interface.


Surely, FS and MM will have their own address space like every other process,
most likely, the kernel uses a 'flat' address space.


C>v.W.

tsarna@polar.bowdoin.edu (Tyler Sarna) (05/16/91)

CvW writes:

> I do not know what exactly has been done around -- but:

Do you know if anything has been done?
	
> Future versions of 68K MINIX with MMU have the following features:
> - all processes have virtual addresses starting at zero (or, near zero.
>   It is sensible to leave the first 8K or so unused to trace NIL pointer
>   dereferences)
> - there will be memory protection

My thoughts exactly.

> This does not change the layout of the system binaries, for example.
> These are actually relocated for use at address zero, but there is
> relocation info that allows MM to relocate it. In 68K-MMU-MINIX, you can
> use the same binaries and just ignore the relocation info.

Yes. The kernel can even be written to detect the MMU and run
like normal Minix if it's not present.

> How it is done in practise is under discussion. Opinions go from
> - integrating MM in the kernel
> to
> - leaving MM as it is, but expanding the MM-Kernel interface.

I vote for #2. 

> Surely, FS and MM will have their own address space like every other process,
> most likely, the kernel uses a 'flat' address space.

FS and MM can be flat too. It might be easier.

One thing I'd like is the ability for processes to expand so
that when a process grows past it's chmem'd limit, it just gets
bigger. This could be done with swapping.

--
Tyler "Ty" Sarna                       tsarna@polar.bowdoin.edu

     "Navy. It's not just a job, it's $98.76 a week." -SNL

HBO043%DJUKFA11.BITNET@cunyvm.cuny.edu (Christoph van Wuellen) (05/16/91)

I have heard of some implementations of MINIX on advanced 68K machines,
but I do not know if they really use the MMU.

I would ask the SPARC MINIX guys first. Maybe they have the MMU MINIX
you are searching for. Although the SPARC processor is different from
others, the MMU principles are often pretty similar across architectural
borders.

C.v.W>

hp@vmars.tuwien.ac.at (Peter Holzer) (05/17/91)

tsarna@polar.bowdoin.edu (Tyler Sarna) writes:

>CvW writes:

>> How it is done in practise is under discussion. Opinions go from
>> - integrating MM in the kernel
>> to
>> - leaving MM as it is, but expanding the MM-Kernel interface.

>I vote for #2. 

I vote for #1. As far as I can see, MM does very little without aid by
the kernel, so making separating it from the kernel makes things more
complicated, not easier. (Maybe the 64k segment limit of the 8086 was
the reason to separate it from kernel, I don't know the sizes offhand)
Process control should go into the kernel, IMHO. (I guess, I will get a
lot of flames for this)

In fact I don't really like the Minix Servers. They have to know much
too much about processes to work properly. If a process forks or exits
all servers need to know about this (This is not a problem now, because
there are only two, and one of them (MM) is responsible for this type
of events anyway, but consider a system which has many servers (FS, MM,
remoteFS, some graphics server, ...)

>> Surely, FS and MM will have their own address space like every other process,
>> most likely, the kernel uses a 'flat' address space.

>FS and MM can be flat too. It might be easier.

They are not flat now on 80x86 Minix. I see no reason to introduce such
a big conceptual difference between PC-Minix and Atari-Minix.

>One thing I'd like is the ability for processes to expand so
>that when a process grows past it's chmem'd limit, it just gets
>bigger. This could be done with swapping.

This won't work because the Stack grows downward from the chmem'ed
address. When stack and heap meet, you cannot just expand your
data/stack segment and copy the stack to its new location without
invalidating all pointers pointing into the stack area (e.g. argv). 

But, most programs only use limited stack space but want to malloc lots
of data. So you could reserve a limited area at the _beginning_ of the
data space for the stack and the heap can grow to the end of RAM.

Of course what I really would like is a MMU that uses signed addresses
and both an upper and a lower bound of the segment.
The heap grows into the positive area and the stack into the negative.
You can simulate this with MMUs that fit segment+offset into 32 bit by
using segment 0 for data and segment ((unsigned) -1 % (NO_OF_SEGS) 
for the stack or by paging.

--
|    _  | Peter J. Holzer                       | Think of it   |
| |_|_) | Technical University Vienna           | as evolution  |
| | |   | Dept. for Real-Time Systems           | in action!    |
| __/   | hp@vmars.tuwien.ac.at                 |     Tony Rand |

st12a@menudo.uh.edu (richard henderson~) (05/17/91)

In article <1991May16.171429.438@email.tuwien.ac.at>
	hp@vmars.tuwien.ac.at (Peter Holzer) writes:

>I vote for #1. As far as I can see, MM does very little without aid by
>the kernel, so making separating it from the kernel makes things more
>complicated, not easier. (Maybe the 64k segment limit of the 8086 was
>the reason to separate it from kernel, I don't know the sizes offhand)
>Process control should go into the kernel, IMHO. (I guess, I will get a
>lot of flames for this)

It does violate the ring protection scheme, however, things might just
run a bit faster if the system task and the mm were merged; there would
be no waiting for the task switch.

>>One thing I'd like is the ability for processes to expand so
>>that when a process grows past it's chmem'd limit, it just gets
>>bigger. This could be done with swapping.
>
>This won't work because the Stack grows downward from the chmem'ed
>address. When stack and heap meet, you cannot just expand your
>data/stack segment and copy the stack to its new location without
>invalidating all pointers pointing into the stack area (e.g. argv). 

Not true.  Simply put the stack at the "top" of addressable memory for
each process and leave the memory between _brk and sp unmapped.  That
way, when the stack grows, a page fault is generated, and the os tacks
on more memory.  When brk(2) is called, more memory is tacked on from 
the bottom end.

At least, that is how it works on 80386 and 68020 and better.  I do not
know if a 68000 with MMU can generate faults instead of exceptions.
(Faults are restartable, exceptions are not).

This was something that I had been hoping for when I found out about the
386 patches.  By-the-by, have the people working on vm for minix gotten
that far?

----------
richard~
richard@stat.tamu.edu
st12a@menudo.uh.edu

tsarna@polar.bowdoin.edu (Tyler Sarna) (05/17/91)

Peter Holzer <hp%VMARS.TUWIEN.AC.@@VM1.NoDak.EDU> writes:

> tsarna@polar.bowdoin.edu (Tyler Sarna) writes:
> >CvW writes:
> 
> >> How it is done in practise is under discussion. Opinions go from
> >> - integrating MM in the kernel
> >> to
> >> - leaving MM as it is, but expanding the MM-Kernel interface.
> 
> >I vote for #2.
> 
> I vote for #1. As far as I can see, MM does very little without aid by
> the kernel, so making separating it from the kernel makes things more
> complicated, not easier. (Maybe the 64k segment limit of the 8086 was
> the reason to separate it from kernel, I don't know the sizes offhand)
> Process control should go into the kernel, IMHO. (I guess, I will get a
> lot of flames for this)

Yes, but this is such a major change that the resultant system
would barely be minix anymore, and any possibility of upgrading
to a new version of Minix (say 2.0) would be virtually nil. Not
that the whole venture itself doesn't imply many, many changes,
but the number should be kept as low as possible.

> >> most likely, the kernel uses a 'flat' address space.
> 
> >FS and MM can be flat too. It might be easier.
> 
> They are not flat now on 80x86 Minix. I see no reason to introduce such
> a big conceptual difference between PC-Minix and Atari-Minix.

Who said Atari? This applies to any 68k minix (sorry, pet
peeve). This is not "introducing", so much as keeping things the
way they are now.

> >One thing I'd like is the ability for processes to expand so
> >that when a process grows past it's chmem'd limit, it just gets
> >bigger. This could be done with swapping.
> 
> This won't work because the Stack grows downward from the chmem'ed
> address. When stack and heap meet, you cannot just expand your
> data/stack segment and copy the stack to its new location without
> invalidating all pointers pointing into the stack area (e.g. argv).

Sure it will work. If things not being in the same place in
memory was in insurmountable problem, we wouldn't now be talking
about virtual addreses, would we? The MMU can be used to map the
bottom of the data segment right after the code segment, and the
top of the segment at the top of the virtual address space. If
the stack of data space needs to grow, we simply move the stack
space up in real memory. The mapping takes care of everything.

> But, most programs only use limited stack space but want to malloc lots
> of data. So you could reserve a limited area at the _beginning_ of the

Look at the GNU tools. They allocate massive amounts of space on
the stack with alloca.

At any rate, it looks doable to me.

--
Tyler "Ty" Sarna                       tsarna@polar.bowdoin.edu

     "Navy. It's not just a job, it's $98.76 a week." -SNL

HBO043%DJUKFA11.BITNET@cunyvm.cuny.edu (Christoph van Wuellen) (05/17/91)

Of course, if you want to forget chmem, you have to allocate the stack
at the upper region of the (4GB) virtual address space.

C.v.W>

hp@vmars.tuwien.ac.at (Peter Holzer) (05/17/91)

st12a@menudo.uh.edu (richard henderson~) writes:

>In article <1991May16.171429.438@email.tuwien.ac.at>
>	hp@vmars.tuwien.ac.at (Peter Holzer) writes:

>> [proposed merging kernel and MM]

>It does violate the ring protection scheme, however, things might just
>run a bit faster if the system task and the mm were merged; there would
>be no waiting for the task switch.

This is true. It is cleaner if user processes never communicate
directly with the kernel but only with servers. That reminds me, that I
have not yet discovered any scheme that prevents user processes from
sending messages to kernel tasks except code in these tasks like:
if (sender != FS && sender != MM) panic ();
That would make a great way to reboot without pressing ctrl-alt-del :-)
(I haven't tried it yet, though).


>>>One thing I'd like is the ability for processes to expand so
>>>that when a process grows past it's chmem'd limit, it just gets
>>>bigger. This could be done with swapping.
>>
>>This won't work because the Stack grows downward from the chmem'ed
>>address. When stack and heap meet, you cannot just expand your
>>data/stack segment and copy the stack to its new location without
>>invalidating all pointers pointing into the stack area (e.g. argv).

>Not true.  Simply put the stack at the "top" of addressable memory for
>each process and leave the memory between _brk and sp unmapped.  That
>way, when the stack grows, a page fault is generated, and the os tacks
>on more memory.  When brk(2) is called, more memory is tacked on from
>the bottom end.

You have to add paging to do that (at least on the 386, I do not know
about 68k MMUs) and Andy doesn't like paging at all
(As far as I know even Amoeba doesn't page), so we have little chance
to add this to standard minix. My proposal is a small change that could
easily be added to Minix and works with or without MMU. Of course it is
not quite as flexible but much simpler. Even with paging I would stay
with the current scheme of chmem'ing programs (only chmem every program
to 16MB or so) because it gives the kernel simultaneous access to all
processes. Minix does copy lots of data between user processes and the
servers so I think barring the kernel from seeing both of them is not a
good idea (Of course you could reserve 1GB for a user proc., 1 GB for a
server, and 1 for the kernel tasks and one for the interrupt
multiplexer, but I think this is ugly).

On a related note why, is shadowing used in 68k minix? You could
simulate an MMU by reserving one register for a base address and do all
addressing relative to this register. Has anyone tried this approach and
timed it? How much slower is it in the normal case (exec immediately
after fork) and how much faster would programs be that use parallel
processes (e.g. kermit)?

--
|    _  | Peter J. Holzer                       | Think of it   |
| |_|_) | Technical University Vienna           | as evolution  |
| | |   | Dept. for Real-Time Systems           | in action!    |
| __/   | hp@vmars.tuwien.ac.at                 |     Tony Rand |

hp@vmars.tuwien.ac.at (Peter Holzer) (05/17/91)

tsarna@polar.bowdoin.edu (Tyler Sarna) writes:

>Peter Holzer <hp%VMARS.TUWIEN.AC.@@VM1.NoDak.EDU> writes:

>> [...]
>> Process control should go into the kernel, IMHO. (I guess, I will get a
>> lot of flames for this)

>Yes, but this is such a major change that the resultant system
>would barely be minix anymore, and any possibility of upgrading
>to a new version of Minix (say 2.0) would be virtually nil. Not
>that the whole venture itself doesn't imply many, many changes,
>but the number should be kept as low as possible.

Well, of course this change should be incorporated into 2.0 (ducks).

>> >> most likely, the kernel uses a 'flat' address space.
>>
>> >FS and MM can be flat too. It might be easier.
>>
>> They are not flat now on 80x86 Minix. I see no reason to introduce such
>> a big conceptual difference between PC-Minix and Atari-Minix.

>Who said Atari? This applies to any 68k minix (sorry, pet
>peeve). This is not "introducing", so much as keeping things the
>way they are now.

Sorry, of course I meant 68k-Minix in general, not just Atari-Minix.
They are identical at this level, aren't they?

How does FS copy data from a user process into its buffers? On the PC
it sends a message to systask to copy the data. Does it the same on 
68K-Minix (You see, I learn :-), or does it copy directly (via memcpy).
I know it could do it directly, because all processes share the same
address space, but I don't think it does.


>> >One thing I'd like is the ability for processes to expand so
>> >that when a process grows past it's chmem'd limit, it just gets
>> >bigger. This could be done with swapping.
>>
>> This won't work because the Stack grows downward from the chmem'ed
>> address. When stack and heap meet, you cannot just expand your
>> data/stack segment and copy the stack to its new location without
>> invalidating all pointers pointing into the stack area (e.g. argv).

>Sure it will work. If things not being in the same place in
>memory was in insurmountable problem, we wouldn't now be talking
>about virtual addreses, would we? The MMU can be used to map the
>bottom of the data segment right after the code segment, and the
>top of the segment at the top of the virtual address space. If
>the stack of data space needs to grow, we simply move the stack
>space up in real memory. The mapping takes care of everything.

There are two kinds of VM: Segmentation and paging. Minix now (on 80x86
machines) uses segmentation. So for each segment, physical address is
base address + virtual address. If the maximum segment size is larger
than physical memory, you can create one segment with base address zero
and size == physical mem. size that covers all existing memory and can
be used to access memory inside all other segments (e.g. for copying
data from one segment to another). This is done on the 386. If a
pointer is large enough to hold both the segment number and the offset,
you can use separate segments for stack and data. Both can grow
independently and be copied to different physical addresses as you
said. I think most MMU's for 68k-processors that support segmenting do
it like this so you have no problem and can forget chmem. On Intel
processors however (sorry for mentioning that brain-damage, but I have
one, so I have to cope with it) segment and offset do not fit into one
machine word, so you have two possibilities: Either you split your
pointers over two machine words, which makes C-programs rather
inefficient (because optimizers don't cope well with such huge
variables and loading segment registers is costly) or you put stack and
data into the same segment. This was done on Minix, and is the reason
for the chmem kludge.

The second possibility is to use paging. Give every process the whole
address range of virtual memory, map only pages that are actually used
to physical memory and change this mapping on every context switch.
This is done in every Unix-implementation I know, and it works well,
because kernel and the active process share the same virtual memory. On
Minix, it is ugly, because FS and MM are in fact user processes
(although privileged0 ones) and they frequently have to ask the kernel
to copy data from them to their clients and vice versa. So the kernel
would have to switch between page tables frequently while copying or it
would have to construct a special page table which contains the address
space of both processes just for copying. (Reserving a range for each
layer as I mentioned in my last posting, doesn't help much, because MM
and FS are also calling each other, and when (or if) other servers are
added, the situation gets worse)

>> But, most programs only use limited stack space but want to malloc lots
>> of data. So you could reserve a limited area at the _beginning_ of the

>Look at the GNU tools. They allocate massive amounts of space on
>the stack with alloca.

Hmm, I hadn't thought of that. But anyway, even they seem to use much
less stack than heap. I have seen gcc use 40MB heap, but it never
exceeded its stack limit of 512k on our DECstations.

>At any rate, it looks doable to me.

I don't doubt it is doable if you have a sane MMU. I just wanted to
propose a solution that is independent of the MMU and works with minor
changes to the compiler even without one.

--
|    _  | Peter J. Holzer                       | Think of it   |
| |_|_) | Technical University Vienna           | as evolution  |
| | |   | Dept. for Real-Time Systems           | in action!    |
| __/   | hp@vmars.tuwien.ac.at                 |     Tony Rand |

evans@syd.dit.CSIRO.AU (Bruce.Evans) (05/17/91)

In article <1991May16.171429.438@email.tuwien.ac.at> hp@vmars.tuwien.ac.at (Peter Holzer) writes:
>
>I vote for #1. As far as I can see, MM does very little without aid by
>the kernel, so making separating it from the kernel makes things more
>complicated, not easier.

There's one very important thing that it does that won't work from the
kernel: calling FS to read() executables.

>(Maybe the 64k segment limit of the 8086 was
>the reason to separate it from kernel, I don't know the sizes offhand)

kernel+mm would fit easily. fs data space (cache) would not fit. I think
the linker for an ancient version did not support separate I&D. 64K is
much more limiting than 64K+64K.
-- 
Bruce Evans		evans@syd.dit.csiro.au

leo@krabat.marco.de (Matthias Pfaller) (05/21/91)

In article <53697@nigel.ee.udel.edu>, tsarna@polar.bowdoin.edu (Tyler Sarna) writes:
> CvW writes:
> 
> > I do not know what exactly has been done around -- but:
> 
> Do you know if anything has been done?
> 	
> > Future versions of 68K MINIX with MMU have the following features:
> > - all processes have virtual addresses starting at zero (or, near zero.
> >   It is sensible to leave the first 8K or so unused to trace NIL pointer
> >   dereferences)
> > - there will be memory protection
> 
> My thoughts exactly.
Ok,
but I have to remember that there is a very nice chip called 68070.
This chip is a sort of 68010 with serial I/O, Timer, two DMA-Channels and
a segmented mmu.
With this mmu you can split the address-space of every process in 8 segments
of 2mb each. A segment is specified by a base-address (1k-aligned) and a
length (also in 1k-units). You can make segments where the address specifies
the upper bound of the segment (for the stack) and segments where the address
specifies the lower bound of the segment. If you wish to run a normal
minix-68k binary on a system where such a mmu is in use, you have to
specify the textsegment as a downward-growing segment and the data segment
as an upward growing segment. Thus on the 68070 not the BASE-address of the
textsegment but the END-address of the textsegment is fix.
The mmu provides 8 on-chip segmentregisters.
	Matthias Pfaller (leo @ marco.de)

PS: There is at least one comercial computer with this CPU; see comp.os.os9.

feustel@netcom.COM (David Feustel) (05/22/91)

Oh My GOD!!! A 68k chip infected with the SEGMENT VIRUS!!! 
-- 
David Feustel, 1930 Curdes Ave, Fort Wayne, IN 46805, (219) 482-9631
EMAIL: feustel@netcom.com  or feustel@cvax.ipfw.indiana.edu

HBO043%DJUKFA11.BITNET@cunyvm.cuny.edu (Christoph van Wuellen) (05/22/91)

Compared to 80386, 68030, SPARC etc, the MMU of the 68070 is somewhat
exotic. Perhaps I will think about making a small CPU card of this and
plug it into my homemade box.

I remember that the 68070 is slower than the 68000 at the same clock speed.

C.v.W.