Hi,
When CPU has no (classic) FPU, and math emulation is disabled,
fp instructions are not allowed in kernel mode.
This bug has been found with crashme (crash01) of LTP, on a e500 system.
The patch was made against linux 2.6.11.6.
A trivial typo fix has been appended.
Rem: a CONFIG_PPCFPU define could make life easier.
Signed-off-by: Stephane Fillod <redacted>
--- linux/arch/ppc/kernel/align.c 6 Dec 2004 16:18:11 -0000
1.1.1.1
+++ linux/arch/ppc/kernel/align.c 31 Mar 2005 16:33:25 -0000
@@ -333,10 +333,14 @@}
=20
if (flags & F) {
+#if !(defined(CONFIG_4xx) || defined(CONFIG_8xx) ||
defined(CONFIG_E500)) || defined(CONFIG_MATH_EMULATION)
preempt_disable();
if (regs->msr & MSR_FP)
giveup_fpu(current);
preempt_enable();
+#else
+ return 0;
+#endif
}
=20
/* If we read the operand, copy it in, else get register values
*/
@@ -366,6 +370,8 @@ } break;
=20
+#if !(defined(CONFIG_4xx) || defined(CONFIG_8xx) ||
defined(CONFIG_E500)) || defined(CONFIG_MATH_EMULATION)
+
/* Single-precision FP load and store require conversions... */
case LD+F+S:
preempt_disable();
From: Dan Malek <hidden> Date: 2005-03-31 18:16:08
On Mar 31, 2005, at 12:47 PM, Fillod Stephane wrote:
When CPU has no (classic) FPU, and math emulation is disabled,
fp instructions are not allowed in kernel mode.
FP Instructions are never allowed in kernel mode regardless of the CPU.
However, with math emulation disabled and no FPU, we still emulate
FP load/store operations because they are usually hard coded in
some of the context save/restore functions of the C library.
This bug has been found with crashme (crash01) of LTP, on a e500 system.
What is the bug? This patch disables a big feature we have been
using for many years. Please take another look at this.
Thanks.
-- Dan
From: Kumar Gala <hidden> Date: 2005-04-01 10:04:44
What is the crash01 test doing that causes this code to get invoked? =20
is the kernel you are using using build with math emulation on or off?
- kumar
On Mar 31, 2005, at 11:47 AM, Fillod Stephane wrote:
quoted hunk
Hi,
When CPU has no (classic) FPU, and math emulation is disabled,
fp instructions are not allowed in kernel mode.
This bug has been found with crashme (crash01) of LTP, on a e500=20
system.
The patch was made against linux 2.6.11.6.
A trivial typo fix has been appended.
Rem: a CONFIG_PPCFPU define could make life easier.
Signed-off-by: Stephane Fillod <redacted>
--- linux/arch/ppc/kernel/align.c=A0=A0=A0=A0=A0=A0 6 Dec 2004 =
16:18:11 -0000
1.1.1.1
+++ linux/arch/ppc/kernel/align.c=A0=A0=A0=A0=A0=A0 31 Mar 2005 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 preempt_enable();
+#else
+=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 return 0;
+#endif
=A0=A0=A0=A0=A0=A0=A0 }
=A0
=A0=A0=A0=A0=A0=A0=A0 /* If we read the operand, copy it in, else get =
1.1.1.2
+++ linux/arch/ppc/kernel/misc.S=A0=A0=A0=A0=A0=A0=A0 31 Mar 2005 =
16:33:25 -0000
@@ -1096,7 +1096,8 @@
=A0 * and exceptions as if the cpu had performed the load or store.
=A0 */
=A0
-#if defined(CONFIG_4xx) || defined(CONFIG_E500)
+#if !(defined(CONFIG_4xx) || defined(CONFIG_E500) ||
defined(CONFIG_8xx)) ||=A0 defined(CONFIG_MATH_EMULATION)
+#if defined(CONFIG_4xx) || defined(CONFIG_E500)
=A0_GLOBAL(cvt_fd)
=A0=A0=A0=A0=A0=A0=A0 lfs=A0=A0=A0=A0 0,0(r3)
=A0=A0=A0=A0=A0=A0=A0 stfd=A0=A0=A0 0,0(r4)
@@ -1125,6 +1126,7 @@
=A0=A0=A0=A0=A0=A0=A0 stfd=A0=A0=A0 0,-4(r5)
=A0=A0=A0=A0=A0=A0=A0 blr
=A0#endif
+#endif
=A0
=A0/*
=A0 * Create a kernel thread
--- linux/arch/ppc/kernel/process.c=A0=A0=A0=A0 26 Mar 2005 03:28:20 =
-0000
1.1.1.2
+++ linux/arch/ppc/kernel/process.c=A0=A0=A0=A0 31 Mar 2005 16:33:25 =
-0000
@@ -342,7 +342,7 @@
=A0=A0=A0=A0=A0=A0=A0 printk("\n");
=A0#ifdef CONFIG_KALLSYMS
=A0=A0=A0=A0=A0=A0=A0 /*
-=A0=A0=A0=A0=A0=A0=A0 * Lookup NIP late so we have the best change =
of getting the
+=A0=A0=A0=A0=A0=A0=A0 * Lookup NIP late so we have the best chance =
of getting the
=A0=A0=A0=A0=A0=A0=A0=A0 * above info out without failing
=A0=A0=A0=A0=A0=A0=A0=A0 */
=A0=A0=A0=A0=A0=A0=A0 printk("NIP [%08lx] ", regs->nip);
Best Regards,
--=20
Stephane
The problem here is, HEY! (classic) FP instrs in the kernel. The
question is why? Or rather, why are these four classic FP instrs
(lfs/lfd/stfd/stfs) being done on CONFIG_4xx || E500 when neither has
classic FP? I think the problem here is that on !FPU
(which is 4xx||E500||8xx, or so), we need to rewrite these two
functions (yes, 8xx does emulate them if hit, but that's a tangent).
--
Tom Rini
http://gate.crashing.org/~trini/
>=A0 =A0=A0=A0=A0 stfd=A0=A0=A0 0,0(r4)
> @@ -1125,6 +1126,7 @@
>=A0 =A0=A0=A0=A0 stfd=A0=A0=A0 0,-4(r5)
>=A0 =A0=A0=A0=A0 blr
>=A0 #endif
> +#endif
The problem here is, HEY! (classic) FP instrs in the kernel.=A0 The
question is why?=A0 Or rather, why are these four classic FP instrs
(lfs/lfd/stfd/stfs) being done on CONFIG_4xx || E500 when neither has
classic FP?=A0 I think the problem here is that on !FPU
(which is 4xx||E500||8xx, or so), we need to rewrite these two
functions (yes, 8xx does emulate them if hit, but that's a tangent).
What is not clear to me is what condition causes these to get hit on an=20=
e500.
- kumar
On Thu, Apr 07, 2005 at 04:41:59PM -0500, Kumar Gala wrote:
On Apr 7, 2005, at 12:38 PM, Tom Rini wrote:
quoted
On Thu, Mar 31, 2005 at 07:47:32PM +0200, Fillod Stephane wrote:
quoted
When CPU has no (classic) FPU, and math emulation is disabled,
fp instructions are not allowed in kernel mode.
[snip]
quoted
--- linux/arch/ppc/kernel/misc.S????? 26 Mar 2005 03:28:36 -0000
1.1.1.2
+++ linux/arch/ppc/kernel/misc.S????? 31 Mar 2005 16:33:25 -0000
@@ -1096,7 +1096,8 @@
?? * and exceptions as if the cpu had performed the load or store.
?? */
?
-#if defined(CONFIG_4xx) || defined(CONFIG_E500)
+#if !(defined(CONFIG_4xx) || defined(CONFIG_E500) ||
defined(CONFIG_8xx)) ||? defined(CONFIG_MATH_EMULATION)
+#if defined(CONFIG_4xx) || defined(CONFIG_E500)
? _GLOBAL(cvt_fd)
? ???? lfs???? 0,0(r3)
? ???? stfd??? 0,0(r4)
The problem here is, HEY! (classic) FP instrs in the kernel.? The
question is why?? Or rather, why are these four classic FP instrs
(lfs/lfd/stfd/stfs) being done on CONFIG_4xx || E500 when neither has
classic FP?? I think the problem here is that on !FPU
(which is 4xx||E500||8xx, or so), we need to rewrite these two
functions (yes, 8xx does emulate them if hit, but that's a tangent).
What is not clear to me is what condition causes these to get hit on an
e500.
They are called in align.c from fix_alignment(). As has been said, some
of the stress testing apps in LTP will trigger this. Since the comment
around the code in question (in fix_alignent()) is
/* Single-precision FP load and store require conversions... */
perhaps it's more valid to not define these functions on e500 || 4xx,
and make the two cases in the switch there depend on !e500 && !4xx.
--
Tom Rini
http://gate.crashing.org/~trini/
From: Kumar Gala <hidden> Date: 2005-04-07 22:29:44
[snip]
> >The problem here is, HEY! (classic) FP instrs in the kernel.? The
> > question is why?? Or rather, why are these four classic FP instrs
> > (lfs/lfd/stfd/stfs) being done on CONFIG_4xx || E500 when neither=20=
has
> > classic FP?? I think the problem here is that on !FPU
> >(which is 4xx||E500||8xx, or so), we need to rewrite these two
> > functions (yes, 8xx does emulate them if hit, but that's a=20
tangent).
>
quoted
What is not clear to me is what condition causes these to get hit on=20=
an
quoted
e500.
They are called in align.c from fix_alignment().=A0 As has been said,=20=
some
of the stress testing apps in LTP will trigger this.=A0 Since the=20
comment
around the code in question (in fix_alignent()) is
/* Single-precision FP load and store require conversions... */
perhaps it's more valid to not define these functions on e500 || 4xx,
and make the two cases in the switch there depend on !e500 && !4xx.
What I'm concerned about what instruction is actually causing this=20
fault that e500 actually gets into this case to began with. Maybe I=20
missed something in the email thread, but it would seem the only way to=20=
get here is via kernel emulation of the floating point load/store=20
instructions, but that seems odd since they would have to be doing=20
normal integer load/store... something is not quiet right in all this.
Before we go start making changes I really do want to know what=20
instruction, with what effective address is causing this case to get=20
triggered.
Can someone add something like the following:
if (__get_user(instr, (unsigned int __user *) regs->nip))
return 0;
int insn_orig;
....
insn_orig =3D instr;
....
case LD+F+S:
printk ("align fault [LD+F+S] for insn =3D %x @ %x\n", insn_orig,=20=
regs->nip);
..
case ST+F+S:
printk ("align fault [ST+F+S] for insn =3D %x @ %x\n", insn_orig,=20=
regs->nip);
and report back the results.
thanks
- kumar
From: Kumar Gala <hidden> Date: 2005-04-08 16:02:50
Fillod,
Are you running this via a ramdisk or nfs? If ramdisk can you post it somewhere that I can get to?
Also, can you email the list with the kernel oops that shows up.
thanks
- kumar