diff options
-rw-r--r-- | arch/s390/include/asm/fpu-insn.h | 22 | ||||
-rw-r--r-- | arch/s390/kernel/fpu.c | 2 |
2 files changed, 15 insertions, 9 deletions
diff --git a/arch/s390/include/asm/fpu-insn.h b/arch/s390/include/asm/fpu-insn.h index ccdaacdeaa97..64ba3d9bcd14 100644 --- a/arch/s390/include/asm/fpu-insn.h +++ b/arch/s390/include/asm/fpu-insn.h @@ -11,6 +11,7 @@ #ifndef __ASSEMBLY__ +#include <linux/instrumented.h> #include <asm/asm-extable.h> asm(".include \"asm/fpu-insn-asm.h\"\n"); @@ -36,26 +37,31 @@ asm(".include \"asm/fpu-insn-asm.h\"\n"); */ /** - * sfpc_safe - Set floating point control register safely. + * fpu_lfpc_safe - Load floating point control register safely. * @fpc: new value for floating point control register * - * Set floating point control register. This may lead to an exception, + * Load floating point control register. This may lead to an exception, * since a saved value may have been modified by user space (ptrace, * signal return, kvm registers) to an invalid value. In such a case * set the floating point control register to zero. */ -static inline void sfpc_safe(u32 fpc) +static inline void fpu_lfpc_safe(unsigned int *fpc) { + u32 tmp; + + instrument_read(fpc, sizeof(*fpc)); asm volatile("\n" - "0: sfpc %[fpc]\n" + "0: lfpc %[fpc]\n" "1: nopr %%r7\n" ".pushsection .fixup, \"ax\"\n" - "2: lghi %[fpc],0\n" - " jg 0b\n" + "2: lghi %[tmp],0\n" + " sfpc %[tmp]\n" + " jg 1b\n" ".popsection\n" EX_TABLE(1b, 2b) - : [fpc] "+d" (fpc) - : : "memory"); + : [tmp] "=d" (tmp) + : [fpc] "Q" (*fpc) + : "memory"); } #endif /* __ASSEMBLY__ */ diff --git a/arch/s390/kernel/fpu.c b/arch/s390/kernel/fpu.c index 5d6a2339db40..98dc9f593a14 100644 --- a/arch/s390/kernel/fpu.c +++ b/arch/s390/kernel/fpu.c @@ -174,7 +174,7 @@ void __load_fpu_regs(void) unsigned long *regs = current->thread.fpu.regs; struct fpu *state = ¤t->thread.fpu; - sfpc_safe(state->fpc); + fpu_lfpc_safe(&state->fpc); if (likely(cpu_has_vx())) { asm volatile("lgr 1,%0\n" "VLM 0,15,0,1\n" |