linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] MIPS: Fix exception entry when CONFIG_EVA enabled
@ 2017-10-11  8:59 Matt Redfearn
  2017-10-11 13:12 ` Corey Minyard
  2017-10-18 17:34 ` Maciej W. Rozycki
  0 siblings, 2 replies; 8+ messages in thread
From: Matt Redfearn @ 2017-10-11  8:59 UTC (permalink / raw)
  To: Ralf Baechle, James Hogan
  Cc: Matthew Fortune, linux-mips, Matt Redfearn, Corey Minyard,
	linux-kernel, Jason A. Donenfeld, Paul Burton

Commit 9fef68686317b ("MIPS: Make SAVE_SOME more standard") made several
changes to the order in which registers are saved in the SAVE_SOME
macro, used by exception handlers to save the processor state. In
particular, it removed the
move   k1, sp
in the delay slot of the branch testing if the processor is already in
kernel mode. This is replaced later in the macro by a
move   k0, sp
When CONFIG_EVA is disabled, this instruction actually appears in the
delay slot of the branch. However, when CONFIG_EVA is enabled, instead
the RPS workaround of
MFC0	k0, CP0_ENTRYHI
appears in the delay slot. This results in k0 not containing the stack
pointer, but some unrelated value, which is then saved to the kernel
stack. On exit from the exception, this bogus value is restored to the
stack pointer, resulting in an OOPS.

Fix this by moving the save of SP in k0 explicitly in the delay slot of
the branch, outside of the CONFIG_EVA section, restoring the expected
instruction ordering when CONFIG_EVA is active.

Fixes: 9fef68686317b ("MIPS: Make SAVE_SOME more standard")
Signed-off-by: Matt Redfearn <matt.redfearn@mips.com>
Reported-by: Vladimir Kondratiev <vladimir.kondratiev@intel.com>

---

Note that some of our compiler people are dubious about putting frame
related instructions in conditionally executed blocks of code. In this
case, presuming that we only care about unwinding the kernel stack, then
we only care about the case in which the branch is taken, and k0 always
contains the SP to be saved. There is also a question about putting
frame related instructions in branch delay slots. Again, in this case,
we think it's OK to use them since the only path that ought to be
unwound will be the "branch taken" route where we are already on the
kernel stack.
Not having access to a CFI based kernel stack unwinder makes this change
difficult to verify, but since the same construct already existed when
CONFIG_EVA is disabled, I don't think this change is likely to break the
unwinder, and fixes exception entry when CONFIG_EVA is enabled.

Thanks,
Matt

---
 arch/mips/include/asm/stackframe.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index 5d3563c55e0c..2161357cc68f 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -199,6 +199,10 @@
 		sll	k0, 3		/* extract cu0 bit */
 		.set	noreorder
 		bltz	k0, 8f
+		 move	k0, sp
+		.if \docfi
+		.cfi_register sp, k0
+		.endif
 #ifdef CONFIG_EVA
 		/*
 		 * Flush interAptiv's Return Prediction Stack (RPS) by writing
@@ -225,10 +229,6 @@
 		MTC0	k0, CP0_ENTRYHI
 #endif
 		.set	reorder
-		 move	k0, sp
-		.if \docfi
-		.cfi_register sp, k0
-		.endif
 		/* Called from user mode, new stack. */
 		get_saved_sp docfi=\docfi tosp=1
 8:
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH] MIPS: Fix exception entry when CONFIG_EVA enabled
  2017-10-11  8:59 [PATCH] MIPS: Fix exception entry when CONFIG_EVA enabled Matt Redfearn
