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.