All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/13] MSA fixes
@ 2014-07-11 15:44 ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

This series fixes a bunch of issues with MSA support the have been
discovered as it has been tested against the P5600 implementation of
MSA, and in light of the recent revert of saving MSA context around
signals it marks the support as experimental. This is not really a
change given that the only hardware implementation is the 32bit P5600
which requires the experimental CONFIG_MIPS_O32_FP64_SUPPORT Kconfig
option be enabled before MSA can actually be used. A replacement for
the signal handling has been written but needs further discussion, so
will be submitted later.

Paul Burton (13):
  MIPS: allow msa.h to be included in assembly files
  MIPS: save/restore MSACSR register on context switch
  MIPS: preserve scalar FP CSR when switching vector context
  MIPS: save/disable MSA in lose_fpu
  MIPS: clear upper 64b of vector registers when MSA is first used
  MIPS: fix MSA context for tasks which don't use FP first
  MIPS: fix read_msa_* & write_msa_* functions on non-MSA toolchains
  MIPS: ensure MSA gets disabled during boot
  MIPS: disable preemption whilst initialising MSA
  MIPS: 16 byte align MSA vector context
  MIPS: consistently clear MSA flags when starting & copying threads
  MIPS: don't build MSA support unless it can be used
  MIPS: mark MSA experimental

 arch/mips/Kconfig                 |  4 ++--
 arch/mips/include/asm/asmmacro.h  | 31 +++++++++++++++++++++++++++++++
 arch/mips/include/asm/fpu.h       | 19 ++++++++++++-------
 arch/mips/include/asm/msa.h       | 31 ++++++++++++++++++-------------
 arch/mips/include/asm/processor.h | 10 ++++++++--
 arch/mips/kernel/asm-offsets.c    |  1 +
 arch/mips/kernel/cpu-probe.c      |  5 ++---
 arch/mips/kernel/process.c        |  3 +++
 arch/mips/kernel/r4k_switch.S     |  9 ++++++++-
 arch/mips/kernel/traps.c          | 29 +++++++++++++++++++++++------
 10 files changed, 108 insertions(+), 34 deletions(-)

-- 
2.0.1

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

* [PATCH 00/13] MSA fixes
@ 2014-07-11 15:44 ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

This series fixes a bunch of issues with MSA support the have been
discovered as it has been tested against the P5600 implementation of
MSA, and in light of the recent revert of saving MSA context around
signals it marks the support as experimental. This is not really a
change given that the only hardware implementation is the 32bit P5600
which requires the experimental CONFIG_MIPS_O32_FP64_SUPPORT Kconfig
option be enabled before MSA can actually be used. A replacement for
the signal handling has been written but needs further discussion, so
will be submitted later.

Paul Burton (13):
  MIPS: allow msa.h to be included in assembly files
  MIPS: save/restore MSACSR register on context switch
  MIPS: preserve scalar FP CSR when switching vector context
  MIPS: save/disable MSA in lose_fpu
  MIPS: clear upper 64b of vector registers when MSA is first used
  MIPS: fix MSA context for tasks which don't use FP first
  MIPS: fix read_msa_* & write_msa_* functions on non-MSA toolchains
  MIPS: ensure MSA gets disabled during boot
  MIPS: disable preemption whilst initialising MSA
  MIPS: 16 byte align MSA vector context
  MIPS: consistently clear MSA flags when starting & copying threads
  MIPS: don't build MSA support unless it can be used
  MIPS: mark MSA experimental

 arch/mips/Kconfig                 |  4 ++--
 arch/mips/include/asm/asmmacro.h  | 31 +++++++++++++++++++++++++++++++
 arch/mips/include/asm/fpu.h       | 19 ++++++++++++-------
 arch/mips/include/asm/msa.h       | 31 ++++++++++++++++++-------------
 arch/mips/include/asm/processor.h | 10 ++++++++--
 arch/mips/kernel/asm-offsets.c    |  1 +
 arch/mips/kernel/cpu-probe.c      |  5 ++---
 arch/mips/kernel/process.c        |  3 +++
 arch/mips/kernel/r4k_switch.S     |  9 ++++++++-
 arch/mips/kernel/traps.c          | 29 +++++++++++++++++++++++------
 10 files changed, 108 insertions(+), 34 deletions(-)

-- 
2.0.1

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

* [PATCH 01/13] MIPS: allow msa.h to be included in assembly files
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

Just #ifdef away the C functions when included from an assembly file,
as will be done in a following commit.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/include/asm/msa.h | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h
index 538f6d4..e80e85c 100644
--- a/arch/mips/include/asm/msa.h
+++ b/arch/mips/include/asm/msa.h
@@ -12,6 +12,8 @@
 
 #include <asm/mipsregs.h>
 
+#ifndef __ASSEMBLY__
+
 extern void _save_msa(struct task_struct *);
 extern void _restore_msa(struct task_struct *);
 
@@ -133,15 +135,6 @@ static inline void write_msa_##name(unsigned int val)		\
 
 #endif /* !TOOLCHAIN_SUPPORTS_MSA */
 
-#define MSA_IR		0
-#define MSA_CSR		1
-#define MSA_ACCESS	2
-#define MSA_SAVE	3
-#define MSA_MODIFY	4
-#define MSA_REQUEST	5
-#define MSA_MAP		6
-#define MSA_UNMAP	7
-
 __BUILD_MSA_CTL_REG(ir, 0)
 __BUILD_MSA_CTL_REG(csr, 1)
 __BUILD_MSA_CTL_REG(access, 2)
@@ -151,6 +144,17 @@ __BUILD_MSA_CTL_REG(request, 5)
 __BUILD_MSA_CTL_REG(map, 6)
 __BUILD_MSA_CTL_REG(unmap, 7)
 
+#endif /* !__ASSEMBLY__ */
+
+#define MSA_IR		0
+#define MSA_CSR		1
+#define MSA_ACCESS	2
+#define MSA_SAVE	3
+#define MSA_MODIFY	4
+#define MSA_REQUEST	5
+#define MSA_MAP		6
+#define MSA_UNMAP	7
+
 /* MSA Implementation Register (MSAIR) */
 #define MSA_IR_REVB		0
 #define MSA_IR_REVF		(_ULCAST_(0xff) << MSA_IR_REVB)
-- 
2.0.1

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

* [PATCH 01/13] MIPS: allow msa.h to be included in assembly files
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

Just #ifdef away the C functions when included from an assembly file,
as will be done in a following commit.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/include/asm/msa.h | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h
index 538f6d4..e80e85c 100644
--- a/arch/mips/include/asm/msa.h
+++ b/arch/mips/include/asm/msa.h
@@ -12,6 +12,8 @@
 
 #include <asm/mipsregs.h>
 
+#ifndef __ASSEMBLY__
+
 extern void _save_msa(struct task_struct *);
 extern void _restore_msa(struct task_struct *);
 
@@ -133,15 +135,6 @@ static inline void write_msa_##name(unsigned int val)		\
 
 #endif /* !TOOLCHAIN_SUPPORTS_MSA */
 
-#define MSA_IR		0
-#define MSA_CSR		1
-#define MSA_ACCESS	2
-#define MSA_SAVE	3
-#define MSA_MODIFY	4
-#define MSA_REQUEST	5
-#define MSA_MAP		6
-#define MSA_UNMAP	7
-
 __BUILD_MSA_CTL_REG(ir, 0)
 __BUILD_MSA_CTL_REG(csr, 1)
 __BUILD_MSA_CTL_REG(access, 2)
@@ -151,6 +144,17 @@ __BUILD_MSA_CTL_REG(request, 5)
 __BUILD_MSA_CTL_REG(map, 6)
 __BUILD_MSA_CTL_REG(unmap, 7)
 
