[OpenBIOS] Running client with MMU off

Mark Cave-Ayland mark.cave-ayland at ilande.co.uk
Tue Jun 17 22:40:31 CEST 2014


On 17/06/14 01:01, BALATON Zoltan wrote:

> On Mon, 9 Jun 2014, BALATON Zoltan wrote:
>>> Therefore for a load/store not to fault on real hardware then that
>>> means the entry is already in the TLB, i.e. it must have already been
>>> accessed AND also not been previously evicted by hash collision (see
>>> hash_page32).
>>
>> Unfortunately PPC has many other ways to translate an address not only
>> via the TLB so this is not that simple. I suspect the TLB is not used
>> on Macs during boot but BAT translation is because MorphOS only
>> disables the MMU during replacing the BAT registers.
>
> In the tests I wrote about here:
>
> http://lists.nongnu.org/archive/html/qemu-devel/2014-06/msg02828.html
>
> I've also tried to find answers to these questions. The results so far
> are here:
>
> http://goliat.eik.bme.hu/~balaton/oftest/results/
>
> It seems BAT registers are not used only a TLB which is near the end of
> the memory like in OpenBIOS.

I had a feeling that would be the case, however I'm glad at least we 
have some evidence to back this up. BTW you mean hash table, not TLB 
here, right?

>>> Hence you need to trace through previous accesses to the addresses
>>> that fault and determine why the entry is no longer in the TLB in
>>> QEMU/OpenBIOS when it should be there on real hardware.
>>
>> The vectors are only accessed by OpenBIOS during the inital copying of
>> the vectors before setting up the MMU then by MorphOS when copying
>> it's vectors that cause the exception which crashes. No other access
>> inbetween so it's not evicted from TLB as it never gets into it.
>>
>>>> Actually after writing the sr0-sr15 and sdr1 registers it clears the
>>>> MMU
>>>> bits and then writes to the ibat and dbat registers and seems to set up
>>>> the TLB and then enable the bits in the MSR. So maybe Apple relies on
>>>> translations in these registers and that's why it works there.
>>>
>>> Not that I have the definitive answer, but I can't see why on earth
>>> Apple would map the trap table with an IBAT/DBAT. My understanding is
>>> that these are designed for optimally mapping large blocks of memory,
>>> e.g. kernels, so why would you implement a second form of translation
>>> in a BIOS environment when you already have limited resources? It
>>> just doesn't make any sense. Plus you still get a fault once you
>>> effectively "preload" the trap table into the TLB with your fake
>>> access above, so something else is still missing from the picture.
>
> The fake access would still be needed I think because otherwise a
> translation for the page starting at 0x1000 would not be in the TLB. The
> fault I got with the fake access was not when writing to 0x1000 like
> without it but accessing the stack that the fake access did not preload.
>
>> With 128MB it will overwrite the stack as I've found earlier here:
>> http://www.openfirmware.info/pipermail/openbios/2014-March/008186.html
>>
>> With 512MB it will freeze after clearing the TLB and replacing BAT
>> registers with it's own values like this:
>>
>> Set IBAT0l to 00000000 (0041ce54)
>> Set IBAT0u to 00000000 (0041ce54)
>> Flush BAT from 00000000 to 00020000 (00000000)
>> Flush done
>> Flush BAT from 00000000 to 00020000 (00000000)
>> Flush done
>> Set IBAT1l to f0000012 (0041ce54)
>> Set IBAT1u to f0001ffe (0041ce54)
>> Flush BAT from 00000000 to 10000000 (0ffe0000)
>> Flush done
>> Flush BAT from f0000000 to 00000000 (0ffe0000)
>> Flush done
>> Set IBAT2l to 00000000 (0041ce54)
>> Set IBAT2u to 00000000 (0041ce54)
>> Set IBAT3l to 00000012 (0041ce54)
>> Set IBAT3u to 00000ffe (0041ce54)
>> Flush BAT from 00000000 to 08000000 (07fe0000)
>> Flush done
>> Flush BAT from 00000000 to 08000000 (07fe0000)
>> Flush done
>> Set DBAT0l to f000002a (0041ce54)
>> Set DBAT0u to f0001ffe (0041ce54)
>> Flush BAT from 00000000 to 10000000 (0ffe0000)
>> Flush done
>> Flush BAT from f0000000 to 00000000 (0ffe0000)
>> Flush done
>> Set DBAT1l to 00000012 (0041ce54)
>> Set DBAT1u to 00001ffe (0041ce54)
>> Flush BAT from 1fdc0000 to 2fdc0000 (0ffe0000)
>> Flush done
>> Flush BAT from 00000000 to 10000000 (0ffe0000)
>> Flush done
>> Set DBAT2l to 00000000 (0041ce54)
>> Set DBAT2u to 00000000 (0041ce54)
>> Set DBAT3l to 8000002a (0041ce54)
>> Set DBAT3u to 80001ffe (0041ce54)
>>
>> and then trying to access a variable on the stack:
>>
>> 0x0041cf40:  lmw     r13,20(r1)
>> 0x0041cf44:  addi    r1,r1,96
>> 0x0041cf48:  blr
>>
>> htab_base 0000000000000000 htab_mask 000000000000ffff hash
>> 000000000000fde7
>> 0 htab=0000000000000000/000000000000ffff vsid=0 ptem=3f
>> hash=000000000000fde7
>> 1 htab=0000000000000000/000000000000ffff vsid=0 api=3f
>> hash=ffffffffffff0218
>> Raise exception at 0041cf40 => 00000002 (00)
>>
>> r0             0x3030   12336
>> r1             0x1fde7e70       534675056
>>
>> which is not covered by any translation now. So I think the stack must
>> be in the first 256MB to which a translation is added to the BAT and
>> this is why it works with 256MB of memory. Thus to be complete the
>> stack should be moved from the end of the memory where it is now
>> (described in a comment in arch/ppc/qemu/start.S) to somwhere else.
>> But where? There's another comment in arch/ppc/qemu/ofmem.c that seems
>> to originate from here:
>>
>> http://opensource.apple.com/source/BootX/BootX-81/bootx.tproj/include.subproj/sl.h
>>
>>
>> but seems it has changed at the origin since it was copied. Does
>> anyone know a good location that is left free by the boot loaders we
>> care about where the stack could be placed within the first 256MB?
>> MoprhOS seems to start using memory from the end so maybe the stack
>> should not be there.
>> Any more ideas?
>
>> From the test results it seems that Apple puts the stack after the image
> (and probably clears it or otherwise adds a mapping in the TLB for it so
> accessing it will not generate exceptions). How could this be
> implemented in OpenBIOS? I've tried to look at the code to find a good
> place but there seems to be different cases for different architectures
> and using preloaded kernel image seems to be an additional complication.
> Could the file-size stored in saved-program-state be used as a base to
> place the stack in call_elf? (this would need adding an additional
> parameter to it in the ppc/qemu case because accessing Forth from
> assembly is not something I'd try).

FWIW I don't know much about the PPC side of this, however for SPARC the 
client stack is set as part of the context initialisation (see 
arch/sparc64/context.c for an example of this). This allows the caller 
to initialise a context (including specifying the stack) all in C before 
dropping into asm to finally execute the loaded file.

> Or are my conclusions wrong or you have a better idea? (Also what about
> my other patches on the list? This place seemed abandoned for the last
> week.)

Well, as I mentioned last week I've been away on holiday. Plus it's QEMU 
soft freeze time which means everybody is busy trying to get their 
patches applied in preparation for 2.1. This generally means people are 
very busy.


ATB,

Mark.




More information about the OpenBIOS mailing list