s390/fpu: use lfpc instead of sfpc instruction
authorHeiko Carstens <hca@linux.ibm.com>
Sat, 3 Feb 2024 10:45:04 +0000 (11:45 +0100)
committerHeiko Carstens <hca@linux.ibm.com>
Fri, 16 Feb 2024 13:30:14 +0000 (14:30 +0100)
The only user of sfpc_safe() needs to read the new fpc register value
from memory before it is set with sfpc.

Avoid this indirection and use lfpc, which reads the new value from
memory. Also add the "fpu_" prefix to have a common name space for fpu
related inline assemblies, and provide memory access instrumentation.

Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
arch/s390/include/asm/fpu-insn.h
arch/s390/kernel/fpu.c

index ccdaacdeaa972329354b4ac74dff637f8388d3de..64ba3d9bcd14408725407ff953aef5db577a7b80 100644 (file)
@@ -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__ */
index 5d6a2339db40fb8fdf60ca82059297c145c46470..98dc9f593a1464c1ce481e8b49d81ed0e3b54512 100644 (file)
@@ -174,7 +174,7 @@ void __load_fpu_regs(void)
        unsigned long *regs = current->thread.fpu.regs;
        struct fpu *state = &current->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"