+#endif /* !__ASSEMBLY__ */
+
+#define MSA_IR		0
+#define MSA_CSR		1
+#define MSA_ACCESS	2
+#define MSA_SAVE	3
+#define MSA_MODIFY	4
+#define MSA_REQUEST	5
+#define MSA_MAP		6
+#define MSA_UNMAP	7
+
 /* MSA Implementation Register (MSAIR) */
 #define MSA_IR_REVB		0
 #define MSA_IR_REVF		(_ULCAST_(0xff) << MSA_IR_REVB)
-- 
2.0.1

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

* [PATCH 02/13] MIPS: save/restore MSACSR register on context switch
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

I added a field for the MSACSR register in struct mips_fpu_struct, but
never actually made use of it... This is a clear bug. Save and restore
the MSACSR register along with the vector registers.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/include/asm/asmmacro.h | 11 +++++++++++
 arch/mips/kernel/asm-offsets.c   |  1 +
 2 files changed, 12 insertions(+)

diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 935543f..4986bf5 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -10,6 +10,7 @@
 
 #include <asm/hazards.h>
 #include <asm/asm-offsets.h>
+#include <asm/msa.h>
 
 #ifdef CONFIG_32BIT
 #include <asm/asmmacro-32.h>
@@ -378,9 +379,19 @@
 	st_d	29, THREAD_FPR29, \thread
 	st_d	30, THREAD_FPR30, \thread
 	st_d	31, THREAD_FPR31, \thread
+	.set	push
+	.set	noat
+	cfcmsa	$1, MSA_CSR
+	sw	$1, THREAD_MSA_CSR(\thread)
+	.set	pop
 	.endm
 
 	.macro	msa_restore_all	thread
+	.set	push
+	.set	noat
+	lw	$1, THREAD_MSA_CSR(\thread)
+	ctcmsa	MSA_CSR, $1
+	.set	pop
 	ld_d	0, THREAD_FPR0, \thread
 	ld_d	1, THREAD_FPR1, \thread
 	ld_d	2, THREAD_FPR2, \thread
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index 4bb5107..b1d84bd 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -234,6 +234,7 @@ void output_thread_fpu_defines(void)
 	       thread.fpu.fpr[31].val64[FPR_IDX(64, 0)]);
 
 	OFFSET(THREAD_FCR31, task_struct, thread.fpu.fcr31);
+	OFFSET(THREAD_MSA_CSR, task_struct, thread.fpu.msacsr);
 	BLANK();
 }
 
-- 
2.0.1

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

* [PATCH 02/13] MIPS: save/restore MSACSR register on context switch
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

I added a field for the MSACSR register in struct mips_fpu_struct, but
never actually made use of it... This is a clear bug. Save and restore
the MSACSR register along with the vector registers.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/include/asm/asmmacro.h | 11 +++++++++++
 arch/mips/kernel/asm-offsets.c   |  1 +
 2 files changed, 12 insertions(+)

diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 935543f..4986bf5 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -10,6 +10,7 @@
 
 #include <asm/hazards.h>
 #include <asm/asm-offsets.h>
+#include <asm/msa.h>
 
 #ifdef CONFIG_32BIT
 #include <asm/asmmacro-32.h>
@@ -378,9 +379,19 @@
 	st_d	29, THREAD_FPR29, \thread
 	st_d	30, THREAD_FPR30, \thread
 	st_d	31, THREAD_FPR31, \thread
+	.set	push
+	.set	noat
+	cfcmsa	$1, MSA_CSR
+	sw	$1, THREAD_MSA_CSR(\thread)
+	.set	pop
 	.endm
 
 	.macro	msa_restore_all	thread
+	.set	push
+	.set	noat
+	lw	$1, THREAD_MSA_CSR(\thread)
+	ctcmsa	MSA_CSR, $1
+	.set	pop
 	ld_d	0, THREAD_FPR0, \thread
 	ld_d	1, THREAD_FPR1, \thread
 	ld_d	2, THREAD_FPR2, \thread
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index 4bb5107..b1d84bd 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -234,6 +234,7 @@ void output_thread_fpu_defines(void)
 	       thread.fpu.fpr[31].val64[FPR_IDX(64, 0)]);
 
 	OFFSET(THREAD_FCR31, task_struct, thread.fpu.fcr31);
+	OFFSET(THREAD_MSA_CSR, task_struct, thread.fpu.msacsr);
 	BLANK();
 }
 
-- 
2.0.1

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

* [PATCH 03/13] MIPS: preserve scalar FP CSR when switching vector context
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

Switching the vector context implicitly saves & restores the state of
the aliased scalar FP data registers, however the scalar FP control
& status register is distinct from the MSA control & status register.
In order to allow scalar FP to function correctly in programs using
MSA, the scalar CSR needs to be saved & restored along with the MSA
vector context.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/kernel/r4k_switch.S | 4 +++-
 arch/mips/kernel/traps.c      | 5 +++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 81ca3f7..1a1aef0 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -64,8 +64,10 @@
 	/* Check whether we're saving scalar or vector context. */
 	bgtz	a3, 1f
 
-	/* Save 128b MSA vector context. */
+	/* Save 128b MSA vector context + scalar FP control & status. */
+	cfc1	t1, fcr31
 	msa_save_all	a0
+	sw	t1, THREAD_FCR31(a0)
 	b	2f
 
 1:	/* Save 32b/64b scalar FP context. */
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 51706d6..4792fd7 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1153,6 +1153,11 @@ static int enable_restore_fp_context(int msa)
 
 	/* We need to restore the vector context. */
 	restore_msa(current);
+
+	/* Restore the scalar FP control & status register */
+	if (!was_fpu_owner)
+		asm volatile("ctc1 %0, $31" : : "r"(current->thread.fpu.fcr31));
+
 	return 0;
 }
 
-- 
2.0.1

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

* [PATCH 03/13] MIPS: preserve scalar FP CSR when switching vector context
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

Switching the vector context implicitly saves & restores the state of
the aliased scalar FP data registers, however the scalar FP control
& status register is distinct from the MSA control & status register.
In order to allow scalar FP to function correctly in programs using
MSA, the scalar CSR needs to be saved & restored along with the MSA
vector context.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/kernel/r4k_switch.S | 4 +++-
 arch/mips/kernel/traps.c      | 5 +++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 81ca3f7..1a1aef0 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -64,8 +64,10 @@
 	/* Check whether we're saving scalar or vector context. */
 	bgtz	a3, 1f
 
-	/* Save 128b MSA vector context. */
+	/* Save 128b MSA vector context + scalar FP control & status. */
+	cfc1	t1, fcr31
 	msa_save_all	a0
+	sw	t1, THREAD_FCR31(a0)
 	b	2f
 
 1:	/* Save 32b/64b scalar FP context. */
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 51706d6..4792fd7 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1153,6 +1153,11 @@ static int enable_restore_fp_context(int msa)
 
 	/* We need to restore the vector context. */
 	restore_msa(current);
+
+	/* Restore the scalar FP control & status register */
+	if (!was_fpu_owner)
+		asm volatile("ctc1 %0, $31" : : "r"(current->thread.fpu.fcr31));
+
 	return 0;
 }
 
-- 
2.0.1

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

* [PATCH 04/13] MIPS: save/disable MSA in lose_fpu
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

The kernel depends upon MSA never being enabled when the FPU is not, a
condition which is currently violated in a few places (whilst saving
sigcontext, following mips_cpu_save). Catch all the problem cases by
disabling MSA in lose_fpu, after saving context if necessary.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/include/asm/fpu.h | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
index a939574..71d97eb 100644
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -21,6 +21,7 @@
 #include <asm/hazards.h>
 #include <asm/processor.h>
 #include <asm/current.h>
+#include <asm/msa.h>
 
 #ifdef CONFIG_MIPS_MT_FPAFF
 #include <asm/mips_mt.h>
