On 05.01.2013, at 16:58, Alexander Graf wrote:
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.
Ok, so I did just that with the below patch and got the expected result. Maybe for some reason we're in real mode at the point in time when the breakage occurs?
Alex
agraf@lychee:/home/agraf/release/qemu> ./ppc-softmmu/qemu-system-ppc -nographic -bios /home/agraf/git/openbios-devel/obj-ppc/openbios-qemu.elf
============================================================= OpenBIOS 1.0 [Oct 1 2012 21:06] Configuration device id QEMU version 1 machine id 2 CPUs: 1 global_var: 0 global_var: 123 Memory: 128M UUID: 00000000-0000-0000-0000-000000000000 CPU type PowerPC,750
Welcome to OpenBIOS v1.0 built on Oct 1 2012 21:06 Trying hd:,\:tbxi... Trying hd:,\ppc\bootinfo.txt... No valid state has been set by load or init-program
0 >
diff --git a/arch/ppc/qemu/init.c b/arch/ppc/qemu/init.c index 61374c3..2b526c3 100644 --- a/arch/ppc/qemu/init.c +++ b/arch/ppc/qemu/init.c @@ -628,6 +628,8 @@ static void ffilll(void) } }
+volatile int global_var; + void arch_of_init(void) { @@ -665,6 +667,12 @@ arch_of_init(void)
printk("CPUs: %x\n", temp);
+ printk("global_var: %d\n", global_var); + global_var = 123; + printk("global_var: %d\n", global_var); + if (!global_var) + while(1) { } + ram_size = ofmem->ramsize;
printk("Memory: %lldM\n", ram_size / 1024 / 1024);