From 60bccbed6f53c953c62bdc2ac699395a13b6eecc Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Tue, 19 Dec 2006 17:35:49 +0900 Subject: [POWERPC] Use is_init() instead of pid==1 Use is_init() rather than hard coded pid comparison. Cc: Anton Blanchard Signed-off-by: Akinobu Mita Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/traps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc/kernel/traps.c') diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 535f5066564..6915b91868b 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -174,7 +174,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) * generate the same exception over and over again and we get * nowhere. Better to kill it and let the kernel panic. */ - if (current->pid == 1) { + if (is_init(current)) { __sighandler_t handler; spin_lock_irq(¤t->sighand->siglock); -- cgit v1.2.3 From 04903a30a327513b97c1271fc6bc4dad6502d1b8 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 7 Feb 2007 01:13:32 -0600 Subject: [POWERPC] Enable interrupts if we are doing fp math emulation Anytime we are emulating an instruction we are going to be doing some form of get_user() to get the instruction image to decode. Since get_user() might sleep we need to ensure we have interrupts enabled or we might see something like: Debug: sleeping function called from invalid context at arch/powerpc/kernel/traps.c:697 in_atomic():0, irqs_disabled():1 Call Trace: [D6023EB0] [C0007F84] show_stack+0x58/0x174 (unreliable) [D6023EE0] [C0022C34] __might_sleep+0xbc/0xd0 [D6023EF0] [C000D158] program_check_exception+0x1d8/0x4fc [D6023F40] [C000E744] ret_from_except_full+0x0/0x4c --- Exception: 700 at 0x102a7100 LR = 0xdb9ef04 However, we want to ensure that interrupts are disabled when handling a trap exception that might be used for a kernel breakpoint. This is why ProgramCheck is marked as EXC_XFER_STD instead of EXC_XFER_EE. Signed-off-by: Kumar Gala --- arch/powerpc/kernel/traps.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'arch/powerpc/kernel/traps.c') diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 6915b91868b..f038caa3c2b 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -739,20 +739,7 @@ void __kprobes program_check_exception(struct pt_regs *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 no reason flags will be set */ -#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 - * ESR_DST (!?) or 0. In the process of chasing this with the - * hardware people - not sure if it can happen on any illegal - * instruction or only on FP instructions, whether there is a - * pattern to occurences etc. -dgibson 31/Mar/2003 */ - if (!(reason & REASON_TRAP) && do_mathemu(regs) == 0) { - emulate_single_step(regs); - return; - } -#endif /* CONFIG_MATH_EMULATION */ + * has no FPU, in that case the reason flags will be 0 */ if (reason & REASON_FP) { /* IEEE FP exception */ @@ -778,6 +765,20 @@ void __kprobes program_check_exception(struct pt_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 + * ESR_DST (!?) or 0. In the process of chasing this with the + * hardware people - not sure if it can happen on any illegal + * instruction or only on FP instructions, whether there is a + * pattern to occurences etc. -dgibson 31/Mar/2003 */ + if (do_mathemu(regs) == 0) { + emulate_single_step(regs); + return; + } +#endif /* CONFIG_MATH_EMULATION */ + /* Try to emulate it if we should. */ if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) { switch (emulate_instruction(regs)) { -- cgit v1.2.3 From 5fad293bcbd48d9a2370020cf60e4b4a42559b12 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 7 Feb 2007 01:47:59 -0600 Subject: [POWERPC] Fixup error handling when emulating a floating point instruction When we do full FP emulation its possible that we need to post a SIGFPE based on the results of the emulation. The previous code ignored this case completely. Additionally, the Soft_emulate_8xx case had two issues. One, we should never generate a SIGFPE since the code only does data movement. Second, we were interpreting the return codes incorrectly, it returns 0 on success, 1 on illop and -EFAULT on a data access error. Signed-off-by: Kumar Gala --- arch/powerpc/kernel/traps.c | 82 +++++++++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 22 deletions(-) (limited to 'arch/powerpc/kernel/traps.c') diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index f038caa3c2b..dcc6f159fd9 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -535,34 +535,40 @@ static void emulate_single_step(struct pt_regs *regs) } } -static void parse_fpe(struct pt_regs *regs) +static inline int __parse_fpscr(unsigned long fpscr) { - int code = 0; - unsigned long fpscr; - - flush_fp_to_thread(current); - - fpscr = current->thread.fpscr.val; + int ret = 0; /* Invalid operation */ if ((fpscr & FPSCR_VE) && (fpscr & FPSCR_VX)) - code = FPE_FLTINV; + ret = FPE_FLTINV; /* Overflow */ else if ((fpscr & FPSCR_OE) && (fpscr & FPSCR_OX)) - code = FPE_FLTOVF; + ret = FPE_FLTOVF; /* Underflow */ else if ((fpscr & FPSCR_UE) && (fpscr & FPSCR_UX)) - code = FPE_FLTUND; + ret = FPE_FLTUND; /* Divide by zero */ else if ((fpscr & FPSCR_ZE) && (fpscr & FPSCR_ZX)) - code = FPE_FLTDIV; + ret = FPE_FLTDIV; /* Inexact result */ else if ((fpscr & FPSCR_XE) && (fpscr & FPSCR_XX)) - code = FPE_FLTRES; + ret = FPE_FLTRES; + + return ret; +} + +static void parse_fpe(struct pt_regs *regs) +{ + int code = 0; + + flush_fp_to_thread(current); + + code = __parse_fpscr(current->thread.fpscr.val); _exception(SIGFPE, regs, code, regs->nip); } @@ -773,10 +779,21 @@ void __kprobes program_check_exception(struct pt_regs *regs) * hardware people - not sure if it can happen on any illegal * instruction or only on FP instructions, whether there is a * pattern to occurences etc. -dgibson 31/Mar/2003 */ - if (do_mathemu(regs) == 0) { + switch (do_mathemu(regs)) { + 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); + return; } + /* fall through on any other errors */ #endif /* CONFIG_MATH_EMULATION */ /* Try to emulate it if we should. */ @@ -892,18 +909,39 @@ void SoftwareEmulation(struct pt_regs *regs) #ifdef CONFIG_MATH_EMULATION errcode = do_mathemu(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); + return; + default: + _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); + return; + } + #else errcode = Soft_emulate_8xx(regs); -#endif - if (errcode) { - if (errcode > 0) - _exception(SIGFPE, regs, 0, 0); - else if (errcode == -EFAULT) - _exception(SIGSEGV, regs, 0, 0); - else - _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); - } else + switch (errcode) { + case 0: emulate_single_step(regs); + return; + case 1: + _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); + return; + case -EFAULT: + _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip); + return; + } +#endif } #endif /* CONFIG_8xx */ -- cgit v1.2.3