From d7c5e41387dc81c7b1011e4c3cf2ad8b92a9dabf Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 27 Jan 2014 17:14:47 +0000 Subject: [PATCH] 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 Cc: linux-mips@linux-mips.org Cc: sergei.shtylyov@cogentembedded.com Patchwork: https://patchwork.linux-mips.org/patch/6435/ Signed-off-by: Ralf Baechle --- arch/mips/math-emu/cp1emu.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 196cf1ab65afc..71a697c9d385b 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) -- 2.39.5