[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-ppc] [OpenBIOS] Running client with MMU off
From: |
BALATON Zoltan |
Subject: |
Re: [Qemu-ppc] [OpenBIOS] Running client with MMU off |
Date: |
Wed, 25 Jun 2014 12:29:29 +0200 (CEST) |
User-agent: |
Alpine 2.02 (LMD 1266 2009-07-14) |
On Wed, 25 Jun 2014, BALATON Zoltan wrote:
On Sat, 21 Jun 2014, BALATON Zoltan wrote:
On Fri, 20 Jun 2014, Mark Cave-Ayland wrote:
As for the code that generates the ISIs, is this in MorphOS as opposed to
OpenBIOS? I guess something must have previously accessed an entry on the
same page before the registers were updated, or maybe there is some kind
of hardware readahead?
The code is in the MorphOS boot loader and what it does is trying to take
over memory management. Unfortunately it seems there is a period when it
already replaced the vectors but have not set up the TLB hash table yet so
it cannot actually handle exceptions. I could prevent DSIs but running the
code during this period generates ISI-s. If the code is run in the same
order on real hardware then it's not likely that the page is accessed there
and not on QEMU. A readahead could explain it but I don't know if that
happens. I have no better idea now than manually generating faults for all
pages where the client code is loaded before calling it. I'll try to
implement that unless someone can suggest a better solution.
Experimenting with it some more I could not make it work that way probably
because by the time the ISI happens the vectors are already replaced and the
sr0 register is overwritten so even if I manage to put translations in our
hash table for that code that won't be correct any more by the time the ISI
that causes a crash is handled.
So the only things that might work are using IBATs or disabling the MMU bits
when MorphOS overwrites the vectors. I think this latter option is a bit
cleaner but how can I get an interrupt when a memory address is written to?
(Apart from setting up a watch point for it.) In the OpenBIOS code there are
comments stating that page 0 is not mapped to catch NULL pointer dereferences
but this does not seem to work as MorphOS can write over page 0 and only get
an exception when reaching the next page. (Also I've found documented in one
version of the PPC programming environments document that 0x00-0xff is
reserved for operating system use so they can legally write there.) I'm sure
I'm missing something here again.
It could possibly work on real hardware because of caches and that's where
the read ahead might happen during the critical part. This is what seems to
happen during MorphOS's MMU take over as far as I understand:
1. memcpy to 0, len=0x2000
2. fixup jumps and write base address to 0x80 (this is what's zeroed at
the earlier write at the beginning)
3. Set MSR_BE and tweak HID0 (this may cause code to be preloaded in
cache?)
4. Set sr0-15 from stack variables
5. Values for IBAT and DBAT registers are loaded from the stack and SDR1
is set to 0 dropping the hash table
6. MSR_DR and MSR_IR are cleared
7. BAT registers are set up as shown in this message:
http://www.openfirmware.info/pipermail/openbios/2014-June/008419.html
which means that the stack should be within the first 256MB
8. TLB entries are invalidated then MMU bits are re-enabled (but
hashed page tables are not there yet so it relies on BATs at this point)
9. After doing some other stuff eventually a function is called that sets
up the hash table
10. Vectors are replaced again later during boot after the microkernel has
started its servers
Currently we get a DSI at 0x1000 in step 1. and crash due to our handler
already replaced, probably we don't get a DSI earlier due to a prevoius
zeroing of 0x80 at the very beginning while our handler still works so we
have a translation for that. If we managed to get through this we get a DSI
in step 5. while accessing the stack variable and crash there or get an ISI
running code that replaces sr0 and crash due to that when managed to avoid
DSIs. I have patches to move the stack to after the executable as was shown
in my oftest results and clearing it plus writing to 0x1000 before calling
the client code can avoid DSI-s but I still get the ISI. Alternatively adding
code to ofmem_arch_map_pages which is called from ofmem_map to add
translations to the hash table like this:
void ofmem_arch_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell
mode)
{
unsigned int i;
if (virt < OF_CODE_START) {
for (i = 0; i * PAGE_SIZE < size; i++) {
hash_page(virt + i * PAGE_SIZE, phys + i * PAGE_SIZE, mode);
}
}
}
also seems to help with DSIs but cannot avoid the ISI (maybe because sr0 is
replaced that could possible be used to look up the hash table).
Can anyone see a way through this or has an idea what would be an acceptable
hack to allow this code run? I'm out of ideas now.
I don't get how it works and why I'm still getting an ISI. Can someone
shed some light on it please? Here's what I see:
OpenBIOS sets up MMU like this:
ppc_store_sdr1: 0fe00000
helper_store_sr: reg=0 20000400 00000000
helper_store_sr: reg=1 20000401 00000000
helper_store_sr: reg=2 20000402 00000000
helper_store_sr: reg=3 20000403 00000000
helper_store_sr: reg=4 20000404 00000000
helper_store_sr: reg=5 20000405 00000000
helper_store_sr: reg=6 20000406 00000000
helper_store_sr: reg=7 20000407 00000000
helper_store_sr: reg=8 20000408 00000000
helper_store_sr: reg=9 20000409 00000000
helper_store_sr: reg=10 2000040a 00000000
helper_store_sr: reg=11 2000040b 00000000
helper_store_sr: reg=12 2000040c 00000000
helper_store_sr: reg=13 2000040d 00000000
helper_store_sr: reg=14 2000040e 00000000
helper_store_sr: reg=15 2000040f 00000000
I've also added code to ofmem_arch_map_pages to add all mapped pages to
the hashed page table now like this:
void ofmem_arch_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode)
{
unsigned int i;
for (i = 0; i * PAGE_SIZE < size; i++) {
hash_page(pa2va(phys + i * PAGE_SIZE), phys + i * PAGE_SIZE, mode);
}
}
It now should have a translation in the page table for the executable and
stack as those are mapped when loading like this:
OFMEM: ofmem_claim_phys phys=81000000 size=01000000 align=00000000
OFMEM: ofmem_claim_virt virt=81000000 size=01000000 align=00000000
OFMEM: ofmem_map_page_range 81000000 -> 81000000 01000000 mode 0000006a
filesz: 00284348 memsz: 0028731C p_offset: 00010000 p_vaddr 00400000
OFMEM: ofmem_claim 00400000 0028731c 00000000
OFMEM: ofmem_map_page_range 00400000 -> 00400000 00288000 mode 00000002
OFMEM: ofmem_claim 0068731c 00010000 00000000
OFMEM: ofmem_map_page_range 00687000 -> 00687000 00011000 mode 00000002
Actually the whole memory except page 0 is mapped in ofmem_init so
everything should be translatable via the hash table. Despite of this I
still get DSIs and ISIs although less frequently (why?) which are handled
by OpenBIOS's handlers until MorphOS tries to take over the MMU like this:
IN:
0x004009ac: mfdbsr r0 ; I think this is really HID0 on a G4 CPU
; objdump says: 7c 10 fa a6 mfspr r0,1008
0x004009b0: oris r0,r0,32912
0x004009b4: li r9,-516
0x004009b8: ori r0,r0,132
0x004009bc: and r0,r0,r9
0x004009c0: isync
IN:
0x004009c4: sync
0x004009c8: isync
IN:
0x004009cc: mtdbsr r0
0x004009d0: isync
IN:
0x004009d4: sync
0x004009d8: isync
IN:
0x004009dc: b 0x400acc
IN:
0x00400acc: mfdbsr r0
0x00400ad0: mfl2cr r11
0x00400ad4: addis r9,r10,-1
0x00400ad8: addi r9,r9,32767
0x00400adc: cmplwi r9,1
0x00400ae0: bgt- 0x400af4
IN:
0x00400af4: mficcr r0
0x00400af8: mr r4,r16
0x00400afc: mr r5,r15
0x00400b00: addi r3,r1,16
0x00400b04: li r6,0
0x00400b08: bl 0x41cce8
IN:
0x0041cce8: stwu r1,-96(r1)
0x0041ccec: stmw r13,20(r1)
0x0041ccf0: lwz r0,0(r3)
0x0041ccf4: sync
0x0041ccf8: mtsr 0,r0
0x0041ccfc: isync
helper_store_sr: reg=0 00000000 20000400
Raise exception at 0041cd00 => 00000003 (40000000)
^^^ This exception should not happen. It is trying to handle it but the
handlers are not working yet and gets in an infinite loop. It boots if MMU
is disabled while this part runs but MorphOS does not disable it yet and
according to my oftest results they are enabled on Apple too. How does it
work on real hardware and why does it fail on QEMU? (Note the the value of
sr0 is identical to the one set by OpenBIOS and SDR1 is unchanged so
translations via the page table should still work, shouldn't it?)
The instruction where the exception happens would load the next value for
sr1 but it is an ISI so it's not because of data access:
41cd00: 80 03 00 04 lwz r0,4(r3)
41cd04: 7c 00 04 ac sync
41cd08: 7c 01 01 a4 mtsr 1,r0
41cd0c: 4c 00 01 2c isync
41cd10: 80 03 00 08 lwz r0,8(r3)
41cd14: 7c 00 04 ac sync
41cd18: 7c 02 01 a4 mtsr 2,r0
The rest just shows the path taken instead and the crash in the replaced
exception handlers which reenable the MMU and get another exception
infinitely:
IN:
0x00000400: mtsprg 2,r2
0x00000404: li r2,4
0x00000408: b 0x41f0d4
IN:
0x00000400: mtsprg 2,r2
IN:
0x00000404: li r2,4
IN:
0x00000408: b 0x41f0d4
IN:
0x0041f0d4: mtsprg 1,r1
IN:
0x0041f0d8: mfmsr r1
IN:
0x0041f0dc: ori r1,r1,12336
IN:
0x0041f0e0: sync
IN:
0x0041f0e4: mtmsr r1
Raise exception at 0041f0e8 => 00000003 (40000000)
IN:
0x00000400: mtsprg 2,r2
Regards,
BALATON Zoltan
- Re: [Qemu-ppc] [OpenBIOS] Running client with MMU off, BALATON Zoltan, 2014/06/24
- Re: [Qemu-ppc] [OpenBIOS] Running client with MMU off, Alexander Graf, 2014/06/24
- Re: [Qemu-ppc] [OpenBIOS] Running client with MMU off,
BALATON Zoltan <=
- Re: [Qemu-ppc] [OpenBIOS] Running client with MMU off, BALATON Zoltan, 2014/06/25
- Re: [Qemu-ppc] [OpenBIOS] Running client with MMU off, Alexander Graf, 2014/06/25
- Re: [Qemu-ppc] [OpenBIOS] Running client with MMU off, BALATON Zoltan, 2014/06/25
- Re: [Qemu-ppc] [OpenBIOS] Running client with MMU off, Alexander Graf, 2014/06/26
- Re: [Qemu-ppc] [OpenBIOS] Running client with MMU off, BALATON Zoltan, 2014/06/26
- Re: [Qemu-ppc] [OpenBIOS] Running client with MMU off, Alexander Graf, 2014/06/26
- Re: [Qemu-ppc] [OpenBIOS] Running client with MMU off, BALATON Zoltan, 2014/06/26
- Re: [Qemu-ppc] [OpenBIOS] Running client with MMU off, Alexander Graf, 2014/06/26
- Re: [Qemu-ppc] [OpenBIOS] Running client with MMU off, BALATON Zoltan, 2014/06/26
- Re: [Qemu-ppc] [OpenBIOS] Running client with MMU off, Alexander Graf, 2014/06/26