|
@@ -1055,11 +1055,41 @@ int is_valid_bugaddr(unsigned long addr)
|
|
|
return is_kernel_addr(addr);
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_MATH_EMULATION
|
|
|
+static int emulate_math(struct pt_regs *regs)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+ extern int do_mathemu(struct pt_regs *regs);
|
|
|
+
|
|
|
+ ret = do_mathemu(regs);
|
|
|
+ if (ret >= 0)
|
|
|
+ PPC_WARN_EMULATED(math, regs);
|
|
|
+
|
|
|
+ switch (ret) {
|
|
|
+ case 0:
|
|
|
+ emulate_single_step(regs);
|
|
|
+ return 0;
|
|
|
+ case 1: {
|
|
|
+ int code = 0;
|
|
|
+ code = __parse_fpscr(current->thread.fpscr.val);
|
|
|
+ _exception(SIGFPE, regs, code, regs->nip);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ case -EFAULT:
|
|
|
+ _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+#else
|
|
|
+static inline int emulate_math(struct pt_regs *regs) { return -1; }
|
|
|
+#endif
|
|
|
+
|
|
|
void __kprobes program_check_exception(struct pt_regs *regs)
|
|
|
{
|
|
|
enum ctx_state prev_state = exception_enter();
|
|
|
unsigned int reason = get_reason(regs);
|
|
|
- extern int do_mathemu(struct pt_regs *regs);
|
|
|
|
|
|
/* We can now get here via a FP Unavailable exception if the core
|
|
|
* has no FPU, in that case the reason flags will be 0 */
|
|
@@ -1125,7 +1155,6 @@ void __kprobes program_check_exception(struct pt_regs *regs)
|
|
|
if (!arch_irq_disabled_regs(regs))
|
|
|
local_irq_enable();
|
|
|
|
|
|
-#ifdef CONFIG_MATH_EMULATION
|
|
|
/* (reason & REASON_ILLEGAL) would be the obvious thing here,
|
|
|
* but there seems to be a hardware bug on the 405GP (RevD)
|
|
|
* that means ESR is sometimes set incorrectly - either to
|
|
@@ -1134,22 +1163,8 @@ void __kprobes program_check_exception(struct pt_regs *regs)
|
|
|
* instruction or only on FP instructions, whether there is a
|
|
|
* pattern to occurrences etc. -dgibson 31/Mar/2003
|
|
|
*/
|
|
|
- switch (do_mathemu(regs)) {
|
|
|
- case 0:
|
|
|
- emulate_single_step(regs);
|
|
|
- goto bail;
|
|
|
- case 1: {
|
|
|
- int code = 0;
|
|
|
- code = __parse_fpscr(current->thread.fpscr.val);
|
|
|
- _exception(SIGFPE, regs, code, regs->nip);
|
|
|
- goto bail;
|
|
|
- }
|
|
|
- case -EFAULT:
|
|
|
- _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
|
|
|
+ if (!emulate_math(regs))
|
|
|
goto bail;
|
|
|
- }
|
|
|
- /* fall through on any other errors */
|
|
|
-#endif /* CONFIG_MATH_EMULATION */
|
|
|
|
|
|
/* Try to emulate it if we should. */
|
|
|
if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) {
|
|
@@ -1428,11 +1443,6 @@ void performance_monitor_exception(struct pt_regs *regs)
|
|
|
#ifdef CONFIG_8xx
|
|
|
void SoftwareEmulation(struct pt_regs *regs)
|
|
|
{
|
|
|
- extern int do_mathemu(struct pt_regs *);
|
|
|
-#if defined(CONFIG_MATH_EMULATION)
|
|
|
- int errcode;
|
|
|
-#endif
|
|
|
-
|
|
|
CHECK_FULL_REGS(regs);
|
|
|
|
|
|
if (!user_mode(regs)) {
|
|
@@ -1440,31 +1450,10 @@ void SoftwareEmulation(struct pt_regs *regs)
|
|
|
die("Kernel Mode Software FPU Emulation", regs, SIGFPE);
|
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_MATH_EMULATION
|
|
|
- errcode = do_mathemu(regs);
|
|
|
- if (errcode >= 0)
|
|
|
- PPC_WARN_EMULATED(math, regs);
|
|
|
-
|
|
|
- switch (errcode) {
|
|
|
- case 0:
|
|
|
- emulate_single_step(regs);
|
|
|
- return;
|
|
|
- case 1: {
|
|
|
- int code = 0;
|
|
|
- code = __parse_fpscr(current->thread.fpscr.val);
|
|
|
- _exception(SIGFPE, regs, code, regs->nip);
|
|
|
- return;
|
|
|
- }
|
|
|
- case -EFAULT:
|
|
|
- _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
|
|
|
+ if (!emulate_math(regs))
|
|
|
return;
|
|
|
- default:
|
|
|
- _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
|
|
|
- return;
|
|
|
- }
|
|
|
-#else
|
|
|
+
|
|
|
_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
|
|
|
-#endif
|
|
|
}
|
|
|
#endif /* CONFIG_8xx */
|
|
|
|