All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] MIPS: MSA: bugfixes of context switch
@ 2015-05-19 21:13 ` Leonid Yegoshin
  0 siblings, 0 replies; 24+ messages in thread
From: Leonid Yegoshin @ 2015-05-19 21:13 UTC (permalink / raw)
  To: linux-mips, rusty, alexinbeijing, paul.burton, david.daney, alex,
	linux-kernel, ralf, james.hogan, markos.chandras, macro,
	eunb.song, manuel.lauss, andreas.herrmann

Two bug fixes of MSA registers set handling during context switch.

This fixes are respones to multithreading MSA application crash.
It was traced to incorrect handling of MSA registers set during
thread cloning. See inside.
---

Leonid Yegoshin (2):
      MIPS: MSA: bugfix - disable MSA during thread switch correctly
      MIPS: MSA: bugfix of keeping MSA live context through clone or fork


 arch/mips/include/asm/switch_to.h |    1 -
 arch/mips/kernel/process.c        |    1 -
 arch/mips/kernel/r4k_switch.S     |    6 ++++++
 3 files changed, 6 insertions(+), 2 deletions(-)

--
Signature

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

* [PATCH 0/2] MIPS: MSA: bugfixes of context switch
@ 2015-05-19 21:13 ` Leonid Yegoshin
  0 siblings, 0 replies; 24+ messages in thread
From: Leonid Yegoshin @ 2015-05-19 21:13 UTC (permalink / raw)
  To: linux-mips, rusty, alexinbeijing, paul.burton, david.daney, alex,
	linux-kernel, ralf, james.hogan, markos.chandras, macro,
	eunb.song, manuel.lauss, andreas.herrmann

Two bug fixes of MSA registers set handling during context switch.

This fixes are respones to multithreading MSA application crash.
It was traced to incorrect handling of MSA registers set during
thread cloning. See inside.
---

Leonid Yegoshin (2):
      MIPS: MSA: bugfix - disable MSA during thread switch correctly
      MIPS: MSA: bugfix of keeping MSA live context through clone or fork


 arch/mips/include/asm/switch_to.h |    1 -
 arch/mips/kernel/process.c        |    1 -
 arch/mips/kernel/r4k_switch.S     |    6 ++++++
 3 files changed, 6 insertions(+), 2 deletions(-)

--
Signature

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

* [PATCH 1/2] MIPS: MSA: bugfix - disable MSA during thread switch correctly
@ 2015-05-19 21:13   ` Leonid Yegoshin
  0 siblings, 0 replies; 24+ messages in thread
From: Leonid Yegoshin @ 2015-05-19 21:13 UTC (permalink / raw)
  To: linux-mips, rusty, alexinbeijing, paul.burton, david.daney, alex,
	linux-kernel, ralf, james.hogan, markos.chandras, macro,
	eunb.song, manuel.lauss, andreas.herrmann

During thread cloning the new (child) thread should have MSA disabled even
at first thread entry. So, the code to disable MSA is moved from macro
'switch_to' to assembler function 'resume' before it switches kernel stack
to 'next' (new) thread. Call of 'disable_msa' after 'resume' in 'switch_to'
macro never called a first time entry into thread.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
---
 arch/mips/include/asm/switch_to.h |    1 -
 arch/mips/kernel/r4k_switch.S     |    6 ++++++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
index e92d6c4b5ed1..0d0f7f8f8b3a 100644
--- a/arch/mips/include/asm/switch_to.h
+++ b/arch/mips/include/asm/switch_to.h
@@ -104,7 +104,6 @@ do {									\
 	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA))		\
 		__fpsave = FP_SAVE_VECTOR;				\
 	(last) = resume(prev, next, task_thread_info(next), __fpsave);	\
-	disable_msa();							\
 } while (0)
 
 #define finish_arch_switch(prev)					\
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 04cbbde3521b..7dbb64656bfe 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -25,6 +25,7 @@
 /* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */
 #undef fp
 
+#define t4  $12
 /*
  * Offset to the current process status flags, the first 32 bytes of the
  * stack are not used.
@@ -73,6 +74,11 @@
 	cfc1	t1, fcr31
 	msa_save_all	a0
 	.set pop	/* SET_HARDFLOAT */
+	li      t4, MIPS_CONF5_MSAEN
+	mfc0    t3, CP0_CONFIG, 5
+	or      t3, t3, t4
+	xor     t3, t3, t4
+	mtc0    t3, CP0_CONFIG, 5
 
 	sw	t1, THREAD_FCR31(a0)
 	b	2f


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

* [PATCH 1/2] MIPS: MSA: bugfix - disable MSA during thread switch correctly
@ 2015-05-19 21:13   ` Leonid Yegoshin
  0 siblings, 0 replies; 24+ messages in thread
From: Leonid Yegoshin @ 2015-05-19 21:13 UTC (permalink / raw)
  To: linux-mips, rusty, alexinbeijing, paul.burton, david.daney, alex,
	linux-kernel, ralf, james.hogan, markos.chandras, macro,
	eunb.song, manuel.lauss, andreas.herrmann

During thread cloning the new (child) thread should have MSA disabled even
at first thread entry. So, the code to disable MSA is moved from macro
'switch_to' to assembler function 'resume' before it switches kernel stack
to 'next' (new) thread. Call of 'disable_msa' after 'resume' in 'switch_to'
macro never called a first time entry into thread.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
---
 arch/mips/include/asm/switch_to.h |    1 -
 arch/mips/kernel/r4k_switch.S     |    6 ++++++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
index e92d6c4b5ed1..0d0f7f8f8b3a 100644
--- a/arch/mips/include/asm/switch_to.h
+++ b/arch/mips/include/asm/switch_to.h
@@ -104,7 +104,6 @@ do {									\
 	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA))		\
 		__fpsave = FP_SAVE_VECTOR;				\
 	(last) = resume(prev, next, task_thread_info(next), __fpsave);	\
-	disable_msa();							\
 } while (0)
 
 #define finish_arch_switch(prev)					\
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 04cbbde3521b..7dbb64656bfe 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -25,6 +25,7 @@
 /* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */
 #undef fp
 
+#define t4  $12
 /*
  * Offset to the current process status flags, the first 32 bytes of the
  * stack are not used.
@@ -73,6 +74,11 @@
 	cfc1	t1, fcr31
 	msa_save_all	a0
 	.set pop	/* SET_HARDFLOAT */
+	li      t4, MIPS_CONF5_MSAEN
+	mfc0    t3, CP0_CONFIG, 5
+	or      t3, t3, t4
+	xor     t3, t3, t4
+	mtc0    t3, CP0_CONFIG, 5
 
 	sw	t1, THREAD_FCR31(a0)
 	b	2f

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

* [PATCH 2/2] MIPS: MSA: bugfix of keeping MSA live context through clone or fork
@ 2015-05-19 21:13   ` Leonid Yegoshin
  0 siblings, 0 replies; 24+ messages in thread
From: Leonid Yegoshin @ 2015-05-19 21:13 UTC (permalink / raw)
  To: linux-mips, rusty, alexinbeijing, paul.burton, david.daney, alex,
	linux-kernel, ralf, james.hogan, markos.chandras, macro,
	eunb.song, manuel.lauss, andreas.herrmann

It seems the patch 39148e94e3e1f0477ce8ed3fda00123722681f3a

    "MIPS: fork: Fix MSA/FPU/DSP context duplication race"

assumes that DSP/FPU and MSA context should be inherited in child at clone/fork
(look into patch description). It was done on Matthew Fortune request from
toolchain team, I guess.

Well, in this case it should prevent clearing TIF_MSA_CTX_LIVE in copy_thread().

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
---
 arch/mips/kernel/process.c |    1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index f2975d4d1e44..a16e62d40210 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -163,7 +163,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 
 	clear_tsk_thread_flag(p, TIF_USEDFPU);
 	clear_tsk_thread_flag(p, TIF_USEDMSA);
-	clear_tsk_thread_flag(p, TIF_MSA_CTX_LIVE);
 
 #ifdef CONFIG_MIPS_MT_FPAFF
 	clear_tsk_thread_flag(p, TIF_FPUBOUND);


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

* [PATCH 2/2] MIPS: MSA: bugfix of keeping MSA live context through clone or fork
@ 2015-05-19 21:13   ` Leonid Yegoshin
  0 siblings, 0 replies; 24+ messages in thread
