Loading arch/mips/include/asm/fpu_emulator.h +6 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,12 @@ do { \ extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc); extern int do_dsemulret(struct pt_regs *xcp); extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, int has_fpu, void *__user *fault_addr); int process_fpemu_return(int sig, void __user *fault_addr); int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, unsigned long *contpc); /* * Instruction inserted following the badinst to further tag the sequence Loading arch/mips/include/asm/inst.h +9 −0 Original line number Diff line number Diff line Loading @@ -73,4 +73,13 @@ typedef unsigned int mips_instruction; /* microMIPS instruction decode structure. Do NOT export!!! */ struct mm_decoded_insn { mips_instruction insn; mips_instruction next_insn; int pc_inc; int next_pc_inc; int micro_mips_mode; }; #endif /* _ASM_INST_H */ arch/mips/include/uapi/asm/inst.h +5 −0 Original line number Diff line number Diff line Loading @@ -423,6 +423,11 @@ enum mm_16d_minor_op { mm_addiusp_func, }; /* * (microMIPS & MIPS16e) NOP instruction. */ #define MM_NOP16 0x0c00 /* * Damn ... bitfields depend from byteorder :-( */ Loading arch/mips/kernel/traps.c +1 −1 Original line number Diff line number Diff line Loading @@ -675,7 +675,7 @@ asmlinkage void do_ov(struct pt_regs *regs) force_sig_info(SIGFPE, &info, current); } static int process_fpemu_return(int sig, void __user *fault_addr) int process_fpemu_return(int sig, void __user *fault_addr) { if (sig == SIGSEGV || sig == SIGBUS) { struct siginfo si = {0}; Loading arch/mips/kernel/unaligned.c +18 −4 Original line number Diff line number Diff line Loading @@ -83,6 +83,8 @@ #include <asm/branch.h> #include <asm/byteorder.h> #include <asm/cop2.h> #include <asm/fpu.h> #include <asm/fpu_emulator.h> #include <asm/inst.h> #include <asm/uaccess.h> Loading @@ -108,6 +110,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, union mips_instruction insn; unsigned long value; unsigned int res; void __user *fault_addr = NULL; perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0); Loading Loading @@ -447,10 +450,21 @@ static void emulate_load_store_insn(struct pt_regs *regs, case ldc1_op: case swc1_op: case sdc1_op: /* * I herewith declare: this does not happen. So send SIGBUS. */ goto sigbus; die_if_kernel("Unaligned FP access in kernel code", regs); BUG_ON(!used_math()); BUG_ON(!is_fpu_owner()); lose_fpu(1); /* Save FPU state for the emulator. */ res = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, &fault_addr); own_fpu(1); /* Restore FPU state. */ /* Signal if something went wrong. */ process_fpemu_return(res, fault_addr); if (res == 0) break; return; /* * COP2 is available to implementor for application specific use. Loading Loading
arch/mips/include/asm/fpu_emulator.h +6 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,12 @@ do { \ extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc); extern int do_dsemulret(struct pt_regs *xcp); extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, int has_fpu, void *__user *fault_addr); int process_fpemu_return(int sig, void __user *fault_addr); int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, unsigned long *contpc); /* * Instruction inserted following the badinst to further tag the sequence Loading
arch/mips/include/asm/inst.h +9 −0 Original line number Diff line number Diff line Loading @@ -73,4 +73,13 @@ typedef unsigned int mips_instruction; /* microMIPS instruction decode structure. Do NOT export!!! */ struct mm_decoded_insn { mips_instruction insn; mips_instruction next_insn; int pc_inc; int next_pc_inc; int micro_mips_mode; }; #endif /* _ASM_INST_H */
arch/mips/include/uapi/asm/inst.h +5 −0 Original line number Diff line number Diff line Loading @@ -423,6 +423,11 @@ enum mm_16d_minor_op { mm_addiusp_func, }; /* * (microMIPS & MIPS16e) NOP instruction. */ #define MM_NOP16 0x0c00 /* * Damn ... bitfields depend from byteorder :-( */ Loading
arch/mips/kernel/traps.c +1 −1 Original line number Diff line number Diff line Loading @@ -675,7 +675,7 @@ asmlinkage void do_ov(struct pt_regs *regs) force_sig_info(SIGFPE, &info, current); } static int process_fpemu_return(int sig, void __user *fault_addr) int process_fpemu_return(int sig, void __user *fault_addr) { if (sig == SIGSEGV || sig == SIGBUS) { struct siginfo si = {0}; Loading
arch/mips/kernel/unaligned.c +18 −4 Original line number Diff line number Diff line Loading @@ -83,6 +83,8 @@ #include <asm/branch.h> #include <asm/byteorder.h> #include <asm/cop2.h> #include <asm/fpu.h> #include <asm/fpu_emulator.h> #include <asm/inst.h> #include <asm/uaccess.h> Loading @@ -108,6 +110,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, union mips_instruction insn; unsigned long value; unsigned int res; void __user *fault_addr = NULL; perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0); Loading Loading @@ -447,10 +450,21 @@ static void emulate_load_store_insn(struct pt_regs *regs, case ldc1_op: case swc1_op: case sdc1_op: /* * I herewith declare: this does not happen. So send SIGBUS. */ goto sigbus; die_if_kernel("Unaligned FP access in kernel code", regs); BUG_ON(!used_math()); BUG_ON(!is_fpu_owner()); lose_fpu(1); /* Save FPU state for the emulator. */ res = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, &fault_addr); own_fpu(1); /* Restore FPU state. */ /* Signal if something went wrong. */ process_fpemu_return(res, fault_addr); if (res == 0) break; return; /* * COP2 is available to implementor for application specific use. Loading