diff options
| -rw-r--r-- | arch/mips/include/asm/break.h | 1 | ||||
| -rw-r--r-- | arch/mips/include/asm/fpu_emulator.h | 17 | ||||
| -rw-r--r-- | arch/mips/kernel/traps.c | 16 | ||||
| -rw-r--r-- | arch/mips/kernel/unaligned.c | 12 | ||||
| -rw-r--r-- | arch/mips/math-emu/cp1emu.c | 4 | ||||
| -rw-r--r-- | arch/mips/math-emu/dsemul.c | 7 | ||||
| -rw-r--r-- | arch/mips/math-emu/dsemul.h | 17 |
7 files changed, 37 insertions, 37 deletions
diff --git a/arch/mips/include/asm/break.h b/arch/mips/include/asm/break.h index 25b980c91e7..44437ed765e 100644 --- a/arch/mips/include/asm/break.h +++ b/arch/mips/include/asm/break.h | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #define _BRK_THREADBP 11 /* For threads, user bp (used by debuggers) */ | 29 | #define _BRK_THREADBP 11 /* For threads, user bp (used by debuggers) */ |
| 30 | #define BRK_BUG 512 /* Used by BUG() */ | 30 | #define BRK_BUG 512 /* Used by BUG() */ |
| 31 | #define BRK_KDB 513 /* Used in KDB_ENTER() */ | 31 | #define BRK_KDB 513 /* Used in KDB_ENTER() */ |
| 32 | #define BRK_MEMU 514 /* Used by FPU emulator */ | ||
| 32 | #define BRK_MULOVF 1023 /* Multiply overflow */ | 33 | #define BRK_MULOVF 1023 /* Multiply overflow */ |
| 33 | 34 | ||
| 34 | #endif /* __ASM_BREAK_H */ | 35 | #endif /* __ASM_BREAK_H */ |
diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h index 2731c38bd7a..e5189572956 100644 --- a/arch/mips/include/asm/fpu_emulator.h +++ b/arch/mips/include/asm/fpu_emulator.h | |||
| @@ -23,6 +23,9 @@ | |||
| 23 | #ifndef _ASM_FPU_EMULATOR_H | 23 | #ifndef _ASM_FPU_EMULATOR_H |
| 24 | #define _ASM_FPU_EMULATOR_H | 24 | #define _ASM_FPU_EMULATOR_H |
| 25 | 25 | ||
| 26 | #include <asm/break.h> | ||
| 27 | #include <asm/inst.h> | ||
| 28 | |||
| 26 | struct mips_fpu_emulator_stats { | 29 | struct mips_fpu_emulator_stats { |
| 27 | unsigned int emulated; | 30 | unsigned int emulated; |
| 28 | unsigned int loads; | 31 | unsigned int loads; |
| @@ -34,4 +37,18 @@ struct mips_fpu_emulator_stats { | |||
| 34 | 37 | ||
| 35 | extern struct mips_fpu_emulator_stats fpuemustats; | 38 | extern struct mips_fpu_emulator_stats fpuemustats; |
| 36 | 39 | ||
| 40 | extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir, | ||
| 41 | unsigned long cpc); | ||
| 42 | extern int do_dsemulret(struct pt_regs *xcp); | ||
| 43 | |||
| 44 | /* | ||
| 45 | * Instruction inserted following the badinst to further tag the sequence | ||
| 46 | */ | ||
| 47 | #define BD_COOKIE 0x0000bd36 /* tne $0, $0 with baggage */ | ||
| 48 | |||
| 49 | /* | ||
| 50 | * Break instruction with special math emu break code set | ||
| 51 | */ | ||
| 52 | #define BREAK_MATH (0x0000000d | (BRK_MEMU << 16)) | ||
| 53 | |||
| 37 | #endif /* _ASM_FPU_EMULATOR_H */ | 54 | #endif /* _ASM_FPU_EMULATOR_H */ |
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 3f6de76d485..353056110f2 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <asm/cpu.h> | 32 | #include <asm/cpu.h> |
| 33 | #include <asm/dsp.h> | 33 | #include <asm/dsp.h> |
| 34 | #include <asm/fpu.h> | 34 | #include <asm/fpu.h> |
| 35 | #include <asm/fpu_emulator.h> | ||
| 35 | #include <asm/mipsregs.h> | 36 | #include <asm/mipsregs.h> |
| 36 | #include <asm/mipsmtregs.h> | 37 | #include <asm/mipsmtregs.h> |
| 37 | #include <asm/module.h> | 38 | #include <asm/module.h> |
| @@ -722,6 +723,21 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, | |||
| 722 | die_if_kernel("Kernel bug detected", regs); | 723 | die_if_kernel("Kernel bug detected", regs); |
| 723 | force_sig(SIGTRAP, current); | 724 | force_sig(SIGTRAP, current); |
| 724 | break; | 725 | break; |
| 726 | case BRK_MEMU: | ||
| 727 | /* | ||
| 728 | * Address errors may be deliberately induced by the FPU | ||
| 729 | * emulator to retake control of the CPU after executing the | ||
| 730 | * instruction in the delay slot of an emulated branch. | ||
| 731 | * | ||
| 732 | * Terminate if exception was recognized as a delay slot return | ||
| 733 | * otherwise handle as normal. | ||
| 734 | */ | ||
| 735 | if (do_dsemulret(regs)) | ||
| 736 | return; | ||
| 737 | |||
| 738 | die_if_kernel("Math emu break/trap", regs); | ||
| 739 | force_sig(SIGTRAP, current); | ||
| 740 | break; | ||
| 725 | default: | 741 | default: |
| 726 | scnprintf(b, sizeof(b), "%s instruction in kernel code", str); | 742 | scnprintf(b, sizeof(b), "%s instruction in kernel code", str); |
| 727 | die_if_kernel(b, regs); | 743 | die_if_kernel(b, regs); |
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 20709669e59..bf4c4a979ab 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c | |||
| @@ -499,22 +499,10 @@ sigill: | |||
| 499 | 499 | ||
| 500 | asmlinkage void do_ade(struct pt_regs *regs) | 500 | asmlinkage void do_ade(struct pt_regs *regs) |
| 501 | { | 501 | { |
| 502 | extern int do_dsemulret(struct pt_regs *); | ||
| 503 | unsigned int __user *pc; | 502 | unsigned int __user *pc; |
| 504 | mm_segment_t seg; | 503 | mm_segment_t seg; |
| 505 | 504 | ||
| 506 | /* | 505 | /* |
| 507 | * Address errors may be deliberately induced by the FPU emulator to | ||
| 508 | * retake control of the CPU after executing the instruction in the | ||
| 509 | * delay slot of an emulated branch. | ||
| 510 | */ | ||
| 511 | /* Terminate if exception was recognized as a delay slot return */ | ||
| 512 | if (do_dsemulret(regs)) | ||
| 513 | return; | ||
| 514 | |||
| 515 | /* Otherwise handle as normal */ | ||
| 516 | |||
| 517 | /* | ||
| 518 | * Did we catch a fault trying to load an instruction? | 506 | * Did we catch a fault trying to load an instruction? |
| 519 | * Or are we running in MIPS16 mode? | 507 | * Or are we running in MIPS16 mode? |
| 520 | */ | 508 | */ |
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 7ec0b217dfd..890f77927d6 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c | |||
| @@ -48,7 +48,6 @@ | |||
| 48 | #include <asm/branch.h> | 48 | #include <asm/branch.h> |
| 49 | 49 | ||
| 50 | #include "ieee754.h" | 50 | #include "ieee754.h" |
| 51 | #include "dsemul.h" | ||
| 52 | 51 | ||
| 53 | /* Strap kernel emulator for full MIPS IV emulation */ | 52 | /* Strap kernel emulator for full MIPS IV emulation */ |
| 54 | 53 | ||
| @@ -346,9 +345,6 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) | |||
| 346 | /* cop control register rd -> gpr[rt] */ | 345 | /* cop control register rd -> gpr[rt] */ |
| 347 | u32 value; | 346 | u32 value; |
| 348 | 347 | ||
| 349 | if (ir == CP1UNDEF) { | ||
| 350 | return do_dsemulret(xcp); | ||
| 351 | } | ||
| 352 | if (MIPSInst_RD(ir) == FPCREG_CSR) { | 348 | if (MIPSInst_RD(ir) == FPCREG_CSR) { |
| 353 | value = ctx->fcr31; | 349 | value = ctx->fcr31; |
| 354 | value = (value & ~0x3) | mips_rm[value & 0x3]; | 350 | value = (value & ~0x3) | mips_rm[value & 0x3]; |
diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c index 653e325849e..df7b9d928ef 100644 --- a/arch/mips/math-emu/dsemul.c +++ b/arch/mips/math-emu/dsemul.c | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | #include <asm/fpu_emulator.h> | 18 | #include <asm/fpu_emulator.h> |
| 19 | 19 | ||
| 20 | #include "ieee754.h" | 20 | #include "ieee754.h" |
| 21 | #include "dsemul.h" | ||
| 22 | 21 | ||
| 23 | /* Strap kernel emulator for full MIPS IV emulation */ | 22 | /* Strap kernel emulator for full MIPS IV emulation */ |
| 24 | 23 | ||
| @@ -94,7 +93,7 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc) | |||
| 94 | return SIGBUS; | 93 | return SIGBUS; |
| 95 | 94 | ||
| 96 | err = __put_user(ir, &fr->emul); | 95 | err = __put_user(ir, &fr->emul); |
| 97 | err |= __put_user((mips_instruction)BADINST, &fr->badinst); | 96 | err |= __put_user((mips_instruction)BREAK_MATH, &fr->badinst); |
| 98 | err |= __put_user((mips_instruction)BD_COOKIE, &fr->cookie); | 97 | err |= __put_user((mips_instruction)BD_COOKIE, &fr->cookie); |
| 99 | err |= __put_user(cpc, &fr->epc); | 98 | err |= __put_user(cpc, &fr->epc); |
| 100 | 99 | ||
| @@ -130,13 +129,13 @@ int do_dsemulret(struct pt_regs *xcp) | |||
| 130 | /* | 129 | /* |
| 131 | * Do some sanity checking on the stackframe: | 130 | * Do some sanity checking on the stackframe: |
| 132 | * | 131 | * |
| 133 | * - Is the instruction pointed to by the EPC an BADINST? | 132 | * - Is the instruction pointed to by the EPC an BREAK_MATH? |
| 134 | * - Is the following memory word the BD_COOKIE? | 133 | * - Is the following memory word the BD_COOKIE? |
| 135 | */ | 134 | */ |
| 136 | err = __get_user(insn, &fr->badinst); | 135 | err = __get_user(insn, &fr->badinst); |
| 137 | err |= __get_user(cookie, &fr->cookie); | 136 | err |= __get_user(cookie, &fr->cookie); |
| 138 | 137 | ||
| 139 | if (unlikely(err || (insn != BADINST) || (cookie != BD_COOKIE))) { | 138 | if (unlikely(err || (insn != BREAK_MATH) || (cookie != BD_COOKIE))) { |
| 140 | fpuemustats.errors++; | 139 | fpuemustats.errors++; |
| 141 | return 0; | 140 | return 0; |
| 142 | } | 141 | } |
diff --git a/arch/mips/math-emu/dsemul.h b/arch/mips/math-emu/dsemul.h deleted file mode 100644 index 091f0e76730..00000000000 --- a/arch/mips/math-emu/dsemul.h +++ /dev/null | |||
| @@ -1,17 +0,0 @@ | |||
| 1 | extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc); | ||
| 2 | extern int do_dsemulret(struct pt_regs *xcp); | ||
| 3 | |||
| 4 | /* Instruction which will always cause an address error */ | ||
| 5 | #define AdELOAD 0x8c000001 /* lw $0,1($0) */ | ||
| 6 | /* Instruction which will plainly cause a CP1 exception when FPU is disabled */ | ||
| 7 | #define CP1UNDEF 0x44400001 /* cfc1 $0,$0 undef */ | ||
| 8 | |||
| 9 | /* Instruction inserted following the badinst to further tag the sequence */ | ||
| 10 | #define BD_COOKIE 0x0000bd36 /* tne $0,$0 with baggage */ | ||
| 11 | |||
| 12 | /* Setup which instruction to use for trampoline */ | ||
| 13 | #ifdef STANDALONE_EMULATOR | ||
| 14 | #define BADINST CP1UNDEF | ||
| 15 | #else | ||
| 16 | #define BADINST AdELOAD | ||
| 17 | #endif | ||