@ 2017-10-11 13:12 ` Corey Minyard
  2017-10-31 23:48   ` James Hogan
  2017-10-18 17:34 ` Maciej W. Rozycki
  1 sibling, 1 reply; 8+ messages in thread
From: Corey Minyard @ 2017-10-11 13:12 UTC (permalink / raw)
  To: Matt Redfearn, Ralf Baechle, James Hogan
  Cc: Matthew Fortune, linux-mips, linux-kernel, Jason A. Donenfeld,
	Paul Burton

On 10/11/2017 03:59 AM, Matt Redfearn wrote:
> Commit 9fef68686317b ("MIPS: Make SAVE_SOME more standard") made several
> changes to the order in which registers are saved in the SAVE_SOME
> macro, used by exception handlers to save the processor state. In
> particular, it removed the
> move   k1, sp
> in the delay slot of the branch testing if the processor is already in
> kernel mode. This is replaced later in the macro by a
> move   k0, sp
> When CONFIG_EVA is disabled, this instruction actually appears in the
> delay slot of the branch. However, when CONFIG_EVA is enabled, instead
> the RPS workaround of
> MFC0	k0, CP0_ENTRYHI
> appears in the delay slot. This results in k0 not containing the stack
> pointer, but some unrelated value, which is then saved to the kernel
> stack. On exit from the exception, this bogus value is restored to the
> stack pointer, resulting in an OOPS.
>
> Fix this by moving the save of SP in k0 explicitly in the delay slot of
> the branch, outside of the CONFIG_EVA section, restoring the expected
> instruction ordering when CONFIG_EVA is active.
>
> Fixes: 9fef68686317b ("MIPS: Make SAVE_SOME more standard")
> Signed-off-by: Matt Redfearn <matt.redfearn@mips.com>
> Reported-by: Vladimir Kondratiev <vladimir.kondratiev@intel.com>

I looked this over pretty carefully and it looks correct to me.  It 
makes no difference
in the instructions generated by the non-EVA case.  I shouldn't have 
missed this :(.

Reviewed-by: Corey Minyard <cminyard@mvista.com>

>
> ---
>
> Note that some of our compiler people are dubious about putting frame
> related instructions in conditionally executed blocks of code. In this
> case, presuming that we only care about unwinding the kernel stack, then
> we only care about the case in which the branch is taken, and k0 always
> contains the SP to be saved. There is also a question about putting
> frame related instructions in branch delay slots. Again, in this case,
> we think it's OK to use them since the only path that ought to be
> unwound will be the "branch taken" route where we are already on the
> kernel stack.

Since the compiler can put frame-related instructions in delay slots (see
aee16625b19 MIPS: Fix issues in backtraces), it's probably ok.  I have 
tested
this before with kernel dumps and gdb, and gdb had no issues with this.

That said, this is a tricky case.  But looking at the generated unwinding
info, it seems to do the right thing.

> Not having access to a CFI based kernel stack unwinder makes this change
> difficult to verify, but since the same construct already existed when
> CONFIG_EVA is disabled, I don't think this change is likely to break the
> unwinder, and fixes exception entry when CONFIG_EVA is enabled.

Agreed.  Thanks for fixing this.

-corey

> Thanks,
> Matt
>
> ---
>   arch/mips/include/asm/stackframe.h | 8 ++++----
>   1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
> index 5d3563c55e0c..2161357cc68f 100644
> --- a/arch/mips/include/asm/stackframe.h
> +++ b/arch/mips/include/asm/stackframe.h
> @@ -199,6 +199,10 @@
>   		sll	k0, 3		/* extract cu0 bit */
>   		.set	noreorder
>   		bltz	k0, 8f
> +		 move	k0, sp
> +		.if \docfi
> +		.cfi_register sp, k0
> +		.endif
>   #ifdef CONFIG_EVA
>   		/*
>   		 * Flush interAptiv's Return Prediction Stack (RPS) by writing
> @@ -225,10 +229,6 @@
>   		MTC0	k0, CP0_ENTRYHI
>   #endif
>   		.set	reorder
> -		 move	k0, sp
> -		.if \docfi
> -		.cfi_register sp, k0
> -		.endif
>   		/* Called from user mode, new stack. */
>   		get_saved_sp docfi=\docfi tosp=1
>   8:

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] MIPS: Fix exception entry when CONFIG_EVA enabled
  2017-10-11  8:59 [PATCH] MIPS: Fix exception entry when CONFIG_EVA enabled Matt Redfearn
  2017-10-11 13:12 ` Corey Minyard
@ 2017-10-18 17:34 ` Maciej W. Rozycki
  1 sibling, 0 replies; 8+ messages in thread
From: Maciej W. Rozycki @ 2017-10-18 17:34 UTC (permalink / raw)
  To: Matt Redfearn
  Cc: Ralf Baechle, James Hogan, Matthew Fortune, linux-mips,
	Corey Minyard, linux-kernel, Jason A. Donenfeld, Paul Burton

On Wed, 11 Oct 2017, Matt Redfearn wrote:

> diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
> index 5d3563c55e0c..2161357cc68f 100644
> --- a/arch/mips/include/asm/stackframe.h
> +++ b/arch/mips/include/asm/stackframe.h
> @@ -199,6 +199,10 @@
>  		sll	k0, 3		/* extract cu0 bit */
>  		.set	noreorder
>  		bltz	k0, 8f
> +		 move	k0, sp
> +		.if \docfi
> +		.cfi_register sp, k0
> +		.endif

 Using $k1 for the Status.CU0 check would let us get rid of the 
`noreorder' block, making this code less fragile at no run-time cost, 
i.e.:

		mfc0	k1, CP0_STATUS
		sll	k1, 3
		move	k0, sp
		bltz	k1, 8f