@@ -141,13 +142,21 @@ static inline int own_fpu(int restore)
 static inline void lose_fpu(int save)
 {
 	preempt_disable();
-	if (is_fpu_owner()) {
+	if (is_msa_enabled()) {
+		if (save) {
+			save_msa(current);
+			asm volatile("cfc1 %0, $31"
+				: "=r"(current->thread.fpu.fcr31));
+		}
+		disable_msa();
+		clear_thread_flag(TIF_USEDMSA);
+	} else if (is_fpu_owner()) {
 		if (save)
 			_save_fp(current);
-		KSTK_STATUS(current) &= ~ST0_CU1;
-		clear_thread_flag(TIF_USEDFPU);
 		__disable_fpu();
 	}
+	KSTK_STATUS(current) &= ~ST0_CU1;
+	clear_thread_flag(TIF_USEDFPU);
 	preempt_enable();
 }
 
-- 
2.0.1

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

* [PATCH 04/13] MIPS: save/disable MSA in lose_fpu
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

The kernel depends upon MSA never being enabled when the FPU is not, a
condition which is currently violated in a few places (whilst saving
sigcontext, following mips_cpu_save). Catch all the problem cases by
disabling MSA in lose_fpu, after saving context if necessary.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/include/asm/fpu.h | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
index a939574..71d97eb 100644
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -21,6 +21,7 @@
 #include <asm/hazards.h>
 #include <asm/processor.h>
 #include <asm/current.h>
+#include <asm/msa.h>
 
 #ifdef CONFIG_MIPS_MT_FPAFF
 #include <asm/mips_mt.h>
@@ -141,13 +142,21 @@ static inline int own_fpu(int restore)
 static inline void lose_fpu(int save)
 {
 	preempt_disable();
-	if (is_fpu_owner()) {
+	if (is_msa_enabled()) {
+		if (save) {
+			save_msa(current);
+			asm volatile("cfc1 %0, $31"
+				: "=r"(current->thread.fpu.fcr31));
+		}
+		disable_msa();
+		clear_thread_flag(TIF_USEDMSA);
+	} else if (is_fpu_owner()) {
 		if (save)
 			_save_fp(current);
-		KSTK_STATUS(current) &= ~ST0_CU1;
-		clear_thread_flag(TIF_USEDFPU);
 		__disable_fpu();
 	}
+	KSTK_STATUS(current) &= ~ST0_CU1;
+	clear_thread_flag(TIF_USEDFPU);
 	preempt_enable();
 }
 
-- 
2.0.1

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

* [PATCH 05/13] MIPS: clear upper 64b of vector registers when MSA is first used
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

When a task first makes use of MSA we need to ensure that the upper
64b of the vector registers are cleared, so that no information can be
leaked to it from the previous task to use MSA context on the CPU. The
architecture specification formerly specified that these bits would be
cleared to 0 when a scalar FP instructions wrote to the aliased FP
registers but more recent versions of the specification now state that
the bits are unpredictable. Clear then explicitly to be sure.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/include/asm/asmmacro.h | 20 ++++++++++++++++++++
 arch/mips/include/asm/msa.h      |  1 +
 arch/mips/kernel/r4k_switch.S    |  5 +++++
 arch/mips/kernel/traps.c         | 12 +++++++++---
 4 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 4986bf5..2d601e7 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -426,4 +426,24 @@
 	ld_d	31, THREAD_FPR31, \thread
 	.endm
 
+	.macro	msa_clear_upper wd
+#ifdef CONFIG_64BIT
+	insert_d \wd, 1
+#else
+	insert_w \wd, 2
+	insert_w \wd, 3
+#endif
+	.if	31-\wd
+	msa_clear_upper	(\wd+1)
+	.endif
+	.endm
+
+	.macro	msa_clear_all_upper
+	.set	push
+	.set	noat
+	move	$1, zero
+	msa_clear_upper	0
+	.set	pop
+	.endm
+
 #endif /* _ASM_ASMMACRO_H */
diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h
index e80e85c..f32aa06 100644
--- a/arch/mips/include/asm/msa.h
+++ b/arch/mips/include/asm/msa.h
@@ -16,6 +16,7 @@
 
 extern void _save_msa(struct task_struct *);
 extern void _restore_msa(struct task_struct *);
+extern void _clear_msa_upper(void);
 
 static inline void enable_msa(void)
 {
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 1a1aef0..e459c04 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -144,6 +144,11 @@ LEAF(_restore_msa)
 	jr	ra
 	END(_restore_msa)
 
+LEAF(_clear_msa_upper)
+	msa_clear_all_upper
+	jr	ra
+	END(_clear_msa_upper)
+
 #endif
 
 /*
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 4792fd7..9359907 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1093,8 +1093,10 @@ static int enable_restore_fp_context(int msa)
 	if (!used_math()) {
 		/* First time FP context user. */
 		err = init_fpu();
-		if (msa && !err)
+		if (msa && !err) {
 			enable_msa();
+			_clear_msa_upper();
+		}
 		if (!err)
 			set_used_math();
 		return err;
@@ -1146,10 +1148,14 @@ static int enable_restore_fp_context(int msa)
 	/*
 	 * If this is the first time that the task is using MSA and it has
 	 * previously used scalar FP in this time slice then we already nave
-	 * FP context which we shouldn't clobber.
+	 * FP context which we shouldn't clobber. We do however need to clear
+	 * the upper 64b of each vector register so that this task has no
+	 * opportunity to see data left behind by another.
 	 */
-	if (!test_and_set_thread_flag(TIF_MSA_CTX_LIVE) && was_fpu_owner)
+	if (!test_and_set_thread_flag(TIF_MSA_CTX_LIVE) && was_fpu_owner) {
+		_clear_msa_upper();
 		return 0;
+	}
 
 	/* We need to restore the vector context. */
 	restore_msa(current);
-- 
2.0.1

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

* [PATCH 05/13] MIPS: clear upper 64b of vector registers when MSA is first used
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

When a task first makes use of MSA we need to ensure that the upper
64b of the vector registers are cleared, so that no information can be
leaked to it from the previous task to use MSA context on the CPU. The
architecture specification formerly specified that these bits would be
cleared to 0 when a scalar FP instructions wrote to the aliased FP
registers but more recent versions of the specification now state that
the bits are unpredictable. Clear then explicitly to be sure.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/include/asm/asmmacro.h | 20 ++++++++++++++++++++
 arch/mips/include/asm/msa.h      |  1 +
 arch/mips/kernel/r4k_switch.S    |  5 +++++
 arch/mips/kernel/traps.c         | 12 +++++++++---
 4 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 4986bf5..2d601e7 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -426,4 +426,24 @@
 	ld_d	31, THREAD_FPR31, \thread
 	.endm
 
+	.macro	msa_clear_upper wd
+#ifdef CONFIG_64BIT
+	insert_d \wd, 1
+#else
+	insert_w \wd, 2
+	insert_w \wd, 3
+#endif
+	.if	31-\wd
+	msa_clear_upper	(\wd+1)
+	.endif
+	.endm
+
+	.macro	msa_clear_all_upper
+	.set	push
+	.set	noat
+	move	$1, zero
+	msa_clear_upper	0
+	.set	pop
+	.endm
+
 #endif /* _ASM_ASMMACRO_H */
diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h
index e80e85c..f32aa06 100644
--- a/arch/mips/include/asm/msa.h
+++ b/arch/mips/include/asm/msa.h
@@ -16,6 +16,7 @@
 
 extern void _save_msa(struct task_struct *);
 extern void _restore_msa(struct task_struct *);
+extern void _clear_msa_upper(void);
 
 static inline void enable_msa(void)
 {
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 1a1aef0..e459c04 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -144,6 +144,11 @@ LEAF(_restore_msa)
 	jr	ra
 	END(_restore_msa)
 
+LEAF(_clear_msa_upper)
+	msa_clear_all_upper
+	jr	ra
+	END(_clear_msa_upper)
+
 #endif
 
 /*
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 4792fd7..9359907 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1093,8 +1093,10 @@ static int enable_restore_fp_context(int msa)
 	if (!used_math()) {
 		/* First time FP context user. */
 		err = init_fpu();
-		if (msa && !err)
+		if (msa && !err) {
 			enable_msa();
+			_clear_msa_upper();
+		}
 		if (!err)
 			set_used_math();
 		return err;
@@ -1146,10 +1148,14 @@ static int enable_restore_fp_context(int msa)
 	/*
 	 * If this is the first time that the task is using MSA and it has
 	 * previously used scalar FP in this time slice then we already nave
-	 * FP context which we shouldn't clobber.
+	 * FP context which we shouldn't clobber. We do however need to clear
+	 * the upper 64b of each vector register so that this task has no
+	 * opportunity to see data left behind by another.
 	 */
-	if (!test_and_set_thread_flag(TIF_MSA_CTX_LIVE) && was_fpu_owner)
+	if (!test_and_set_thread_flag(TIF_MSA_CTX_LIVE) && was_fpu_owner) {
+		_clear_msa_upper();
 		return 0;
+	}
 
 	/* We need to restore the vector context. */
 	restore_msa(current);
-- 
2.0.1

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

* [PATCH 06/13] MIPS: fix MSA context for tasks which don't use FP first
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

If a task does not execute scalar FP instructions prior to using MSA
then the flags indicating that the task has live MSA context were not
being set. The upper 64b of each vector register would then be lost
upon the tasks first context switch after using MSA.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/kernel/traps.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 9359907..58a067f 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1096,6 +1096,8 @@ static int enable_restore_fp_context(int msa)
 		if (msa && !err) {
 			enable_msa();
 			_clear_msa_upper();
+			set_thread_flag(TIF_USEDMSA);
+			set_thread_flag(TIF_MSA_CTX_LIVE);
 		}
 		if (!err)
 			set_used_math();
-- 
2.0.1

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

* [PATCH 06/13] MIPS: fix MSA context for tasks which don't use FP first
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

If a task does not execute scalar FP instructions prior to using MSA
then the flags indicating that the task has live MSA context were not
being set. The upper 64b of each vector register would then be lost
upon the tasks first context switch after using MSA.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/kernel/traps.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 9359907..58a067f 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1096,6 +1096,8 @@ static int enable_restore_fp_context(int msa)
 		if (msa && !err) {
 			enable_msa();
 			_clear_msa_upper();
+			set_thread_flag(TIF_USEDMSA);
+			set_thread_flag(TIF_MSA_CTX_LIVE);
 		}
 		if (!err)
 			set_used_math();
-- 
2.0.1

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

* [PATCH 07/13] MIPS: fix read_msa_* & write_msa_* functions on non-MSA toolchains
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

Commit d96cc3d1ec5d "MIPS: Add microMIPS MSA support." attempted to use
the value of a macro within an inline asm statement but instead emitted
a comment leading to the cfcmsa & ctcmsa instructions being omitted. Fix
that by passing CFC_MSA_INSN & CTC_MSA_INSN as arguments to the asm
statements.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/include/asm/msa.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h
index f32aa06..7002c18 100644
--- a/arch/mips/include/asm/msa.h
+++ b/arch/mips/include/asm/msa.h
@@ -115,10 +115,10 @@ static inline unsigned int read_msa_##name(void)		\
 	"	.set	push\n"					\
 	"	.set	noat\n"					\
 	"	.insn\n"					\
-	"	.word	#CFC_MSA_INSN | (" #cs " << 11)\n"	\
+	"	.word	%1 | (" #cs " << 11)\n"			\
 	"	move	%0, $1\n"				\
 	"	.set	pop\n"					\
-	: "=r"(reg));						\
+	: "=r"(reg) : "i"(CFC_MSA_INSN));			\
 	return reg;						\
 }								\
 								\
@@ -129,9 +129,9 @@ static inline void write_msa_##name(unsigned int val)		\
 	"	.set	noat\n"					\
 	"	move	$1, %0\n"				\
 	"	.insn\n"					\
-	"	.word	#CTC_MSA_INSN | (" #cs " << 6)\n"	\
+	"	.word	%1 | (" #cs " << 6)\n"			\
 	"	.set	pop\n"					\
-	: : "r"(val));						\
+	: : "r"(val), "i"(CTC_MSA_INSN));			\
 }
 
 #endif /* !TOOLCHAIN_SUPPORTS_MSA */
