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.