From: Leonid Yegoshin @ 2015-05-19 21:13 UTC (permalink / raw)
  To: linux-mips, rusty, alexinbeijing, paul.burton, david.daney, alex,
	linux-kernel, ralf, james.hogan, markos.chandras, macro,
	eunb.song, manuel.lauss, andreas.herrmann

It seems the patch 39148e94e3e1f0477ce8ed3fda00123722681f3a

    "MIPS: fork: Fix MSA/FPU/DSP context duplication race"

assumes that DSP/FPU and MSA context should be inherited in child at clone/fork
(look into patch description). It was done on Matthew Fortune request from
toolchain team, I guess.

Well, in this case it should prevent clearing TIF_MSA_CTX_LIVE in copy_thread().

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
---
 arch/mips/kernel/process.c |    1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index f2975d4d1e44..a16e62d40210 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -163,7 +163,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 
 	clear_tsk_thread_flag(p, TIF_USEDFPU);
 	clear_tsk_thread_flag(p, TIF_USEDMSA);
-	clear_tsk_thread_flag(p, TIF_MSA_CTX_LIVE);
 
 #ifdef CONFIG_MIPS_MT_FPAFF
 	clear_tsk_thread_flag(p, TIF_FPUBOUND);

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

* Re: [PATCH 2/2] MIPS: MSA: bugfix of keeping MSA live context through clone or fork
@ 2015-05-20 19:23     ` Leonid Yegoshin
  0 siblings, 0 replies; 24+ messages in thread
From: Leonid Yegoshin @ 2015-05-20 19:23 UTC (permalink / raw)
  To: linux-mips, rusty, alexinbeijing, paul.burton, david.daney, alex,
	linux-kernel, ralf, james.hogan, markos.chandras, macro,
	eunb.song, manuel.lauss, andreas.herrmann

Cancel this, please.

Reason - MSA registers are not supposed to be preserved through 
caller-called interface, including syscall.
In other side, keeping MSA context is expensive.

- Leonid.


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

* Re: [PATCH 2/2] MIPS: MSA: bugfix of keeping MSA live context through clone or fork
@ 2015-05-20 19:23     ` Leonid Yegoshin
  0 siblings, 0 replies; 24+ messages in thread
From: Leonid Yegoshin @ 2015-05-20 19:23 UTC (permalink / raw)
  To: linux-mips, rusty, alexinbeijing, paul.burton, david.daney, alex,
	linux-kernel, ralf, james.hogan, markos.chandras, macro,
	eunb.song, manuel.lauss, andreas.herrmann

Cancel this, please.

Reason - MSA registers are not supposed to be preserved through 
caller-called interface, including syscall.
In other side, keeping MSA context is expensive.

- Leonid.

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

* Re: [PATCH 1/2] MIPS: MSA: bugfix - disable MSA during thread switch correctly
@ 2015-05-21  9:12     ` Paul Burton
  0 siblings, 0 replies; 24+ messages in thread
From: Paul Burton @ 2015-05-21  9:12 UTC (permalink / raw)
  To: Leonid Yegoshin
  Cc: linux-mips, rusty, alexinbeijing, david.daney, alex,
	linux-kernel, ralf, james.hogan, markos.chandras, macro,
	eunb.song, manuel.lauss, andreas.herrmann

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

On Tue, May 19, 2015 at 02:13:51PM -0700, Leonid Yegoshin wrote:
> During thread cloning the new (child) thread should have MSA disabled even
> at first thread entry. So, the code to disable MSA is moved from macro
> 'switch_to' to assembler function 'resume' before it switches kernel stack
> to 'next' (new) thread. Call of 'disable_msa' after 'resume' in 'switch_to'
> macro never called a first time entry into thread.

Hi Leonid,

I'm not sure I understand what you're trying to say here. Do you have an
example of a program that demonstrates the behaviour you believe to be
broken?

Thanks,
    Paul

> Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
> ---
>  arch/mips/include/asm/switch_to.h |    1 -
>  arch/mips/kernel/r4k_switch.S     |    6 ++++++
>  2 files changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
> index e92d6c4b5ed1..0d0f7f8f8b3a 100644
> --- a/arch/mips/include/asm/switch_to.h
> +++ b/arch/mips/include/asm/switch_to.h
> @@ -104,7 +104,6 @@ do {									\
>  	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA))		\
>  		__fpsave = FP_SAVE_VECTOR;				\
>  	(last) = resume(prev, next, task_thread_info(next), __fpsave);	\
> -	disable_msa();							\
>  } while (0)
>  
>  #define finish_arch_switch(prev)					\
> diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
> index 04cbbde3521b..7dbb64656bfe 100644
> --- a/arch/mips/kernel/r4k_switch.S
> +++ b/arch/mips/kernel/r4k_switch.S
> @@ -25,6 +25,7 @@
>  /* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */
>  #undef fp
>  
> +#define t4  $12
>  /*
>   * Offset to the current process status flags, the first 32 bytes of the
>   * stack are not used.
> @@ -73,6 +74,11 @@
>  	cfc1	t1, fcr31
>  	msa_save_all	a0
>  	.set pop	/* SET_HARDFLOAT */
> +	li      t4, MIPS_CONF5_MSAEN
> +	mfc0    t3, CP0_CONFIG, 5
> +	or      t3, t3, t4
> +	xor     t3, t3, t4
> +	mtc0    t3, CP0_CONFIG, 5
>  
>  	sw	t1, THREAD_FCR31(a0)
>  	b	2f
> 

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

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

* Re: [PATCH 1/2] MIPS: MSA: bugfix - disable MSA during thread switch correctly
@ 2015-05-21  9:12     ` Paul Burton
  0 siblings, 0 replies; 24+ messages in thread
From: Paul Burton @ 2015-05-21  9:12 UTC (permalink / raw)
  To: Leonid Yegoshin
  Cc: linux-mips, rusty, alexinbeijing, david.daney, alex,
	linux-kernel, ralf, james.hogan, markos.chandras, macro,
	eunb.song, manuel.lauss, andreas.herrmann

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

On Tue, May 19, 2015 at 02:13:51PM -0700, Leonid Yegoshin wrote:
> During thread cloning the new (child) thread should have MSA disabled even
> at first thread entry. So, the code to disable MSA is moved from macro
> 'switch_to' to assembler function 'resume' before it switches kernel stack
> to 'next' (new) thread. Call of 'disable_msa' after 'resume' in 'switch_to'
> macro never called a first time entry into thread.

Hi Leonid,

I'm not sure I understand what you're trying to say here. Do you have an
example of a program that demonstrates the behaviour you believe to be
broken?

Thanks,
    Paul

> Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
> ---
>  arch/mips/include/asm/switch_to.h |    1 -
>  arch/mips/kernel/r4k_switch.S     |    6 ++++++
>  2 files changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
> index e92d6c4b5ed1..0d0f7f8f8b3a 100644
> --- a/arch/mips/include/asm/switch_to.h
> +++ b/arch/mips/include/asm/switch_to.h
> @@ -104,7 +104,6 @@ do {									\
>  	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA))		\
>  		__fpsave = FP_SAVE_VECTOR;				\
>  	(last) = resume(prev, next, task_thread_info(next), __fpsave);	\
> -	disable_msa();							\
>  } while (0)
>  
>  #define finish_arch_switch(prev)					\
> diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
> index 04cbbde3521b..7dbb64656bfe 100644
> --- a/arch/mips/kernel/r4k_switch.S
> +++ b/arch/mips/kernel/r4k_switch.S
> @@ -25,6 +25,7 @@
>  /* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */
>  #undef fp
>  
> +#define t4  $12
>  /*
>   * Offset to the current process status flags, the first 32 bytes of the
>   * stack are not used.
> @@ -73,6 +74,11 @@
>  	cfc1	t1, fcr31
>  	msa_save_all	a0
>  	.set pop	/* SET_HARDFLOAT */
> +	li      t4, MIPS_CONF5_MSAEN
> +	mfc0    t3, CP0_CONFIG, 5
> +	or      t3, t3, t4
> +	xor     t3, t3, t4
> +	mtc0    t3, CP0_CONFIG, 5
>  
>  	sw	t1, THREAD_FCR31(a0)
>  	b	2f
> 

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

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

