summaryrefslogtreecommitdiffstats
path: root/arch/mips/math-emu
diff options
context:
space:
mode:
authorPaul Burton2014-01-27 18:14:47 +0100
committerRalf Baechle2014-03-26 23:09:10 +0100
commitef1c47afc0e1b7cd1b0102e02d3c3a57fe5f16d8 (patch)
tree4a7912f9c445ceb5a6fec92e3257048e507c56c2 /arch/mips/math-emu
parentMIPS: Replace hardcoded 32 with NUM_FPU_REGS in ptrace (diff)
downloadkernel-qcow2-linux-ef1c47afc0e1b7cd1b0102e02d3c3a57fe5f16d8.tar.gz
kernel-qcow2-linux-ef1c47afc0e1b7cd1b0102e02d3c3a57fe5f16d8.tar.xz
kernel-qcow2-linux-ef1c47afc0e1b7cd1b0102e02d3c3a57fe5f16d8.zip
MIPS: Clear upper bits of FP registers on emulator writes
The upper bits of an FP register are architecturally defined as unpredictable following an instructions which only writes the lower bits. The prior behaviour of the kernel is to leave them unmodified. This patch modifies that to clear the upper bits to zero. This is what the MSA architecture reference manual specifies should happen for its wider registers and is still permissible for scalar FP instructions given the bits unpredictability there. Signed-off-by: Paul Burton <paul.burton@imgtec.com> Cc: linux-mips@linux-mips.org Cc: sergei.shtylyov@cogentembedded.com Patchwork: https://patchwork.linux-mips.org/patch/6435/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/math-emu')
-rw-r--r--arch/mips/math-emu/cp1emu.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 196cf1ab65af..71a697c9d385 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -884,20 +884,35 @@ static inline int cop1_64bit(struct pt_regs *xcp)
} while (0)
#define SITOREG(si, x) do { \
- if (cop1_64bit(xcp)) \
+ if (cop1_64bit(xcp)) { \
+ unsigned i; \
set_fpr32(&ctx->fpr[x], 0, si); \
- else \
+ for (i = 1; i < ARRAY_SIZE(ctx->fpr[x].val32); i++) \
+ set_fpr32(&ctx->fpr[x], i, 0); \
+ } else { \
set_fpr32(&ctx->fpr[(x) & ~1], (x) & 1, si); \
+ } \
} while (0)
#define SIFROMHREG(si, x) ((si) = get_fpr32(&ctx->fpr[x], 1))
-#define SITOHREG(si, x) set_fpr32(&ctx->fpr[x], 1, si)
+
+#define SITOHREG(si, x) do { \
+ unsigned i; \
+ set_fpr32(&ctx->fpr[x], 1, si); \
+ for (i = 2; i < ARRAY_SIZE(ctx->fpr[x].val32); i++) \
+ set_fpr32(&ctx->fpr[x], i, 0); \
+} while (0)
#define DIFROMREG(di, x) \
((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0))
-#define DITOREG(di, x) \
- set_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0, di)
+#define DITOREG(di, x) do { \
+ unsigned fpr, i; \
+ fpr = (x) & ~(cop1_64bit(xcp) == 0); \
+ set_fpr64(&ctx->fpr[fpr], 0, di); \
+ for (i = 1; i < ARRAY_SIZE(ctx->fpr[x].val64); i++) \
+ set_fpr64(&ctx->fpr[fpr], i, 0); \
+} while (0)
#define SPFROMREG(sp, x) SIFROMREG((sp).bits, x)
#define SPTOREG(sp, x) SITOREG((sp).bits, x)