(unfortunately I can't see a way to usefully fill the coprocessor move 
delay slot automatically scheduled by GAS here between MFC0 and SLL for 
processors that require it).

  Maciej

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] MIPS: Fix exception entry when CONFIG_EVA enabled
  2017-10-11 13:12 ` Corey Minyard
@ 2017-10-31 23:48   ` James Hogan
  2017-11-13 10:47     ` Maciej W. Rozycki
  0 siblings, 1 reply; 8+ messages in thread
From: James Hogan @ 2017-10-31 23:48 UTC (permalink / raw)
  To: Corey Minyard
  Cc: Matt Redfearn, Ralf Baechle, Matthew Fortune, linux-mips,
	linux-kernel, Jason A. Donenfeld, Paul Burton

[-- Attachment #1: Type: text/plain, Size: 1808 bytes --]

On Wed, Oct 11, 2017 at 08:12:31AM -0500, Corey Minyard wrote:
> On 10/11/2017 03:59 AM, Matt Redfearn wrote:
> > Commit 9fef68686317b ("MIPS: Make SAVE_SOME more standard") made several
> > changes to the order in which registers are saved in the SAVE_SOME
> > macro, used by exception handlers to save the processor state. In
> > particular, it removed the
> > move   k1, sp
> > in the delay slot of the branch testing if the processor is already in
> > kernel mode. This is replaced later in the macro by a
> > move   k0, sp
> > When CONFIG_EVA is disabled, this instruction actually appears in the
> > delay slot of the branch. However, when CONFIG_EVA is enabled, instead
> > the RPS workaround of
> > MFC0	k0, CP0_ENTRYHI
> > appears in the delay slot. This results in k0 not containing the stack
> > pointer, but some unrelated value, which is then saved to the kernel
> > stack. On exit from the exception, this bogus value is restored to the
> > stack pointer, resulting in an OOPS.
> >
> > Fix this by moving the save of SP in k0 explicitly in the delay slot of
> > the branch, outside of the CONFIG_EVA section, restoring the expected
> > instruction ordering when CONFIG_EVA is active.
> >
> > Fixes: 9fef68686317b ("MIPS: Make SAVE_SOME more standard")
> > Signed-off-by: Matt Redfearn <matt.redfearn@mips.com>
> > Reported-by: Vladimir Kondratiev <vladimir.kondratiev@intel.com>
> 
> I looked this over pretty carefully and it looks correct to me.  It 
> makes no difference
> in the instructions generated by the non-EVA case.  I shouldn't have 
> missed this :(.
> 
> Reviewed-by: Corey Minyard <cminyard@mvista.com>

Yeh, having stared at it for a little while it looks correct to me too.

Reviewed-by: James Hogan <jhogan@kernel.org>

Cheers
James

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] MIPS: Fix exception entry when CONFIG_EVA enabled
  2017-10-31 23:48   ` James Hogan
@ 2017-11-13 10:47     ` Maciej W. Rozycki
  2017-11-15 10:32       ` Matt Redfearn
  0 siblings, 1 reply; 8+ messages in thread
From: Maciej W. Rozycki @ 2017-11-13 10:47 UTC (permalink / raw)
  To: James Hogan
  Cc: Corey Minyard, Matt Redfearn, Ralf Baechle, Matthew Fortune,
	linux-mips, linux-kernel, Jason A. Donenfeld, Paul Burton

On Tue, 31 Oct 2017, James Hogan wrote:

> > I looked this over pretty carefully and it looks correct to me.  It 
> > makes no difference
> > in the instructions generated by the non-EVA case.  I shouldn't have 
> > missed this :(.
> > 
> > Reviewed-by: Corey Minyard <cminyard@mvista.com>
> 
> Yeh, having stared at it for a little while it looks correct to me too.
> 
> Reviewed-by: James Hogan <jhogan@kernel.org>

 How about getting rid of the `noreorder' mode and the manually scheduled 
delay slot here altogether though, as I outlined?

  Maciej

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] MIPS: Fix exception entry when CONFIG_EVA enabled
  2017-11-13 10:47     ` Maciej W. Rozycki
@ 2017-11-15 10:32       ` Matt Redfearn
  2017-11-15 13:48         ` Maciej W. Rozycki
  0 siblings, 1 reply; 8+ messages in thread
From: Matt Redfearn @ 2017-11-15 10:32 UTC (permalink / raw)
  To: Maciej W. Rozycki, James Hogan
  Cc: Corey Minyard, Ralf Baechle, Matthew Fortune, linux-mips,
	linux-kernel, Jason A. Donenfeld, Paul Burton



On 13/11/17 10:47, Maciej W. Rozycki wrote:
> On Tue, 31 Oct 2017, James Hogan wrote:
> 
>>> I looked this over pretty carefully and it looks correct to me.  It
>>> makes no difference
>>> in the instructions generated by the non-EVA case.  I shouldn't have
>>> missed this :(.
>>>
>>> Reviewed-by: Corey Minyard <cminyard@mvista.com>
>>
>> Yeh, having stared at it for a little while it looks correct to me too.
>>
>> Reviewed-by: James Hogan <jhogan@kernel.org>
> 
>   How about getting rid of the `noreorder' mode and the manually scheduled
> delay slot here altogether though, as I outlined?
> 
>    Maciej
> 

Hi Maciej,

I like the change you propose, however I can't coax GAS to reorder the 
instructions appropriately. With this patch on top of 4.14:

--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -195,14 +195,16 @@
                 .set    push
                 .set    noat
                 .set    reorder
-               mfc0    k0, CP0_STATUS
-               sll     k0, 3           /* extract cu0 bit */
-               .set    noreorder
-               bltz    k0, 8f
-                move   k0, sp
+               mfc0    k1, CP0_STATUS
+               sll     k1, 3           /* extract cu0 bit */
+
+               move    k0, sp
                 .if \docfi
                 .cfi_register sp, k0
                 .endif
+
+               bltz    k1, 8f
+
  #ifdef CONFIG_EVA
                 /*
                  * Flush interAptiv's Return Prediction Stack (RPS) by 
writing
@@ -228,7 +230,6 @@
                 MFC0    k0, CP0_ENTRYHI
                 MTC0    k0, CP0_ENTRYHI
  #endif
-               .set    reorder
                 /* Called from user mode, new stack. */
                 get_saved_sp docfi=\docfi tosp=1
  8:


The generated assembly is:

80405d00 <handle_int>:
80405d00:       401b6000        mfc0    k1,c0_status
80405d04:       001bd8c0        sll     k1,k1,0x3
80405d08:       03a0d025        move    k0,sp
80405d0c:       07600007        bltz    k1,80405d2c <handle_int+0x2c>
80405d10:       00000000        nop
80405d14:       401a2000        mfc0    k0,c0_context

Apparently GAS has not been able to reorder the move into the branch 
delay slot for some reason. Any ideas?

Thanks,
Matt

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] MIPS: Fix exception entry when CONFIG_EVA enabled
  2017-11-15 10:32       ` Matt Redfearn
@ 2017-11-15 13:48         ` Maciej W. Rozycki
  2017-11-15 14:53           ` Maciej W. Rozycki
  0 siblings, 1 reply; 8+ messages in thread
From: Maciej W. Rozycki @ 2017-11-15 13:48 UTC (permalink / raw)
  To: Matt Redfearn
  Cc: James Hogan, Corey Minyard, Ralf Baechle, Matthew Fortune,
	linux-mips, linux-kernel, Jason A. Donenfeld, Paul Burton

On Wed, 15 Nov 2017, Matt Redfearn wrote:

> I like the change you propose, however I can't coax GAS to reorder the
> instructions appropriately. With this patch on top of 4.14:
> 
> --- a/arch/mips/include/asm/stackframe.h
> +++ b/arch/mips/include/asm/stackframe.h
> @@ -195,14 +195,16 @@
>                 .set    push
>                 .set    noat
>                 .set    reorder
> -               mfc0    k0, CP0_STATUS
> -               sll     k0, 3           /* extract cu0 bit */
> -               .set    noreorder
> -               bltz    k0, 8f
> -                move   k0, sp
> +               mfc0    k1, CP0_STATUS
> +               sll     k1, 3           /* extract cu0 bit */
> +
> +               move    k0, sp
>                 .if \docfi
>                 .cfi_register sp, k0
>                 .endif
> +
> +               bltz    k1, 8f
> +
>  #ifdef CONFIG_EVA
>                 /*
>                  * Flush interAptiv's Return Prediction Stack (RPS) by writing
> @@ -228,7 +230,6 @@
>                 MFC0    k0, CP0_ENTRYHI
>                 MTC0    k0, CP0_ENTRYHI
>  #endif
> -               .set    reorder
>                 /* Called from user mode, new stack. */
>                 get_saved_sp docfi=\docfi tosp=1
>  8:
> 
> 
> The generated assembly is:
> 
> 80405d00 <handle_int>:
> 80405d00:       401b6000        mfc0    k1,c0_status
> 80405d04:       001bd8c0        sll     k1,k1,0x3
> 80405d08:       03a0d025        move    k0,sp
> 80405d0c:       07600007        bltz    k1,80405d2c <handle_int+0x2c>
> 80405d10:       00000000        nop
> 80405d14:       401a2000        mfc0    k0,c0_context
> 
> Apparently GAS has not been able to reorder the move into the branch delay
> slot for some reason. Any ideas?

 It could be the `.cfi_register' pseudo-op acting as a scheduling barrier.  
I think it can be moved further down, beyond the branch, because until 
clobbered later on $sp still holds the original value, so using either 
register for frame access or the value itself will yield the same result.

 Can you send me .i output from the offending source along with GCC 
options used to make .o output (use `V=1' with `make' if needed)?  I'll 
check if my hypothesis is right or find the actual cause otherwise.

  Maciej

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] MIPS: Fix exception entry when CONFIG_EVA enabled
  2017-11-15 13:48         ` Maciej W. Rozycki
@ 2017-11-15 14:53           ` Maciej W. Rozycki
  0 siblings, 0 replies; 8+ messages in thread