* Re: [PATCH 1/2] MIPS: MSA: bugfix - disable MSA during thread switch correctly
@ 2015-05-21 16:11       ` Leonid Yegoshin
  0 siblings, 0 replies; 24+ messages in thread
From: Leonid Yegoshin @ 2015-05-21 16:11 UTC (permalink / raw)
  To: Paul Burton
  Cc: linux-mips, rusty, alexinbeijing, david.daney, alex,
	linux-kernel, ralf, James Hogan, Markos Chandras, macro,
	eunb.song, manuel.lauss, andreas.herrmann

Yes, I have a program but it is binary only.

If you want to understand why disable_DMA() after resume() doesn't work,
search for restoring RA register in resume() after changing SP.

- Leonid.


Paul Burton <Paul.Burton@imgtec.com> wrote:


On Tue, May 19, 2015 at 02:13:51PM -0700, Leonid Yegoshin wrote:
> During thread cloning the new (child) thread should have MSA disabled even
> at first thread entry. So, the code to disable MSA is moved from macro
> 'switch_to' to assembler function 'resume' before it switches kernel stack
> to 'next' (new) thread. Call of 'disable_msa' after 'resume' in 'switch_to'
> macro never called a first time entry into thread.

Hi Leonid,

I'm not sure I understand what you're trying to say here. Do you have an
example of a program that demonstrates the behaviour you believe to be
broken?

Thanks,
    Paul

> Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
> ---
>  arch/mips/include/asm/switch_to.h |    1 -
>  arch/mips/kernel/r4k_switch.S     |    6 ++++++
>  2 files changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
> index e92d6c4b5ed1..0d0f7f8f8b3a 100644
> --- a/arch/mips/include/asm/switch_to.h
> +++ b/arch/mips/include/asm/switch_to.h
> @@ -104,7 +104,6 @@ do {                                                                      \
>       if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA))          \
>               __fpsave = FP_SAVE_VECTOR;                              \
>       (last) = resume(prev, next, task_thread_info(next), __fpsave);  \
> -     disable_msa();                                                  \
>  } while (0)
>
>  #define finish_arch_switch(prev)                                     \
> diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
> index 04cbbde3521b..7dbb64656bfe 100644
> --- a/arch/mips/kernel/r4k_switch.S
> +++ b/arch/mips/kernel/r4k_switch.S
> @@ -25,6 +25,7 @@
>  /* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */
>  #undef fp
>
> +#define t4  $12
>  /*
>   * Offset to the current process status flags, the first 32 bytes of the
>   * stack are not used.
> @@ -73,6 +74,11 @@
>       cfc1    t1, fcr31
>       msa_save_all    a0
>       .set pop        /* SET_HARDFLOAT */
> +     li      t4, MIPS_CONF5_MSAEN
> +     mfc0    t3, CP0_CONFIG, 5
> +     or      t3, t3, t4
> +     xor     t3, t3, t4
> +     mtc0    t3, CP0_CONFIG, 5
>
>       sw      t1, THREAD_FCR31(a0)
>       b       2f
>

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

* Re: [PATCH 1/2] MIPS: MSA: bugfix - disable MSA during thread switch correctly
@ 2015-05-21 16:11       ` Leonid Yegoshin
  0 siblings, 0 replies; 24+ messages in thread
From: Leonid Yegoshin @ 2015-05-21 16:11 UTC (permalink / raw)
  To: Paul Burton
  Cc: linux-mips, rusty, alexinbeijing, david.daney, alex,
	linux-kernel, ralf, James Hogan, Markos Chandras, macro,
	eunb.song, manuel.lauss, andreas.herrmann

Yes, I have a program but it is binary only.

If you want to understand why disable_DMA() after resume() doesn't work,
search for restoring RA register in resume() after changing SP.

- Leonid.


Paul Burton <Paul.Burton@imgtec.com> wrote:


On Tue, May 19, 2015 at 02:13:51PM -0700, Leonid Yegoshin wrote:
> During thread cloning the new (child) thread should have MSA disabled even
> at first thread entry. So, the code to disable MSA is moved from macro
> 'switch_to' to assembler function 'resume' before it switches kernel stack
> to 'next' (new) thread. Call of 'disable_msa' after 'resume' in 'switch_to'
> macro never called a first time entry into thread.

Hi Leonid,

I'm not sure I understand what you're trying to say here. Do you have an
example of a program that demonstrates the behaviour you believe to be
broken?

Thanks,
    Paul

> Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
> ---
>  arch/mips/include/asm/switch_to.h |    1 -
>  arch/mips/kernel/r4k_switch.S     |    6 ++++++
>  2 files changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
> index e92d6c4b5ed1..0d0f7f8f8b3a 100644
> --- a/arch/mips/include/asm/switch_to.h
> +++ b/arch/mips/include/asm/switch_to.h
> @@ -104,7 +104,6 @@ do {                                                                      \
>       if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA))          \
>               __fpsave = FP_SAVE_VECTOR;                              \
>       (last) = resume(prev, next, task_thread_info(next), __fpsave);  \
> -     disable_msa();                                                  \
>  } while (0)
>
>  #define finish_arch_switch(prev)                                     \
> diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
> index 04cbbde3521b..7dbb64656bfe 100644
> --- a/arch/mips/kernel/r4k_switch.S
> +++ b/arch/mips/kernel/r4k_switch.S
> @@ -25,6 +25,7 @@
>  /* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */
>  #undef fp
>
> +#define t4  $12
>  /*
>   * Offset to the current process status flags, the first 32 bytes of the
>   * stack are not used.
> @@ -73,6 +74,11 @@
>       cfc1    t1, fcr31
>       msa_save_all    a0
>       .set pop        /* SET_HARDFLOAT */
> +     li      t4, MIPS_CONF5_MSAEN
> +     mfc0    t3, CP0_CONFIG, 5
> +     or      t3, t3, t4
> +     xor     t3, t3, t4
> +     mtc0    t3, CP0_CONFIG, 5
>
>       sw      t1, THREAD_FCR31(a0)
>       b       2f
>

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

