diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c index 388c15c376..1a8e847687 100644 --- a/hw/mips/mips_jazz.c +++ b/hw/mips/mips_jazz.c @@ -123,6 +123,28 @@ static void mips_jazz_do_unassigned_access(CPUState *cpu, hwaddr addr, (*real_do_unassigned_access)(cpu, addr, is_write, is_exec, opaque, size); } +static void (*real_do_transaction_failed)(CPUState *cpu, hwaddr physaddr, + vaddr addr, unsigned size, + MMUAccessType access_type, + int mmu_idx, MemTxAttrs attrs, + MemTxResult response, + uintptr_t retaddr); + +static void mips_jazz_do_transaction_failed(CPUState *cs, hwaddr physaddr, + vaddr addr, unsigned size, + MMUAccessType access_type, + int mmu_idx, MemTxAttrs attrs, + MemTxResult response, + uintptr_t retaddr) +{ + if (access_type != MMU_INST_FETCH) { + /* ignore invalid access (ie do not raise exception) */ + return; + } + (*real_do_transaction_failed)(cs, physaddr, addr, size, access_type, + mmu_idx, attrs, response, retaddr); +} + static void mips_jazz_init(MachineState *machine, enum jazz_model_e jazz_model) { @@ -157,16 +179,32 @@ static void mips_jazz_init(MachineState *machine, env = &cpu->env; qemu_register_reset(main_cpu_reset, cpu); - /* Chipset returns 0 in invalid reads and do not raise data exceptions. + /* + * Chipset returns 0 in invalid reads and do not raise data exceptions. * However, we can't simply add a global memory region to catch - * everything, as memory core directly call unassigned_mem_read/write - * on some invalid accesses, which call do_unassigned_access on the - * CPU, which raise an exception. - * Handle that case by hijacking the do_unassigned_access method on - * the CPU, and do not raise exceptions for data access. */ + * everything, as this would make all accesses including instruction + * accesses be ignored and not raise exceptions. + * So instead we hijack either the do_unassigned_access method or + * the do_transaction_failed method on the CPU, and do not raise exceptions + * for data access. + * + * NOTE: this behaviour of raising exceptions for bad instruction + * fetches but not bad data accesses was added in commit 54e755588cf1e9 + * to restore behaviour broken by c658b94f6e8c206, but it is not clear + * whether the real hardware behaves this way. It is possible that + * real hardware ignores bad instruction fetches as well -- if so then + * we could replace this hijacking of CPU methods with a simple global + * memory region that catches all memory accesses, as we do on Malta. + */ cc = CPU_GET_CLASS(cpu); - real_do_unassigned_access = cc->do_unassigned_access; - cc->do_unassigned_access = mips_jazz_do_unassigned_access; + if (cc->do_unassigned_access) { + real_do_unassigned_access = cc->do_unassigned_access; + cc->do_unassigned_access = mips_jazz_do_unassigned_access; + } + if (cc->do_transaction_failed) { + real_do_transaction_failed = cc->do_transaction_failed; + cc->do_transaction_failed = mips_jazz_do_transaction_failed; + } /* allocate RAM */ memory_region_allocate_system_memory(ram, NULL, "mips_jazz.ram",