[PATCH] invalid instructions in kernel mode

STALE7865d

8 messages, 4 authors, 2005-04-08 · open the first message on its own page

[PATCH] invalid instructions in kernel mode

From: Fillod Stephane <hidden>
Date: 2005-03-31 17:47:51

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();
@@ -379,6 +385,7 @@
 		cvt_df(&data.d, &data.f, &current->thread.fpscr);
 		preempt_enable();
 		break;
+#endif
 	}
=20
 	if (flags & ST) {
--- 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.
  */
=20
-#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)
@@ -1125,6 +1126,7 @@
 	stfd	0,-4(r5)
 	blr
 #endif
+#endif
=20
 /*
  * Create a kernel thread
--- linux/arch/ppc/kernel/process.c	26 Mar 2005 03:28:20 -0000
1.1.1.2
+++ linux/arch/ppc/kernel/process.c	31 Mar 2005 16:33:25 -0000
@@ -342,7 +342,7 @@
 	printk("\n");
 #ifdef CONFIG_KALLSYMS
 	/*
-	 * Lookup NIP late so we have the best change of getting the
+	 * Lookup NIP late so we have the best chance of getting the
 	 * above info out without failing
 	 */
 	printk("NIP [%08lx] ", regs->nip);

Best Regards,

--=20
Stephane

Re: [PATCH] invalid instructions in kernel mode

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

Re: [PATCH] invalid instructions in kernel mode

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 =
16:33:25 -0000
 @@ -333,10 +333,14 @@
 =A0=A0=A0=A0=A0=A0=A0 }
 =A0
 =A0=A0=A0=A0=A0=A0=A0 if (flags & F) {
 +#if !(defined(CONFIG_4xx) || defined(CONFIG_8xx) ||
 defined(CONFIG_E500)) || defined(CONFIG_MATH_EMULATION)
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 preempt_disable();
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 if (regs->msr & MSR_FP)
 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
giveup_fpu(current);
=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 =
register=20
values
*/
 @@ -366,6 +370,8 @@
 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 }
 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 break;
 =A0
 +#if !(defined(CONFIG_4xx) || defined(CONFIG_8xx) ||
 defined(CONFIG_E500)) || defined(CONFIG_MATH_EMULATION)
+
 =A0=A0=A0=A0=A0=A0=A0 /* Single-precision FP load and store require =
conversions...=20
quoted hunk
*/
 =A0=A0=A0=A0=A0=A0=A0 case LD+F+S:
 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 preempt_disable();
@@ -379,6 +385,7 @@
 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 cvt_df(&data.d, &data.f, =
&current->thread.fpscr);
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 preempt_enable();
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 break;
 +#endif
 =A0=A0=A0=A0=A0=A0=A0 }
 =A0
 =A0=A0=A0=A0=A0=A0=A0 if (flags & ST) {
 --- linux/arch/ppc/kernel/misc.S=A0=A0=A0=A0=A0=A0=A0 26 Mar 2005 =
03:28:36 -0000
 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

Re: [PATCH] invalid instructions in kernel mode

From: Tom Rini <hidden>
Date: 2005-04-07 17:38:27

On Thu, Mar 31, 2005 at 07:47:32PM +0200, Fillod Stephane wrote:
When CPU has no (classic) FPU, and math emulation is disabled,
fp instructions are not allowed in kernel mode.
[snip]
quoted hunk
--- 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)
@@ -1125,6 +1126,7 @@
 	stfd	0,-4(r5)
 	blr
 #endif
+#endif
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/

Re: [PATCH] invalid instructions in kernel mode

From: Kumar Gala <hidden>
Date: 2005-04-07 21:42:13

On Apr 7, 2005, at 12:38 PM, Tom Rini wrote:
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]
 > --- linux/arch/ppc/kernel/misc.S=A0=A0=A0=A0=A0 26 Mar 2005 =
03:28:36 -0000
 > 1.1.1.2
 > +++ linux/arch/ppc/kernel/misc.S=A0=A0=A0=A0=A0 31 Mar 2005 =
16:33:25 -0000
 > @@ -1096,7 +1096,8 @@
 >=A0=A0 * and exceptions as if the cpu had performed the load or =
store.
 >=A0=A0 */
 >=A0
quoted
-#if defined(CONFIG_4xx) || defined(CONFIG_E500)
+#if !(defined(CONFIG_4xx) || defined(CONFIG_E500) ||
 > defined(CONFIG_8xx)) ||=A0 defined(CONFIG_MATH_EMULATION)
quoted
+#if defined(CONFIG_4xx) || defined(CONFIG_E500)
=A0 _GLOBAL(cvt_fd)
=A0 =A0=A0=A0=A0 lfs=A0=A0=A0=A0 0,0(r3)
 >=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

Re: [PATCH] invalid instructions in kernel mode

From: Tom Rini <hidden>
Date: 2005-04-07 22:14:42

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)
@@ -1125,6 +1126,7 @@
? ???? stfd??? 0,-4(r5)
? ???? blr
? #endif
+#endif
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/

Re: [PATCH] invalid instructions in kernel mode

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

Re: [PATCH] invalid instructions in kernel mode

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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help