[OpenBIOS] PPC: QEMU breaks static variables in OpenBIOS

Alexander Graf agraf at suse.de
Sat Jan 5 16:58:51 CET 2013


On 05.01.2013, at 13:05, Mark Cave-Ayland wrote:

> On 02/01/13 21:58, Alexander Graf wrote:
> 
>> Well, .bss is easy as we can just move that down to a r/w memory location. .data is slightly more tricky, as we need to copy data early on. Do we need any global preassigned (.data) variables before we get into C? I highly doubt so :).
>> 
>> Thus, I'd be very inclined to believe that we don't need any asm code at all, making this an all-arch solution.
> 
> Okay, I spent some time looking at the PPC MMU code in detail last night and my current thinking is that this might be a QEMU bug.
> 
> The initial physical memory map (before MMU is enabled on startup) looks like this:
> 
> 0x0000000  - 0x8000000   RAM
> 0xfff00000 - 0xffffffff  OpenBIOS image
> 
> In setup_mmu(), just before the MMU is enabled, the entire image is memcpy()'d from the OpenBIOS image area to the top area of RAM so we now have this:
> 
> 0x0000000  - 0x7efffff   Free RAM
> 0x7f00000  - 0x7ffffff   OpenBIOS RAM image
> 0xfff00000 - 0xffffffff  OpenBIOS ROM image
> 
> Now the reason that OpenBIOS actually executes from RAM is because of this section of code in the MMU fault handler code:
> 
>    if (ea >= OF_CODE_START && ea <= 0xffffffffUL) {
>        /* ROM into RAM */
>        ea -= OF_CODE_START;
>        phys = get_rom_base() + ea;
>        *mode = 0x02;
> 	return phys;
>    }
> 
> Given that OF_CODE_START is 0xfff00000 and get_rom_base() returns 0x7f00000, it's fairly easy to see that accesses to the virtual address range from 0xfff00000 - 0xffffffff are mapped to the OpenBIOS RAM image physical addresses 0x7f00000 - 0x7ffffff. Hence I would expect OpenBIOS to be running from RAM.

So far things make sense. Looking at the first MMU miss we get, QEMU seems to agree with this:

Check segment v=00000000fff08614 15 000000002000040f nip=00000000fff08614 lr=00000000fff08608 ir=1 dr=1 pr=0 0 t=16
pte segment: key=0 ds 0 nx 0 vsid 000000000000040f
htab_base 0000000007e00000 htab_mask 000000000000ffff hash 000000000000fb07
0 htab=0000000007e00000/000000000000ffff vsid=000000000000040f ptem=00000000000207bf hash=000000000000fb07
PTE access granted !
Load pte from 000000000000c1c0 => 00000000800207bf 0000000007f08002 1 0 0 00000000000207bf
found PTE at addr 0000000007f08002 prot=7 ret=0

> I wonder if what is happening is that QEMU is not only marking the *physical* range 0xfff00000 - 0xffffffff as read-only, but also the *virtual* range 0xfff00000 - 0xffffffff when the MMU is enabled? If so, I think this may be a QEMU bug since after these addresses have been remapped into RAM then they should be writeable.

The logic that marks virtual pages r/o and the logic that marks physical pages r/o are running in two completely different frameworks. Physical r/o marking happens through the memory api, while virtual r/o marking happens during virtual page lookup. Also, when a virtual address is mapped r/o, the obvious thing happening would be a page fault, not a silent write ignore.

But as you can see from the log above, the prot mask is 0x7, meaning rwx:

#define PAGE_READ      0x0001
#define PAGE_WRITE     0x0002
#define PAGE_EXEC      0x0004

Do you think you could narrow this down to a simple test case? Somewhere in openbios' init function, access a global variable, check that the write fails and if so, go into an endless loop? That way we might be able to track it down with all logging facilities enabled.


Alex




More information about the OpenBIOS mailing list