* [PATCH] MIPS: tidy up FPU context switching
@ 2015-05-21 16:20     ` Paul Burton
  0 siblings, 0 replies; 24+ messages in thread
From: Paul Burton @ 2015-05-21 16:20 UTC (permalink / raw)
  To: linux-mips
  Cc: Paul Burton, Leonid Yegoshin, Maciej W. Rozycki, linux-kernel,
	Leonid Yegoshin, David Daney, Markos Chandras, Ralf Baechle,
	Manuel Lauss

Rather than saving the scalar FP or vector context in the assembly
resume function, simply call lose_fpu(1) from the switch_to macro in
order to save the appropriate context, disabling the FPU & MSA.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
How about this (lightly tested for the moment) alternative?

 arch/mips/include/asm/switch_to.h | 21 ++++----------------
 arch/mips/kernel/r4k_switch.S     | 41 +--------------------------------------
 2 files changed, 5 insertions(+), 57 deletions(-)

diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
index e92d6c4b..1a7a316 100644
--- a/arch/mips/include/asm/switch_to.h
+++ b/arch/mips/include/asm/switch_to.h
@@ -16,29 +16,21 @@
 #include <asm/watch.h>
 #include <asm/dsp.h>
 #include <asm/cop2.h>
-#include <asm/msa.h>
+#include <asm/fpu.h>
 
 struct task_struct;
 
-enum {
-	FP_SAVE_NONE	= 0,
-	FP_SAVE_VECTOR	= -1,
-	FP_SAVE_SCALAR	= 1,
-};
-
 /**
  * resume - resume execution of a task
  * @prev:	The task previously executed.
  * @next:	The task to begin executing.
  * @next_ti:	task_thread_info(next).
- * @fp_save:	Which, if any, FP context to save for prev.
  *
  * This function is used whilst scheduling to save the context of prev & load
  * the context of next. Returns prev.
  */
 extern asmlinkage struct task_struct *resume(struct task_struct *prev,
-		struct task_struct *next, struct thread_info *next_ti,
-		s32 fp_save);
+		struct task_struct *next, struct thread_info *next_ti);
 
 extern unsigned int ll_bit;
 extern struct task_struct *ll_task;
@@ -86,8 +78,8 @@ do {	if (cpu_has_rw_llb) {						\
 #define switch_to(prev, next, last)					\
 do {									\
 	u32 __c0_stat;							\
-	s32 __fpsave = FP_SAVE_NONE;					\
 	__mips_mt_fpaff_switch_to(prev);				\
+	lose_fpu(1);							\
 	if (cpu_has_dsp)						\
 		__save_dsp(prev);					\
 	if (cop2_present && (KSTK_STATUS(prev) & ST0_CU2)) {		\
@@ -99,12 +91,7 @@ do {									\
 		write_c0_status(__c0_stat & ~ST0_CU2);			\
 	}								\
 	__clear_software_ll_bit();					\
-	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU))		\
-		__fpsave = FP_SAVE_SCALAR;				\
-	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA))		\
-		__fpsave = FP_SAVE_VECTOR;				\
-	(last) = resume(prev, next, task_thread_info(next), __fpsave);	\
-	disable_msa();							\
+	(last) = resume(prev, next, task_thread_info(next));		\
 } while (0)
 
 #define finish_arch_switch(prev)					\
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 04cbbde3..92cd051 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -34,7 +34,7 @@
 #ifndef USE_ALTERNATE_RESUME_IMPL
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
- *		       struct thread_info *next_ti, s32 fp_save)
+ *		       struct thread_info *next_ti)
  */
 	.align	5
 	LEAF(resume)
@@ -43,45 +43,6 @@
 	cpu_save_nonscratch a0
 	LONG_S	ra, THREAD_REG31(a0)
 
-	/*
-	 * Check whether we need to save any FP context. FP context is saved
-	 * iff the process has used the context with the scalar FPU or the MSA
-	 * ASE in the current time slice, as indicated by _TIF_USEDFPU and
-	 * _TIF_USEDMSA respectively. switch_to will have set fp_save
-	 * accordingly to an FP_SAVE_ enum value.
-	 */
-	beqz	a3, 2f
-
-	/*
-	 * We do. Clear the saved CU1 bit for prev, such that next time it is
-	 * scheduled it will start in userland with the FPU disabled. If the
-	 * task uses the FPU then it will be enabled again via the do_cpu trap.
-	 * This allows us to lazily restore the FP context.
-	 */
-	PTR_L	t3, TASK_THREAD_INFO(a0)
-	LONG_L	t0, ST_OFF(t3)
-	li	t1, ~ST0_CU1
-	and	t0, t0, t1
-	LONG_S	t0, ST_OFF(t3)
-
-	/* Check whether we're saving scalar or vector context. */
-	bgtz	a3, 1f
-
-	/* Save 128b MSA vector context + scalar FP control & status. */
-	.set push
-	SET_HARDFLOAT
-	cfc1	t1, fcr31
-	msa_save_all	a0
-	.set pop	/* SET_HARDFLOAT */
-
-	sw	t1, THREAD_FCR31(a0)
-	b	2f
-
-1:	/* Save 32b/64b scalar FP context. */
-	fpu_save_double a0 t0 t1		# c0_status passed in t0
-						# clobbers t1
-2:
-
 #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
 	PTR_LA	t8, __stack_chk_guard
 	LONG_L	t9, TASK_STACK_CANARY(a1)
-- 
2.4.1


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

* [PATCH] MIPS: tidy up FPU context switching
@ 2015-05-21 16:20     ` Paul Burton
  0 siblings, 0 replies; 24+ messages in thread
From: Paul Burton @ 2015-05-21 16:20 UTC (permalink / raw)
  To: linux-mips
  Cc: Paul Burton, Leonid Yegoshin, Maciej W. Rozycki, linux-kernel,
	Leonid Yegoshin, David Daney, Markos Chandras, Ralf Baechle,
	Manuel Lauss

Rather than saving the scalar FP or vector context in the assembly
resume function, simply call lose_fpu(1) from the switch_to macro in
order to save the appropriate context, disabling the FPU & MSA.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
How about this (lightly tested for the moment) alternative?

 arch/mips/include/asm/switch_to.h | 21 ++++----------------
 arch/mips/kernel/r4k_switch.S     | 41 +--------------------------------------
 2 files changed, 5 insertions(+), 57 deletions(-)

diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
index e92d6c4b..1a7a316 100644
--- a/arch/mips/include/asm/switch_to.h
+++ b/arch/mips/include/asm/switch_to.h
@@ -16,29 +16,21 @@
 #include <asm/watch.h>
 #include <asm/dsp.h>
 #include <asm/cop2.h>
-#include <asm/msa.h>
+#include <asm/fpu.h>
 
 struct task_struct;
 
-enum {
-	FP_SAVE_NONE	= 0,
-	FP_SAVE_VECTOR	= -1,
-	FP_SAVE_SCALAR	= 1,
-};
-
 /**
  * resume - resume execution of a task
  * @prev:	The task previously executed.
  * @next:	The task to begin executing.
  * @next_ti:	task_thread_info(next).
- * @fp_save:	Which, if any, FP context to save for prev.
  *
  * This function is used whilst scheduling to save the context of prev & load
  * the context of next. Returns prev.
  */
 extern asmlinkage struct task_struct *resume(struct task_struct *prev,
-		struct task_struct *next, struct thread_info *next_ti,
-		s32 fp_save);
+		struct task_struct *next, struct thread_info *next_ti);
 
 extern unsigned int ll_bit;
 extern struct task_struct *ll_task;
@@ -86,8 +78,8 @@ do {	if (cpu_has_rw_llb) {						\
 #define switch_to(prev, next, last)					\
 do {									\
 	u32 __c0_stat;							\
-	s32 __fpsave = FP_SAVE_NONE;					\
 	__mips_mt_fpaff_switch_to(prev);				\
+	lose_fpu(1);							\
 	if (cpu_has_dsp)						\
 		__save_dsp(prev);					\
 	if (cop2_present && (KSTK_STATUS(prev) & ST0_CU2)) {		\
@@ -99,12 +91,7 @@ do {									\
 		write_c0_status(__c0_stat & ~ST0_CU2);			\
 	}								\
 	__clear_software_ll_bit();					\
-	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU))		\
-		__fpsave = FP_SAVE_SCALAR;				\
-	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA))		\
-		__fpsave = FP_SAVE_VECTOR;				\
-	(last) = resume(prev, next, task_thread_info(next), __fpsave);	\
-	disable_msa();							\
+	(last) = resume(prev, next, task_thread_info(next));		\
 } while (0)
 
 #define finish_arch_switch(prev)					\
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 04cbbde3..92cd051 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -34,7 +34,7 @@
 #ifndef USE_ALTERNATE_RESUME_IMPL
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
- *		       struct thread_info *next_ti, s32 fp_save)
+ *		       struct thread_info *next_ti)
  */
 	.align	5
 	LEAF(resume)
@@ -43,45 +43,6 @@
 	cpu_save_nonscratch a0
 	LONG_S	ra, THREAD_REG31(a0)
 
-	/*
-	 * Check whether we need to save any FP context. FP context is saved
-	 * iff the process has used the context with the scalar FPU or the MSA
-	 * ASE in the current time slice, as indicated by _TIF_USEDFPU and
-	 * _TIF_USEDMSA respectively. switch_to will have set fp_save
-	 * accordingly to an FP_SAVE_ enum value.
-	 */
-	beqz	a3, 2f
-
-	/*
-	 * We do. Clear the saved CU1 bit for prev, such that next time it is
-	 * scheduled it will start in userland with the FPU disabled. If the
-	 * task uses the FPU then it will be enabled again via the do_cpu trap.
-	 * This allows us to lazily restore the FP context.
-	 */
-	PTR_L	t3, TASK_THREAD_INFO(a0)
-	LONG_L	t0, ST_OFF(t3)
-	li	t1, ~ST0_CU1
-	and	t0, t0, t1
-	LONG_S	t0, ST_OFF(t3)
-
-	/* Check whether we're saving scalar or vector context. */
-	bgtz	a3, 1f
-
-	/* Save 128b MSA vector context + scalar FP control & status. */
-	.set push
-	SET_HARDFLOAT
-	cfc1	t1, fcr31
-	msa_save_all	a0
-	.set pop	/* SET_HARDFLOAT */
-
-	sw	t1, THREAD_FCR31(a0)
-	b	2f
-
-1:	/* Save 32b/64b scalar FP context. */
-	fpu_save_double a0 t0 t1		# c0_status passed in t0
-						# clobbers t1
-2:
-
 #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
 	PTR_LA	t8, __stack_chk_guard
 	LONG_L	t9, TASK_STACK_CANARY(a1)
-- 
2.4.1

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

* Re: [PATCH 1/2] MIPS: MSA: bugfix - disable MSA during thread switch correctly
  2015-05-19 21:13   ` Leonid Yegoshin
                     ` (2 preceding siblings ...)
  (?)
@ 2015-05-22  9:38   ` Ralf Baechle
  2015-05-22 18:37       ` Leonid Yegoshin
  -1 siblings, 1 reply; 24+ messages in thread
From: Ralf Baechle @ 2015-05-22  9:38 UTC (permalink / raw)
  To: Leonid Yegoshin
  Cc: linux-mips, rusty, alexinbeijing, paul.burton, david.daney, alex,
	linux-kernel, james.hogan, markos.chandras, macro, eunb.song,
	manuel.lauss, andreas.herrmann

On Tue, May 19, 2015 at 02:13:51PM -0700, Leonid Yegoshin wrote:

> During thread cloning the new (child) thread should have MSA disabled even
> at first thread entry. So, the code to disable MSA is moved from macro
> 'switch_to' to assembler function 'resume' before it switches kernel stack
> to 'next' (new) thread. Call of 'disable_msa' after 'resume' in 'switch_to'
> macro never called a first time entry into thread.
> 
> Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
> ---
>  arch/mips/include/asm/switch_to.h |    1 -
>  arch/mips/kernel/r4k_switch.S     |    6 ++++++
>  2 files changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
> index e92d6c4b5ed1..0d0f7f8f8b3a 100644
> --- a/arch/mips/include/asm/switch_to.h
> +++ b/arch/mips/include/asm/switch_to.h
> @@ -104,7 +104,6 @@ do {									\
>  	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA))		\
>  		__fpsave = FP_SAVE_VECTOR;				\
>  	(last) = resume(prev, next, task_thread_info(next), __fpsave);	\
> -	disable_msa();							\
>  } while (0)
>  
>  #define finish_arch_switch(prev)					\
> diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
> index 04cbbde3521b..7dbb64656bfe 100644
> --- a/arch/mips/kernel/r4k_switch.S
> +++ b/arch/mips/kernel/r4k_switch.S
> @@ -25,6 +25,7 @@
>  /* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */
>  #undef fp
>  
> +#define t4  $12

You're kidding, right?

>  /*
>   * Offset to the current process status flags, the first 32 bytes of the
>   * stack are not used.
> @@ -73,6 +74,11 @@
>  	cfc1	t1, fcr31
>  	msa_save_all	a0
>  	.set pop	/* SET_HARDFLOAT */
> +	li      t4, MIPS_CONF5_MSAEN
> +	mfc0    t3, CP0_CONFIG, 5
> +	or      t3, t3, t4
> +	xor     t3, t3, t4
> +	mtc0    t3, CP0_CONFIG, 5
>  
>  	sw	t1, THREAD_FCR31(a0)
>  	b	2f

Just move the call to finish_arch_switch().

Your rewrite also dropped the if (cpu_has_msa) condition from disable_msa()
probably causing havoc on lots of CPUs which will likely not decode the
set bits of the MFC0/MTC0 instructions thus end up accessing Config0.

  Ralf

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

* [PATCH v2] MIPS: tidy up FPU context switching
@ 2015-05-22 10:42       ` Paul Burton
  0 siblings, 0 replies; 24+ messages in thread
From: Paul Burton @ 2015-05-22 10:42 UTC (permalink / raw)
  To: linux-mips
  Cc: Paul Burton, Leonid Yegoshin, Maciej W. Rozycki, linux-kernel,
	Leonid Yegoshin, James Hogan, David Daney, Markos Chandras,
	Ralf Baechle, Manuel Lauss

Rather than saving the scalar FP or vector context in the assembly
resume function, reuse the existing C code we have in fpu.h to do
exactly that. This reduces duplication, results in a much easier to read
resume function & should allow the compiler to optimise out more MSA
code due to is_msa_enabled()/cpu_has_msa being known-zero at compile
time for kernels without MSA support.

As a side effect this correctly disables MSA on the first entry to a
task, in which case resume will "return" to ret_from_kernel_thread or
ret_from_fork in order to call schedule_tail. This would lead to the
disable_msa call in switch_to not being executed, as reported by Leonid.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Reported-by: Leonid Yegoshin <leonid.yegoshin@imgtec.com>
---
How about this (lightly tested for the moment) alternative to 10082?

Changes in v2:
- Introduce lose_fpu_inatomic to skip the preempt_{en,dis}able calls
  and operate on the provided struct task_struct, which should be prev
  rather than current.

 arch/mips/include/asm/fpu.h       | 21 ++++++++++++--------
 arch/mips/include/asm/switch_to.h | 21 ++++----------------
 arch/mips/kernel/r4k_switch.S     | 41 +--------------------------------------
 3 files changed, 18 insertions(+), 65 deletions(-)

diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
index 084780b..87e8c78 100644
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -164,25 +164,30 @@ static inline int own_fpu(int restore)
 	return ret;
 }
 
-static inline void lose_fpu(int save)
+static inline void lose_fpu_inatomic(int save, struct task_struct *tsk)
 {
-	preempt_disable();
 	if (is_msa_enabled()) {
 		if (save) {
-			save_msa(current);
-			current->thread.fpu.fcr31 =
+			save_msa(tsk);
+			tsk->thread.fpu.fcr31 =
 					read_32bit_cp1_register(CP1_STATUS);
 		}
 		disable_msa();
-		clear_thread_flag(TIF_USEDMSA);
+		clear_tsk_thread_flag(tsk, TIF_USEDMSA);
 		__disable_fpu();
 	} else if (is_fpu_owner()) {
 		if (save)
-			_save_fp(current);
+			_save_fp(tsk);
 		__disable_fpu();
 	}
-	KSTK_STATUS(current) &= ~ST0_CU1;
-	clear_thread_flag(TIF_USEDFPU);
+	KSTK_STATUS(tsk) &= ~ST0_CU1;
+	clear_tsk_thread_flag(tsk, TIF_USEDFPU);
+}
+
+static inline void lose_fpu(int save)
+{
+	preempt_disable();
+	lose_fpu_inatomic(save, current);
 	preempt_enable();
 }
 
diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
index e92d6c4b..c429d1a 100644
--- a/arch/mips/include/asm/switch_to.h
+++ b/arch/mips/include/asm/switch_to.h
@@ -16,29 +16,21 @@
 #include <asm/watch.h>
 #include <asm/dsp.h>
 #include <asm/cop2.h>
-#include <asm/msa.h>
+#include <asm/fpu.h>
 
 struct task_struct;
 
-enum {
-	FP_SAVE_NONE	= 0,
-	FP_SAVE_VECTOR	= -1,
-	FP_SAVE_SCALAR	= 1,
-};
-
 /**
  * resume - resume execution of a task
  * @prev:	The task previously executed.
  * @next:	The task to begin executing.
  * @next_ti:	task_thread_info(next).
- * @fp_save:	Which, if any, FP context to save for prev.
  *
  * This function is used whilst scheduling to save the context of prev & load
  * the context of next. Returns prev.
  */
 extern asmlinkage struct task_struct *resume(struct task_struct *prev,
-		struct task_struct *next, struct thread_info *next_ti,
-		s32 fp_save);
+		struct task_struct *next, struct thread_info *next_ti);
 
 extern unsigned int ll_bit;
 extern struct task_struct *ll_task;
@@ -86,8 +78,8 @@ do {	if (cpu_has_rw_llb) {						\
 #define switch_to(prev, next, last)					\
 do {									\
 	u32 __c0_stat;							\
-	s32 __fpsave = FP_SAVE_NONE;					\
 	__mips_mt_fpaff_switch_to(prev);				\
+	lose_fpu_inatomic(1, prev);					\
 	if (cpu_has_dsp)						\
 		__save_dsp(prev);					\
 	if (cop2_present && (KSTK_STATUS(prev) & ST0_CU2)) {		\
@@ -99,12 +91,7 @@ do {									\
 		write_c0_status(__c0_stat & ~ST0_CU2);			\
 	}								\
 	__clear_software_ll_bit();					\
-	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU))		\
-		__fpsave = FP_SAVE_SCALAR;				\
-	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA))		\
-		__fpsave = FP_SAVE_VECTOR;				\
-	(last) = resume(prev, next, task_thread_info(next), __fpsave);	\
-	disable_msa();							\
+	(last) = resume(prev, next, task_thread_info(next));		\
 } while (0)
 
 #define finish_arch_switch(prev)					\
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 04cbbde3..92cd051 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -34,7 +34,7 @@
 #ifndef USE_ALTERNATE_RESUME_IMPL
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
- *		       struct thread_info *next_ti, s32 fp_save)
+ *		       struct thread_info *next_ti)
  */
 	.align	5
 	LEAF(resume)
@@ -43,45 +43,6 @@
 	cpu_save_nonscratch a0
 	LONG_S	ra, THREAD_REG31(a0)
 
-	/*
-	 * Check whether we need to save any FP context. FP context is saved
-	 * iff the process has used the context with the scalar FPU or the MSA
-	 * ASE in the current time slice, as indicated by _TIF_USEDFPU and
-	 * _TIF_USEDMSA respectively. switch_to will have set fp_save
-	 * accordingly to an FP_SAVE_ enum value.
-	 */
-	beqz	a3, 2f
-
-	/*
-	 * We do. Clear the saved CU1 bit for prev, such that next time it is
-	 * scheduled it will start in userland with the FPU disabled. If the
-	 * task uses the FPU then it will be enabled again via the do_cpu trap.
-	 * This allows us to lazily restore the FP context.
-	 */
-	PTR_L	t3, TASK_THREAD_INFO(a0)
-	LONG_L	t0, ST_OFF(t3)
-	li	t1, ~ST0_CU1
-	and	t0, t0, t1
-	LONG_S	t0, ST_OFF(t3)
-
-	/* Check whether we're saving scalar or vector context. */
-	bgtz	a3, 1f
-
-	/* Save 128b MSA vector context + scalar FP control & status. */
-	.set push
-	SET_HARDFLOAT
-	cfc1	t1, fcr31
-	msa_save_all	a0
-	.set pop	/* SET_HARDFLOAT */
-
-	sw	t1, THREAD_FCR31(a0)
-	b	2f
-
-1:	/* Save 32b/64b scalar FP context. */
-	fpu_save_double a0 t0 t1		# c0_status passed in t0
-						# clobbers t1
-2:
-
 #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
 	PTR_LA	t8, __stack_chk_guard
 	LONG_L	t9, TASK_STACK_CANARY(a1)
-- 
2.4.1


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

* [PATCH v2] MIPS: tidy up FPU context switching
@ 2015-05-22 10:42       ` Paul Burton
  0 siblings, 0 replies; 24+ messages in thread