-- 
2.0.1

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

* [PATCH 07/13] MIPS: fix read_msa_* & write_msa_* functions on non-MSA toolchains
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

Commit d96cc3d1ec5d "MIPS: Add microMIPS MSA support." attempted to use
the value of a macro within an inline asm statement but instead emitted
a comment leading to the cfcmsa & ctcmsa instructions being omitted. Fix
that by passing CFC_MSA_INSN & CTC_MSA_INSN as arguments to the asm
statements.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/include/asm/msa.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h
index f32aa06..7002c18 100644
--- a/arch/mips/include/asm/msa.h
+++ b/arch/mips/include/asm/msa.h
@@ -115,10 +115,10 @@ static inline unsigned int read_msa_##name(void)		\
 	"	.set	push\n"					\
 	"	.set	noat\n"					\
 	"	.insn\n"					\
-	"	.word	#CFC_MSA_INSN | (" #cs " << 11)\n"	\
+	"	.word	%1 | (" #cs " << 11)\n"			\
 	"	move	%0, $1\n"				\
 	"	.set	pop\n"					\
-	: "=r"(reg));						\
+	: "=r"(reg) : "i"(CFC_MSA_INSN));			\
 	return reg;						\
 }								\
 								\
@@ -129,9 +129,9 @@ static inline void write_msa_##name(unsigned int val)		\
 	"	.set	noat\n"					\
 	"	move	$1, %0\n"				\
 	"	.insn\n"					\
-	"	.word	#CTC_MSA_INSN | (" #cs " << 6)\n"	\
+	"	.word	%1 | (" #cs " << 6)\n"			\
 	"	.set	pop\n"					\
-	: : "r"(val));						\
+	: : "r"(val), "i"(CTC_MSA_INSN));			\
 }
 
 #endif /* !TOOLCHAIN_SUPPORTS_MSA */
-- 
2.0.1

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

* [PATCH 08/13] MIPS: ensure MSA gets disabled during boot
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

The kernel relies upon MSA being disabled when a task begins running,
so that it can initialise or restore context in response to the
resulting MSA disabled exception. Previously the state of MSA following
boot was left as it was before the kernel ran, where MSA could
potentially have been enabled. Explicitly disable it during boot to
prevent any problems.

As a nice side effect the code reads a little better too.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/kernel/cpu-probe.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index e818547..1b345f0 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -130,14 +130,13 @@ static inline int __cpu_has_fpu(void)
 
 static inline unsigned long cpu_get_msa_id(void)
 {
-	unsigned long status, conf5, msa_id;
+	unsigned long status, msa_id;
 
 	status = read_c0_status();
 	__enable_fpu(FPU_64BIT);
-	conf5 = read_c0_config5();
 	enable_msa();
 	msa_id = read_msa_ir();
-	write_c0_config5(conf5);
+	disable_msa();
 	write_c0_status(status);
 	return msa_id;
 }
-- 
2.0.1

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

* [PATCH 08/13] MIPS: ensure MSA gets disabled during boot
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

The kernel relies upon MSA being disabled when a task begins running,
so that it can initialise or restore context in response to the
resulting MSA disabled exception. Previously the state of MSA following
boot was left as it was before the kernel ran, where MSA could
potentially have been enabled. Explicitly disable it during boot to
prevent any problems.

As a nice side effect the code reads a little better too.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/kernel/cpu-probe.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index e818547..1b345f0 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -130,14 +130,13 @@ static inline int __cpu_has_fpu(void)
 
 static inline unsigned long cpu_get_msa_id(void)
 {
-	unsigned long status, conf5, msa_id;
+	unsigned long status, msa_id;
 
 	status = read_c0_status();
 	__enable_fpu(FPU_64BIT);
-	conf5 = read_c0_config5();
 	enable_msa();
 	msa_id = read_msa_ir();
-	write_c0_config5(conf5);
+	disable_msa();
 	write_c0_status(status);
 	return msa_id;
 }
-- 
2.0.1

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

* [PATCH 09/13] MIPS: disable preemption whilst initialising MSA
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

Preemption must be disabled throughout the process of enabling the FPU,
enabling MSA & initialising the vector registers. Without doing so it
is possible to lose the FPU or MSA whilst initialising them causing
that initialisation to fail.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/include/asm/fpu.h |  4 ----
 arch/mips/kernel/traps.c    | 12 ++++++++----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
index 71d97eb..4d0aeda 100644
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -164,8 +164,6 @@ static inline int init_fpu(void)
 {
 	int ret = 0;
 
-	preempt_disable();
-
 	if (cpu_has_fpu) {
 		ret = __own_fpu();
 		if (!ret)
@@ -173,8 +171,6 @@ static inline int init_fpu(void)
 	} else
 		fpu_emulator_init_fpu();
 
-	preempt_enable();
-
 	return ret;
 }
 
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 58a067f..0528246 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1092,6 +1092,7 @@ static int enable_restore_fp_context(int msa)
 
 	if (!used_math()) {
 		/* First time FP context user. */
+		preempt_disable();
 		err = init_fpu();
 		if (msa && !err) {
 			enable_msa();
@@ -1099,6 +1100,7 @@ static int enable_restore_fp_context(int msa)
 			set_thread_flag(TIF_USEDMSA);
 			set_thread_flag(TIF_MSA_CTX_LIVE);
 		}
+		preempt_enable();
 		if (!err)
 			set_used_math();
 		return err;
@@ -1138,10 +1140,11 @@ static int enable_restore_fp_context(int msa)
 	 * This task is using or has previously used MSA. Thus we require
 	 * that Status.FR == 1.
 	 */
+	preempt_disable();
 	was_fpu_owner = is_fpu_owner();
-	err = own_fpu(0);
+	err = own_fpu_inatomic(0);
 	if (err)
-		return err;
+		goto out;
 
 	enable_msa();
 	write_msa_csr(current->thread.fpu.msacsr);
@@ -1156,7 +1159,7 @@ static int enable_restore_fp_context(int msa)
 	 */
 	if (!test_and_set_thread_flag(TIF_MSA_CTX_LIVE) && was_fpu_owner) {
 		_clear_msa_upper();
-		return 0;
+		goto out;
 	}
 
 	/* We need to restore the vector context. */
@@ -1165,7 +1168,8 @@ static int enable_restore_fp_context(int msa)
 	/* Restore the scalar FP control & status register */
 	if (!was_fpu_owner)
 		asm volatile("ctc1 %0, $31" : : "r"(current->thread.fpu.fcr31));
-
+out:
+	preempt_enable();
 	return 0;
 }
 
-- 
2.0.1

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

* [PATCH 09/13] MIPS: disable preemption whilst initialising MSA
@ 2014-07-11 15:44   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:44 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

Preemption must be disabled throughout the process of enabling the FPU,
enabling MSA & initialising the vector registers. Without doing so it
is possible to lose the FPU or MSA whilst initialising them causing
that initialisation to fail.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/include/asm/fpu.h |  4 ----
 arch/mips/kernel/traps.c    | 12 ++++++++----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
index 71d97eb..4d0aeda 100644
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -164,8 +164,6 @@ static inline int init_fpu(void)
 {
 	int ret = 0;
 
-	preempt_disable();
-
 	if (cpu_has_fpu) {
 		ret = __own_fpu();
 		if (!ret)
@@ -173,8 +171,6 @@ static inline int init_fpu(void)
 	} else
 		fpu_emulator_init_fpu();
 
-	preempt_enable();
-
 	return ret;
 }
 
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 58a067f..0528246 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1092,6 +1092,7 @@ static int enable_restore_fp_context(int msa)
 
 	if (!used_math()) {
 		/* First time FP context user. */
+		preempt_disable();
 		err = init_fpu();
 		if (msa && !err) {
 			enable_msa();
@@ -1099,6 +1100,7 @@ static int enable_restore_fp_context(int msa)
 			set_thread_flag(TIF_USEDMSA);
 			set_thread_flag(TIF_MSA_CTX_LIVE);
 		}
+		preempt_enable();
 		if (!err)
 			set_used_math();
 		return err;
@@ -1138,10 +1140,11 @@ static int enable_restore_fp_context(int msa)
 	 * This task is using or has previously used MSA. Thus we require
 	 * that Status.FR == 1.
 	 */
+	preempt_disable();
 	was_fpu_owner = is_fpu_owner();
-	err = own_fpu(0);
+	err = own_fpu_inatomic(0);
 	if (err)
-		return err;
+		goto out;
 
 	enable_msa();
 	write_msa_csr(current->thread.fpu.msacsr);
@@ -1156,7 +1159,7 @@ static int enable_restore_fp_context(int msa)
 	 */
 	if (!test_and_set_thread_flag(TIF_MSA_CTX_LIVE) && was_fpu_owner) {
 		_clear_msa_upper();
-		return 0;
+		goto out;
 	}
 
 	/* We need to restore the vector context. */
@@ -1165,7 +1168,8 @@ static int enable_restore_fp_context(int msa)
 	/* Restore the scalar FP control & status register */
 	if (!was_fpu_owner)
 		asm volatile("ctc1 %0, $31" : : "r"(current->thread.fpu.fcr31));
-
+out:
+	preempt_enable();
 	return 0;
 }
 
-- 
2.0.1

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

* [PATCH 10/13] MIPS: 16 byte align MSA vector context
@ 2014-07-11 15:46   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

The MSA specification upon first read appears to suggest that it is safe
to perform vector loads & stores with arbitrary alignment. However it
leaves provision for "address-dependent exceptions"... Align the vector
context to a 16 byte boundary to ensure that the kernel cannot cause any
such exceptions.

Note that the fpu field of struct thread_struct was already at a 16 byte
boundary within the struct, the introduction of FPU_ALIGN simply makes
the requirement explicit. The only part of this impacting the generated
kernel binary is ARCH_MIN_TASKALIGN.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/include/asm/processor.h | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index ad70cba..5733fab 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -238,7 +238,13 @@ typedef struct {
 	unsigned long seg;
 } mm_segment_t;
 
-#define ARCH_MIN_TASKALIGN	8
+#ifdef CONFIG_CPU_HAS_MSA
+# define ARCH_MIN_TASKALIGN	16
+# define FPU_ALIGN		__aligned(16)
+#else
+# define ARCH_MIN_TASKALIGN	8
+# define FPU_ALIGN
+#endif
 
 struct mips_abi;
 
