s390: Remove VLAIS in ptff() and clear_table()
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>
Tue, 29 Nov 2016 12:52:01 +0000 (13:52 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 7 Dec 2016 06:22:30 +0000 (07:22 +0100)
The ptff() and clear_table() functions use the gcc extension "variable
length arrays in structures" (VLAIS) to define in the inline assembler
constraints the area of the clobbered memory. This extension will most
likely never be supported by LLVM/Clang.

Since currently BPF programs are compiled with LLVM, this leads to the
following compile errors:

 $ cd samples/bpf
 $ make

 In file included from /root/linux-master/samples/bpf/tracex1_kern.c:8:
 In file included from ./include/linux/netdevice.h:44:
 ...
 In file included from ./arch/s390/include/asm/mmu_context.h:10:
  ./arch/s390/include/asm/pgalloc.h:30:24: error: fields must have a
  constant size: 'variable length array in structure' extension will never
  be supported
         typedef struct { char _[n]; } addrtype;

 In file included from /root/linux-master/samples/bpf/tracex1_kern.c:7:
 In file included from ./include/linux/skbuff.h:18:
 ...
 In file included from ./include/linux/jiffies.h:8:
 In file included from ./include/linux/timex.h:65:
  ./arch/s390/include/asm/timex.h:105:24: error: fields must have a
  constant size: 'variable length array in structure' extension will never
  be supported
        typedef struct { char _[len]; } addrtype;

To fix this do the following:

 - Convert ptff() into a macro that then uses a fixed size array
   when expanded.
 - Convert the clear_table() function and use an inline assembly
   with fixed size array in a loop.
   The runtime performance of the new version is even better than
   the old version (tested with EC12/z13 and gcc 4.8.5/6.2.1 with
   "-march=z196 -O2").

Reported-by: Zvonko Kosic <zvonko.kosic@de.ibm.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/pgalloc.h
arch/s390/include/asm/timex.h

index f4eb9843eed4a6bfc399bacfd2ab5f325b9b743f..166f703dad7c4f0459ddf60825373962189342da 100644 (file)
@@ -27,17 +27,17 @@ extern int page_table_allocate_pgste;
 
 static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
 {
-       typedef struct { char _[n]; } addrtype;
-
-       *s = val;
-       n = (n / 256) - 1;
-       asm volatile(
-               "       mvc     8(248,%0),0(%0)\n"
-               "0:     mvc     256(256,%0),0(%0)\n"
-               "       la      %0,256(%0)\n"
-               "       brct    %1,0b\n"
-               : "+a" (s), "+d" (n), "=m" (*(addrtype *) s)
-               : "m" (*(addrtype *) s));
+       struct addrtype { char _[256]; };
+       int i;
+
+       for (i = 0; i < n; i += 256) {
+               *s = val;
+               asm volatile(
+                       "mvc    8(248,%[s]),0(%[s])\n"
+                       : "+m" (*(struct addrtype *) s)
+                       : [s] "a" (s));
+               s += 256 / sizeof(long);
+       }
 }
 
 static inline void crst_table_init(unsigned long *crst, unsigned long entry)
index b62d8c4ec022e64f0fd53786ef789536e197a0f3..de829880072245585895846e1dfed1731e66663c 100644 (file)
@@ -98,21 +98,28 @@ struct ptff_qui {
        unsigned int pad_0x5c[41];
 } __packed;
 
-static inline int ptff(void *ptff_block, size_t len, unsigned int func)
-{
-       typedef struct { char _[len]; } addrtype;
-       register unsigned int reg0 asm("0") = func;
-       register unsigned long reg1 asm("1") = (unsigned long) ptff_block;
-       int rc;
-
-       asm volatile(
-               "       .word   0x0104\n"
-               "       ipm     %0\n"
-               "       srl     %0,28\n"
-               : "=d" (rc), "+m" (*(addrtype *) ptff_block)
-               : "d" (reg0), "d" (reg1) : "cc");
-       return rc;
-}
+/*
+ * ptff - Perform timing facility function
+ * @ptff_block: Pointer to ptff parameter block
+ * @len: Length of parameter block
+ * @func: Function code
+ * Returns: Condition code (0 on success)
+ */
+#define ptff(ptff_block, len, func)                                    \
+({                                                                     \
+       struct addrtype { char _[len]; };                               \
+       register unsigned int reg0 asm("0") = func;                     \
+       register unsigned long reg1 asm("1") = (unsigned long) (ptff_block);\
+       int rc;                                                         \
+                                                                       \
+       asm volatile(                                                   \
+               "       .word   0x0104\n"                               \
+               "       ipm     %0\n"                                   \
+               "       srl     %0,28\n"                                \
+               : "=d" (rc), "+m" (*(struct addrtype *) reg1)           \
+               : "d" (reg0), "d" (reg1) : "cc");                       \
+       rc;                                                             \
+})
 
 static inline unsigned long long local_tick_disable(void)
 {