@@ -158,12 +158,24 @@ done_syscall:
break;
case EXCP_TLBL:
case EXCP_TLBS:
- case EXCP_AdEL:
- case EXCP_AdES:
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
- /* XXX: check env->error_code */
- info.si_code = TARGET_SEGV_MAPERR;
+ info.si_code = (env->error_code & EXCP_TLB_NOMATCH
+ ? TARGET_SEGV_MAPERR : TARGET_SEGV_ACCERR);
+ info._sifields._sigfault._addr = env->CP0_BadVAddr;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
+ case EXCP_AdEL:
+ case EXCP_AdES:
+ /*
+ * Note that on real hw AdE is also raised for access to a
+ * kernel address from user mode instead of a TLB error.
+ * For simplicity, we do not distinguish this in the user
+ * version of mips_cpu_tlb_fill so only unaligned comes here.
+ */
+ info.si_signo = TARGET_SIGBUS;
+ info.si_errno = 0;
+ info.si_code = TARGET_BUS_ADRALN;
info._sifields._sigfault._addr = env->CP0_BadVAddr;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
@@ -541,11 +541,11 @@ static const struct TCGCPUOps mips_tcg_ops = {
.synchronize_from_tb = mips_cpu_synchronize_from_tb,
.cpu_exec_interrupt = mips_cpu_exec_interrupt,
.tlb_fill = mips_cpu_tlb_fill,
+ .do_unaligned_access = mips_cpu_do_unaligned_access,
#if !defined(CONFIG_USER_ONLY)
.do_interrupt = mips_cpu_do_interrupt,
.do_transaction_failed = mips_cpu_do_transaction_failed,
- .do_unaligned_access = mips_cpu_do_unaligned_access,
.io_recompile_replay_branch = mips_io_recompile_replay_branch,
#endif /* !CONFIG_USER_ONLY */
};
@@ -375,8 +375,6 @@ void helper_pmon(CPUMIPSState *env, int function)
}
}
-#if !defined(CONFIG_USER_ONLY)
-
void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
MMUAccessType access_type,
int mmu_idx, uintptr_t retaddr)
@@ -402,6 +400,7 @@ void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
do_raise_exception_err(env, excp, error_code, retaddr);
}
+#if !defined(CONFIG_USER_ONLY)
void mips_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
vaddr addr, unsigned size,
MMUAccessType access_type,
@@ -26,24 +26,23 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,
MMUAccessType access_type)
{
CPUState *cs = env_cpu(env);
+ int error_code = 0;
+ int flags;
- env->error_code = 0;
if (access_type == MMU_INST_FETCH) {
- env->error_code |= EXCP_INST_NOTAVAIL;
+ error_code |= EXCP_INST_NOTAVAIL;
}
- /* Reference to kernel address from user mode or supervisor mode */
- /* Reference to supervisor address from user mode */
- if (access_type == MMU_DATA_STORE) {
- cs->exception_index = EXCP_AdES;
- } else {
- cs->exception_index = EXCP_AdEL;
+ flags = page_get_flags(address);
+ if (!(flags & PAGE_VALID)) {
+ error_code |= EXCP_TLB_NOMATCH;
}
- /* Raise exception */
- if (!(env->hflags & MIPS_HFLAG_DM)) {
- env->CP0_BadVAddr = address;
- }
+ cs->exception_index = (access_type == MMU_DATA_STORE
+ ? EXCP_TLBS : EXCP_TLBL);
+
+ env->error_code = error_code;
+ env->CP0_BadVAddr = address;
}
bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- linux-user/mips/cpu_loop.c | 20 ++++++++++++++++---- target/mips/cpu.c | 2 +- target/mips/tcg/op_helper.c | 3 +-- target/mips/tcg/user/tlb_helper.c | 23 +++++++++++------------ 4 files changed, 29 insertions(+), 19 deletions(-) -- 2.25.1