From: Paul Burton @ 2015-05-22 10:42 UTC (permalink / raw)
  To: linux-mips
  Cc: Paul Burton, Leonid Yegoshin, Maciej W. Rozycki, linux-kernel,
	Leonid Yegoshin, James Hogan, David Daney, Markos Chandras,
	Ralf Baechle, Manuel Lauss

Rather than saving the scalar FP or vector context in the assembly
resume function, reuse the existing C code we have in fpu.h to do
exactly that. This reduces duplication, results in a much easier to read
resume function & should allow the compiler to optimise out more MSA
code due to is_msa_enabled()/cpu_has_msa being known-zero at compile
time for kernels without MSA support.

As a side effect this correctly disables MSA on the first entry to a
task, in which case resume will "return" to ret_from_kernel_thread or
ret_from_fork in order to call schedule_tail. This would lead to the
disable_msa call in switch_to not being executed, as reported by Leonid.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Reported-by: Leonid Yegoshin <leonid.yegoshin@imgtec.com>
---
How about this (lightly tested for the moment) alternative to 10082?

Changes in v2:
- Introduce lose_fpu_inatomic to skip the preempt_{en,dis}able calls
  and operate on the provided struct task_struct, which should be prev
  rather than current.

 arch/mips/include/asm/fpu.h       | 21 ++++++++++++--------
 arch/mips/include/asm/switch_to.h | 21 ++++----------------
 arch/mips/kernel/r4k_switch.S     | 41 +--------------------------------------
 3 files changed, 18 insertions(+), 65 deletions(-)

diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
index 084780b..87e8c78 100644
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -164,25 +164,30 @@ static inline int own_fpu(int restore)
 	return ret;
 }
 
-static inline void lose_fpu(int save)
+static inline void lose_fpu_inatomic(int save, struct task_struct *tsk)
 {
-	preempt_disable();
 	if (is_msa_enabled()) {
 		if (save) {
-			save_msa(current);
-			current->thread.fpu.fcr31 =
+			save_msa(tsk);
+			tsk->thread.fpu.fcr31 =
 					read_32bit_cp1_register(CP1_STATUS);
 		}
 		disable_msa();
-		clear_thread_flag(TIF_USEDMSA);
+		clear_tsk_thread_flag(tsk, TIF_USEDMSA);
 		__disable_fpu();
 	} else if (is_fpu_owner()) {
 		if (save)
-			_save_fp(current);
+			_save_fp(tsk);
 		__disable_fpu();
 	}
-	KSTK_STATUS(current) &= ~ST0_CU1;
-	clear_thread_flag(TIF_USEDFPU);
+	KSTK_STATUS(tsk) &= ~ST0_CU1;
+	clear_tsk_thread_flag(tsk, TIF_USEDFPU);
+}
+
+static inline void lose_fpu(int save)
+{
+	preempt_disable();
+	lose_fpu_inatomic(save, current);
 	preempt_enable();
 }
 
diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
index e92d6c4b..c429d1a 100644
--- a/arch/mips/include/asm/switch_to.h
+++ b/arch/mips/include/asm/switch_to.h
@@ -16,29 +16,21 @@
 #include <asm/watch.h>
 #include <asm/dsp.h>
 #include <asm/cop2.h>
-#include <asm/msa.h>
+#include <asm/fpu.h>
 
 struct task_struct;
 
-enum {
-	FP_SAVE_NONE	= 0,
-	FP_SAVE_VECTOR	= -1,
-	FP_SAVE_SCALAR	= 1,
-};
-
 /**
  * resume - resume execution of a task
  * @prev:	The task previously executed.
  * @next:	The task to begin executing.
  * @next_ti:	task_thread_info(next).
- * @fp_save:	Which, if any, FP context to save for prev.
  *
  * This function is used whilst scheduling to save the context of prev & load
  * the context of next. Returns prev.
  */
 extern asmlinkage struct task_struct *resume(struct task_struct *prev,
-		struct task_struct *next, struct thread_info *next_ti,
-		s32 fp_save);
+		struct task_struct *next, struct thread_info *next_ti);
 
 extern unsigned int ll_bit;
 extern struct task_struct *ll_task;
@@ -86,8 +78,8 @@ do {	if (cpu_has_rw_llb) {						\
 #define switch_to(prev, next, last)					\
 do {									\
 	u32 __c0_stat;							\
-	s32 __fpsave = FP_SAVE_NONE;					\
 	__mips_mt_fpaff_switch_to(prev);				\
+	lose_fpu_inatomic(1, prev);					\
 	if (cpu_has_dsp)						\
 		__save_dsp(prev);					\
 	if (cop2_present && (KSTK_STATUS(prev) & ST0_CU2)) {		\
@@ -99,12 +91,7 @@ do {									\
 		write_c0_status(__c0_stat & ~ST0_CU2);			\
 	}								\
 	__clear_software_ll_bit();					\
-	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU))		\
-		__fpsave = FP_SAVE_SCALAR;				\
-	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA))		\
-		__fpsave = FP_SAVE_VECTOR;				\
-	(last) = resume(prev, next, task_thread_info(next), __fpsave);	\
-	disable_msa();							\
+	(last) = resume(prev, next, task_thread_info(next));		\
 } while (0)
 
 #define finish_arch_switch(prev)					\
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 04cbbde3..92cd051 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -34,7 +34,7 @@
 #ifndef USE_ALTERNATE_RESUME_IMPL
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
- *		       struct thread_info *next_ti, s32 fp_save)
+ *		       struct thread_info *next_ti)
  */
 	.align	5
 	LEAF(resume)
@@ -43,45 +43,6 @@
 	cpu_save_nonscratch a0
 	LONG_S	ra, THREAD_REG31(a0)
 
-	/*
-	 * Check whether we need to save any FP context. FP context is saved
-	 * iff the process has used the context with the scalar FPU or the MSA
-	 * ASE in the current time slice, as indicated by _TIF_USEDFPU and
-	 * _TIF_USEDMSA respectively. switch_to will have set fp_save
-	 * accordingly to an FP_SAVE_ enum value.
-	 */
-	beqz	a3, 2f
-
-	/*
-	 * We do. Clear the saved CU1 bit for prev, such that next time it is
-	 * scheduled it will start in userland with the FPU disabled. If the
-	 * task uses the FPU then it will be enabled again via the do_cpu trap.
-	 * This allows us to lazily restore the FP context.
-	 */
-	PTR_L	t3, TASK_THREAD_INFO(a0)
-	LONG_L	t0, ST_OFF(t3)
-	li	t1, ~ST0_CU1
-	and	t0, t0, t1
-	LONG_S	t0, ST_OFF(t3)
-
-	/* Check whether we're saving scalar or vector context. */
-	bgtz	a3, 1f
-
-	/* Save 128b MSA vector context + scalar FP control & status. */
-	.set push
-	SET_HARDFLOAT
-	cfc1	t1, fcr31
-	msa_save_all	a0
-	.set pop	/* SET_HARDFLOAT */
-
-	sw	t1, THREAD_FCR31(a0)
-	b	2f
-
-1:	/* Save 32b/64b scalar FP context. */
-	fpu_save_double a0 t0 t1		# c0_status passed in t0
-						# clobbers t1
-2:
-
 #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
 	PTR_LA	t8, __stack_chk_guard
 	LONG_L	t9, TASK_STACK_CANARY(a1)
-- 
2.4.1

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

* Re: [PATCH 1/2] MIPS: MSA: bugfix - disable MSA during thread switch correctly
@ 2015-05-22 18:37       ` Leonid Yegoshin
  0 siblings, 0 replies; 24+ messages in thread
From: Leonid Yegoshin @ 2015-05-22 18:37 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, rusty, alexinbeijing, paul.burton, david.daney, alex,
	linux-kernel, james.hogan, markos.chandras, macro, eunb.song,
	manuel.lauss, andreas.herrmann

On 05/22/2015 02:38 AM, Ralf Baechle wrote:
> Just move the call to finish_arch_switch(). 

It might be a problem later, then a correct MSA partiton starts working. 
It should be tight to saving MSA registers in that case.

> Your rewrite also dropped the if (cpu_has_msa) condition from 
> disable_msa() probably causing havoc on lots of CPUs which will likely 
> not decode the set bits of the MFC0/MTC0 instructions thus end up 
> accessing Config0. Ralf

Right before this chunk of code there is a saving MSA registers. Does it 
causing a havoc or else?

May I ask you to look into switch_to macro to figure out how "if 
(cpu_has_msa)" check works in this case?

- Leonid.


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

* Re: [PATCH 1/2] MIPS: MSA: bugfix - disable MSA during thread switch correctly
@ 2015-05-22 18:37       ` Leonid Yegoshin
  0 siblings, 0 replies; 24+ messages in thread
From: Leonid Yegoshin @ 2015-05-22 18:37 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, rusty, alexinbeijing, paul.burton, david.daney, alex,
	linux-kernel, james.hogan, markos.chandras, macro, eunb.song,
	manuel.lauss, andreas.herrmann

On 05/22/2015 02:38 AM, Ralf Baechle wrote:
> Just move the call to finish_arch_switch(). 

It might be a problem later, then a correct MSA partiton starts working. 
It should be tight to saving MSA registers in that case.

> Your rewrite also dropped the if (cpu_has_msa) condition from 
> disable_msa() probably causing havoc on lots of CPUs which will likely 
> not decode the set bits of the MFC0/MTC0 instructions thus end up 
> accessing Config0. Ralf

Right before this chunk of code there is a saving MSA registers. Does it 
causing a havoc or else?

May I ask you to look into switch_to macro to figure out how "if 
(cpu_has_msa)" check works in this case?

- Leonid.

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

* Re: [PATCH 1/2] MIPS: MSA: bugfix - disable MSA during thread switch correctly
@ 2015-05-22 19:06         ` Leonid Yegoshin
  0 siblings, 0 replies; 24+ messages in thread
From: Leonid Yegoshin @ 2015-05-22 19:06 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, rusty, alexinbeijing, paul.burton, david.daney, alex,
	linux-kernel, james.hogan, markos.chandras, macro, eunb.song,
	manuel.lauss, andreas.herrmann

Ralf,

If there was TIF_USEDMSA in "prev" task then it means that all MSA HW is 
in use.
And switch_to() checks this and transfers it to resume() to indicate 
that MSA processing should be done.

Macro call "msa_save_all    a0" right before disabling MSA in Config5 
does a save of MSA registers. If it doesn't cause an exception then it 
means that Config5 does exist and Config5.MIPS_CONF5_MSAEN does exist too.

- Leonid.


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

* Re: [PATCH 1/2] MIPS: MSA: bugfix - disable MSA during thread switch correctly
@ 2015-05-22 19:06         ` Leonid Yegoshin
  0 siblings, 0 replies; 24+ messages in thread
From: Leonid Yegoshin @ 2015-05-22 19:06 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, rusty, alexinbeijing, paul.burton, david.daney, alex,
	linux-kernel, james.hogan, markos.chandras, macro, eunb.song,
	manuel.lauss, andreas.herrmann

Ralf,

If there was TIF_USEDMSA in "prev" task then it means that all MSA HW is 
in use.
And switch_to() checks this and transfers it to resume() to indicate 
that MSA processing should be done.

Macro call "msa_save_all    a0" right before disabling MSA in Config5 
does a save of MSA registers. If it doesn't cause an exception then it 
means that Config5 does exist and Config5.MIPS_CONF5_MSAEN does exist too.

- Leonid.

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

* Re: [PATCH 1/2] MIPS: MSA: bugfix - disable MSA during thread switch correctly
  2015-05-22 18:37       ` Leonid Yegoshin
  (?)
  (?)
@ 2015-05-22 23:20       ` Ralf Baechle
  2015-05-23  0:00           ` Leonid Yegoshin
  -1 siblings, 1 reply; 24+ messages in thread
From: Ralf Baechle @ 2015-05-22 23:20 UTC (permalink / raw)
  To: Leonid Yegoshin
  Cc: linux-mips, rusty, alexinbeijing, paul.burton, david.daney, alex,
	linux-kernel, james.hogan, markos.chandras, macro, eunb.song,
	manuel.lauss, andreas.herrmann

On Fri, May 22, 2015 at 11:37:34AM -0700, Leonid Yegoshin wrote:

> On 05/22/2015 02:38 AM, Ralf Baechle wrote:
> >Just move the call to finish_arch_switch().
> 
> It might be a problem later, then a correct MSA partiton starts working. It
> should be tight to saving MSA registers in that case.
> 
> >Your rewrite also dropped the if (cpu_has_msa) condition from
> >disable_msa() probably causing havoc on lots of CPUs which will likely not
> >decode the set bits of the MFC0/MTC0 instructions thus end up accessing
> >Config0. Ralf
> 
> Right before this chunk of code there is a saving MSA registers. Does it
> causing a havoc or else?
> 
> May I ask you to look into switch_to macro to figure out how "if
> (cpu_has_msa)" check works in this case?

Ah sorry I now see that your added code is not executed for all CPUs but
only those having MSA.  So then it's safe.

Still I don't stylistically like defining the register t4 in the middle
of the code.

Below my suggested patch.  It's advantage is that for non-MSA platforms
the call to disable_msa() will be removed entirely.

Something like Paul's http://patchwork.linux-mips.org/patch/10111/ (assuming
it's correct and tested) seems like a full cleanup but it's way too
complex for 4.1 or the stable kernels.

  Ralf

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

 arch/mips/include/asm/switch_to.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
index e92d6c4b..7163cd7 100644
--- a/arch/mips/include/asm/switch_to.h
+++ b/arch/mips/include/asm/switch_to.h
@@ -104,7 +104,6 @@ do {									\
 	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA))		\
 		__fpsave = FP_SAVE_VECTOR;				\
 	(last) = resume(prev, next, task_thread_info(next), __fpsave);	\
-	disable_msa();							\
 } while (0)
 
 #define finish_arch_switch(prev)					\
@@ -122,6 +121,7 @@ do {									\
 	if (cpu_has_userlocal)						\
 		write_c0_userlocal(current_thread_info()->tp_value);	\
 	__restore_watch();						\
+	disable_msa();							\
 } while (0)
 
 #endif /* _ASM_SWITCH_TO_H */

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

* Re: [PATCH 1/2] MIPS: MSA: bugfix - disable MSA during thread switch correctly
@ 2015-05-23  0:00           ` Leonid Yegoshin
  0 siblings, 0 replies; 24+ messages in thread
From: Leonid Yegoshin @ 2015-05-23  0:00 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, rusty, alexinbeijing, paul.burton, david.daney, alex,
	linux-kernel, james.hogan, markos.chandras, macro, eunb.song,
	manuel.lauss, andreas.herrmann

On 05/22/2015 04:20 PM, Ralf Baechle wrote:
> On Fri, May 22, 2015 at 11:37:34AM -0700, Leonid Yegoshin wrote:
>
>> On 05/22/2015 02:38 AM, Ralf Baechle wrote:
>>> Just move the call to finish_arch_switch().
>> It might be a problem later, then a correct MSA partiton starts working. It
>> should be tight to saving MSA registers in that case.
>>
>>> Your rewrite also dropped the if (cpu_has_msa) condition from
>>> disable_msa() probably causing havoc on lots of CPUs which will likely not
>>> decode the set bits of the MFC0/MTC0 instructions thus end up accessing
>>> Config0. Ralf
>> Right before this chunk of code there is a saving MSA registers. Does it
>> causing a havoc or else?
>>
>> May I ask you to look into switch_to macro to figure out how "if
>> (cpu_has_msa)" check works in this case?
> Ah sorry I now see that your added code is not executed for all CPUs but
> only those having MSA.  So then it's safe.
>
> Still I don't stylistically like defining the register t4 in the middle
> of the code.
>
> Below my suggested patch.  It's advantage is that for non-MSA platforms
> the call to disable_msa() will be removed entirely.
>
> Something like Paul's http://patchwork.linux-mips.org/patch/10111/ (assuming
> it's correct and tested) seems like a full cleanup but it's way too
> complex for 4.1 or the stable kernels.
>
>    Ralf
>
>
All 3 patches seems working (I tested), but if you don't like mine then 
I prefer Paul's patch more - it concentrates stuff more closely and 
removes some assembly stuff.

Besides that, it introduces lose_fpu_inatomic() which is needed for me :)

- Leonid.


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

* Re: [PATCH 1/2] MIPS: MSA: bugfix - disable MSA during thread switch correctly
@ 2015-05-23  0:00           ` Leonid Yegoshin
  0 siblings, 0 replies; 24+ messages in thread
From: Leonid Yegoshin @ 2015-05-23  0:00 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, rusty, alexinbeijing, paul.burton, david.daney, alex,
	linux-kernel, james.hogan, markos.chandras, macro, eunb.song,
	manuel.lauss, andreas.herrmann

On 05/22/2015 04:20 PM, Ralf Baechle wrote:
> On Fri, May 22, 2015 at 11:37:34AM -0700, Leonid Yegoshin wrote:
>
>> On 05/22/2015 02:38 AM, Ralf Baechle wrote:
>>> Just move the call to finish_arch_switch().
>> It might be a problem later, then a correct MSA partiton starts working. It
>> should be tight to saving MSA registers in that case.
>>
>>> Your rewrite also dropped the if (cpu_has_msa) condition from
>>> disable_msa() probably causing havoc on lots of CPUs which will likely not
>>> decode the set bits of the MFC0/MTC0 instructions thus end up accessing
>>> Config0. Ralf
>> Right before this chunk of code there is a saving MSA registers. Does it
>> causing a havoc or else?
>>
>> May I ask you to look into switch_to macro to figure out how "if
>> (cpu_has_msa)" check works in this case?
> Ah sorry I now see that your added code is not executed for all CPUs but
> only those having MSA.  So then it's safe.
>
> Still I don't stylistically like defining the register t4 in the middle
> of the code.
>
> Below my suggested patch.  It's advantage is that for non-MSA platforms
> the call to disable_msa() will be removed entirely.
>
> Something like Paul's http://patchwork.linux-mips.org/patch/10111/ (assuming
> it's correct and tested) seems like a full cleanup but it's way too
> complex for 4.1 or the stable kernels.
>
>    Ralf
>
>
All 3 patches seems working (I tested), but if you don't like mine then 
I prefer Paul's patch more - it concentrates stuff more closely and 
removes some assembly stuff.

Besides that, it introduces lose_fpu_inatomic() which is needed for me :)

- Leonid.

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

end of thread, other threads:[~2015-05-23  0:02 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-19 21:13 [PATCH 0/2] MIPS: MSA: bugfixes of context switch Leonid Yegoshin
2015-05-19 21:13 ` Leonid Yegoshin
2015-05-19 21:13 ` [PATCH 1/2] MIPS: MSA: bugfix - disable MSA during thread switch correctly Leonid Yegoshin
2015-05-19 21:13   ` Leonid Yegoshin
2015-05-21  9:12   ` Paul Burton
2015-05-21  9:12     ` Paul Burton
2015-05-21 16:11     ` Leonid Yegoshin
2015-05-21 16:11       ` Leonid Yegoshin
2015-05-21 16:20   ` [PATCH] MIPS: tidy up FPU context switching Paul Burton
2015-05-21 16:20     ` Paul Burton
2015-05-22 10:42     ` [PATCH v2] " Paul Burton
2015-05-22 10:42       ` Paul Burton
2015-05-22  9:38   ` [PATCH 1/2] MIPS: MSA: bugfix - disable MSA during thread switch correctly Ralf Baechle
2015-05-22 18:37     ` Leonid Yegoshin
2015-05-22 18:37       ` Leonid Yegoshin
2015-05-22 19:06       ` Leonid Yegoshin
2015-05-22 19:06         ` Leonid Yegoshin
2015-05-22 23:20       ` Ralf Baechle
2015-05-23  0:00         ` Leonid Yegoshin
2015-05-23  0:00           ` Leonid Yegoshin
2015-05-19 21:13 ` [PATCH 2/2] MIPS: MSA: bugfix of keeping MSA live context through clone or fork Leonid Yegoshin
2015-05-19 21:13   ` Leonid Yegoshin
2015-05-20 19:23   ` Leonid Yegoshin
2015-05-20 19:23     ` Leonid Yegoshin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.