[PATCH 05/13] MIPS: clear upper 64b of vector registers when MSA is first used

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>
---
 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



[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux