s390/sysinfo: convert bogomips calculation to C
authorHeiko Carstens <hca@linux.ibm.com>
Sat, 3 Feb 2024 10:45:25 +0000 (11:45 +0100)
committerHeiko Carstens <hca@linux.ibm.com>
Fri, 16 Feb 2024 13:30:17 +0000 (14:30 +0100)
Provide several one instruction fpu inline assemebles and use them to
implement the bogomips calculation in C like style. This is more for
illustration purposes on how kernel fpu code can be written in C.

This has the advantage that the author only has to take care of the
floating point instructions, but doesn't need to take care of general
purpose register allocation (if needed), and the semantics of all other
instructions not related to fpu.

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

index 028d285701705caf817b8d10c683b16b71b54d5a..bbf782a2965d4669aca54af38b5e6b5933a606fc 100644 (file)
@@ -36,6 +36,33 @@ asm(".include \"asm/fpu-insn-asm.h\"\n");
  * barrier.
  */
 
+static __always_inline void fpu_cefbr(u8 f1, s32 val)
+{
+       asm volatile("cefbr     %[f1],%[val]\n"
+                    :
+                    : [f1] "I" (f1), [val] "d" (val)
+                    : "memory");
+}
+
+static __always_inline unsigned long fpu_cgebr(u8 f2, u8 mode)
+{
+       unsigned long val;
+
+       asm volatile("cgebr     %[val],%[mode],%[f2]\n"
+                    : [val] "=d" (val)
+                    : [f2] "I" (f2), [mode] "I" (mode)
+                    : "memory");
+       return val;
+}
+
+static __always_inline void fpu_debr(u8 f1, u8 f2)
+{
+       asm volatile("debr      %[f1],%[f2]\n"
+                    :
+                    : [f1] "I" (f1), [f2] "I" (f2)
+                    : "memory");
+}
+
 static __always_inline void fpu_ld(unsigned short fpr, freg_t *reg)
 {
        instrument_read(reg, sizeof(*reg));
@@ -45,6 +72,14 @@ static __always_inline void fpu_ld(unsigned short fpr, freg_t *reg)
                     : "memory");
 }
 
+static __always_inline void fpu_ldgr(u8 f1, u32 val)
+{
+       asm volatile("ldgr      %[f1],%[val]\n"
+                    :
+                    : [f1] "I" (f1), [val] "d" (val)
+                    : "memory");
+}
+
 static __always_inline void fpu_lfpc(unsigned int *fpc)
 {
        instrument_read(fpc, sizeof(*fpc));
index 4cd6428bfab2a497d20c528ac176fc3a69fce1e7..1b1be3110cfc111e71ecf06d2c513700a63b59aa 100644 (file)
@@ -447,21 +447,14 @@ void s390_adjust_jiffies(void)
                 * point division ..
                 */
                kernel_fpu_begin(&fpu, KERNEL_FPR);
-               asm volatile(
-                       "       sfpc    %3\n"
-                       "       l       %0,%1\n"
-                       "       tmlh    %0,0xff80\n"
-                       "       jnz     0f\n"
-                       "       cefbr   %%f2,%0\n"
-                       "       j       1f\n"
-                       "0:     le      %%f2,%1\n"
-                       "1:     cefbr   %%f0,%2\n"
-                       "       debr    %%f0,%%f2\n"
-                       "       cgebr   %0,5,%%f0\n"
-                       : "=&d" (capability)
-                       : "Q" (info->capability), "d" (10000000), "d" (0)
-                       : "cc"
-                       );
+               fpu_sfpc(0);
+               if (info->capability & 0xff800000)
+                       fpu_ldgr(2, info->capability);
+               else
+                       fpu_cefbr(2, info->capability);
+               fpu_cefbr(0, 10000000);
+               fpu_debr(0, 2);
+               capability = fpu_cgebr(0, 5);
                kernel_fpu_end(&fpu, KERNEL_FPR);
        } else
                /*