On Mon, 9 Jun 2014, Mark Cave-Ayland wrote:
A quick look around shows that you probably want to look at DEBUG_MMU/DEBUG_BAT in target-ppc/mmu_has32.c. And I'm not even a PPC guy :)
Me neither... These give some more debug output but they are only useful for debugging BATs not debugging translation via the TLB as it only prints TLB address and hashes so I can only see if the TLB was consulted but not the address that was looked up.
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.
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.
After more experiments I think I got a bit closer to the solution. The other exeption I got with my last patch while setting the sr0 register was because the value was read from a local variable on the stack which generated the exception. With this patch:
--- a/openbios-devel/arch/ppc/qemu/ofmem.c +++ b/openbios-devel/arch/ppc/qemu/ofmem.c @@ -531,6 +531,32 @@ setup_mmu(unsigned long ramsize) asm volatile("mtsrin %0,%1" :: "r" (sr_base + i), "r" (j)); }
+ /* Add permanent translations for the first 128MB and the client stack area + * via BAT registers on 32bit CPUs where this is supported */ + if (!is_ppc64()) { + unsigned long stack_addr; + mBAT bat; + + memset(&bat, 0, sizeof(bat)); + bat.batu.bl = 0x3ff; /* 128 MB */ + bat.batu.vs = 1; /* supervisor access */ + bat.batl.pp = 2; /* read/write */ + mtspr(S_DBAT0L, bat.batl); + mtspr(S_IBAT0L, bat.batl); + mtspr(S_DBAT0U, bat.batu); + mtspr(S_IBAT0U, bat.batu); + + stack_addr = get_heap_top(); + /* only add if not overlapping the previous one */ + if (stack_addr > 0x8000000) { + bat.batu.bepi = stack_addr >> 17; + bat.batu.bl = 1; /* 256 kB */ + bat.batl.brpn = stack_addr >> 17; + mtspr(S_DBAT1L, bat.batl); + mtspr(S_DBAT1U, bat.batu); + } + asm volatile("isync"); + } #endif
ofmem = ofmem_arch_get_private();
it boots but only with 256MB of memory.
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.subpro...
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?
Regards, BALATON Zoltan