From: Maciej W. Rozycki @ 2017-11-15 14:53 UTC (permalink / raw)
  To: Matt Redfearn
  Cc: James Hogan, Corey Minyard, Ralf Baechle, Matthew Fortune,
	linux-mips, linux-kernel, Jason A. Donenfeld, Paul Burton

Hi Matt,

On Wed, 15 Nov 2017, Maciej W. Rozycki wrote:

>  Can you send me .i output from the offending source along with GCC 
> options used to make .o output (use `V=1' with `make' if needed)?  I'll 
> check if my hypothesis is right or find the actual cause otherwise.

 Thanks for the pieces requested.

 I can see what is going on here: the problem is the source is built with 
no optimisation enabled.  Consequently GAS does not schedule delay slots 
itself.  I wasn't aware we had this problem with kernel build flags -- it 
certainly affects more than just this piece of code.

 For GAS to schedule delay slots it has to be passed -O2 by the GCC 
driver.  The driver in turn will pass -O2 to GAS whenever at least -O has 
been used.  By default -O1 is passed, which only enables the removal of 
unnecessary NOPs, i.e. those that have been inserted precautionarily for 
execution hazard avoidance in the assembly pass and in the end turned out 
unnecessary and can be optionally removed in the relaxation pass.  NB 
GAS's default is actually -O2, i.e. when invoked directly, however this is 
overridden by the GCC driver as described.

 My recommendation would be using just the same CFLAGS for assembly 
sources that are used for C language sources; the GCC driver will silently 
filter out options that are irrelevant and interpret all the options that 
do have relevance.  This may be important for various `-f<foo>' and 
`-m<bar>' options which may sometimes affect assembly generation and, for 
that matter, multilib selection.

 This also means all CFLAGS should be passed to the linker as well, 
because again, they may affect linker options.

 So if you stick say `-O2' with your compiler invocation, for the purpose 
of this consideration possibly just like this:

$ make AFLAGS_genex.o=-O2 arch/mips/kernel/genex.o

then you should get the delay slot in question (and any other ones) 
scheduled.  Indeed with this build recipe applied I can already see a 
small code size reduction in `genex.o' even without your change:

$ size arch/mips/kernel/genex-?.o
   text	   data	    bss	    dec	    hex	filename
   8236	     48	      0	   8284	   205c	arch/mips/kernel/genex-0.o
   8204	     48	      0	   8252	   203c	arch/mips/kernel/genex-1.o
$

 HTH,

  Maciej

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-11-15 14:57 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-11  8:59 [PATCH] MIPS: Fix exception entry when CONFIG_EVA enabled Matt Redfearn
2017-10-11 13:12 ` Corey Minyard
2017-10-31 23:48   ` James Hogan
2017-11-13 10:47     ` Maciej W. Rozycki
2017-11-15 10:32       ` Matt Redfearn
2017-11-15 13:48         ` Maciej W. Rozycki
2017-11-15 14:53           ` Maciej W. Rozycki
2017-10-18 17:34 ` Maciej W. Rozycki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).