[comp.os.minix] Loading in protected mode...

kevin@nuchat.UUCP (Kevin Brown) (12/21/90)

In article <3492@bruce.cs.monash.OZ.AU> cechew@bruce.cs.monash.OZ.AU (Earl Chew) writes:
>In <39678@nigel.ee.udel.edu> pillay.kda@exeter.ac.uk writes:
>>>  In the referenced article kevin@nuchat.UUCP (Kevin Brown) writes:
>>>> What I REALLY want is a loader that does its thing in 386 mode so it can
>>>> load the kernel anywhere in memory, not just in the first 640K.
>
>>I wrote a loader for MS-DOS .EXE files for 80x8/6 systems (PCs) which I
>>subsequently used on a target 80186 system. You have to find out what
>>format the relocatable binary code produced by the compiler/linker is stored
>>as. In my case, it was the standard MS-DOS .EXE file structure. See my
>>article 'Relocating Loader for MS-DOS .EXE executable files' in
>>Microprocessors and Microsystems Vol 14, No 7, Sept 1990, pp 427-434.
>
>>To have such a loader under Minix, you have to find out what the
>>ACK compiler produces as relocatable code. The rest is pretty straight
>>forward as all you do is extract the relocatable binary from the file,
>>perform relocation (i.e. fix up the relocating items within the program)
>>and then jump to the entry point of the fixed-up program.
>
>This, I think, misses the point. I think that Andrew would still like Minix to
>load at 0x600 and not necessarily to relocate it. Relocation is trivial (to a
>certain degree) by suitably aligning the load point and reloading the segment
>registers (because Minix only uses the `small' model). What he wishes is to be
>able to load an arbitrarily large kernel image (eg larger than 640k). The
>current problem is that the loader (bootblok.s) moves itelf to some high
>address and begins loading Minix at 0x600. If your kernel image is
>large enough, the loader will quite happily plaster itself with bits
>from the kernel.
>
>bootblok.s can maximise the size of the allowable kernel image by doing as
>shoelace already does --- moving itself to the last 64k below 640k (assuming
>you have more than 640k machine as most do these days). This limits the size of
>kernels to about 586k.

This is not strictly true.  The segment registers have a resolution of 16
bytes.  That is, they form the upper 16 bits of a 20 bit base address (for
8088 mode, that is).  With this in mind, you can place the loader such that 
its end is within 16 bytes of the end of 640K (but make sure you have room 
for any data space the loader might want to use at the end of the loader 
image!).  This is what I have effectively done.

My kernel image is now 638464 bytes in size.  That's with 380 blocks in the
buffer cache and 64 process slots.

While I would like to see the kernel, fs, and mm dynamically allocate 
everything they use, this is a start.  At least my system is now usable
with 8 virtual consoles!  Needless to say, I'm happy.  :-)

Once I have 16 meg, the "need" for a protected-mode loader which dynamically
allocates uninitialized data segments will be greater.

Now, now, Earl...no need to be jealous.  :-) :-) :-)

>What Andrew wishes is for the loader to switch to 32 bit mode to allow loading
>of large kernel images. In 32 bit mode, memory above 1Mb can be accessed. This
>means that large kernel images can be loaded.
>
>The need for this can be reduced somewhat by dynamically allocating many of the
>large buffers required by the kernel (so that the load image is small, even
>though the runtime image is large). Bruce has already done this. It does
>require a patch to stop shoelace from allocating space.

Have you guys patched up the kernel in such a way that this behavior is
portable, i.e. not dependent on the existence of shoelace?  It would be
very nice to be able to allocate arbitrarily large buffer caches and such.  
In fact, it would be real nice to be able to grow the process table on 
demand, too.

Is your system set up so that the data space for the kernel, mm, and fs can
be allocated from memory higher than 1 meg?  I would think this wouldn't be
too hard to implement, although it might require implementing a "global
page table" or something.  Of course, now I'm talking about 386-specific
stuff...

>If you read the kernel code, I think that you will find that the kernel expects
>to be located at the bottom of physical memory. Loading it elsewhere may just
>cause more headaches for mm (more holes to fill).
>
>So if one decides to leave the kernel low, and the size of the kernel image
>exceeds 584k, what does one do about the 384k hole between 640k and 1Mb?
>There's not much one can do, I suppose. The loader would have to load the first
>584k of the kernel below the 640k boundary and the rest of the kernel above
>1Mb. But this causes a problem because things like the BIOS interface and the
>video drivers expect their stuff to live in the 640k-1Mb region. Because of
>this, it is difficult to map things into this region. Moving, for example, the
>BIOS out of this region is probably too difficult.

I was under the impression that, once Minix got started, it didn't use anything
in the BIOS space.  I know it needs it for initialization, though, but that's
about it as far as I know.

>Perhaps the easiest thing to do would be to load the kernel starting at 1Mb,
>leaving memory below 1Mb unused. 

You can probably get away with using memory below 1Mb as uninitialized data
space for some of the kernel structures.  Or you can cause mm to realize that
there's free memory there and it will allocate it when it can.

>With Bruce's 386 implementation, memory below
>640kb can be easily mapped high -- other implementations may have a hole to
>fill. Now, the problem is --- how do you start Minix? Loading above 1Mb is
>possible with minimal effort, even using the current shoelace code. However,
>the loader would have to switch to protected mode to execute code above 1Mb.
>This is possible with a little trickery I presume.

Well, how does the kernel switch to protected mode to begin with?  I would
think you could use the same technique.  Pardon my simplicity, but why can't
you simply move the code to do this from the kernel bootstrap procedure to
the loader?

>Hmmm... sounds interesting... I might do this in the new year... now if someone
>would like to donate some memory so that I have something to load into above
>1Mb :-)

Ouch.  No memory above 1M?  I don't know if I would be able to live with
that.  I can barely live with 8 meg.  :-)

Jealous flames redirected to /dev/null.  :-) :-) :-) :-)

>Earl


--
			Kevin Brown
		Addresses in preferred order:
		    csci31f7@cl.uh.edu 
		nuchat!kevin@uunet.uu.net

cechew@bruce.cs.monash.OZ.AU (Earl Chew) (12/23/90)

In <1990Dec21.061152.22251@menudo.uh.edu> kevin@nuchat.UUCP (Kevin Brown) writes:

>>you have more than 640k machine as most do these days). This limits the size of
>>kernels to about 586k.

>This is not strictly true.  The segment registers have a resolution of 16
>bytes.  That is, they form the upper 16 bits of a 20 bit base address (for
>8088 mode, that is).  With this in mind, you can place the loader such that 
>its end is within 16 bytes of the end of 640K (but make sure you have room 
>for any data space the loader might want to use at the end of the loader 
>image!).  This is what I have effectively done.

Yes. What you say is true. For shoelace I had to invoke the `64k dma rule'
hence 640k-64k=586k.

>Once I have 16 meg, the "need" for a protected-mode loader which dynamically
>allocates uninitialized data segments will be greater.

>Now, now, Earl...no need to be jealous.  :-) :-) :-)

