asmlinkage void do_ade(struct pt_regs *regs) { unsigned long pc; /* * Did we catch a fault trying to load an instruction? * This also catches attempts to activate MIPS16 code on * CPUs which don't support it. */ if (regs->cp0_badvaddr == regs->cp0_epc) goto sigbus; pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0); if (compute_return_epc(regs)) return; if ((current->tss.mflags & MF_FIXADE) == 0) goto sigbus; emulate_load_store_insn(regs, regs->cp0_badvaddr, pc); unaligned_instructions++; return; sigbus: lock_kernel(); force_sig(SIGBUS, current); unlock_kernel(); return; }
asmlinkage void do_ade(struct pt_regs *regs) { enum ctx_state prev_state; unsigned int __user *pc; mm_segment_t seg; prev_state = exception_enter(); perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, regs->cp0_badvaddr); /* * Did we catch a fault trying to load an instruction? */ if (regs->cp0_badvaddr == regs->cp0_epc) goto sigbus; if (user_mode(regs) && !test_thread_flag(TIF_FIXADE)) goto sigbus; if (unaligned_action == UNALIGNED_ACTION_SIGNAL) goto sigbus; /* * Do branch emulation only if we didn't forward the exception. * This is all so but ugly ... */ /* * Are we running in microMIPS mode? */ if (get_isa16_mode(regs->cp0_epc)) { /* * Did we catch a fault trying to load an instruction in * 16-bit mode? */ if (regs->cp0_badvaddr == msk_isa16_mode(regs->cp0_epc)) goto sigbus; if (unaligned_action == UNALIGNED_ACTION_SHOW) show_registers(regs); if (cpu_has_mmips) { seg = get_fs(); if (!user_mode(regs)) set_fs(KERNEL_DS); emulate_load_store_microMIPS(regs, (void __user *)regs->cp0_badvaddr); set_fs(seg); return; } if (cpu_has_mips16) { seg = get_fs(); if (!user_mode(regs)) set_fs(KERNEL_DS); emulate_load_store_MIPS16e(regs, (void __user *)regs->cp0_badvaddr); set_fs(seg); return; } goto sigbus; } if (unaligned_action == UNALIGNED_ACTION_SHOW) show_registers(regs); pc = (unsigned int __user *)exception_epc(regs); seg = get_fs(); if (!user_mode(regs)) set_fs(KERNEL_DS); emulate_load_store_insn(regs, (void __user *)regs->cp0_badvaddr, pc); set_fs(seg); return; sigbus: die_if_kernel("Kernel unaligned instruction access", regs); force_sig(SIGBUS, current); /* * XXX On return from the signal handler we should advance the epc */ exception_exit(prev_state); }