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

Alexander Graf agraf at suse.de
Wed Jul 30 18:05:00 CEST 2014


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.

The code above doesn't skip - it turns off paging. First off I'm not 
sure whether a & b && c actually does what you like it to do. Other that 
than, I guess your best bet would be gdbstub and a breakpoint to see 
whether you hit that point ;)


Alex




More information about the OpenBIOS mailing list