I suppose that until I get another 1-3Mb, my need won't be so great --- so you
might have to be patient :-)

>Have you guys patched up the kernel in such a way that this behavior is
>portable, i.e. not dependent on the existence of shoelace?  It would be
>very nice to be able to allocate arbitrarily large buffer caches and such.  
>In fact, it would be real nice to be able to grow the process table on 
>demand, too.

I'm not really in a position to answer these are Bruce's mods and I am not
using them yet (remember, I've got the `little' machine).

>I was under the impression that, once Minix got started, it didn't use anything
>in the BIOS space.  I know it needs it for initialization, though, but that's
>about it as far as I know.

bios_wini uses the bios. tty uses the video page(s).

>You can probably get away with using memory below 1Mb as uninitialized data
>space for some of the kernel structures.  Or you can cause mm to realize that
>there's free memory there and it will allocate it when it can.

This is painful. PC memory is already fragmented. Using paging to provide a
clean map is easiest (until VM comes).

>Well, how does the kernel switch to protected mode to begin with?  I would
>think you could use the same technique.  Pardon my simplicity, but why can't
>you simply move the code to do this from the kernel bootstrap procedure to
>the loader?

I suppose so, but there may be complications when the kernel wants to set up
page tables then switch to paged mode when it's already in paged mode!

>Ouch.  No memory above 1M?  I don't know if I would be able to live with
>that.  I can barely live with 8 meg.  :-)

I used to live in 16k many years ago. 1M is comparative bliss. Actually, those
with C&T 386 chipsets can reclaim lots of shadow ram and get most of their
lower 1M back.

Merry Christmas

Earl
-- 
Earl Chew, Dept of Computer Science, Monash University, Australia 3168
EMAIL: cechew@bruce.cs.monash.edu.au PHONE: 03 5655447 FAX: 03 5655146
----------------------------------------------------------------------