@@ -255,7 +261,7 @@ struct thread_struct {
 	unsigned long cp0_status;
 
 	/* Saved fpu/fpu emulator stuff. */
-	struct mips_fpu_struct fpu;
+	struct mips_fpu_struct fpu FPU_ALIGN;
 #ifdef CONFIG_MIPS_MT_FPAFF
 	/* Emulated instruction count */
 	unsigned long emulated_fp;
-- 
2.0.1

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

* [PATCH 10/13] MIPS: 16 byte align MSA vector context
@ 2014-07-11 15:46   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

The MSA specification upon first read appears to suggest that it is safe
to perform vector loads & stores with arbitrary alignment. However it
leaves provision for "address-dependent exceptions"... Align the vector
context to a 16 byte boundary to ensure that the kernel cannot cause any
such exceptions.

Note that the fpu field of struct thread_struct was already at a 16 byte
boundary within the struct, the introduction of FPU_ALIGN simply makes
the requirement explicit. The only part of this impacting the generated
kernel binary is ARCH_MIN_TASKALIGN.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/include/asm/processor.h | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index ad70cba..5733fab 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -238,7 +238,13 @@ typedef struct {
 	unsigned long seg;
 } mm_segment_t;
 
-#define ARCH_MIN_TASKALIGN	8
+#ifdef CONFIG_CPU_HAS_MSA
+# define ARCH_MIN_TASKALIGN	16
+# define FPU_ALIGN		__aligned(16)
+#else
+# define ARCH_MIN_TASKALIGN	8
+# define FPU_ALIGN
+#endif
 
 struct mips_abi;
 
@@ -255,7 +261,7 @@ struct thread_struct {
 	unsigned long cp0_status;
 
 	/* Saved fpu/fpu emulator stuff. */
-	struct mips_fpu_struct fpu;
+	struct mips_fpu_struct fpu FPU_ALIGN;
 #ifdef CONFIG_MIPS_MT_FPAFF
 	/* Emulated instruction count */
 	unsigned long emulated_fp;
-- 
2.0.1

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

* [PATCH 11/13] MIPS: consistently clear MSA flags when starting & copying threads
@ 2014-07-11 15:47   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:47 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

The TIF_MSA_CTX_LIVE flag (indicating that a task has MSA context which
needs to be preserved) was being cleared in start_thread, but the
TIF_USEDMSA flag (indicating that a task has used MSA in this timeslice)
was not. In copy_thread neither flag was cleared, but both need to be.
Without clearing these flags the kernel will proceed to attempt to save
MSA context when the task is context switched out, and if the task had
not used MSA in the meantime then it will fail because MSA or the FPU
are disabled. The end result is typically:

  do_cpu invoked from kernel context![#1]:
  CPU: 0 PID: 99 Comm: sh Not tainted 3.16.0-rc4-00025-g6dc9476-dirty #88
  task: 8f23dc60 ti: 8f1d8000 task.ti: 8f1d8000
  ...
  Call Trace:
  [<8010edbc>] resume+0x5c/0x280
  [<80481e0c>] __schedule+0x370/0x800
  [<80104838>] work_resched+0x8/0x2c

Fix by consistently clearing both flags in both functions.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/kernel/process.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 0a1ec0f..8e0e7d6 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -66,6 +66,7 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
 	clear_used_math();
 	clear_fpu_owner();
 	init_dsp();
+	clear_thread_flag(TIF_USEDMSA);
 	clear_thread_flag(TIF_MSA_CTX_LIVE);
 	disable_msa();
 	regs->cp0_epc = pc;
@@ -141,6 +142,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
 
 	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);
-- 
2.0.1

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

* [PATCH 11/13] MIPS: consistently clear MSA flags when starting & copying threads
@ 2014-07-11 15:47   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:47 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

The TIF_MSA_CTX_LIVE flag (indicating that a task has MSA context which
needs to be preserved) was being cleared in start_thread, but the
TIF_USEDMSA flag (indicating that a task has used MSA in this timeslice)
was not. In copy_thread neither flag was cleared, but both need to be.
Without clearing these flags the kernel will proceed to attempt to save
MSA context when the task is context switched out, and if the task had
not used MSA in the meantime then it will fail because MSA or the FPU
are disabled. The end result is typically:

  do_cpu invoked from kernel context![#1]:
  CPU: 0 PID: 99 Comm: sh Not tainted 3.16.0-rc4-00025-g6dc9476-dirty #88
  task: 8f23dc60 ti: 8f1d8000 task.ti: 8f1d8000
  ...
  Call Trace:
  [<8010edbc>] resume+0x5c/0x280
  [<80481e0c>] __schedule+0x370/0x800
  [<80104838>] work_resched+0x8/0x2c

Fix by consistently clearing both flags in both functions.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/kernel/process.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 0a1ec0f..8e0e7d6 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -66,6 +66,7 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
 	clear_used_math();
 	clear_fpu_owner();
 	init_dsp();
+	clear_thread_flag(TIF_USEDMSA);
 	clear_thread_flag(TIF_MSA_CTX_LIVE);
 	disable_msa();
 	regs->cp0_epc = pc;
@@ -141,6 +142,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
 
 	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);
-- 
2.0.1

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

* [PATCH 12/13] MIPS: don't build MSA support unless it can be used
@ 2014-07-11 15:47   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:47 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

MSA requires that Status.FR == 1, so for MIPS32 tasks MSA can only be
used if CONFIG_MIPS_O32_FP64_SUPPORT is enabled. If it is not & the
kernel is 32bit, there's no point including support for MSA.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 4e238e6..857a49c 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2112,6 +2112,7 @@ config CPU_MICROMIPS
 config CPU_HAS_MSA
 	bool "Support for the MIPS SIMD Architecture"
 	depends on CPU_SUPPORTS_MSA
+	depends on 64BIT || MIPS_O32_FP64_SUPPORT
 	default y
 	help
 	  MIPS SIMD Architecture (MSA) introduces 128 bit wide vector registers
-- 
2.0.1

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

* [PATCH 12/13] MIPS: don't build MSA support unless it can be used
@ 2014-07-11 15:47   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:47 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

MSA requires that Status.FR == 1, so for MIPS32 tasks MSA can only be
used if CONFIG_MIPS_O32_FP64_SUPPORT is enabled. If it is not & the
kernel is 32bit, there's no point including support for MSA.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 4e238e6..857a49c 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2112,6 +2112,7 @@ config CPU_MICROMIPS
 config CPU_HAS_MSA
 	bool "Support for the MIPS SIMD Architecture"
 	depends on CPU_SUPPORTS_MSA
+	depends on 64BIT || MIPS_O32_FP64_SUPPORT
 	default y
 	help
 	  MIPS SIMD Architecture (MSA) introduces 128 bit wide vector registers
-- 
2.0.1

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

* [PATCH 13/13] MIPS: mark MSA experimental
@ 2014-07-11 15:47   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:47 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

In light of the commit 16f77de82f2d (Revert "MIPS: Save/restore MSA
context around signals") the MSA support in the kernel is incomplete.
Until the replacement for the former sigcontext changes is agreed upon
and in tree, mark MSA experimental & disable it by default.

MSA is only implemented by one CPU supported by the kernel, the P5600.
The P5600 is a 32 bit core, and thus MSA can only be used when the
experimental CONFIG_MIPS_O32_FP64_SUPPORT option is enabled. Therefore
MSA is only being used in experimental settings anyway and this change
doesn't actually make any difference beyond clarifying the state of
MSA support.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/Kconfig | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 857a49c..d747273 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2110,10 +2110,9 @@ config CPU_MICROMIPS
 	  microMIPS ISA
 
 config CPU_HAS_MSA
-	bool "Support for the MIPS SIMD Architecture"
+	bool "Support for the MIPS SIMD Architecture (EXPERIMENTAL)"
 	depends on CPU_SUPPORTS_MSA
 	depends on 64BIT || MIPS_O32_FP64_SUPPORT
-	default y
 	help
 	  MIPS SIMD Architecture (MSA) introduces 128 bit wide vector registers
 	  and a set of SIMD instructions to operate on them. When this option
-- 
2.0.1

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

* [PATCH 13/13] MIPS: mark MSA experimental
@ 2014-07-11 15:47   ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-11 15:47 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

In light of the commit 16f77de82f2d (Revert "MIPS: Save/restore MSA
context around signals") the MSA support in the kernel is incomplete.
Until the replacement for the former sigcontext changes is agreed upon
and in tree, mark MSA experimental & disable it by default.

MSA is only implemented by one CPU supported by the kernel, the P5600.
The P5600 is a 32 bit core, and thus MSA can only be used when the
experimental CONFIG_MIPS_O32_FP64_SUPPORT option is enabled. Therefore
MSA is only being used in experimental settings anyway and this change
doesn't actually make any difference beyond clarifying the state of
MSA support.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/Kconfig | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 857a49c..d747273 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2110,10 +2110,9 @@ config CPU_MICROMIPS
 	  microMIPS ISA
 
 config CPU_HAS_MSA
-	bool "Support for the MIPS SIMD Architecture"
+	bool "Support for the MIPS SIMD Architecture (EXPERIMENTAL)"
 	depends on CPU_SUPPORTS_MSA
 	depends on 64BIT || MIPS_O32_FP64_SUPPORT
-	default y
 	help
 	  MIPS SIMD Architecture (MSA) introduces 128 bit wide vector registers
 	  and a set of SIMD instructions to operate on them. When this option
-- 
2.0.1

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

* [PATCH v2 05/13] MIPS: init upper 64b of vector registers when MSA is first used
@ 2014-07-30  7:53     ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-30  7:53 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

When a task first makes use of MSA we need to ensure that the upper
64b of the vector registers are set to some value such that no
information can be leaked to it from the previous task to use MSA
context on the CPU. The architecture formerly specified that these
bits would be cleared to 0 when a scalar FP instructions wrote to the
aliased FP registers, which would have implicitly handled this as the
kernel restored scalar FP context. However more recent versions of the
specification now state that the value of the bits in such cases is
unpredictable. Initialise them explictly to be sure, and set all the
bits to 1 rather than 0 for consistency with the least significant
64b.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
Changes in v2:
  - Handle the case of a task which has formerly used FP, but doesn't
    currently have live FP context & has not formerly used MSA.
  - Initialise to all-1s rather than all-0s for consistency with the
    64b scalar FP registers.
---
 arch/mips/include/asm/asmmacro.h | 20 ++++++++++++++++++++
 arch/mips/include/asm/msa.h      |  1 +
 arch/mips/kernel/r4k_switch.S    |  5 +++++
 arch/mips/kernel/traps.c         | 39 ++++++++++++++++++++++++++++++---------
 4 files changed, 56 insertions(+), 9 deletions(-)

diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 4986bf5..cd9a98b 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -426,4 +426,24 @@
 	ld_d	31, THREAD_FPR31, \thread
 	.endm
 
+	.macro	msa_init_upper wd
+#ifdef CONFIG_64BIT
+	insert_d \wd, 1
+#else
+	insert_w \wd, 2
+	insert_w \wd, 3
+#endif
+	.if	31-\wd
+	msa_init_upper	(\wd+1)
+	.endif
+	.endm
+
+	.macro	msa_init_all_upper
+	.set	push
+	.set	noat
+	not	$1, zero
+	msa_init_upper	0
+	.set	pop
+	.endm
+
 #endif /* _ASM_ASMMACRO_H */
diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h
index e80e85c..fe25a17 100644
--- a/arch/mips/include/asm/msa.h
+++ b/arch/mips/include/asm/msa.h
@@ -16,6 +16,7 @@
 
 extern void _save_msa(struct task_struct *);
 extern void _restore_msa(struct task_struct *);
+extern void _init_msa_upper(void);
 
 static inline void enable_msa(void)
 {
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 1a1aef0..4c4ec18 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -144,6 +144,11 @@ LEAF(_restore_msa)
 	jr	ra
 	END(_restore_msa)
 
+LEAF(_init_msa_upper)
+	msa_init_all_upper
+	jr	ra
+	END(_init_msa_upper)
+
 #endif
 
 /*
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 4792fd7..4aca484 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1088,13 +1088,15 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action,
 
 static int enable_restore_fp_context(int msa)
 {
-	int err, was_fpu_owner;
+	int err, was_fpu_owner, prior_msa;
 
 	if (!used_math()) {
 		/* First time FP context user. */
 		err = init_fpu();
-		if (msa && !err)
+		if (msa && !err) {
 			enable_msa();
+			_init_msa_upper();
+		}
 		if (!err)
 			set_used_math();
 		return err;
@@ -1146,18 +1148,37 @@ static int enable_restore_fp_context(int msa)
 	/*
 	 * If this is the first time that the task is using MSA and it has
 	 * previously used scalar FP in this time slice then we already nave
-	 * FP context which we shouldn't clobber.
+	 * FP context which we shouldn't clobber. We do however need to clear
+	 * the upper 64b of each vector register so that this task has no
+	 * opportunity to see data left behind by another.
 	 */
-	if (!test_and_set_thread_flag(TIF_MSA_CTX_LIVE) && was_fpu_owner)
+	prior_msa = test_and_set_thread_flag(TIF_MSA_CTX_LIVE);
+	if (!prior_msa && was_fpu_owner) {
+		_init_msa_upper();
 		return 0;
+	}
 
-	/* We need to restore the vector context. */
-	restore_msa(current);
+	if (!prior_msa) {
+		/*
+		 * Restore the least significant 64b of each vector register
+		 * from the existing scalar FP context.
+		 */
+		_restore_fp(current);
 
-	/* Restore the scalar FP control & status register */
-	if (!was_fpu_owner)
-		asm volatile("ctc1 %0, $31" : : "r"(current->thread.fpu.fcr31));
+		/*
+		 * The task has not formerly used MSA, so clear the upper 64b
+		 * of each vector register such that it cannot see data left
+		 * behind by another task.
+		 */
+		_init_msa_upper();
+	} else {
+		/* We need to restore the vector context. */
+		restore_msa(current);
 
+		/* Restore the scalar FP control & status register */
+		if (!was_fpu_owner)
+			asm volatile("ctc1 %0, $31" : : "r"(current->thread.fpu.fcr31));
+	}
 	return 0;
 }
 
-- 
2.0.2

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

* [PATCH v2 05/13] MIPS: init upper 64b of vector registers when MSA is first used
@ 2014-07-30  7:53     ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-30  7:53 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

When a task first makes use of MSA we need to ensure that the upper
64b of the vector registers are set to some value such that no
information can be leaked to it from the previous task to use MSA
context on the CPU. The architecture formerly specified that these
bits would be cleared to 0 when a scalar FP instructions wrote to the
aliased FP registers, which would have implicitly handled this as the
kernel restored scalar FP context. However more recent versions of the
specification now state that the value of the bits in such cases is
unpredictable. Initialise them explictly to be sure, and set all the
bits to 1 rather than 0 for consistency with the least significant
64b.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
Changes in v2:
  - Handle the case of a task which has formerly used FP, but doesn't
    currently have live FP context & has not formerly used MSA.
  - Initialise to all-1s rather than all-0s for consistency with the
    64b scalar FP registers.
---
 arch/mips/include/asm/asmmacro.h | 20 ++++++++++++++++++++
 arch/mips/include/asm/msa.h      |  1 +
 arch/mips/kernel/r4k_switch.S    |  5 +++++
 arch/mips/kernel/traps.c         | 39 ++++++++++++++++++++++++++++++---------
 4 files changed, 56 insertions(+), 9 deletions(-)

diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 4986bf5..cd9a98b 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -426,4 +426,24 @@
 	ld_d	31, THREAD_FPR31, \thread
 	.endm
 
+	.macro	msa_init_upper wd
+#ifdef CONFIG_64BIT
+	insert_d \wd, 1
+#else
+	insert_w \wd, 2
+	insert_w \wd, 3
+#endif
+	.if	31-\wd
+	msa_init_upper	(\wd+1)
+	.endif
+	.endm
+
+	.macro	msa_init_all_upper
+	.set	push
+	.set	noat
+	not	$1, zero
+	msa_init_upper	0
+	.set	pop
+	.endm
+
 #endif /* _ASM_ASMMACRO_H */
diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h
index e80e85c..fe25a17 100644
--- a/arch/mips/include/asm/msa.h
+++ b/arch/mips/include/asm/msa.h
@@ -16,6 +16,7 @@
 
 extern void _save_msa(struct task_struct *);
 extern void _restore_msa(struct task_struct *);
+extern void _init_msa_upper(void);
 
 static inline void enable_msa(void)
 {
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 1a1aef0..4c4ec18 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -144,6 +144,11 @@ LEAF(_restore_msa)
 	jr	ra
 	END(_restore_msa)
 
+LEAF(_init_msa_upper)
+	msa_init_all_upper
+	jr	ra
+	END(_init_msa_upper)
+
 #endif
 
 /*
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 4792fd7..4aca484 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1088,13 +1088,15 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action,
 
 static int enable_restore_fp_context(int msa)
 {
-	int err, was_fpu_owner;
+	int err, was_fpu_owner, prior_msa;
 
 	if (!used_math()) {
 		/* First time FP context user. */
 		err = init_fpu();
-		if (msa && !err)
+		if (msa && !err) {
 			enable_msa();
+			_init_msa_upper();
+		}
 		if (!err)
 			set_used_math();
 		return err;
@@ -1146,18 +1148,37 @@ static int enable_restore_fp_context(int msa)
 	/*
 	 * If this is the first time that the task is using MSA and it has
 	 * previously used scalar FP in this time slice then we already nave
-	 * FP context which we shouldn't clobber.
+	 * FP context which we shouldn't clobber. We do however need to clear
+	 * the upper 64b of each vector register so that this task has no
+	 * opportunity to see data left behind by another.
 	 */
-	if (!test_and_set_thread_flag(TIF_MSA_CTX_LIVE) && was_fpu_owner)
+	prior_msa = test_and_set_thread_flag(TIF_MSA_CTX_LIVE);
+	if (!prior_msa && was_fpu_owner) {
+		_init_msa_upper();
 		return 0;
+	}
 
-	/* We need to restore the vector context. */
-	restore_msa(current);
+	if (!prior_msa) {
+		/*
+		 * Restore the least significant 64b of each vector register
+		 * from the existing scalar FP context.
+		 */
+		_restore_fp(current);
 
-	/* Restore the scalar FP control & status register */
-	if (!was_fpu_owner)
-		asm volatile("ctc1 %0, $31" : : "r"(current->thread.fpu.fcr31));
+		/*
+		 * The task has not formerly used MSA, so clear the upper 64b
+		 * of each vector register such that it cannot see data left
+		 * behind by another task.
+		 */
+		_init_msa_upper();
+	} else {
+		/* We need to restore the vector context. */
+		restore_msa(current);
 
+		/* Restore the scalar FP control & status register */
+		if (!was_fpu_owner)
+			asm volatile("ctc1 %0, $31" : : "r"(current->thread.fpu.fcr31));
+	}
 	return 0;
 }
 
-- 
2.0.2

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

* [PATCH v2 06/13] MIPS: fix MSA context for tasks which don't use FP first
@ 2014-07-31 13:53     ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-31 13:53 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

If a task does not execute scalar FP instructions prior to using MSA
then the flags indicating that the task has live MSA context were not
being set. The upper 64b of each vector register would then be lost
upon the tasks first context switch after using MSA.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
Changes in v2:
  - Rebase atop v2 of patch 5 as requested by Ralf.
---
 arch/mips/kernel/traps.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 4aca484..00f3143 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1096,6 +1096,8 @@ static int enable_restore_fp_context(int msa)
 		if (msa && !err) {
 			enable_msa();
 			_init_msa_upper();
+			set_thread_flag(TIF_USEDMSA);
+			set_thread_flag(TIF_MSA_CTX_LIVE);
 		}
 		if (!err)
 			set_used_math();
-- 
2.0.2

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

* [PATCH v2 06/13] MIPS: fix MSA context for tasks which don't use FP first
@ 2014-07-31 13:53     ` Paul Burton
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Burton @ 2014-07-31 13:53 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

If a task does not execute scalar FP instructions prior to using MSA
then the flags indicating that the task has live MSA context were not
being set. The upper 64b of each vector register would then be lost
upon the tasks first context switch after using MSA.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
Changes in v2:
  - Rebase atop v2 of patch 5 as requested by Ralf.
---
 arch/mips/kernel/traps.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 4aca484..00f3143 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1096,6 +1096,8 @@ static int enable_restore_fp_context(int msa)
 		if (msa && !err) {
 			enable_msa();
 			_init_msa_upper();
+			set_thread_flag(TIF_USEDMSA);
+			set_thread_flag(TIF_MSA_CTX_LIVE);
 		}
 		if (!err)
 			set_used_math();
-- 
2.0.2

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

end of thread, other threads:[~2014-07-31 13:54 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-11 15:44 [PATCH 00/13] MSA fixes Paul Burton
2014-07-11 15:44 ` Paul Burton
2014-07-11 15:44 ` [PATCH 01/13] MIPS: allow msa.h to be included in assembly files Paul Burton
2014-07-11 15:44   ` Paul Burton
2014-07-11 15:44 ` [PATCH 02/13] MIPS: save/restore MSACSR register on context switch Paul Burton
2014-07-11 15:44   ` Paul Burton
2014-07-11 15:44 ` [PATCH 03/13] MIPS: preserve scalar FP CSR when switching vector context Paul Burton
2014-07-11 15:44   ` Paul Burton
2014-07-11 15:44 ` [PATCH 04/13] MIPS: save/disable MSA in lose_fpu Paul Burton
2014-07-11 15:44   ` Paul Burton
2014-07-11 15:44 ` [PATCH 05/13] MIPS: clear upper 64b of vector registers when MSA is first used Paul Burton
2014-07-11 15:44   ` Paul Burton
2014-07-30  7:53   ` [PATCH v2 05/13] MIPS: init " Paul Burton
2014-07-30  7:53     ` Paul Burton
2014-07-11 15:44 ` [PATCH 06/13] MIPS: fix MSA context for tasks which don't use FP first Paul Burton
2014-07-11 15:44   ` Paul Burton
2014-07-31 13:53   ` [PATCH v2 " Paul Burton
2014-07-31 13:53     ` Paul Burton
2014-07-11 15:44 ` [PATCH 07/13] MIPS: fix read_msa_* & write_msa_* functions on non-MSA toolchains Paul Burton
2014-07-11 15:44   ` Paul Burton
2014-07-11 15:44 ` [PATCH 08/13] MIPS: ensure MSA gets disabled during boot Paul Burton
2014-07-11 15:44   ` Paul Burton
2014-07-11 15:44 ` [PATCH 09/13] MIPS: disable preemption whilst initialising MSA Paul Burton
2014-07-11 15:44   ` Paul Burton
2014-07-11 15:46 ` [PATCH 10/13] MIPS: 16 byte align MSA vector context Paul Burton
2014-07-11 15:46   ` Paul Burton
2014-07-11 15:47 ` [PATCH 11/13] MIPS: consistently clear MSA flags when starting & copying threads Paul Burton
2014-07-11 15:47   ` Paul Burton
2014-07-11 15:47 ` [PATCH 12/13] MIPS: don't build MSA support unless it can be used Paul Burton
2014-07-11 15:47   ` Paul Burton
2014-07-11 15:47 ` [PATCH 13/13] MIPS: mark MSA experimental Paul Burton
2014-07-11 15:47   ` Paul Burton

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.