[OpenBIOS] [Qemu-ppc] Running client with MMU off

BALATON Zoltan balaton at eik.bme.hu
Wed Jul 30 19:59:30 CEST 2014


On Wed, 30 Jul 2014, Alexander Graf wrote:
> On 30.07.14 17:47, BALATON Zoltan wrote:
>> On Wed, 30 Jul 2014, Alexander Graf wrote:
>>>> Am 30.07.2014 um 16:42 schrieb BALATON Zoltan <balaton at eik.bme.hu>:
>>>>>> As a start I've tried this patch:
>>>>>> --- a/openbios-devel/arch/ppc/qemu/ofmem.c
>>>>>> +++ b/openbios-devel/arch/ppc/qemu/ofmem.c
>>>>>> @@ -460,15 +460,26 @@ static void hash_page(unsigned long ea, 
>>>>>> phys_addr_t phys,
>>>>>> void
>>>>>> dsi_exception(void)
>>>>>> {
>>>>>> -    unsigned long dar, dsisr;
>>>>>> +    unsigned long dar, dsisr, srr1;
>>>>>>     ucell mode;
>>>>>>     phys_addr_t phys;
>>>>>>
>>>>>>     asm volatile("mfdar %0" : "=r" (dar) : );
>>>>>>     asm volatile("mfdsisr %0" : "=r" (dsisr) : );
>>>>>> -
>>>>>> +    asm volatile("mfsrr1 %0" : "=r" (srr1) : );
>>>>>>     phys = ea_to_phys(dar, &mode);
>>>>>> -    hash_page(dar, phys, mode);
>>>>>> +
>>>>>> +    if (dsisr & BIT(1)) {
>>>>>> +        /* handle page fault */
>>>>>> +        hash_page(dar, phys, mode);
>>>>>> +    }
>>>>>> +
>>>>>> +    if (dsisr & BIT(4) && dar == 0) {
>>>>>> +        /* handle protection violation */
>>>>>> +        hash_page(dar, phys, mode);
>>>>>> +        srr1 &= ~(MSR_IR | MSR_DR);
>>>>>> +        asm volatile("mtsrr1 %0" :: "r" (srr1));
>>>>>> +    }
>>>>>> }
>>>>>> 
>>>>>> void
>>>>>> @@ -554,9 +565,10 @@ ofmem_init(void)
>>>>>>     ofmem_claim_virt(PAGE_SIZE, get_ram_bottom() - PAGE_SIZE, 0);
>>>>>>     ofmem_map(PAGE_SIZE, PAGE_SIZE, get_ram_bottom() - PAGE_SIZE, 0);
>>>>>> -    /* Mark the first page as non-free */
>>>>>> +    /* Mark the first page as non-free and write protect it */
>>>>>>     ofmem_claim_phys(0, PAGE_SIZE, 0);
>>>>>>     ofmem_claim_virt(0, PAGE_SIZE, 0);
>>>>>> +    hash_page(0, 0, 3);
>>>>>>
>>>>>>     /* Map everything at the top of physical RAM 1:1, minus the 
>>>>>> OpenBIOS ROM in
>>>>>>     ofmem_claim_phys(get_ram_top(), get_hash_base() + HASH_SIZE - 
>>>>>> get_ram_top()
>>>>>> which does not break Finnix but does not work with MorphOS because it 
>>>>>> catches the write to 0x80 as it should but instead of ignoring it this 
>>>>>> protection violation exception is always retrigerring infinitely and it 
>>>>>> does not go further. What am I missing to ignore protection violations 
>>>>>> for writes to page 0 without emulating the writes at the moment. (The 
>>>>>> initial write to 0x80 is setting it to 0 which is the value it already 
>>>>>> has.) Unfortunatly it is hard to debug because if I call printk from 
>>>>>> the exception handler it seems to break beyond repair possibly due to 
>>>>>> side effects.
>>>>>> I've also looked at the code you've referred to but that uses kvm 
>>>>>> functions not included in the patch so it may be more complicated than 
>>>>>> that. If I get it correctly I can get the instruction from the address 
>>>>>> in srr0, the target memory cell from dar but still need to find out the 
>>>>>> source which is probably a register that does not contain the value by 
>>>>>> the time I get it so it may not be trivial to emulate the write.
>>>>> 
>>>>> They have to be somewhere, because we have to swap them all back in 
>>>>> after the interrupt.
>>>> 
>>>> They are probably on a stack somewhere but the handlers replace the stack 
>>>> if I remember correctly so it's not trivial to access that from C code.
>>> 
>>> Then pass a pointer to them to the C handler code?
>> 
>> Good idea, but I'd like to make it work first before starting emulating 
>> instructions.
>> 
>>>> But my question was primarily about why the exception is retriggering? Do 
>>>> I need to do something else to signal to the CPU that the protection 
>>>> violation is handled or how can I ignore an exception so the execution 
>>>> continues?
>>> 
>>> If you don't fix up the reason why the interrupt occured in the first 
>>> place it will simply happen again.
>> 
>> I don't get it. The exception happens because of a write to 0x80 which is 
>> in a protected page. (The value written is the same that is already in that 
>> memory cell by the way so no action is needed.) What could I do to "fix up 
>> the reason" so that the exception does not happen again after returning 
>> from the handler? I thought that simply ignoring the write and returning 
>> from the handler should make it continue execution but it does not seem to 
>> work that way. I'm clearly missing something but I don't know what. Can you 
>> spot a problem in the code above?
>
> If you just return you return to the same instruction that caused the 
> interrupt, so it will trigger again. You need to return to SRR0+4 if you want 
> to "skip" the instruction.

Ahh, OK. Probably this it what I was missing.

> The code above doesn't skip - it turns off paging. First off I'm not sure

What I intended is to turn off page protection on first write to address 0 
and should ignore the write to 0x80 before that.

> whether a & b && c actually does what you like it to do. Other that than, I

The & should be higher precedence than && but adding paranthesis to make 
it clearer would not hurt.

> guess your best bet would be gdbstub and a breakpoint to see whether you hit 
> that point ;)

The handler is called but I could experiment with what happens after 
returning. Thanks for the ideas, I'll try to make it work if I find some 
time for it.

Regards,
BALATON Zoltan



More information about the OpenBIOS mailing list