Commit ef1c47af authored by Paul Burton's avatar Paul Burton Committed by Ralf Baechle

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: default avatarPaul 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: default avatarRalf Baechle <ralf@linux-mips.org>
parent 6bbfd65e
...@@ -884,20 +884,35 @@ static inline int cop1_64bit(struct pt_regs *xcp) ...@@ -884,20 +884,35 @@ static inline int cop1_64bit(struct pt_regs *xcp)
} while (0) } while (0)
#define SITOREG(si, x) do { \ #define SITOREG(si, x) do { \
if (cop1_64bit(xcp)) \ if (cop1_64bit(xcp)) { \
unsigned i; \
set_fpr32(&ctx->fpr[x], 0, si); \ 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); \ set_fpr32(&ctx->fpr[(x) & ~1], (x) & 1, si); \
} \
} while (0) } while (0)
#define SIFROMHREG(si, x) ((si) = get_fpr32(&ctx->fpr[x], 1)) #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) \ #define DIFROMREG(di, x) \
((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0)) ((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0))
#define DITOREG(di, x) \ #define DITOREG(di, x) do { \
set_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0, di) 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 SPFROMREG(sp, x) SIFROMREG((sp).bits, x)
#define SPTOREG(sp, x) SITOREG((sp).bits, x) #define SPTOREG(sp, x) SITOREG((sp).bits, x)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment