Skip to contentSkip to conversation

bitops: add parity functions

PATCH In review Zeng Zhaoxiu 17 participants 88 messages Apr 5, 2016 – May 18, 2016

Subsystems (33)
lore
Share & tools
lore
#0 lore raw

PATCH v2 1/30 bitops: add parity functions

From: Zhaoxiu Zeng <[email protected]>

These patches provide generic and architecture-specific odd parity calculations.

I did not use GCC's __builtin_parity* functions, based on the following reasons:
1. I don't know where to identify which version of GCC from the beginning supported __builtin_parity for the architecture.
2. For the architectures that doesn't have popcount instruction, GCC
instead use

     "call __paritysi2" (__paritydi2 for 64-bits). So if use 

__builtin_parity, we must
provide __paritysi2 and __paritydi2 functions for these architectures. Additionally, parity4,8,16 might be "__builtin_parity(x & mask)",
but the "& mask"
operation is totally unnecessary.
3. For the architectures that have popcount instruction, we do the
same things.
4. For powerpc, sparc, and x86, we do runtime patching to use
popcount instruction
if the CPU support.

I have compiled successfully with x86_64_defconfig, i386_defconfig, pseries_defconfig and sparc64_defconfig. And I used the following codes to test:

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>

    #ifdef __x86_64__
    /* popcnt %edi, %eax -- redundant REX prefix for alignment */
    #define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7"
    /* popcnt %rdi, %rax */
    #define POPCNT64 ".byte 0xf3,0x48,0x0f,0xb8,0xc7"
    #define REG_IN "D"
    #define REG_OUT "a"
    #else
    /* popcnt %eax, %eax */
    #define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc0"
    #define REG_IN "a"
    #define REG_OUT "a"
    #endif

    static inline int c_parity4(unsigned int w)
    {
        w &= 0xf;
        return (0x6996 >> w) & 1;
    }

    static inline int c_parity8(unsigned int w)
    {
        w ^= w >> 4;
        return c_parity4(w);
    }

    static inline int c_parity16(unsigned int w)
    {
        w ^= w >> 8;
        return c_parity8(w);
    }

    static inline int c_parity32(unsigned int w)
    {
        w ^= w >> 16;
        return c_parity16(w);
    }

    static inline int c_parity64(uint64_t w)
    {
        return c_parity32((unsigned int)w ^ (unsigned int)(w >> 32));
    }

    static inline int asm_parity4(unsigned int w)
    {
        unsigned int res = 0;

        asm("test    $0xf, %1        \n"
            "setpo    %b0                \n"
            : "+q" (res)
            : "r" (w)
            : "cc");

        return res;
    }

    static inline int asm_parity8(unsigned int w)
    {
        unsigned int res = 0;

        asm("test    %1, %1            \n"
            "setpo    %b0            \n"
            : "+q" (res)
            : "r" (w)
            : "cc");

        return res;
    }

    static inline int asm_parity16(unsigned int w)
    {
        unsigned int res = 0;

        asm("xor    %h1, %b1        \n"
            "setpo    %b0            \n"
            : "+q" (res), "+q" (w)
            : : "cc");

        return res;
    }

    static inline int asm_parity32_1(unsigned int w)
    {
        unsigned int res;

        w ^= w >> 16;
        asm("xor    %%ah, %%al        \n"
            "mov    $0, %%eax        \n"
            "setpo    %%al            \n"
            : "=a" (res)
            : "a" (w)
            : "cc");

        return res;
    }

    static inline int asm_parity32_2(unsigned int w)
    {
        unsigned int res;

        asm(POPCNT32 "                \n"
            "andl    $1, %0            \n"
            : "="REG_OUT (res)
            : REG_IN (w)
            : "cc");

        return res;
    }

    #ifdef __x86_64__
    static inline int asm_parity64_1(uint64_t w)
    {
        unsigned int res = (unsigned int)w ^ (unsigned int)(w >> 32);

        res ^= res >> 16;
        asm("xor    %%ah, %%al        \n"
            "mov    $0, %%eax        \n"
            "setpo    %%al            \n"
            : "=a" (res)
            : "a" (res)
            : "cc");

        return res;
    }

    static inline int asm_parity64_2(uint64_t w)
    {
        unsigned int res;

        asm(POPCNT64 "                \n"
            "andl    $1, %0            \n"
            : "="REG_OUT (res)
            : REG_IN (w)
            : "cc");

        return res;
    }
    #else
    static inline int asm_parity64_1(uint64_t w)
    {
        return asm_parity32_1((unsigned int)(w >> 32) ^ (unsigned int)w);
    }

    static inline int asm_parity64_2(uint64_t w)
    {
        return asm_parity32_2((unsigned int)(w >> 32) ^ (unsigned int)w);
    }
    #endif

    int main(int argc, char **argv)
    {
        int ok = 1;
        int count = 1000, i;

        if (argc >= 2)
            count = atoi(argv[1]);

        srand((unsigned)time(NULL));

        for (i = 0; i < count; i++) {
            uint64_t w = rand() | (uint64_t)rand() << 32;
            int p4_1 = c_parity4(w);
            int p4_2 = asm_parity4(w);
            int p8_1 = c_parity8(w);
            int p8_2 = asm_parity8(w);
            int p16_1 = c_parity16(w);
            int p16_2 = asm_parity16(w);
            int p32_1 = c_parity32(w);
            int p32_2 = asm_parity32_1(w);
            int p32_3 = asm_parity32_2(w);
            int p64_1 = c_parity64(w);
            int p64_2 = asm_parity64_1(w);
            int p64_3 = asm_parity64_2(w);
            if (p4_1 != p4_2 ||
                p8_1 != p8_2 ||
                p16_1 != p16_2 ||
                p32_1 != p32_2 || p32_1 != p32_3 ||
                p64_1 != p64_2 || p64_1 != p64_3) {
                fprintf(stderr, "Err: %llx\n"
                            "\tc_parity4 = %d, asm_parity4 = %d,\n"
                            "\tc_parity8 = %d, asm_parity8 = %d,\n"
                            "\tc_parity16 = %d, asm_parity16 = %d,\n"
                            "\tc_parity32 = %d, asm_parity32_1 = %d, 
asm_parity32_2 = %d\n"
                            "\tc_parity64 = %d, asm_parity64_1 = %d, 
asm_parity64_2 = %d\n",
                            w, p4_1, p4_2, p8_1, p8_2, p16_1, p16_2, 
p32_1, p32_2, p32_3, p64_1, p64_2, p64_3);
                ok = 0;
            }
        }

        fprintf(stderr, "%s\n", ok ? "OK" : "FAIL");
        return 0;
    }
---
 include/asm-generic/bitops.h              |  1 +
 include/asm-generic/bitops/arch_parity.h  | 39 
+++++++++++++++++++++++++++++++
 include/asm-generic/bitops/const_parity.h | 36 
++++++++++++++++++++++++++++
 include/asm-generic/bitops/parity.h       |  7 ++++++
 include/linux/bitops.h                    |  5 ++++
 5 files changed, 88 insertions(+)
 create mode 100644 include/asm-generic/bitops/arch_parity.h
 create mode 100644 include/asm-generic/bitops/const_parity.h
 create mode 100644 include/asm-generic/bitops/parity.h
include/asm-generic/bitops.h +1 -0
index dcdcacf..d85722f 100644
@@ -27,6 +27,7 @@
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/ffs.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/atomic.h>
include/asm-generic/bitops/arch_parity.h new file +39 -0
new file mode 100644
index 0000000..cddc555
@@ -0,0 +1,39 @@
+#ifndef _ASM_GENERIC_BITOPS_ARCH_PARITY_H_
+#define _ASM_GENERIC_BITOPS_ARCH_PARITY_H_
+
+#include <asm/types.h>
+
+/*
+ * Refrence to 'https://graphics.stanford.edu/~seander/bithacks.html#ParityParallel'.
+ */
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+    w &= 0xf;
+    return (0x6996 >> w) & 1;
+}
+
+static inline unsigned int __arch_parity8(unsigned int w)
+{
+    w ^= w >> 4;
+    return __arch_parity4(w);
+}
+
+static inline unsigned int __arch_parity16(unsigned int w)
+{
+    w ^= w >> 8;
+    return __arch_parity8(w);
+}
+
+static inline unsigned int __arch_parity32(unsigned int w)
+{
+    w ^= w >> 16;
+    return __arch_parity16(w);
+}
+
+static inline unsigned int __arch_parity64(__u64 w)
+{
+    return __arch_parity32((unsigned int)(w >> 32) ^ (unsigned int)w);
+}
+
+#endif /* _ASM_GENERIC_BITOPS_ARCH_PARITY_H_ */
include/asm-generic/bitops/const_parity.h new file +36 -0
new file mode 100644
index 0000000..6af7987
@@ -0,0 +1,36 @@
+#ifndef _ASM_GENERIC_BITOPS_CONST_PARITY_H_
+#define _ASM_GENERIC_BITOPS_CONST_PARITY_H_
+
+/*
+ * Compile time versions of __arch_parityN()
+ */
+#define __const_parity4(w)   ((0x6996 >> ((w) & 0xf)) & 1)
+#define __const_parity8(w)   (__const_parity4((w) ^ ((w) >> 4)))
+#define __const_parity16(w)  (__const_parity8((w) ^ ((w) >> 8)))
+#define __const_parity32(w)  (__const_parity16((w) ^ ((w) >> 16)))
+#define __const_parity64(w)  (__const_parity32((w) ^ ((w) >> 32)))
+
+/*
+ * Generic interface.
+ */
+#define parity4(w)   (__builtin_constant_p(w) ? __const_parity4(w) : __arch_parity4(w))
+#define parity8(w)   (__builtin_constant_p(w) ? __const_parity8(w) : __arch_parity8(w))
+#define parity16(w)  (__builtin_constant_p(w) ? __const_parity16(w) : __arch_parity16(w))
+#define parity32(w)  (__builtin_constant_p(w) ? __const_parity32(w) : __arch_parity32(w))
+#define parity64(w)  (__builtin_constant_p(w) ? __const_parity64(w) : __arch_parity64(w))
+
+/*
+ * Interface for known constant arguments
+ */
+#define PARITY4(w)   (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity4(w))
+#define PARITY8(w)   (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity8(w))
+#define PARITY16(w)  (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity16(w))
+#define PARITY32(w)  (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity32(w))
+#define PARITY64(w)  (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity64(w))
+
+/*
+ * Type invariant interface to the compile time constant parity functions.
+ */
+#define PARITY(w)    PARITY64((u64)(w))
+
+#endif /* _ASM_GENERIC_BITOPS_CONST_PARITY_H_ */
include/asm-generic/bitops/parity.h new file +7 -0
new file mode 100644
index 0000000..a91dce7
@@ -0,0 +1,7 @@
+#ifndef _ASM_GENERIC_BITOPS_PARITY_H_
+#define _ASM_GENERIC_BITOPS_PARITY_H_
+
+#include <asm-generic/bitops/arch_parity.h>
+#include <asm-generic/bitops/const_parity.h>
+
+#endif /* _ASM_GENERIC_BITOPS_PARITY_H_ */
include/linux/bitops.h +5 -0
index defeaac..8952f88 100644
@@ -80,6 +80,11 @@ static __always_inline unsigned long hweight_long(unsigned long w)
     return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
 }
 
+static __always_inline unsigned int parity_long(unsigned long w)
+{
+    return sizeof(w) == 4 ? parity32(w) : parity64(w);
+}
+
 /**
  * rol64 - rotate a 64-bit value left
  * @word: value to rotate
Signature · 1 line
2.5.0
#1 lore raw

PATCH v2 2/30 Include generic parity.h in some architectures' bitops.h

From: Zhaoxiu Zeng <[email protected]>

Use the generic version

---
  arch/arc/include/asm/bitops.h      | 1 +
  arch/arm/include/asm/bitops.h      | 1 +
  arch/arm64/include/asm/bitops.h    | 1 +
  arch/avr32/include/asm/bitops.h    | 1 +
  arch/c6x/include/asm/bitops.h      | 1 +
  arch/cris/include/asm/bitops.h     | 1 +
  arch/frv/include/asm/bitops.h      | 1 +
  arch/h8300/include/asm/bitops.h    | 1 +
  arch/hexagon/include/asm/bitops.h  | 1 +
  arch/m32r/include/asm/bitops.h     | 1 +
  arch/m68k/include/asm/bitops.h     | 1 +
  arch/metag/include/asm/bitops.h    | 1 +
  arch/mn10300/include/asm/bitops.h  | 1 +
  arch/openrisc/include/asm/bitops.h | 1 +
  arch/parisc/include/asm/bitops.h   | 1 +
  arch/s390/include/asm/bitops.h     | 1 +
  arch/sh/include/asm/bitops.h       | 1 +
  arch/xtensa/include/asm/bitops.h   | 1 +
  18 files changed, 18 insertions(+)
arch/arc/include/asm/bitops.h +0 -0
index 0352fb8..7967e47 100644
@@ -370,6 +370,7 @@ static inline __attribute__ ((const)) int 

__ffs(unsigned long x)
#define ffz(x) __ffs(~(x))

#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/lock.h>

arch/arm/include/asm/bitops.h +1 -0
index e943e6c..99f28a6 100644
@@ -313,6 +313,7 @@ static inline unsigned long __ffs(unsigned long x)
 
  #include <asm-generic/bitops/sched.h>
  #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
  #include <asm-generic/bitops/lock.h>
 
  #ifdef __ARMEB__
(quoted diff) +0 -0

b/arch/arm64/include/asm/bitops.h
index 9c19594..eac4965 100644

arch/arm64/include/asm/bitops.h +0 -0
@@ -44,6 +44,7 @@ extern int test_and_change_bit(int nr, volatile 

unsigned long *p);

#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

#include <asm-generic/bitops/non-atomic.h>

(quoted diff) +0 -0

b/arch/avr32/include/asm/bitops.h
index 910d537..9f4a2ce 100644

arch/avr32/include/asm/bitops.h +1 -0
@@ -298,6 +298,7 @@ static inline int ffs(unsigned long word)
  #include <asm-generic/bitops/fls64.h>
  #include <asm-generic/bitops/sched.h>
  #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
  #include <asm-generic/bitops/lock.h>
 
  extern unsigned long find_next_zero_bit_le(const void *addr,
arch/c6x/include/asm/bitops.h +1 -0
index f0ab012..94eb0d1 100644
@@ -87,6 +87,7 @@ static inline int ffs(int x)
 
  #include <asm-generic/bitops/sched.h>
  #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
  #include <asm-generic/bitops/lock.h>
 
  #include <asm-generic/bitops/atomic.h>
arch/cris/include/asm/bitops.h +1 -0
index 8062cb5..06bc246 100644
@@ -36,6 +36,7 @@
  #include <asm-generic/bitops/__fls.h>
  #include <asm-generic/bitops/fls64.h>
  #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
  #include <asm-generic/bitops/find.h>
  #include <asm-generic/bitops/lock.h>
 
arch/frv/include/asm/bitops.h +1 -0
index 0df8e95..f2a7ee8 100644
@@ -314,6 +314,7 @@ int __ilog2_u64(u64 n)
 
  #include <asm-generic/bitops/sched.h>
  #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
  #include <asm-generic/bitops/lock.h>
 
  #include <asm-generic/bitops/le.h>
(quoted diff) +0 -0

b/arch/h8300/include/asm/bitops.h
index 05999ab..e392db2 100644

arch/h8300/include/asm/bitops.h +1 -0
@@ -172,6 +172,7 @@ static inline unsigned long __ffs(unsigned long word)
  #include <asm-generic/bitops/find.h>
  #include <asm-generic/bitops/sched.h>
  #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
  #include <asm-generic/bitops/lock.h>
  #include <asm-generic/bitops/le.h>
  #include <asm-generic/bitops/ext2-atomic.h>
(quoted diff) +0 -0

b/arch/hexagon/include/asm/bitops.h
index 5e4a59b..2df614e 100644

arch/hexagon/include/asm/bitops.h +1 -0
@@ -290,6 +290,7 @@ static inline unsigned long __fls(unsigned long word)
  #include <asm-generic/bitops/fls64.h>
  #include <asm-generic/bitops/sched.h>
  #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 
  #include <asm-generic/bitops/le.h>
  #include <asm-generic/bitops/ext2-atomic.h>
arch/m32r/include/asm/bitops.h +0 -0
index 86ba2b4..e3cf46b 100644
@@ -259,6 +259,7 @@ static __inline__ int test_and_change_bit(int nr, 

volatile void * addr)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

#endif /* __KERNEL__ */

arch/m68k/include/asm/bitops.h +1 -0
index b4a9b0d..fd673ea 100644
@@ -519,6 +519,7 @@ static inline int __fls(int x)
  #include <asm-generic/bitops/fls64.h>
  #include <asm-generic/bitops/sched.h>
  #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
  #include <asm-generic/bitops/lock.h>
  #endif /* __KERNEL__ */
 
(quoted diff) +0 -0

b/arch/metag/include/asm/bitops.h
index 2671134..ad13087 100644

arch/metag/include/asm/bitops.h +1 -0
@@ -118,6 +118,7 @@ static inline int test_and_change_bit(unsigned int bit,
  #include <asm-generic/bitops/__fls.h>
  #include <asm-generic/bitops/fls64.h>
  #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
  #include <asm-generic/bitops/lock.h>
  #include <asm-generic/bitops/sched.h>
  #include <asm-generic/bitops/le.h>
(quoted diff) +0 -0

b/arch/mn10300/include/asm/bitops.h
index fe6f8e2..60761b7 100644

arch/mn10300/include/asm/bitops.h +1 -0
@@ -225,6 +225,7 @@ int ffs(int x)
  #include <asm-generic/bitops/find.h>
  #include <asm-generic/bitops/sched.h>
  #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
  #include <asm-generic/bitops/ext2-atomic-setbit.h>
  #include <asm-generic/bitops/le.h>
 
(quoted diff) +0 -0

b/arch/openrisc/include/asm/bitops.h
index 3003cda..8c97642 100644

arch/openrisc/include/asm/bitops.h +1 -0
@@ -43,6 +43,7 @@
  #include <asm-generic/bitops/sched.h>
  #include <asm/bitops/ffs.h>
  #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
  #include <asm-generic/bitops/lock.h>
 
  #include <asm-generic/bitops/atomic.h>
(quoted diff) +0 -0

b/arch/parisc/include/asm/bitops.h
index 3f9406d..867ba10 100644

arch/parisc/include/asm/bitops.h +1 -0
@@ -211,6 +211,7 @@ static __inline__ int fls(int x)
  #include <asm-generic/bitops/__fls.h>
  #include <asm-generic/bitops/fls64.h>
  #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
  #include <asm-generic/bitops/lock.h>
  #include <asm-generic/bitops/sched.h>
 
arch/s390/include/asm/bitops.h +1 -0
index 8043f10..198eead 100644
@@ -460,6 +460,7 @@ static inline int fls(int word)
  #include <asm-generic/bitops/ffz.h>
  #include <asm-generic/bitops/find.h>
  #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
  #include <asm-generic/bitops/sched.h>
  #include <asm-generic/bitops/le.h>
  #include <asm-generic/bitops/ext2-atomic-setbit.h>
arch/sh/include/asm/bitops.h +1 -0
index fc8e652..4bf0c35 100644
@@ -86,6 +86,7 @@ static inline unsigned long ffz(unsigned long word)
  #include <asm-generic/bitops/find.h>
  #include <asm-generic/bitops/ffs.h>
  #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
  #include <asm-generic/bitops/lock.h>
  #include <asm-generic/bitops/sched.h>
  #include <asm-generic/bitops/le.h>
(quoted diff) +0 -0

b/arch/xtensa/include/asm/bitops.h
index 3f44fa2..981fa83 100644

arch/xtensa/include/asm/bitops.h +0 -0
@@ -229,6 +229,7 @@ test_and_change_bit(unsigned int bit, volatile 

unsigned long *p)
#include <asm-generic/bitops/ext2-atomic-setbit.h>

#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/sched.h>

Signature · 1 line
2.5.0
#2 lore raw

PATCH v2 2/30 Include generic parity.h in some architectures' bitops.h

From: Zhaoxiu Zeng <[email protected]>

Use the generic version

---
 arch/arc/include/asm/bitops.h      | 1 +
 arch/arm/include/asm/bitops.h      | 1 +
 arch/arm64/include/asm/bitops.h    | 1 +
 arch/avr32/include/asm/bitops.h    | 1 +
 arch/c6x/include/asm/bitops.h      | 1 +
 arch/cris/include/asm/bitops.h     | 1 +
 arch/frv/include/asm/bitops.h      | 1 +
 arch/h8300/include/asm/bitops.h    | 1 +
 arch/hexagon/include/asm/bitops.h  | 1 +
 arch/m32r/include/asm/bitops.h     | 1 +
 arch/m68k/include/asm/bitops.h     | 1 +
 arch/metag/include/asm/bitops.h    | 1 +
 arch/mn10300/include/asm/bitops.h  | 1 +
 arch/openrisc/include/asm/bitops.h | 1 +
 arch/parisc/include/asm/bitops.h   | 1 +
 arch/s390/include/asm/bitops.h     | 1 +
 arch/sh/include/asm/bitops.h       | 1 +
 arch/xtensa/include/asm/bitops.h   | 1 +
 18 files changed, 18 insertions(+)
arch/arc/include/asm/bitops.h +1 -0
index 0352fb8..7967e47 100644
@@ -370,6 +370,7 @@ static inline __attribute__ ((const)) int __ffs(unsigned long x)
 #define ffz(x)	__ffs(~(x))
 
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/lock.h>
arch/arm/include/asm/bitops.h +1 -0
index e943e6c..99f28a6 100644
@@ -313,6 +313,7 @@ static inline unsigned long __ffs(unsigned long x)
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #ifdef __ARMEB__
arch/arm64/include/asm/bitops.h +1 -0
index 9c19594..eac4965 100644
@@ -44,6 +44,7 @@ extern int test_and_change_bit(int nr, volatile unsigned long *p);
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/non-atomic.h>
arch/avr32/include/asm/bitops.h +1 -0
index 910d537..9f4a2ce 100644
@@ -298,6 +298,7 @@ static inline int ffs(unsigned long word)
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 extern unsigned long find_next_zero_bit_le(const void *addr,
arch/c6x/include/asm/bitops.h +1 -0
index f0ab012..94eb0d1 100644
@@ -87,6 +87,7 @@ static inline int ffs(int x)
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/atomic.h>
arch/cris/include/asm/bitops.h +1 -0
index 8062cb5..06bc246 100644
@@ -36,6 +36,7 @@
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/lock.h>
 
arch/frv/include/asm/bitops.h +1 -0
index 0df8e95..f2a7ee8 100644
@@ -314,6 +314,7 @@ int __ilog2_u64(u64 n)
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/le.h>
arch/h8300/include/asm/bitops.h +1 -0
index 05999ab..e392db2 100644
@@ -172,6 +172,7 @@ static inline unsigned long __ffs(unsigned long word)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
arch/hexagon/include/asm/bitops.h +1 -0
index 5e4a59b..2df614e 100644
@@ -290,6 +290,7 @@ static inline unsigned long __fls(unsigned long word)
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 
 #include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
arch/m32r/include/asm/bitops.h +1 -0
index 86ba2b4..e3cf46b 100644
@@ -259,6 +259,7 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/ffs.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #endif /* __KERNEL__ */
arch/m68k/include/asm/bitops.h +1 -0
index b4a9b0d..fd673ea 100644
@@ -519,6 +519,7 @@ static inline int __fls(int x)
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #endif /* __KERNEL__ */
 
arch/metag/include/asm/bitops.h +1 -0
index 2671134..ad13087 100644
@@ -118,6 +118,7 @@ static inline int test_and_change_bit(unsigned int bit,
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/le.h>
arch/mn10300/include/asm/bitops.h +1 -0
index fe6f8e2..60761b7 100644
@@ -225,6 +225,7 @@ int ffs(int x)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
 #include <asm-generic/bitops/le.h>
 
arch/openrisc/include/asm/bitops.h +1 -0
index 3003cda..8c97642 100644
@@ -43,6 +43,7 @@
 #include <asm-generic/bitops/sched.h>
 #include <asm/bitops/ffs.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/atomic.h>
arch/parisc/include/asm/bitops.h +1 -0
index 3f9406d..867ba10 100644
@@ -211,6 +211,7 @@ static __inline__ int fls(int x)
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 
arch/s390/include/asm/bitops.h +1 -0
index 8043f10..198eead 100644
@@ -460,6 +460,7 @@ static inline int fls(int word)
 #include <asm-generic/bitops/ffz.h>
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
arch/sh/include/asm/bitops.h +1 -0
index fc8e652..4bf0c35 100644
@@ -86,6 +86,7 @@ static inline unsigned long ffz(unsigned long word)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/ffs.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/le.h>
arch/xtensa/include/asm/bitops.h +1 -0
index 3f44fa2..981fa83 100644
@@ -229,6 +229,7 @@ test_and_change_bit(unsigned int bit, volatile unsigned long *p)
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 
Signature · 1 line
2.5.0
#3 lore raw

PATCH v2 2/30 Include generic parity.h in some architectures' bitops.h

Hi?Zhaoxiu,

Quoted 24 lines · On Wed, 2016-04-06 at 16:41 +0800, zengzhaoxiu at 163.com wrote:

From: Zhaoxiu Zeng <[email protected]>

Use the generic version

---

?arch/arc/include/asm/bitops.h??????| 1 +
?arch/arm/include/asm/bitops.h??????| 1 +
?arch/arm64/include/asm/bitops.h????| 1 +
?arch/avr32/include/asm/bitops.h????| 1 +
?arch/c6x/include/asm/bitops.h??????| 1 +
?arch/cris/include/asm/bitops.h?????| 1 +
?arch/frv/include/asm/bitops.h??????| 1 +
?arch/h8300/include/asm/bitops.h????| 1 +
?arch/hexagon/include/asm/bitops.h??| 1 +
?arch/m32r/include/asm/bitops.h?????| 1 +
?arch/m68k/include/asm/bitops.h?????| 1 +
?arch/metag/include/asm/bitops.h????| 1 +
?arch/mn10300/include/asm/bitops.h??| 1 +
?arch/openrisc/include/asm/bitops.h | 1 +
?arch/parisc/include/asm/bitops.h???| 1 +
?arch/s390/include/asm/bitops.h?????| 1 +
?arch/sh/include/asm/bitops.h???????| 1 +
?arch/xtensa/include/asm/bitops.h???| 1 +
Quoted 1 line

?18 files changed, 18 insertions(+)

Could you please include a changelog below your commit message? Otherwise it's barely possible to understand what that v2 improves/fixes.

Also it makes sense to send at least cover letter to all people mentioned at least in one patch of the series. That gives an idea what this series does and in particular why patch I'm mentioned in is required.

-Alexey

#4 lore raw

PATCH v2 2/30 Include generic parity.h in some architectures' bitops.h

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

Use the generic version

---
 arch/arc/include/asm/bitops.h      | 1 +
 arch/arm/include/asm/bitops.h      | 1 +
 arch/arm64/include/asm/bitops.h    | 1 +
 arch/avr32/include/asm/bitops.h    | 1 +
 arch/c6x/include/asm/bitops.h      | 1 +
 arch/cris/include/asm/bitops.h     | 1 +
 arch/frv/include/asm/bitops.h      | 1 +
 arch/h8300/include/asm/bitops.h    | 1 +
 arch/hexagon/include/asm/bitops.h  | 1 +
 arch/m32r/include/asm/bitops.h     | 1 +
 arch/m68k/include/asm/bitops.h     | 1 +
 arch/metag/include/asm/bitops.h    | 1 +
 arch/mn10300/include/asm/bitops.h  | 1 +
 arch/openrisc/include/asm/bitops.h | 1 +
 arch/parisc/include/asm/bitops.h   | 1 +
 arch/s390/include/asm/bitops.h     | 1 +
 arch/sh/include/asm/bitops.h       | 1 +
 arch/xtensa/include/asm/bitops.h   | 1 +
 18 files changed, 18 insertions(+)
arch/arc/include/asm/bitops.h +1 -0
index 0352fb8..7967e47 100644
@@ -370,6 +370,7 @@ static inline __attribute__ ((const)) int __ffs(unsigned long x)
 #define ffz(x)	__ffs(~(x))
 
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/lock.h>
arch/arm/include/asm/bitops.h +1 -0
index e943e6c..99f28a6 100644
@@ -313,6 +313,7 @@ static inline unsigned long __ffs(unsigned long x)
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #ifdef __ARMEB__
arch/arm64/include/asm/bitops.h +1 -0
index 9c19594..eac4965 100644
@@ -44,6 +44,7 @@ extern int test_and_change_bit(int nr, volatile unsigned long *p);
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/non-atomic.h>
arch/avr32/include/asm/bitops.h +1 -0
index 910d537..9f4a2ce 100644
@@ -298,6 +298,7 @@ static inline int ffs(unsigned long word)
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 extern unsigned long find_next_zero_bit_le(const void *addr,
arch/c6x/include/asm/bitops.h +1 -0
index f0ab012..94eb0d1 100644
@@ -87,6 +87,7 @@ static inline int ffs(int x)
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/atomic.h>
arch/cris/include/asm/bitops.h +1 -0
index 8062cb5..06bc246 100644
@@ -36,6 +36,7 @@
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/lock.h>
 
arch/frv/include/asm/bitops.h +1 -0
index 0df8e95..f2a7ee8 100644
@@ -314,6 +314,7 @@ int __ilog2_u64(u64 n)
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/le.h>
arch/h8300/include/asm/bitops.h +1 -0
index 05999ab..e392db2 100644
@@ -172,6 +172,7 @@ static inline unsigned long __ffs(unsigned long word)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
arch/hexagon/include/asm/bitops.h +1 -0
index 5e4a59b..2df614e 100644
@@ -290,6 +290,7 @@ static inline unsigned long __fls(unsigned long word)
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 
 #include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
arch/m32r/include/asm/bitops.h +1 -0
index 86ba2b4..e3cf46b 100644
@@ -259,6 +259,7 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/ffs.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #endif /* __KERNEL__ */
arch/m68k/include/asm/bitops.h +1 -0
index b4a9b0d..fd673ea 100644
@@ -519,6 +519,7 @@ static inline int __fls(int x)
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #endif /* __KERNEL__ */
 
arch/metag/include/asm/bitops.h +1 -0
index 2671134..ad13087 100644
@@ -118,6 +118,7 @@ static inline int test_and_change_bit(unsigned int bit,
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/le.h>
arch/mn10300/include/asm/bitops.h +1 -0
index fe6f8e2..60761b7 100644
@@ -225,6 +225,7 @@ int ffs(int x)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
 #include <asm-generic/bitops/le.h>
 
arch/openrisc/include/asm/bitops.h +1 -0
index 3003cda..8c97642 100644
@@ -43,6 +43,7 @@
 #include <asm-generic/bitops/sched.h>
 #include <asm/bitops/ffs.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/atomic.h>
arch/parisc/include/asm/bitops.h +1 -0
index 3f9406d..867ba10 100644
@@ -211,6 +211,7 @@ static __inline__ int fls(int x)
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 
arch/s390/include/asm/bitops.h +1 -0
index 8043f10..198eead 100644
@@ -460,6 +460,7 @@ static inline int fls(int word)
 #include <asm-generic/bitops/ffz.h>
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
arch/sh/include/asm/bitops.h +1 -0
index fc8e652..4bf0c35 100644
@@ -86,6 +86,7 @@ static inline unsigned long ffz(unsigned long word)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/ffs.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/le.h>
arch/xtensa/include/asm/bitops.h +1 -0
index 3f44fa2..981fa83 100644
@@ -229,6 +229,7 @@ test_and_change_bit(unsigned int bit, volatile unsigned long *p)
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 
Signature · 1 line
2.5.0
#5 lore raw

PATCH v2 2/30 Include generic parity.h in some architectures' bitops.h

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

Use the generic version

---
 arch/arc/include/asm/bitops.h      | 1 +
 arch/arm/include/asm/bitops.h      | 1 +
 arch/arm64/include/asm/bitops.h    | 1 +
 arch/avr32/include/asm/bitops.h    | 1 +
 arch/c6x/include/asm/bitops.h      | 1 +
 arch/cris/include/asm/bitops.h     | 1 +
 arch/frv/include/asm/bitops.h      | 1 +
 arch/h8300/include/asm/bitops.h    | 1 +
 arch/hexagon/include/asm/bitops.h  | 1 +
 arch/m32r/include/asm/bitops.h     | 1 +
 arch/m68k/include/asm/bitops.h     | 1 +
 arch/metag/include/asm/bitops.h    | 1 +
 arch/mn10300/include/asm/bitops.h  | 1 +
 arch/openrisc/include/asm/bitops.h | 1 +
 arch/parisc/include/asm/bitops.h   | 1 +
 arch/s390/include/asm/bitops.h     | 1 +
 arch/sh/include/asm/bitops.h       | 1 +
 arch/xtensa/include/asm/bitops.h   | 1 +
 18 files changed, 18 insertions(+)
arch/arc/include/asm/bitops.h +1 -0
index 0352fb8..7967e47 100644
@@ -370,6 +370,7 @@ static inline __attribute__ ((const)) int __ffs(unsigned long x)
 #define ffz(x)    __ffs(~(x))
 
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/lock.h>
arch/arm/include/asm/bitops.h +1 -0
index e943e6c..99f28a6 100644
@@ -313,6 +313,7 @@ static inline unsigned long __ffs(unsigned long x)
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #ifdef __ARMEB__
arch/arm64/include/asm/bitops.h +1 -0
index 9c19594..eac4965 100644
@@ -44,6 +44,7 @@ extern int test_and_change_bit(int nr, volatile unsigned long *p);
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/non-atomic.h>
arch/avr32/include/asm/bitops.h +1 -0
index 910d537..9f4a2ce 100644
@@ -298,6 +298,7 @@ static inline int ffs(unsigned long word)
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 extern unsigned long find_next_zero_bit_le(const void *addr,
arch/c6x/include/asm/bitops.h +1 -0
index f0ab012..94eb0d1 100644
@@ -87,6 +87,7 @@ static inline int ffs(int x)
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/atomic.h>
arch/cris/include/asm/bitops.h +1 -0
index 8062cb5..06bc246 100644
@@ -36,6 +36,7 @@
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/lock.h>
 
arch/frv/include/asm/bitops.h +1 -0
index 0df8e95..f2a7ee8 100644
@@ -314,6 +314,7 @@ int __ilog2_u64(u64 n)
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/le.h>
arch/h8300/include/asm/bitops.h +1 -0
index 05999ab..e392db2 100644
@@ -172,6 +172,7 @@ static inline unsigned long __ffs(unsigned long word)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
arch/hexagon/include/asm/bitops.h +1 -0
index 5e4a59b..2df614e 100644
@@ -290,6 +290,7 @@ static inline unsigned long __fls(unsigned long word)
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 
 #include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
arch/m32r/include/asm/bitops.h +1 -0
index 86ba2b4..e3cf46b 100644
@@ -259,6 +259,7 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/ffs.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #endif /* __KERNEL__ */
arch/m68k/include/asm/bitops.h +1 -0
index b4a9b0d..fd673ea 100644
@@ -519,6 +519,7 @@ static inline int __fls(int x)
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #endif /* __KERNEL__ */
 
arch/metag/include/asm/bitops.h +1 -0
index 2671134..ad13087 100644
@@ -118,6 +118,7 @@ static inline int test_and_change_bit(unsigned int bit,
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/le.h>
arch/mn10300/include/asm/bitops.h +1 -0
index fe6f8e2..60761b7 100644
@@ -225,6 +225,7 @@ int ffs(int x)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
 #include <asm-generic/bitops/le.h>
 
arch/openrisc/include/asm/bitops.h +1 -0
index 3003cda..8c97642 100644
@@ -43,6 +43,7 @@
 #include <asm-generic/bitops/sched.h>
 #include <asm/bitops/ffs.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/atomic.h>
arch/parisc/include/asm/bitops.h +1 -0
index 3f9406d..867ba10 100644
@@ -211,6 +211,7 @@ static __inline__ int fls(int x)
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 
arch/s390/include/asm/bitops.h +1 -0
index 8043f10..198eead 100644
@@ -460,6 +460,7 @@ static inline int fls(int word)
 #include <asm-generic/bitops/ffz.h>
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
arch/sh/include/asm/bitops.h +1 -0
index fc8e652..4bf0c35 100644
@@ -86,6 +86,7 @@ static inline unsigned long ffz(unsigned long word)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/ffs.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/le.h>
arch/xtensa/include/asm/bitops.h +1 -0
index 3f44fa2..981fa83 100644
@@ -229,6 +229,7 @@ test_and_change_bit(unsigned int bit, volatile unsigned long *p)
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 
Signature · 1 line
2.5.0
#6 lore raw
In reply to Zeng Zhaoxiu
Quoted 4 lines · Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

These patches provide generic and architecture-specific odd parity calculations.

Hi Zeng.

Can you please fix your mail script.
I see only 1/30 (sent to linux-arch) - and patch looks mangeled (broken lines) No mail was sent to sparclinux - but sparc was mentioned.

git send-mail usually do the trick.

Sam

#7 lore raw
Quoted 7 lines · Sam Ravnborg
Quoted 4 lines · Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

These patches provide generic and architecture-specific odd parity calculations.

Hi Zeng.

Quoted 7 lines

Can you please fix your mail script.
I see only 1/30 (sent to linux-arch) - and patch looks mangeled (broken lines) No mail was sent to sparclinux - but sparc was mentioned.

git send-mail usually do the trick.

Sam

When I do "git send-email", I got:
...
5.7.14 JTibJDWdGxPcfa-E9KgtF-grMQl9w> Please log in via your web browser and 5.7.14 then try again.
5.7.14 Learn more at
5.7.14 https://support.google.com/mail/answer/78754 zp5sm464879pac.9 - gsmtp
...

So I use thunderbird to send email, but the text wrap error.

#8 lore raw
Quoted 24 lines · Zeng Zhaoxiu
Quoted 7 lines · Sam Ravnborg
Quoted 4 lines · Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

These patches provide generic and architecture-specific odd parity calculations.

Hi Zeng.

Quoted 7 lines

Can you please fix your mail script.
I see only 1/30 (sent to linux-arch) - and patch looks mangeled (broken lines) No mail was sent to sparclinux - but sparc was mentioned.

git send-mail usually do the trick.

Sam

When I do "git send-email", I got:
...
5.7.14 JTibJDWdGxPcfa-E9KgtF-grMQl9w> Please log in via your web browser and 5.7.14 then try again.
5.7.14 Learn more at
5.7.14 https://support.google.com/mail/answer/78754 zp5sm464879pac.9 - gsmtp
...

Quoted 1 line

So I use thunderbird to send email, but the text wrap error.

Please try to search for "How to configure git send-email to use Gmail" and follow the instructions given in some of the links.
Test with your own mail address before you send to a list.

Also linux-arch only saw 1/30 - make sure to address this too.

Sam

#9 lore raw

PATCH v2 1/30 bitops: add parity functions

In reply to Sam Ravnborg

From: Zhaoxiu Zeng <[email protected]>

These patches provide generic and architecture-specific odd parity calculations.

I did not use GCC's __builtin_parity* functions, based on the following reasons:
1. I don't know where to identify which version of GCC from the beginning supported __builtin_parity for the architecture.
2. For the architecture that doesn't has popcount instruction, GCC instead use "call __paritysi2" (__paritydi2 for 64-bits). So if use __builtin_parity, we must provide __paritysi2 and __paritydi2 functions for these architectures. Additionally, parity4,8,16 might be "__builtin_parity(x & mask)", but the "& mask" operation is totally unnecessary.
3. For the architecture that has popcount instruction, we do the same things.
4. For powerpc64, sparc64, and x86, we do runtime patching to use popcount instruction if the CPU support.

I have compiled successfully with x86_64_defconfig, i386_defconfig, pseries_defconfig and sparc64_defconfig. And I used the following codes to test:

	#include <stdio.h>
	#include <stdlib.h>
	#include <stdint.h>

	#ifdef __x86_64__
	/* popcnt %edi, %eax -- redundant REX prefix for alignment */
	#define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7"
	/* popcnt %rdi, %rax */
	#define POPCNT64 ".byte 0xf3,0x48,0x0f,0xb8,0xc7"
	#define REG_IN "D"
	#define REG_OUT "a"
	#else
	/* popcnt %eax, %eax */
	#define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc0"
	#define REG_IN "a"
	#define REG_OUT "a"
	#endif

	static inline int c_parity4(unsigned int w)
	{
		w &= 0xf;
		return (0x6996 >> w) & 1;
	}

	static inline int c_parity8(unsigned int w)
	{
		w ^= w >> 4;
		return c_parity4(w);
	}

	static inline int c_parity16(unsigned int w)
	{
		w ^= w >> 8;
		return c_parity8(w);
	}

	static inline int c_parity32(unsigned int w)
	{
		w ^= w >> 16;
		return c_parity16(w);
	}

	static inline int c_parity64(uint64_t w)
	{
		return c_parity32((unsigned int)w ^ (unsigned int)(w >> 32));
	}

	static inline int asm_parity4(unsigned int w)
	{
		unsigned int res = 0;

		asm("test	$0xf, %1		\n"
			"setpo	%b0				\n"
			: "+q" (res)
			: "r" (w)
			: "cc");

		return res;
	}

	static inline int asm_parity8(unsigned int w)
	{
		unsigned int res = 0;

		asm("test	%1, %1			\n"
			"setpo	%b0			\n"
			: "+q" (res)
			: "r" (w)
			: "cc");

		return res;
	}

	static inline int asm_parity16(unsigned int w)
	{
		unsigned int res = 0;

		asm("xor	%h1, %b1		\n"
			"setpo	%b0			\n"
			: "+q" (res), "+q" (w)
			: : "cc");

		return res;
	}

	static inline int asm_parity32_1(unsigned int w)
	{
		unsigned int res;

		w ^= w >> 16;
		asm("xor	%%ah, %%al		\n"
			"mov	$0, %%eax		\n"
			"setpo	%%al			\n"
			: "=a" (res)
			: "a" (w)
			: "cc");

		return res;
	}

	static inline int asm_parity32_2(unsigned int w)
	{
		unsigned int res;

		asm(POPCNT32 "				\n"
			"andl	$1, %0			\n"
			: "="REG_OUT (res)
			: REG_IN (w)
			: "cc");

		return res;
	}

	#ifdef __x86_64__
	static inline int asm_parity64_1(uint64_t w)
	{
		unsigned int res = (unsigned int)w ^ (unsigned int)(w >> 32);

		res ^= res >> 16;
		asm("xor	%%ah, %%al		\n"
			"mov	$0, %%eax		\n"
			"setpo	%%al			\n"
			: "=a" (res)
			: "a" (res)
			: "cc");

		return res;
	}

	static inline int asm_parity64_2(uint64_t w)
	{
		unsigned int res;

		asm(POPCNT64 "				\n"
			"andl	$1, %0			\n"
			: "="REG_OUT (res)
			: REG_IN (w)
			: "cc");

		return res;
	}
	#else
	static inline int asm_parity64_1(uint64_t w)
	{
		return asm_parity32_1((unsigned int)(w >> 32) ^ (unsigned int)w);
	}

	static inline int asm_parity64_2(uint64_t w)
	{
		return asm_parity32_2((unsigned int)(w >> 32) ^ (unsigned int)w);
	}
	#endif

	int main(int argc, char **argv)
	{
		int ok = 1;
		int count = 1000, i;

		if (argc >= 2)
			count = atoi(argv[1]);

		srand((unsigned)time(NULL));

		for (i = 0; i < count; i++) {
			uint64_t w = rand() | (uint64_t)rand() << 32;
			int p4_1 = c_parity4(w);
			int p4_2 = asm_parity4(w);
			int p8_1 = c_parity8(w);
			int p8_2 = asm_parity8(w);
			int p16_1 = c_parity16(w);
			int p16_2 = asm_parity16(w);
			int p32_1 = c_parity32(w);
			int p32_2 = asm_parity32_1(w);
			int p32_3 = asm_parity32_2(w);
			int p64_1 = c_parity64(w);
			int p64_2 = asm_parity64_1(w);
			int p64_3 = asm_parity64_2(w);
			if (p4_1 != p4_2 ||
				p8_1 != p8_2 ||
				p16_1 != p16_2 ||
				p32_1 != p32_2 || p32_1 != p32_3 ||
				p64_1 != p64_2 || p64_1 != p64_3) {
				fprintf(stderr, "Err: %llx\n"
							"\tc_parity4 = %d, asm_parity4 = %d,\n"
							"\tc_parity8 = %d, asm_parity8 = %d,\n"
							"\tc_parity16 = %d, asm_parity16 = %d,\n"
							"\tc_parity32 = %d, asm_parity32_1 = %d, asm_parity32_2 = %d\n"
							"\tc_parity64 = %d, asm_parity64_1 = %d, asm_parity64_2 = %d\n",
							w, p4_1, p4_2, p8_1, p8_2, p16_1, p16_2, p32_1, p32_2, p32_3, p64_1, p64_2, p64_3);
				ok = 0;
			}
		}

		fprintf(stderr, "%s\n", ok ? "OK" : "FAIL");
		return 0;
	}
---
 include/asm-generic/bitops.h              |  1 +
 include/asm-generic/bitops/arch_parity.h  | 39 +++++++++++++++++++++++++++++++
 include/asm-generic/bitops/const_parity.h | 36 ++++++++++++++++++++++++++++
 include/asm-generic/bitops/parity.h       |  7 ++++++
 include/linux/bitops.h                    |  5 ++++
 5 files changed, 88 insertions(+)
 create mode 100644 include/asm-generic/bitops/arch_parity.h
 create mode 100644 include/asm-generic/bitops/const_parity.h
 create mode 100644 include/asm-generic/bitops/parity.h
include/asm-generic/bitops.h +1 -0
index dcdcacf..d85722f 100644
@@ -27,6 +27,7 @@
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/ffs.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/atomic.h>
include/asm-generic/bitops/arch_parity.h new file +39 -0
new file mode 100644
index 0000000..cddc555
@@ -0,0 +1,39 @@
+#ifndef _ASM_GENERIC_BITOPS_ARCH_PARITY_H_
+#define _ASM_GENERIC_BITOPS_ARCH_PARITY_H_
+
+#include <asm/types.h>
+
+/*
+ * Refrence to 'https://graphics.stanford.edu/~seander/bithacks.html#ParityParallel'.
+ */
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+	w &= 0xf;
+	return (0x6996 >> w) & 1;
+}
+
+static inline unsigned int __arch_parity8(unsigned int w)
+{
+	w ^= w >> 4;
+	return __arch_parity4(w);
+}
+
+static inline unsigned int __arch_parity16(unsigned int w)
+{
+	w ^= w >> 8;
+	return __arch_parity8(w);
+}
+
+static inline unsigned int __arch_parity32(unsigned int w)
+{
+	w ^= w >> 16;
+	return __arch_parity16(w);
+}
+
+static inline unsigned int __arch_parity64(__u64 w)
+{
+	return __arch_parity32((unsigned int)(w >> 32) ^ (unsigned int)w);
+}
+
+#endif /* _ASM_GENERIC_BITOPS_ARCH_PARITY_H_ */
include/asm-generic/bitops/const_parity.h new file +36 -0
new file mode 100644
index 0000000..6af7987
@@ -0,0 +1,36 @@
+#ifndef _ASM_GENERIC_BITOPS_CONST_PARITY_H_
+#define _ASM_GENERIC_BITOPS_CONST_PARITY_H_
+
+/*
+ * Compile time versions of __arch_parityN()
+ */
+#define __const_parity4(w)   ((0x6996 >> ((w) & 0xf)) & 1)
+#define __const_parity8(w)   (__const_parity4((w) ^ ((w) >> 4)))
+#define __const_parity16(w)  (__const_parity8((w) ^ ((w) >> 8)))
+#define __const_parity32(w)  (__const_parity16((w) ^ ((w) >> 16)))
+#define __const_parity64(w)  (__const_parity32((w) ^ ((w) >> 32)))
+
+/*
+ * Generic interface.
+ */
+#define parity4(w)   (__builtin_constant_p(w) ? __const_parity4(w)  : __arch_parity4(w))
+#define parity8(w)   (__builtin_constant_p(w) ? __const_parity8(w)  : __arch_parity8(w))
+#define parity16(w)  (__builtin_constant_p(w) ? __const_parity16(w) : __arch_parity16(w))
+#define parity32(w)  (__builtin_constant_p(w) ? __const_parity32(w) : __arch_parity32(w))
+#define parity64(w)  (__builtin_constant_p(w) ? __const_parity64(w) : __arch_parity64(w))
+
+/*
+ * Interface for known constant arguments
+ */
+#define PARITY4(w)   (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity4(w))
+#define PARITY8(w)   (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity8(w))
+#define PARITY16(w)  (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity16(w))
+#define PARITY32(w)  (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity32(w))
+#define PARITY64(w)  (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity64(w))
+
+/*
+ * Type invariant interface to the compile time constant parity functions.
+ */
+#define PARITY(w)    PARITY64((u64)(w))
+
+#endif /* _ASM_GENERIC_BITOPS_CONST_PARITY_H_ */
include/asm-generic/bitops/parity.h new file +7 -0
new file mode 100644
index 0000000..a91dce7
@@ -0,0 +1,7 @@
+#ifndef _ASM_GENERIC_BITOPS_PARITY_H_
+#define _ASM_GENERIC_BITOPS_PARITY_H_
+
+#include <asm-generic/bitops/arch_parity.h>
+#include <asm-generic/bitops/const_parity.h>
+
+#endif /* _ASM_GENERIC_BITOPS_PARITY_H_ */
include/linux/bitops.h +5 -0
index defeaac..8952f88 100644
@@ -80,6 +80,11 @@ static __always_inline unsigned long hweight_long(unsigned long w)
 	return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
 }
 
+static __always_inline unsigned int parity_long(unsigned long w)
+{
+	return sizeof(w) == 4 ? parity32(w) : parity64(w);
+}
+
 /**
  * rol64 - rotate a 64-bit value left
  * @word: value to rotate
Signature · 1 line
2.5.0
#10 lore raw

PATCH v2 3/30 Add alpha-specific parity functions

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 arch/alpha/include/asm/bitops.h | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
arch/alpha/include/asm/bitops.h +27 -0
index 4bdfbd4..95a43fa 100644
@@ -421,11 +421,38 @@ static inline unsigned int __arch_hweight8(unsigned int w)
 {
 	return __arch_hweight64(w & 0xff);
 }
+
+static inline unsigned int __arch_parity64(unsigned long w)
+{
+	return (unsigned int)__kernel_ctpop(w) & 1;
+}
+
+static inline unsigned int __arch_parity32(unsigned int w)
+{
+	return __arch_parity64(w);
+}
+
+static inline unsigned int __arch_parity16(unsigned int w)
+{
+	return __arch_parity64(w & 0xffff);
+}
+
+static inline unsigned int __arch_parity8(unsigned int w)
+{
+	return __arch_parity64(w & 0xff);
+}
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+	return __arch_parity64(w & 0xf);
+}
 #else
 #include <asm-generic/bitops/arch_hweight.h>
+#include <asm-generic/bitops/arch_parity.h>
 #endif
 
 #include <asm-generic/bitops/const_hweight.h>
+#include <asm-generic/bitops/const_parity.h>
 
 #endif /* __KERNEL__ */
 
Signature · 1 line
2.5.0
#11 lore raw

PATCH v2 4/30 Add blackfin-specific parity functions

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 arch/blackfin/include/asm/bitops.h | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)
arch/blackfin/include/asm/bitops.h +31 -0
index b298b65..6609b7e 100644
@@ -23,6 +23,7 @@
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/ffs.h>
 #include <asm-generic/bitops/const_hweight.h>
+#include <asm-generic/bitops/const_parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/ext2-atomic.h>
@@ -137,4 +138,34 @@ static inline unsigned int __arch_hweight8(unsigned int w)
 	return __arch_hweight32(w & 0xff);
 }
 
+/*
+ * parityN: returns the parity of a N-bit word,
+ * i.e. the number of 1-bits in w modulo 2.
+ */
+
+static inline unsigned int __arch_parity32(unsigned int w)
+{
+	return __arch_hweight32(w) & 1;
+}
+
+static inline unsigned int __arch_parity64(__u64 w)
+{
+	return __arch_parity32((unsigned int)(w >> 32) ^ (unsigned int)w);
+}
+
+static inline unsigned int __arch_parity16(unsigned int w)
+{
+	return __arch_parity32(w & 0xffff);
+}
+
+static inline unsigned int __arch_parity8(unsigned int w)
+{
+	return __arch_parity32(w & 0xff);
+}
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+	return __arch_parity32(w & 0xf);
+}
+
 #endif				/* _BLACKFIN_BITOPS_H */
Signature · 1 line
2.5.0
#12 lore raw

PATCH v2 5/30 Add ia64-specific parity functions

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 arch/ia64/include/asm/bitops.h | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)
arch/ia64/include/asm/bitops.h +31 -0
index 71e8145..041d1d6 100644
@@ -439,6 +439,37 @@ static __inline__ unsigned long __arch_hweight64(unsigned long x)
 
 #include <asm-generic/bitops/const_hweight.h>
 
+/*
+ * parityN: returns the parity of a N-bit word,
+ * i.e. the number of 1-bits in x modulo 2.
+ */
+static __inline__ unsigned int __arch_parity64(unsigned long x)
+{
+	return (unsigned int)ia64_popcnt(x) & 1;
+}
+
+static __inline__ unsigned int __arch_parity32(unsigned int x)
+{
+	return __arch_parity64((unsigned long)x << 32);
+}
+
+static __inline__ unsigned int __arch_parity16(unsigned int x)
+{
+	return __arch_parity64((unsigned long)x << 48);
+}
+
+static __inline__ unsigned int __arch_parity8(unsigned int x)
+{
+	return __arch_parity64((unsigned long)x << 56);
+}
+
+static __inline__ unsigned int __arch_parity4(unsigned int x)
+{
+	return __arch_parity64((unsigned long)x << 60);
+}
+
+#include <asm-generic/bitops/const_parity.h>
+
 #endif /* __KERNEL__ */
 
 #include <asm-generic/bitops/find.h>
Signature · 1 line
2.5.0
#13 lore raw

PATCH v2 6/30 Add mips-specific parity functions

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

Lifted from arch_hweight.h

---
 arch/mips/include/asm/arch_parity.h | 44 +++++++++++++++++++++++++++++++++++++
 arch/mips/include/asm/bitops.h      |  3 +++
 2 files changed, 47 insertions(+)
 create mode 100644 arch/mips/include/asm/arch_parity.h
arch/mips/include/asm/arch_parity.h new file +44 -0
new file mode 100644
index 0000000..23b3c23
@@ -0,0 +1,44 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+#ifndef _ASM_ARCH_PARITY_H
+#define _ASM_ARCH_PARITY_H
+
+#ifdef ARCH_HAS_USABLE_BUILTIN_POPCOUNT
+
+#include <asm/types.h>
+
+static inline unsigned int __arch_parity32(unsigned int w)
+{
+	return __builtin_popcount(w) & 1;
+}
+
+static inline unsigned int __arch_parity16(unsigned int w)
+{
+	return __arch_parity32(w & 0xffff);
+}
+
+static inline unsigned int __arch_parity8(unsigned int w)
+{
+	return __arch_parity32(w & 0xff);
+}
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+	return __arch_parity32(w & 0xf);
+}
+
+static inline unsigned int __arch_parity64(__u64 w)
+{
+	return (unsigned int)__builtin_popcountll(w) & 1;
+}
+
+#else
+#include <asm-generic/bitops/arch_hweight.h>
+#include <asm-generic/bitops/arch_parity.h>
+#endif
+
+#endif /* _ASM_ARCH_PARITY_H */
arch/mips/include/asm/bitops.h +3 -0
index ce9666c..0b87734 100644
@@ -626,6 +626,9 @@ static inline int ffs(int word)
 #include <asm/arch_hweight.h>
 #include <asm-generic/bitops/const_hweight.h>
 
+#include <asm/arch_parity.h>
+#include <asm-generic/bitops/const_parity.h>
+
 #include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
 
Signature · 1 line
2.5.0
#14 lore raw

PATCH v2 6/30 Add mips-specific parity functions

From: Zhaoxiu Zeng <[email protected]>

Lifted from arch_hweight.h

---
 arch/mips/include/asm/arch_parity.h | 43 +++++++++++++++++++++++++++++++++++++
 arch/mips/include/asm/bitops.h      |  3 +++
 2 files changed, 46 insertions(+)
 create mode 100644 arch/mips/include/asm/arch_parity.h
arch/mips/include/asm/arch_parity.h new file +43 -0
new file mode 100644
index 0000000..23b3c23
@@ -0,0 +1,44 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+#ifndef _ASM_ARCH_PARITY_H
+#define _ASM_ARCH_PARITY_H
+
+#ifdef ARCH_HAS_USABLE_BUILTIN_POPCOUNT
+
+#include <asm/types.h>
+
+static inline unsigned int __arch_parity32(unsigned int w)
+{
+	return __builtin_popcount(w) & 1;
+}
+
+static inline unsigned int __arch_parity16(unsigned int w)
+{
+	return __arch_parity32(w & 0xffff);
+}
+
+static inline unsigned int __arch_parity8(unsigned int w)
+{
+	return __arch_parity32(w & 0xff);
+}
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+	return __arch_parity32(w & 0xf);
+}
+
+static inline unsigned int __arch_parity64(__u64 w)
+{
+	return (unsigned int)__builtin_popcountll(w) & 1;
+}
+
+#else
+#include <asm-generic/bitops/arch_parity.h>
+#endif
+
+#endif /* _ASM_ARCH_PARITY_H */
arch/mips/include/asm/bitops.h +3 -0
index ce9666c..0b87734 100644
@@ -626,6 +626,9 @@ static inline int ffs(int word)
 #include <asm/arch_hweight.h>
 #include <asm-generic/bitops/const_hweight.h>
 
+#include <asm/arch_parity.h>
+#include <asm-generic/bitops/const_parity.h>
+
 #include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
 
Signature · 1 line
2.5.0
#15 lore raw

PATCH v2 7/30 Add powerpc-specific parity functions

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

Use runtime patching for ppc64, lifted from hweight_64

---
 arch/powerpc/include/asm/bitops.h |  11 ++++
 arch/powerpc/lib/Makefile         |   2 +-
 arch/powerpc/lib/parity_64.S      | 107 ++++++++++++++++++++++++++++++++++++++
 arch/powerpc/lib/ppc_ksyms.c      |   5 ++
 4 files changed, 124 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/lib/parity_64.S
arch/powerpc/include/asm/bitops.h +11 -0
index 59abc62..cb92783 100644
@@ -269,8 +269,19 @@ unsigned int __arch_hweight16(unsigned int w);
 unsigned int __arch_hweight32(unsigned int w);
 unsigned long __arch_hweight64(__u64 w);
 #include <asm-generic/bitops/const_hweight.h>
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+	w &= 0xf;
+	return (0x6996 >> w) & 1;
+}
+unsigned int __arch_parity8(unsigned int w);
+unsigned int __arch_parity16(unsigned int w);
+unsigned int __arch_parity32(unsigned int w);
+unsigned int __arch_parity64(__u64 w);
+#include <asm-generic/bitops/const_parity.h>
 #else
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #endif
 
 #include <asm-generic/bitops/find.h>
arch/powerpc/lib/Makefile +1 -1
index ba21be1..cae2e7f 100644
@@ -16,7 +16,7 @@ obj-$(CONFIG_PPC32)	+= div64.o copy_32.o
 
 obj64-y	+= copypage_64.o copyuser_64.o usercopy_64.o mem_64.o hweight_64.o \
 	   copyuser_power7.o string_64.o copypage_power7.o memcpy_power7.o \
-	   memcpy_64.o memcmp_64.o
+	   memcpy_64.o memcmp_64.o parity_64.o
 
 obj64-$(CONFIG_SMP)	+= locks.o
 obj64-$(CONFIG_ALTIVEC)	+= vmx-helper.o
arch/powerpc/lib/parity_64.S new file +107 -0

107 lines not on this page · raw message

arch/powerpc/lib/ppc_ksyms.c +5 -0
index c422812..1ccfc29 100644
@@ -30,4 +30,9 @@ EXPORT_SYMBOL(__arch_hweight8);
 EXPORT_SYMBOL(__arch_hweight16);
 EXPORT_SYMBOL(__arch_hweight32);
 EXPORT_SYMBOL(__arch_hweight64);
+
+EXPORT_SYMBOL(__arch_parity8);
+EXPORT_SYMBOL(__arch_parity16);
+EXPORT_SYMBOL(__arch_parity32);
+EXPORT_SYMBOL(__arch_parity64);
 #endif
Signature · 1 line
2.5.0
#16 lore raw

PATCH v2 8/30 Add sparc-specific parity functions

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

Use runtime patching for sparc64, lifted from hweight

---
 arch/sparc/include/asm/bitops_32.h |  1 +
 arch/sparc/include/asm/bitops_64.h | 18 ++++++++
 arch/sparc/kernel/sparc_ksyms_64.c |  6 +++
 arch/sparc/lib/Makefile            |  2 +-
 arch/sparc/lib/parity.S            | 93 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 119 insertions(+), 1 deletion(-)
 create mode 100644 arch/sparc/lib/parity.S
arch/sparc/include/asm/bitops_32.h +1 -0
index 600ed1d..8c41896 100644
@@ -98,6 +98,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/le.h>
arch/sparc/include/asm/bitops_64.h +18 -0
index 2d52240..5312fed 100644
@@ -47,6 +47,24 @@ unsigned int __arch_hweight16(unsigned int w);
 unsigned int __arch_hweight8(unsigned int w);
 
 #include <asm-generic/bitops/const_hweight.h>
+
+/*
+ * parityN: returns the parity of a N-bit word,
+ * i.e. the number of 1-bits in w modulo 2.
+ */
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+	w &= 0xf;
+	return (0x6996 >> w) & 1;
+}
+unsigned int __arch_parity8(unsigned int w);
+unsigned int __arch_parity16(unsigned int w);
+unsigned int __arch_parity32(unsigned int w);
+unsigned int __arch_parity64(__u64 w);
+
+#include <asm-generic/bitops/const_parity.h>
+
 #include <asm-generic/bitops/lock.h>
 #endif /* __KERNEL__ */
 
arch/sparc/kernel/sparc_ksyms_64.c +6 -0
index 9e034f2..7ee0818 100644
@@ -45,6 +45,12 @@ EXPORT_SYMBOL(__arch_hweight16);
 EXPORT_SYMBOL(__arch_hweight32);
 EXPORT_SYMBOL(__arch_hweight64);
 
+/* from parity.S */
+EXPORT_SYMBOL(__arch_parity8);
+EXPORT_SYMBOL(__arch_parity16);
+EXPORT_SYMBOL(__arch_parity32);
+EXPORT_SYMBOL(__arch_parity64);
+
 /* from ffs_ffz.S */
 EXPORT_SYMBOL(ffs);
 EXPORT_SYMBOL(__ffs);
arch/sparc/lib/Makefile +1 -1
index 3269b02..2dbbcb1 100644
@@ -39,7 +39,7 @@ lib-$(CONFIG_SPARC64) += GENmemcpy.o GENcopy_from_user.o GENcopy_to_user.o
 lib-$(CONFIG_SPARC64) += GENpatch.o GENpage.o GENbzero.o
 
 lib-$(CONFIG_SPARC64) += copy_in_user.o user_fixup.o memmove.o
-lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o ffs.o
+lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o ffs.o parity.o
 
 obj-$(CONFIG_SPARC64) += iomap.o
 obj-$(CONFIG_SPARC32) += atomic32.o ucmpdi2.o
arch/sparc/lib/parity.S new file +93 -0

93 lines not on this page · raw message

Signature · 1 line
2.5.0
#17 lore raw

Re: [PATCH v2 08/30] Add sparc-specific parity functions

Quoted 8 lines · On Wed, Apr 06, 2016 at 05:07:27PM +0800, [email protected] wrote:
arch/sparc/lib/parity.S new file +6 -0
+static inline unsigned int __arch_parity4(unsigned int w)
+	return (0x6996 >> w) & 1;
 
+ENTRY(__arch_parity8)
+	sethi		%hi(0x6996), %g1
+	or		%g1, %lo(0x6996), %g1
 
+ENTRY(__arch_parity16)

arch/sparc/lib/parity.S line 83

Quoted 10 lines
arch/sparc/lib/parity.S new file +8 -0
+	sethi		%hi(0x6996), %g1
+	or		%g1, %lo(0x6996), %g1
 
+ENTRY(__arch_parity32)
+	sethi		%hi(0x6996), %g1
+	or		%g1, %lo(0x6996), %g1
 
+ENTRY(__arch_parity64)
+	sethi		%hi(0x6996), %g1
+	or		%g1, %lo(0x6996), %g1

Given how many times the magic constant is repeated, maybe it would make sense to give it a name?

Signature · 1 line
     2. That which causes joy or happiness.
#18 lore raw

Re: [PATCH v2 08/30] Add sparc-specific parity functions

In reply to [email protected]

Hi Zeng.

Quoted 2 lines

Use runtime patching for sparc64, lifted from hweight

No errors found in patch - but a few comments.
In general patch looks good.

Quoted 6 lines

+++ b/arch/sparc/include/asm/bitops_64.h

arch/sparc/include/asm/bitops_64.h +1 -0
@@ -47,6 +47,24 @@ unsigned int __arch_hweight16(unsigned int w);
 unsigned int __arch_hweight8(unsigned int w);
 
 #include <asm-generic/bitops/const_hweight.h>
+

arch/sparc/include/asm/bitops_64.h unsigned int __arch_hweight16(unsigned int w); · line 60

Quoted 10 lines
arch/sparc/include/asm/bitops_64.h +10 -0
+/*
+ * parityN: returns the parity of a N-bit word,
+ * i.e. the number of 1-bits in w modulo 2.
+ */
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+	w &= 0xf;
+	return (0x6996 >> w) & 1;
+}

As Josef already said - this constant should have a name. PARITY_BIT
?

arch/sparc/kernel/sparc_ksyms_64.c EXPORT_SYMBOL(__arch_hweight16); · line 52

Quoted 10 lines
arch/sparc/kernel/sparc_ksyms_64.c +6 -0
+++ b/arch/sparc/kernel/sparc_ksyms_64.c
@@ -45,6 +45,12 @@ EXPORT_SYMBOL(__arch_hweight16);
 EXPORT_SYMBOL(__arch_hweight32);
 EXPORT_SYMBOL(__arch_hweight64);
 
+/* from parity.S */
+EXPORT_SYMBOL(__arch_parity8);
+EXPORT_SYMBOL(__arch_parity16);
+EXPORT_SYMBOL(__arch_parity32);
+EXPORT_SYMBOL(__arch_parity64);

Did you compile this?
I wonder if bitops_64.h is indirectly included.

Quoted 9 lines

index 0000000..b1945e3

arch/sparc/lib/parity.S new file +5 -0
@@ -0,0 +1,93 @@
+#include <linux/linkage.h>
+
+	.text
+	.align	32
+

arch/sparc/lib/parity.S line 15

Quoted 10 lines
arch/sparc/lib/parity.S new file +10 -0
+ENTRY(__arch_parity8)
+	srl		%o0, 4, %g1
+	xor		%o0, %g1, %o0
+	and		%o0, 0xf, %o0
+	sethi		%hi(0x6996), %g1
+	or		%g1, %lo(0x6996), %g1
+	srl		%g1, %o0, %o0
+	retl
+	 and		%o0, 1, %o0
+ENDPROC(__arch_parity8)

I know the level of comments in hweight is equal to none. But please do not follow this bad example.
At least for each function a one-liner of the C code. And in the top of the file maybe two lines that the functions are patched at run-time if the processor has popc available.

Sam

#19 lore raw

Re: [PATCH v2 08/30] Add sparc-specific parity functions

Quoted 5 lines · Sam Ravnborg

Hi Zeng.

Quoted 1 line

Use runtime patching for sparc64, lifted from hweight

No errors found in patch - but a few comments.
In general patch looks good.

Thanks. Sparc, powerpc, and x86 are all new to me.

Quoted 4 lines
Quoted 4 lines

+++ b/arch/sparc/include/asm/bitops_64.h

arch/sparc/include/asm/bitops_64.h +0 -0
@@ -47,6 +47,24 @@ unsigned int __arch_hweight16(unsigned int w);
  unsigned int __arch_hweight8(unsigned int w);
 
Quoted 16 lines

arch/sparc/include/asm/bitops_64.h unsigned int __arch_hweight16(unsigned int w); · line 60

Quoted 12 lines
arch/sparc/include/asm/bitops_64.h +11 -0
  #include <asm-generic/bitops/const_hweight.h>
+
+/*
+ * parityN: returns the parity of a N-bit word,
+ * i.e. the number of 1-bits in w modulo 2.
+ */
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+	w &= 0xf;
+	return (0x6996 >> w) & 1;
+}

As Josef already said - this constant should have a name. PARITY_BIT
?

Maybe PARITY_MAGIC?

Quoted 5 lines
Quoted 5 lines
arch/sparc/kernel/sparc_ksyms_64.c +1 -0
+++ b/arch/sparc/kernel/sparc_ksyms_64.c
@@ -45,6 +45,12 @@ EXPORT_SYMBOL(__arch_hweight16);
  EXPORT_SYMBOL(__arch_hweight32);
  EXPORT_SYMBOL(__arch_hweight64);
 
Quoted 7 lines

arch/sparc/kernel/sparc_ksyms_64.c EXPORT_SYMBOL(__arch_hweight16); · line 52

Quoted 5 lines
arch/sparc/kernel/sparc_ksyms_64.c +5 -0
+/* from parity.S */
+EXPORT_SYMBOL(__arch_parity8);
+EXPORT_SYMBOL(__arch_parity16);
+EXPORT_SYMBOL(__arch_parity32);
+EXPORT_SYMBOL(__arch_parity64);

Did you compile this?
I wonder if bitops_64.h is indirectly included.

Yes.

Quoted 26 lines
Quoted 9 lines

index 0000000..b1945e3

arch/sparc/lib/parity.S new file +5 -0
@@ -0,0 +1,93 @@
+#include <linux/linkage.h>
+
+	.text
+	.align	32
+

arch/sparc/lib/parity.S line 15

Quoted 10 lines
arch/sparc/lib/parity.S new file +10 -0
+ENTRY(__arch_parity8)
+	srl		%o0, 4, %g1
+	xor		%o0, %g1, %o0
+	and		%o0, 0xf, %o0
+	sethi		%hi(0x6996), %g1
+	or		%g1, %lo(0x6996), %g1
+	srl		%g1, %o0, %o0
+	retl
+	 and		%o0, 1, %o0
+ENDPROC(__arch_parity8)

I know the level of comments in hweight is equal to none. But please do not follow this bad example.
At least for each function a one-liner of the C code. And in the top of the file maybe two lines that the functions are patched at run-time if the processor has popc available.

Quoted 1 line

Sam

OK. I will try, but my english is very poor! :-)

#20 lore raw

PATCH v2 9/30 Add tile-specific parity functions

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 arch/tile/include/asm/bitops.h | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
arch/tile/include/asm/bitops.h +26 -0
index 20caa34..370d007 100644
@@ -81,10 +81,36 @@ static inline unsigned long __arch_hweight64(__u64 w)
 	return __builtin_popcountll(w);
 }
 
+static inline unsigned int __arch_parity32(unsigned int w)
+{
+	return __builtin_popcount(w) & 1;
+}
+
+static inline unsigned int __arch_parity16(unsigned int w)
+{
+	return __arch_parity32(w & 0xffff);
+}
+
+static inline unsigned int __arch_parity8(unsigned int w)
+{
+	return __arch_parity32(w & 0xff);
+}
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+	return __arch_parity32(w & 0xf);
+}
+
+static inline unsigned int __arch_parity64(__u64 w)
+{
+	return (unsigned int)__builtin_popcountll(w) & 1;
+}
+
 #include <asm-generic/bitops/builtin-__ffs.h>
 #include <asm-generic/bitops/builtin-__fls.h>
 #include <asm-generic/bitops/builtin-ffs.h>
 #include <asm-generic/bitops/const_hweight.h>
+#include <asm-generic/bitops/const_parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/sched.h>
Signature · 1 line
2.5.0
#21 lore raw

Re: [PATCH v2 09/30] Add tile-specific parity functions

Quoted 6 lines · On 4/6/2016 5:08 AM, [email protected] wrote:

From: Zhaoxiu Zeng<[email protected]>

---
  arch/tile/include/asm/bitops.h | 26 ++++++++++++++++++++++++++
  1 file changed, 26 insertions(+)

Since all the code you are adding here is architecture-independent, I think it would make more sense to have it be in a file like include/asm-generic/bitops/parity-popcount.h, which can then be included from arch/tile/include/asm/bitops.h.

Signature · 2 lines
Chris Metcalf, Mellanox Technologies
http://www.mellanox.com
#22 lore raw

Re: [PATCH v2 09/30] Add tile-specific parity functions

Quoted 8 lines · Chris Metcalf
Quoted 6 lines · On 4/6/2016 5:08 AM, [email protected] wrote:

From: Zhaoxiu Zeng<[email protected]>

---
  arch/tile/include/asm/bitops.h | 26 ++++++++++++++++++++++++++
  1 file changed, 26 insertions(+)
Quoted 5 lines

Since all the code you are adding here is architecture-independent, I think it would make more sense to have it be in a file like include/asm-generic/bitops/parity-popcount.h, which can then be included from arch/tile/include/asm/bitops.h.

Agreed, thanks!

#23 lore raw

PATCH v2 10/30 Add x86-specific parity functions

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

Use alternatives, lifted from arch_hweight

---
 arch/x86/include/asm/arch_hweight.h |   5 ++
 arch/x86/include/asm/arch_parity.h  | 102 ++++++++++++++++++++++++++++++++++++
 arch/x86/include/asm/bitops.h       |   4 +-
 arch/x86/lib/Makefile               |   8 +++
 arch/x86/lib/parity.c               |  32 ++++++++++++
 5 files changed, 150 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/include/asm/arch_parity.h
 create mode 100644 arch/x86/lib/parity.c
arch/x86/include/asm/arch_hweight.h +5 -0
index 02e799f..c79d50d 100644
@@ -63,4 +63,9 @@ static __always_inline unsigned long __arch_hweight64(__u64 w)
 }
 #endif /* CONFIG_X86_32 */
 
+#undef POPCNT32
+#undef POPCNT64
+#undef REG_IN
+#undef REG_OUT
+
 #endif
arch/x86/include/asm/arch_parity.h new file +100 -0

100 lines not on this page · raw message

+
+#endif

arch/x86/include/asm/bitops.h +3 -1
index 7766d1c..f5b0122 100644
@@ -498,9 +498,11 @@ static __always_inline int fls64(__u64 x)
 #include <asm-generic/bitops/sched.h>
 
 #include <asm/arch_hweight.h>
-
 #include <asm-generic/bitops/const_hweight.h>
 
+#include <asm/arch_parity.h>
+#include <asm-generic/bitops/const_parity.h>
+
 #include <asm-generic/bitops/le.h>
 
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
arch/x86/lib/Makefile +8 -0
index 72a5767..5716295 100644
@@ -4,6 +4,9 @@
 
 # Produces uninteresting flaky coverage.
 KCOV_INSTRUMENT_delay.o	:= n
+# Kernel does not boot if we instrument this file as it uses custom calling
+# convention (see CONFIG_ARCH_HWEIGHT_CFLAGS).
+KCOV_INSTRUMENT_parity.o := n
 
 inat_tables_script = $(srctree)/arch/x86/tools/gen-insn-attr-x86.awk
 inat_tables_maps = $(srctree)/arch/x86/lib/x86-opcode-map.txt
@@ -45,3 +48,8 @@ else
         lib-y += copy_user_64.o
 	lib-y += cmpxchg16b_emu.o
 endif
+
+GCOV_PROFILE_parity.o := n
+CFLAGS_parity.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS))
+obj-y  += parity.o
+
arch/x86/lib/parity.c new file +32 -0
new file mode 100644
index 0000000..762117b
@@ -0,0 +1,32 @@
+#include <linux/export.h>
+#include <linux/bitops.h>
+
+unsigned int __sw_parity32(unsigned int w)
+{
+	unsigned int res;
+	w ^= w >> 16;
+	asm("xor	%%ah, %%al		\n"
+		"mov	$0, %%eax		\n"
+		"setpo	%%al			\n"
+		: "=a" (res)
+		: "a" (w)
+		: "cc");
+	return res;
+}
+EXPORT_SYMBOL(__sw_parity32);
+
+#ifndef CONFIG_X86_32
+unsigned int __sw_parity64(__u64 w)
+{
+	unsigned int res = (unsigned int)w ^ (unsigned int)(w >> 32);
+	res ^= res >> 16;
+	asm("xor	%%ah, %%al		\n"
+		"mov	$0, %%eax		\n"
+		"setpo	%%al			\n"
+		: "=a" (res)
+		: "a" (res)
+		: "cc");
+	return res;
+}
+EXPORT_SYMBOL(__sw_parity64);
+#endif
Signature · 1 line
2.5.0
#24 lore raw

Re: [PATCH v2 10/30] Add x86-specific parity functions

Quoted 14 lines · On Wed, Apr 06, 2016 at 05:14:45PM +0800, [email protected] wrote:

From: Zhaoxiu Zeng <[email protected]>

Use alternatives, lifted from arch_hweight

---
 arch/x86/include/asm/arch_hweight.h |   5 ++
 arch/x86/include/asm/arch_parity.h  | 102 ++++++++++++++++++++++++++++++++++++
 arch/x86/include/asm/bitops.h       |   4 +-
 arch/x86/lib/Makefile               |   8 +++
 arch/x86/lib/parity.c               |  32 ++++++++++++
 5 files changed, 150 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/include/asm/arch_parity.h
 create mode 100644 arch/x86/lib/parity.c

...

arch/x86/include/asm/arch_parity.h line 73

Quoted 8 lines
arch/x86/include/asm/arch_parity.h new file +8 -0
+static __always_inline unsigned int __arch_parity32(unsigned int w)
+{
+	unsigned int res;
+
+	asm(ALTERNATIVE("call __sw_parity32", POPCNT32 "; and $1, %0", X86_FEATURE_POPCNT)
+		: "="REG_OUT (res)
+		: REG_IN (w)
+		: "cc");

So why all that churn instead of simply doing:

static __always_inline unsigned int __arch_parity32(unsigned int w)

{
	return hweight32(w) & 1;
}

Ditto for the 64-bit version.

Signature · 5 lines
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 
#25 lore raw

Re: [PATCH v2 10/30] Add x86-specific parity functions

Quoted 29 lines · On Wed, 6 Apr 2016 12:13:00 +0200 Borislav Petkov <[email protected]> wrote:
Quoted 14 lines · On Wed, Apr 06, 2016 at 05:14:45PM +0800, [email protected] wrote:

From: Zhaoxiu Zeng <[email protected]>

Use alternatives, lifted from arch_hweight

---
 arch/x86/include/asm/arch_hweight.h |   5 ++
 arch/x86/include/asm/arch_parity.h  | 102 ++++++++++++++++++++++++++++++++++++
 arch/x86/include/asm/bitops.h       |   4 +-
 arch/x86/lib/Makefile               |   8 +++
 arch/x86/lib/parity.c               |  32 ++++++++++++
 5 files changed, 150 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/include/asm/arch_parity.h
 create mode 100644 arch/x86/lib/parity.c  

...

arch/x86/include/asm/arch_parity.h line 73

Quoted 8 lines
arch/x86/include/asm/arch_parity.h new file +8 -0
+static __always_inline unsigned int __arch_parity32(unsigned int w)
+{
+	unsigned int res;
+
+	asm(ALTERNATIVE("call __sw_parity32", POPCNT32 "; and $1, %0", X86_FEATURE_POPCNT)
+		: "="REG_OUT (res)
+		: REG_IN (w)
+		: "cc");  

So why all that churn instead of simply doing:

Quoted 6 lines

static __always_inline unsigned int __arch_parity32(unsigned int w)

{
	return hweight32(w) & 1;
}

Ditto for the 64-bit version.

Even that would still be wrong for the smaller parity values. The CPU supports 8bit parity directly going back to the 8086 so the implementation for 8bit and I think 16bit is still wrong.

Alan

#26 lore raw

Re: [PATCH v2 10/30] Add x86-specific parity functions

Quoted 3 lines · One Thousand Gnomes

Even that would still be wrong for the smaller parity values. The CPU supports 8bit parity directly going back to the 8086 so the implementation for 8bit and I think 16bit is still wrong.

I was objecting to the unnecessary replication of the hweight/popcnt glue.

And yes, one could look up the definition of the parity flag on x86 and then base the implementation of all those smaller ones on that as the hardware does it for one practically for free there.

:-)

Signature · 5 lines
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 
#27 lore raw

Re: [PATCH v2 10/30] Add x86-specific parity functions

Quoted 4 lines · Borislav Petkov
Quoted 3 lines · One Thousand Gnomes

Even that would still be wrong for the smaller parity values. The CPU supports 8bit parity directly going back to the 8086 so the implementation for 8bit and I think 16bit is still wrong.

Quoted 9 lines

I was objecting to the unnecessary replication of the hweight/popcnt glue.

And yes, one could look up the definition of the parity flag on x86 and then base the implementation of all those smaller ones on that as the hardware does it for one practically for free there.

:-)

SETcc (SETPO etc.) added since 80386, is this a problem?

#28 lore raw

Re: [PATCH v2 10/30] Add x86-specific parity functions

Quoted 1 line · Zeng Zhaoxiu

SETcc (SETPO etc.) added since 80386, is this a problem?

Sounds to me you didn't make the effort to look up the definition of the Parity Flag...

Signature · 5 lines
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 
#29 lore raw

Re: [PATCH v2 10/30] Add x86-specific parity functions

In reply to One Thousand Gnomes
Quoted 5 lines · One Thousand Gnomes

Even that would still be wrong for the smaller parity values. The CPU supports 8bit parity directly going back to the 8086 so the implementation for 8bit and I think 16bit is still wrong.

Alan

I don't know where the errors. X86 is new to me.

The definition of the parity flag on x86 from Wikipedia:

In x86 processors, the parity flag reflects the parity only of the least significant byte of the result, and is set if the number of set bits of ones is even. According to 80386 Intel manual, the parity flag is changed in the x86 processor family by the following instructions:

    All arithmetic instructions;
    Compare instruction (equivalent to a subtract instruction without storing the result);
    Logical instructions - XOR, AND, OR;
    the TEST instruction (equivalent to the AND instruction without storing the result).
    the POPF instruction
#30 lore raw

Re: [PATCH v2 10/30] Add x86-specific parity functions

Quoted 1 line · Zeng Zhaoxiu

I don't know where the errors. X86 is new to me.

Ok, let me try again by pasting here the relevant text from the manual:

"Parity Flag (PF). Bit 2. Hardware sets the parity flag to 1 if there is an even number of 1 bits in the least-significant byte of the last result of certain operations. Otherwise (i.e., for an odd number of 1 bits), hardware clears the flag to 0. Software can read the flag to implement parity checking."

Signature · 5 lines
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 
#31 lore raw

Re: [PATCH v2 10/30] Add x86-specific parity functions

In reply to Borislav Petkov
Quoted 27 lines · Borislav Petkov
Quoted 14 lines · On Wed, Apr 06, 2016 at 05:14:45PM +0800, [email protected] wrote:

From: Zhaoxiu Zeng <[email protected]>

Use alternatives, lifted from arch_hweight

---
  arch/x86/include/asm/arch_hweight.h |   5 ++
  arch/x86/include/asm/arch_parity.h  | 102 ++++++++++++++++++++++++++++++++++++
  arch/x86/include/asm/bitops.h       |   4 +-
  arch/x86/lib/Makefile               |   8 +++
  arch/x86/lib/parity.c               |  32 ++++++++++++
  5 files changed, 150 insertions(+), 1 deletion(-)

create mode 100644 arch/x86/include/asm/arch_parity.h create mode 100644 arch/x86/lib/parity.c

...

arch/x86/include/asm/arch_parity.h line 73

Quoted 8 lines
arch/x86/include/asm/arch_parity.h new file +8 -0
+static __always_inline unsigned int __arch_parity32(unsigned int w)
+{
+	unsigned int res;
+
+	asm(ALTERNATIVE("call __sw_parity32", POPCNT32 "; and $1, %0", X86_FEATURE_POPCNT)
+		: "="REG_OUT (res)
+		: REG_IN (w)
+		: "cc");

So why all that churn instead of simply doing:

Quoted 7 lines

static __always_inline unsigned int __arch_parity32(unsigned int w)

{
	return hweight32(w) & 1;
}

Ditto for the 64-bit version.

__sw_parity32 is faster than __sw_hweight32.
I don't know how many CPUs do not support the popc, if they are outdated, use __arch_hweight32 is the easiest way.

#32 lore raw

Re: [PATCH v2 10/30] Add x86-specific parity functions

Quoted 3 lines · Zeng Zhaoxiu

__sw_parity32 is faster than __sw_hweight32.
I don't know how many CPUs do not support the popc, if they are outdated, use __arch_hweight32 is the easiest way.

I don't really understand what you're trying to tell me here. And it's not like I didn't try.

Signature · 5 lines
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 
#33 lore raw

Re: [PATCH v2 10/30] Add x86-specific parity functions

In reply to [email protected]
Quoted 3 lines · [email protected] writes:

From: Zhaoxiu Zeng <[email protected]>

Use alternatives, lifted from arch_hweight

Is there actually anything performance critical in the kernel that uses parity?

FWIW the arch hweight custom calling convention is a problem for LTO because it needs different special flags, so I usually have to disable it. Likely other reasonable usages, such as automatic source code analysis, and other tool chain based usages have similar problems.

As far as I can tell both for hweight and likely for parity it is badly overengineering and normal calling conventions would work as well, and cause much less problems.

So if parity is really worth adding here (which I find doubtful, but you may have numbers), please add it without these magic calling hacks.

-Andi

Signature · 1 line
[email protected] -- Speaking for myself only
#34 lore raw

Re: [PATCH v2 10/30] Add x86-specific parity functions

Quoted 17 lines · Andi Kleen
Quoted 3 lines · [email protected] writes:

From: Zhaoxiu Zeng <[email protected]>

Use alternatives, lifted from arch_hweight

Is there actually anything performance critical in the kernel that uses parity?

FWIW the arch hweight custom calling convention is a problem for LTO because it needs different special flags, so I usually have to disable it. Likely other reasonable usages, such as automatic source code analysis, and other tool chain based usages have similar problems.

As far as I can tell both for hweight and likely for parity it is badly overengineering and normal calling conventions would work as well, and cause much less problems.

Quoted 6 lines

So if parity is really worth adding here (which I find doubtful, but you may have numbers), please add it without these magic calling hacks.

-Andi

Thanks. I will instead use __arch_hweight.

#35 lore raw

Re: [PATCH v2 10/30] Add x86-specific parity functions

In reply to Andi Kleen
Quoted 14 lines · Andi Kleen
Quoted 3 lines · [email protected] writes:

From: Zhaoxiu Zeng <[email protected]>

Use alternatives, lifted from arch_hweight

Is there actually anything performance critical in the kernel that uses parity?

FWIW the arch hweight custom calling convention is a problem for LTO because it needs different special flags, so I usually have to disable it. Likely other reasonable usages, such as automatic source code analysis, and other tool chain based usages have similar problems.

Quoted 7 lines

As far as I can tell both for hweight and likely for parity it is badly overengineering and normal calling conventions would work as well, and cause much less problems.

So if parity is really worth adding here (which I find doubtful, but you may have numbers), please add it without these magic calling hacks.

Hweight custom calling convention caused crashes with KCOV coverage. We had to disable instrumentation of the file.

#36 lore raw

Re: [PATCH v2 10/30] Add x86-specific parity functions

Quoted 2 lines · Dmitry Vyukov

Hweight custom calling convention caused crashes with KCOV coverage. We had to disable instrumentation of the file.

I guess we can do something like this:

       if (likely(static_cpu_has(X86_FEATURE_POPCNT)))
               asm volatile(POPCNT32
                            : "="REG_OUT (res)
                            : REG_IN (w));
       else
               res = __sw_hweight32(w);

and get rid of the custom calling convention.

Along with some numbers showing that the change doesn't cause any noticeable slowdown...

Signature · 5 lines
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 
#37 lore raw

RFC PATCH 1/1 x86/hweight: Get rid of the special calling convention

Quoted 9 lines · Borislav Petkov

I guess we can do something like this:

       if (likely(static_cpu_has(X86_FEATURE_POPCNT)))
               asm volatile(POPCNT32
                            : "="REG_OUT (res)
                            : REG_IN (w));
       else
               res = __sw_hweight32(w);
Quoted 4 lines

and get rid of the custom calling convention.

Along with some numbers showing that the change doesn't cause any noticeable slowdown...

Ok, here's something which seems to build and boot in kvm.

I like how we don't need the special calling conventions anymore and we can actually say "popcnt .." and gcc selects registers.

The include files hackery is kinda nasty but I had to do it because I needed to be able to use static_cpu_has() in a header and including asm/cpufeature.h pulls in all kinds of nasty dependencies. I'm certainly open for better ideas...

---
From: Borislav Petkov <[email protected]>
Date: Wed, 4 May 2016 18:52:09 +0200
Subject: [PATCH] x86/hweight: Get rid of the special calling convention

People complained about ARCH_HWEIGHT_CFLAGS and how it throws a wrench into kcov, lto, etc, experimentation.

And its not like we absolutely need it so let's get rid of it and streamline it a bit. I had to do some carving out of facilities so that the include hell doesn't swallow me but other than that, the new __arch_hweight*() versions look much more palatable and gcc is more free to select registers than us hardcoding them in the insn bytes.

---
 arch/x86/Kconfig                      |   5 --
 arch/x86/include/asm/arch_hweight.h   |  43 ++++---------
 arch/x86/include/asm/cpufeature.h     | 112 +-------------------------------
 arch/x86/include/asm/cpuinfo.h        |  65 +++++++++++++++++++
 arch/x86/include/asm/processor.h      |  63 +-----------------
 arch/x86/include/asm/static_cpu_has.h | 116 ++++++++++++++++++++++++++++++++++
 lib/Makefile                          |   5 --
 7 files changed, 197 insertions(+), 212 deletions(-)
 create mode 100644 arch/x86/include/asm/cpuinfo.h
 create mode 100644 arch/x86/include/asm/static_cpu_has.h
arch/x86/Kconfig +0 -5
index 7bb15747fea2..79e0bcd61cb1 100644
@@ -292,11 +292,6 @@ config X86_32_LAZY_GS
 	def_bool y
 	depends on X86_32 && !CC_STACKPROTECTOR
 
-config ARCH_HWEIGHT_CFLAGS
-	string
-	default "-fcall-saved-ecx -fcall-saved-edx" if X86_32
-	default "-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" if X86_64
-
 config ARCH_SUPPORTS_UPROBES
 	def_bool y
 
arch/x86/include/asm/arch_hweight.h +13 -30

62 lines not on this page · raw message

arch/x86/include/asm/cpufeature.h +2 -110

136 lines not on this page · raw message

arch/x86/include/asm/cpuinfo.h new file +65 -0

65 lines not on this page · raw message

arch/x86/include/asm/processor.h +1 -62

81 lines not on this page · raw message

arch/x86/include/asm/static_cpu_has.h new file +116 -0

116 lines not on this page · raw message

lib/Makefile +0 -5
index a65e9a861535..55ad20701dc0 100644
@@ -15,9 +15,6 @@ KCOV_INSTRUMENT_rbtree.o := n
 KCOV_INSTRUMENT_list_debug.o := n
 KCOV_INSTRUMENT_debugobjects.o := n
 KCOV_INSTRUMENT_dynamic_debug.o := n
-# Kernel does not boot if we instrument this file as it uses custom calling
-# convention (see CONFIG_ARCH_HWEIGHT_CFLAGS).
-KCOV_INSTRUMENT_hweight.o := n
 
 lib-y := ctype.o string.o vsprintf.o cmdline.o \
 	 rbtree.o radix-tree.o dump_stack.o timerqueue.o\
@@ -72,8 +69,6 @@ obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
 obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o
 obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
 
-GCOV_PROFILE_hweight.o := n
-CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS))
 obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
 
 obj-$(CONFIG_BTREE) += btree.o
Signature · 4 lines
2.7.3

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 
#38 lore raw

Re: [RFC PATCH] x86/hweight: Get rid of the special calling convention

Quoted 98 lines · Borislav Petkov
Quoted 9 lines · Borislav Petkov

I guess we can do something like this:

       if (likely(static_cpu_has(X86_FEATURE_POPCNT)))
               asm volatile(POPCNT32
                            : "="REG_OUT (res)
                            : REG_IN (w));
       else
               res = __sw_hweight32(w);
Quoted 4 lines

and get rid of the custom calling convention.

Along with some numbers showing that the change doesn't cause any noticeable slowdown...

Ok, here's something which seems to build and boot in kvm.

I like how we don't need the special calling conventions anymore and we can actually say "popcnt .." and gcc selects registers.

The include files hackery is kinda nasty but I had to do it because I needed to be able to use static_cpu_has() in a header and including asm/cpufeature.h pulls in all kinds of nasty dependencies. I'm certainly open for better ideas...

---
From: Borislav Petkov <[email protected]>
Date: Wed, 4 May 2016 18:52:09 +0200
Subject: [PATCH] x86/hweight: Get rid of the special calling convention

People complained about ARCH_HWEIGHT_CFLAGS and how it throws a wrench into kcov, lto, etc, experimentation.

And its not like we absolutely need it so let's get rid of it and streamline it a bit. I had to do some carving out of facilities so that the include hell doesn't swallow me but other than that, the new __arch_hweight*() versions look much more palatable and gcc is more free to select registers than us hardcoding them in the insn bytes.

---
 arch/x86/Kconfig                      |   5 --
 arch/x86/include/asm/arch_hweight.h   |  43 ++++---------
 arch/x86/include/asm/cpufeature.h     | 112 +-------------------------------
 arch/x86/include/asm/cpuinfo.h        |  65 +++++++++++++++++++
 arch/x86/include/asm/processor.h      |  63 +-----------------
 arch/x86/include/asm/static_cpu_has.h | 116 ++++++++++++++++++++++++++++++++++
 lib/Makefile                          |   5 --
 7 files changed, 197 insertions(+), 212 deletions(-)
 create mode 100644 arch/x86/include/asm/cpuinfo.h
 create mode 100644 arch/x86/include/asm/static_cpu_has.h
arch/x86/Kconfig +0 -5
index 7bb15747fea2..79e0bcd61cb1 100644
@@ -292,11 +292,6 @@ config X86_32_LAZY_GS
        def_bool y
        depends on X86_32 && !CC_STACKPROTECTOR
 
-config ARCH_HWEIGHT_CFLAGS
-       string
-       default "-fcall-saved-ecx -fcall-saved-edx" if X86_32
-       default "-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" if X86_64
-
 config ARCH_SUPPORTS_UPROBES
        def_bool y
 
arch/x86/include/asm/arch_hweight.h +1 -20
index 02e799fa43d1..6c1a2d500c4c 100644
@@ -2,36 +2,18 @@
 #define _ASM_X86_HWEIGHT_H
 
 #include <asm/cpufeatures.h>
+#include <asm/static_cpu_has.h>
 
-#ifdef CONFIG_64BIT
-/* popcnt %edi, %eax -- redundant REX prefix for alignment */
-#define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7"
-/* popcnt %rdi, %rax */
-#define POPCNT64 ".byte 0xf3,0x48,0x0f,0xb8,0xc7"
-#define REG_IN "D"
-#define REG_OUT "a"
-#else
-/* popcnt %eax, %eax */
-#define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc0"
-#define REG_IN "a"
-#define REG_OUT "a"
-#endif
-
-/*
- * __sw_hweightXX are called from within the alternatives below
- * and callee-clobbered registers need to be taken care of. See
- * ARCH_HWEIGHT_CFLAGS in <arch/x86/Kconfig> for the respective
- * compiler switches.
- */

arch/x86/include/asm/arch_hweight.h line 12

Quoted 10 lines
arch/x86/include/asm/arch_hweight.h +3 -4
 static __always_inline unsigned int __arch_hweight32(unsigned int w)
 {
-       unsigned int res = 0;
+       unsigned int res;
 
-       asm (ALTERNATIVE("call __sw_hweight32", POPCNT32, X86_FEATURE_POPCNT)
-                    : "="REG_OUT (res)
-                    : REG_IN (w));
+       if (likely(static_cpu_has(X86_FEATURE_POPCNT))) {
+               asm volatile("popcnt %[w], %[res]" : [res] "=r" (res) : [w] "r" (w));

Do all supported versions of the assembler know of the popcnt instruction? That's why is was open coded before. The problem is Intel and AMD are constantly adding new instructions and it's a long cycle for the user's assembler to get updated.

--
Brian Gerst

#39 lore raw

Re: [RFC PATCH] x86/hweight: Get rid of the special calling convention

Quoted 7 lines · Brian Gerst

arch/x86/include/asm/arch_hweight.h line 12

Quoted 6 lines
arch/x86/include/asm/arch_hweight.h +2 -3
-       asm (ALTERNATIVE("call __sw_hweight32", POPCNT32, X86_FEATURE_POPCNT)
-                    : "="REG_OUT (res)
-                    : REG_IN (w));
+       if (likely(static_cpu_has(X86_FEATURE_POPCNT))) {
+               asm volatile("popcnt %[w], %[res]" : [res] "=r" (res) : [w] "r" (w));
Quoted 5 lines

Do all supported versions of the assembler know of the popcnt instruction? That's why is was open coded before. The problem is Intel and AMD are constantly adding new instructions and it's a long cycle for the user's assembler to get updated.

Most likely not. It would be nice to have some more uniform solution to that. I'm wondering if we could use the -Wa option to load some kind of macro package.

-hpa

#40 lore raw

Re: [RFC PATCH] x86/hweight: Get rid of the special calling convention

Quoted 3 lines · H. Peter Anvin

Most likely not. It would be nice to have some more uniform solution to that. I'm wondering if we could use the -Wa option to load some kind of macro package.

Lemme try out some old compilers first, I'm guessing 3.2 won't know about popcnt...

Signature · 5 lines
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 
#41 lore raw

Re: [RFC PATCH] x86/hweight: Get rid of the special calling convention

Quoted 8 lines · Borislav Petkov
Quoted 3 lines · H. Peter Anvin

Most likely not. It would be nice to have some more uniform solution to that. I'm wondering if we could use the -Wa option to load some kind of macro package.

Lemme try out some old compilers first, I'm guessing 3.2 won't know about popcnt...

Sigh. Doesn't look like -Wa is going to help due to the lack of the equivalent of an -include option in gas.

-hpa

#42 lore raw

Re: [RFC PATCH] x86/hweight: Get rid of the special calling convention

Quoted 2 lines · H. Peter Anvin

Sigh. Doesn't look like -Wa is going to help due to the lack of the equivalent of an -include option in gas.

So much for the register "freedom" - I'll resurrect the hardcoded insn bytes. :-\

Unless my gcc friends have some other ideas...

sarge:~# gcc --version
gcc (GCC) 3.3.5 (Debian 1:3.3.5-13)
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
sarge:~# cat popcnt.c
int main(void)
{
        int a, b;
        asm volatile("popcnt %0, %1" : "=r" (a) : "r" (b));

        return 0;
}
sarge:~# gcc -Wall -o popcnt{,.c}
/tmp/ccHmmgjH.s: Assembler messages:
/tmp/ccHmmgjH.s:14: Error: no such instruction: `popcnt %eax,%eax'
sarge:~#
Signature · 5 lines
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 
#43 lore raw

Re: [RFC PATCH] x86/hweight: Get rid of the special calling convention

Quoted 8 lines · Borislav Petkov
Quoted 2 lines · H. Peter Anvin

Sigh. Doesn't look like -Wa is going to help due to the lack of the equivalent of an -include option in gas.

So much for the register "freedom" - I'll resurrect the hardcoded insn bytes. :-\

Unless my gcc friends have some other ideas...

There is the option of looking for assembler support for popcnt and only hard-code the register if not supported. This is where being able to insert a macro package would help...

-hpa

#44 lore raw

Re: [RFC PATCH] x86/hweight: Get rid of the special calling convention

In reply to Borislav Petkov
Quoted 8 lines · Borislav Petkov
Quoted 2 lines · H. Peter Anvin

Sigh. Doesn't look like -Wa is going to help due to the lack of the equivalent of an -include option in gas.

So much for the register "freedom" - I'll resurrect the hardcoded insn bytes. :-\

Unless my gcc friends have some other ideas...

You can probe the assembler in the Makefile and pass a define, like it is done by the dwarf code. When the define is not set use the hard coded registers

Not very scalable, but may work in this case.

Longer term would probably need compiler probes at Kconfig time (this would be useful for a lot of things)

-Andi

Signature · 1 line
[email protected] -- Speaking for myself only.
#45 lore raw

Re: [RFC PATCH] x86/hweight: Get rid of the special calling convention

In reply to Borislav Petkov
Quoted 20 lines · Borislav Petkov
Quoted 2 lines · H. Peter Anvin

Sigh. Doesn't look like -Wa is going to help due to the lack of the equivalent of an -include option in gas.

So much for the register "freedom" - I'll resurrect the hardcoded insn bytes. :-\

Unless my gcc friends have some other ideas...

sarge:~# gcc --version
gcc (GCC) 3.3.5 (Debian 1:3.3.5-13)
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
sarge:~# cat popcnt.c
int main(void)
{
        int a, b;
Quoted 8 lines
        asm volatile("popcnt %0, %1" : "=r" (a) : "r" (b));

        return 0;
}
sarge:~# gcc -Wall -o popcnt{,.c}
/tmp/ccHmmgjH.s: Assembler messages:
/tmp/ccHmmgjH.s:14: Error: no such instruction: `popcnt %eax,%eax'
sarge:~#

You are looking at the version of a wrong program. gcc doesn't process assembly, it generates it. as is part of binutils, not gcc. "as --version".

#46 lore raw

Re: [RFC PATCH] x86/hweight: Get rid of the special calling convention

Quoted 3 lines · Denys Vlasenko

You are looking at the version of a wrong program. gcc doesn't process assembly, it generates it. as is part of binutils, not gcc. "as --version".

I know. It doesn't matter a whole lot in this case if there's a subset of gas versions which simply don't know about POPCNT and we do use those in the kernel build.

Pending a better solution, I'll simply revert to the old, spelled POPCNT bytes and don't bother with versions. Especially if someone tries to build the kernel with some other compiler...

Signature · 5 lines
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 
#47 lore raw

PATCH 1/1 x86/hweight: Get rid of the special calling convention

From: Borislav Petkov <[email protected]>
Date: Wed, 4 May 2016 18:52:09 +0200
Subject: [PATCH -v2] x86/hweight: Get rid of the special calling convention

People complained about ARCH_HWEIGHT_CFLAGS and how it throws a wrench into kcov, lto, etc, experimentation.

And its not like we absolutely need it so let's get rid of it and streamline it a bit. I had to do some carving out of facilities so that the include hell doesn't swallow me.

We still need to hardcode POPCNT and register operands as some old gas versions which we support, do not know about POPCNT.

---

-v2: Revert to the old spelled-out POPCNT insn bytes.

 arch/x86/Kconfig                      |   5 --
 arch/x86/include/asm/arch_hweight.h   |  38 +++++------
 arch/x86/include/asm/cpufeature.h     | 112 +-------------------------------
 arch/x86/include/asm/cpuinfo.h        |  65 +++++++++++++++++++
 arch/x86/include/asm/processor.h      |  63 +-----------------
 arch/x86/include/asm/static_cpu_has.h | 116 ++++++++++++++++++++++++++++++++++
 lib/Makefile                          |   5 --
 7 files changed, 204 insertions(+), 200 deletions(-)
 create mode 100644 arch/x86/include/asm/cpuinfo.h
 create mode 100644 arch/x86/include/asm/static_cpu_has.h
arch/x86/Kconfig +0 -5
index 7bb15747fea2..79e0bcd61cb1 100644
@@ -292,11 +292,6 @@ config X86_32_LAZY_GS
 	def_bool y
 	depends on X86_32 && !CC_STACKPROTECTOR
 
-config ARCH_HWEIGHT_CFLAGS
-	string
-	default "-fcall-saved-ecx -fcall-saved-edx" if X86_32
-	default "-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" if X86_64
-
 config ARCH_SUPPORTS_UPROBES
 	def_bool y
 
arch/x86/include/asm/arch_hweight.h +20 -18
index 02e799fa43d1..324f5fb30392 100644
@@ -2,10 +2,11 @@
 #define _ASM_X86_HWEIGHT_H
 
 #include <asm/cpufeatures.h>
+#include <asm/static_cpu_has.h>
 
 #ifdef CONFIG_64BIT
-/* popcnt %edi, %eax -- redundant REX prefix for alignment */
-#define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7"
+/* popcnt %edi, %eax */
+#define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc7"
 /* popcnt %rdi, %rax */
 #define POPCNT64 ".byte 0xf3,0x48,0x0f,0xb8,0xc7"
 #define REG_IN "D"
@@ -17,21 +18,19 @@
 #define REG_OUT "a"
 #endif
 
-/*
- * __sw_hweightXX are called from within the alternatives below
- * and callee-clobbered registers need to be taken care of. See
- * ARCH_HWEIGHT_CFLAGS in <arch/x86/Kconfig> for the respective
- * compiler switches.
- */
 static __always_inline unsigned int __arch_hweight32(unsigned int w)
 {
-	unsigned int res = 0;
+	unsigned int res;
 
-	asm (ALTERNATIVE("call __sw_hweight32", POPCNT32, X86_FEATURE_POPCNT)
-		     : "="REG_OUT (res)
-		     : REG_IN (w));
+	if (likely(static_cpu_has(X86_FEATURE_POPCNT))) {
+		/* popcnt %eax, %eax */
+		asm volatile(POPCNT32
+				: "="REG_OUT (res)
+				: REG_IN (w));
 
-	return res;
+		return res;
+	}
+	return __sw_hweight32(w);
 }
 
 static inline unsigned int __arch_hweight16(unsigned int w)
@@ -53,13 +52,16 @@ static inline unsigned long __arch_hweight64(__u64 w)
 #else
 static __always_inline unsigned long __arch_hweight64(__u64 w)
 {
-	unsigned long res = 0;
+	unsigned long res;
 
-	asm (ALTERNATIVE("call __sw_hweight64", POPCNT64, X86_FEATURE_POPCNT)
-		     : "="REG_OUT (res)
-		     : REG_IN (w));
+	if (likely(static_cpu_has(X86_FEATURE_POPCNT))) {
+		asm volatile(POPCNT64
+				: "="REG_OUT (res)
+				: REG_IN (w));
 
-	return res;
+		return res;
+	}
+	return __sw_hweight64(w);
 }
 #endif /* CONFIG_X86_32 */
 
arch/x86/include/asm/cpufeature.h +2 -110

136 lines not on this page · raw message

arch/x86/include/asm/cpuinfo.h new file +65 -0

65 lines not on this page · raw message

arch/x86/include/asm/processor.h +1 -62

81 lines not on this page · raw message

arch/x86/include/asm/static_cpu_has.h new file +116 -0

116 lines not on this page · raw message

lib/Makefile +0 -5
index a65e9a861535..55ad20701dc0 100644
@@ -15,9 +15,6 @@ KCOV_INSTRUMENT_rbtree.o := n
 KCOV_INSTRUMENT_list_debug.o := n
 KCOV_INSTRUMENT_debugobjects.o := n
 KCOV_INSTRUMENT_dynamic_debug.o := n
-# Kernel does not boot if we instrument this file as it uses custom calling
-# convention (see CONFIG_ARCH_HWEIGHT_CFLAGS).
-KCOV_INSTRUMENT_hweight.o := n
 
 lib-y := ctype.o string.o vsprintf.o cmdline.o \
 	 rbtree.o radix-tree.o dump_stack.o timerqueue.o\
@@ -72,8 +69,6 @@ obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
 obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o
 obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
 
-GCOV_PROFILE_hweight.o := n
-CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS))
 obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
 
 obj-$(CONFIG_BTREE) += btree.o
Signature · 1 line
2.7.3
#48 lore raw

Re: [PATCH -v2] x86/hweight: Get rid of the special calling convention

Quoted 9 lines · Borislav Petkov

static __always_inline unsigned int __arch_hweight32(unsigned int w) {

arch/x86/include/asm/arch_hweight.h +2 -4
-	unsigned int res = 0;
+	unsigned int res;
 
-	asm (ALTERNATIVE("call __sw_hweight32", POPCNT32, X86_FEATURE_POPCNT)
-		     : "="REG_OUT (res)
-		     : REG_IN (w));
+	if (likely(static_cpu_has(X86_FEATURE_POPCNT))) {

arch/x86/include/asm/arch_hweight.h line 34

Quoted 10 lines
arch/x86/include/asm/arch_hweight.h +7 -1
+		/* popcnt %eax, %eax */
+		asm volatile(POPCNT32
+				: "="REG_OUT (res)
+				: REG_IN (w));
 
-	return res;
+		return res;
+	}
+	return __sw_hweight32(w);
 }

So what was wrong with using the normal thunk_*.S wrappers for the calls? That would allow you to use the alternative() stuff which does generate smaller code.

#49 lore raw

Re: [PATCH -v2] x86/hweight: Get rid of the special calling convention

Quoted 3 lines · Peter Zijlstra

So what was wrong with using the normal thunk_*.S wrappers for the calls? That would allow you to use the alternative() stuff which does generate smaller code.

Yeah, so a full allyesconfig vmlinux gives ~22K .text size increase:

text data bss dec hex filename

85391772        105899159       70717440        262008371       f9dee33 vmlinux 	before
85413991        105899223       70746112        262059326       f9eb53e vmlinux		after

--------
22219

I guess I better try the thunk stuff, might make it smaller.

Also, in the next version I'll split out the static_cpu_has() move into a separate patch, as you requested on IRC.

Thanks.

Signature · 5 lines
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 
#50 lore raw

Re: [PATCH -v2] x86/hweight: Get rid of the special calling convention

In reply to Peter Zijlstra
Quoted 16 lines · Peter Zijlstra

arch/x86/include/asm/arch_hweight.h

Quoted 6 lines · Borislav Petkov

static __always_inline unsigned int __arch_hweight32(unsigned int w) {

arch/x86/include/asm/arch_hweight.h +1 -2
-	unsigned int res = 0;
+	unsigned int res;
 
-	asm (ALTERNATIVE("call __sw_hweight32", POPCNT32,

X86_FEATURE_POPCNT)

Quoted 8 lines
arch/x86/include/asm/arch_hweight.h +5 -2
-		     : "="REG_OUT (res)
-		     : REG_IN (w));
+	if (likely(static_cpu_has(X86_FEATURE_POPCNT))) {
+		/* popcnt %eax, %eax */
+		asm volatile(POPCNT32
+				: "="REG_OUT (res)
+				: REG_IN (w));
Quoted 9 lines

arch/x86/include/asm/arch_hweight.h line 34

Quoted 5 lines
arch/x86/include/asm/arch_hweight.h +3 -1
-	return res;
+		return res;
+	}
+	return __sw_hweight32(w);
 }

So what was wrong with using the normal thunk_*.S wrappers for the calls? That would allow you to use the alternative() stuff which does generate smaller code.

Also, to be fair... if the problem is with these being in C then we could just do it in assembly easily enough.

Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.
#51 lore raw

Re: [PATCH -v2] x86/hweight: Get rid of the special calling convention

Quoted 2 lines · H. Peter Anvin

Also, to be fair... if the problem is with these being in C then we could just do it in assembly easily enough.

I thought about converting the __sw_hweight* variants to asm but __sw_hweight32, for example, is 55 bytes here and that's a lot.

Or do you have a better idea?

peterz's sounds ok to me: we call a thunk which then calls __sw_hweight* after having saved regs properly - problem solved.

Signature · 5 lines
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 
#52 lore raw

Re: [PATCH -v2] x86/hweight: Get rid of the special calling convention

Quoted 4 lines · Borislav Petkov
Quoted 2 lines · H. Peter Anvin

Also, to be fair... if the problem is with these being in C then we could just do it in assembly easily enough.

Quoted 8 lines

I thought about converting the __sw_hweight* variants to asm but __sw_hweight32, for example, is 55 bytes here and that's a lot.

Or do you have a better idea?

peterz's sounds ok to me: we call a thunk which then calls __sw_hweight* after having saved regs properly - problem solved.

I didn't mean inline assembly.

-hpa

#53 lore raw

Re: [PATCH -v2] x86/hweight: Get rid of the special calling convention

Quoted 1 line · H. Peter Anvin

I didn't mean inline assembly.

How does that matter?

The problem is having as less insn bytes as possible and the minimal size we can do is issuing POPCNT everywhere which is 4 or 5 bytes. The alternatives then replace that with a CALL which is also 5 bytes.

The way I did it now, it adds 22K more to allyesconfig vmlinux due to the static_cpu_has doubled alternatives sections and the JMPs. The thunks will keep those 5 bytes *and* get rid of the calling convention without the growth.

Or?

Signature · 5 lines
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 
#54 lore raw

Re: [PATCH -v2] x86/hweight: Get rid of the special calling convention

Quoted 9 lines · Borislav Petkov
Quoted 1 line · H. Peter Anvin

I didn't mean inline assembly.

How does that matter?

The problem is having as less insn bytes as possible and the minimal size we can do is issuing POPCNT everywhere which is 4 or 5 bytes. The alternatives then replace that with a CALL which is also 5 bytes.

Quoted 6 lines

The way I did it now, it adds 22K more to allyesconfig vmlinux due to the static_cpu_has doubled alternatives sections and the JMPs. The thunks will keep those 5 bytes *and* get rid of the calling convention without the growth.

Or?

I think he meant the out of line version would be asm, so you could control what registers were clobbered.

--
Brian Gerst

#55 lore raw

Re: [PATCH -v2] x86/hweight: Get rid of the special calling convention

Quoted 2 lines · Brian Gerst

I think he meant the out of line version would be asm, so you could control what registers were clobbered.

Yeah, it might save a few cycles on the call, but given that most machines should have popcnt these days is it worth the hassle/cost of duplicating the lib/hweight.c magic in asm (and remember, twice, once for 32bit and once for 64bit) ?

#56 lore raw

Re: [PATCH -v2] x86/hweight: Get rid of the special calling convention

Quoted 4 lines · Peter Zijlstra

Yeah, it might save a few cycles on the call, but given that most machines should have popcnt these days is it worth the hassle/cost of duplicating the lib/hweight.c magic in asm (and remember, twice, once for 32bit and once for 64bit) ?

Makes sense to me - we can do the funky cool stuff but considering the fact that we have all the required bits already, I think we should do the thunking game and be done with it.

I guess we're older, lazy and more realists now...

Signature · 5 lines
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 
#57 lore raw

Re: [PATCH -v2] x86/hweight: Get rid of the special calling convention

In reply to Peter Zijlstra
Quoted 9 lines · Peter Zijlstra
Quoted 2 lines · Brian Gerst

I think he meant the out of line version would be asm, so you could control what registers were clobbered.

Yeah, it might save a few cycles on the call, but given that most machines should have popcnt these days is it worth the hassle/cost of duplicating the lib/hweight.c magic in asm (and remember, twice, once for 32bit and once for 64bit) ?

I was thinking it isn't really very complex code even in assembly as it is super-regular; you can even crib the gcc-generated code if you wish.

Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.
#58 lore raw

Re: [PATCH -v2] x86/hweight: Get rid of the special calling convention

Quoted 3 lines · H. Peter Anvin

I was thinking it isn't really very complex code even in assembly as it is super-regular; you can even crib the gcc-generated code if you wish.

Do I wanna do experiments in asm? Always! :-)

Ok, so I did steal gcc -m32 -O3 output because there it uses only one additional register. So how about this (only __sw_hweight32 today):

#ifdef CONFIG_X86_32

# define PUSH_DX        "pushl %%edx\n\t"
# define POP_DX         "popl %%edx\n\t"
#else
# define PUSH_DX        "pushq %%rdx\n\t"
# define POP_DX         "popq %%rdx\n\t"
#endif

unsigned int __sw_hweight32(unsigned int w)

{
        asm volatile(PUSH_DX
                     "movl %[w], %%edx\n\t"                     /* w -> t */
                     "shrl %%edx\n\t"                           /* t >> 1 */
                     "andl $0x55555555, %%edx\n\t"              /* t & 0x55555555 */
                     "subl %%edx, %[w]\n"                       /* w -= t */
                     "\n\t"
                     "movl %[w], %%edx\n\t"                     /* w -> t */
                     "shrl $2, %[w]\n\t"                        /* w_tmp >> 2 */
                     "andl $0x33333333, %%edx\n\t"              /* t & 0x33333333 */
                     "andl $0x33333333, %[w]\n\t"               /* w_tmp & 0x33333333 */
                     "addl %%edx, %[w]\n"                       /* w = w_tmp + t */
                     "\n\t"
                     "movl %[w], %%edx\n\t"                     /* w -> t */
                     "shrl $4, %%edx\n\t"                       /* t >> 4 */
                     "addl %%edx, %[w]\n\t"                     /* w_tmp += t */
                     "andl  $0x0f0f0f0f, %[w]\n\t"              /* w_tmp &= 0x0f0f0f0f */
                     "imull $0x01010101, %[w], %[w]\n\t"        /* w_tmp *= 0x01010101 */
                     "shrl $24, %[w]\n\t"                       /* w = w_tmp >> 24 */
                     POP_DX
                     : [w] "+r" (w));

        return w;
}

I've chosen rDX as a temp because gcc takes that one but it doesn't matter which - we're stashing it.

And then we rely on gcc to figure out which reg to use for w. It ends up using rAX as that is the return reg which fits nicely with our intention of returning POPCNT values in rAX.

I'm guessing we can just as well write %%rax in the asm because we're returning that value and that's ABI.

Generated asm looks ok, only on 64-bit it does one

movl %edi, %eax # w, w

before the inline asm in order to stick w in rAX.

Complaints?

Full diff:

---

arch/x86/Kconfig +0 -5
index 7bb15747fea2..79e0bcd61cb1 100644
@@ -292,11 +292,6 @@ config X86_32_LAZY_GS
 	def_bool y
 	depends on X86_32 && !CC_STACKPROTECTOR
 
-config ARCH_HWEIGHT_CFLAGS
-	string
-	default "-fcall-saved-ecx -fcall-saved-edx" if X86_32
-	default "-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" if X86_64
-
 config ARCH_SUPPORTS_UPROBES
 	def_bool y
 
arch/x86/include/asm/arch_hweight.h +16 -16
index 02e799fa43d1..7dd97eaba67d 100644
@@ -2,10 +2,11 @@
 #define _ASM_X86_HWEIGHT_H
 
 #include <asm/cpufeatures.h>
+#include <asm/static_cpu_has.h>
 
 #ifdef CONFIG_64BIT
-/* popcnt %edi, %eax -- redundant REX prefix for alignment */
-#define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7"
+/* popcnt %edi, %eax */
+#define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc7"
 /* popcnt %rdi, %rax */
 #define POPCNT64 ".byte 0xf3,0x48,0x0f,0xb8,0xc7"
 #define REG_IN "D"
@@ -17,19 +18,15 @@
 #define REG_OUT "a"
 #endif
 
-/*
- * __sw_hweightXX are called from within the alternatives below
- * and callee-clobbered registers need to be taken care of. See
- * ARCH_HWEIGHT_CFLAGS in <arch/x86/Kconfig> for the respective
- * compiler switches.
- */
+#define __HAVE_ARCH_SW_HWEIGHT
+
 static __always_inline unsigned int __arch_hweight32(unsigned int w)
 {
-	unsigned int res = 0;
+	unsigned int res;
 
 	asm (ALTERNATIVE("call __sw_hweight32", POPCNT32, X86_FEATURE_POPCNT)
-		     : "="REG_OUT (res)
-		     : REG_IN (w));
+			: "="REG_OUT (res)
+			: REG_IN (w));
 
 	return res;
 }
@@ -53,13 +50,16 @@ static inline unsigned long __arch_hweight64(__u64 w)
 #else
 static __always_inline unsigned long __arch_hweight64(__u64 w)
 {
-	unsigned long res = 0;
+	unsigned long res;
 
-	asm (ALTERNATIVE("call __sw_hweight64", POPCNT64, X86_FEATURE_POPCNT)
-		     : "="REG_OUT (res)
-		     : REG_IN (w));
+	if (likely(static_cpu_has(X86_FEATURE_POPCNT))) {
+		asm volatile(POPCNT64
+				: "="REG_OUT (res)
+				: REG_IN (w));
 
-	return res;
+		return res;
+	}
+	return __sw_hweight64(w);
 }
 #endif /* CONFIG_X86_32 */
 
arch/x86/include/asm/cpufeature.h +2 -110

136 lines not on this page · raw message

arch/x86/include/asm/cpuinfo.h new file +65 -0

65 lines not on this page · raw message

arch/x86/include/asm/processor.h +1 -62

81 lines not on this page · raw message

arch/x86/include/asm/static_cpu_has.h new file +116 -0

116 lines not on this page · raw message

arch/x86/lib/Makefile +1 -1
index 72a576752a7e..ec969cc3eb20 100644
@@ -25,7 +25,7 @@ lib-y += memcpy_$(BITS).o
 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
 lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o
 
-obj-y += msr.o msr-reg.o msr-reg-export.o
+obj-y += msr.o msr-reg.o msr-reg-export.o hweight.o
 
 ifeq ($(CONFIG_X86_32),y)
         obj-y += atomic64_32.o
arch/x86/lib/hweight.c new file +37 -0
new file mode 100644
index 000000000000..5834fb9af6ff
@@ -0,0 +1,37 @@
+#include <linux/export.h>
+#include <linux/compiler.h>
+
+#ifdef CONFIG_X86_32
+# define PUSH_DX	"pushl %%edx\n\t"
+# define POP_DX		"popl %%edx\n\t"
+#else
+# define PUSH_DX	"pushq %%rdx\n\t"
+# define POP_DX		"popq %%rdx\n\t"
+#endif
+
+unsigned int __sw_hweight32(unsigned int w)
+{
+	asm volatile(PUSH_DX
+		     "movl %[w], %%edx\n\t"			/* w -> t */
+		     "shrl %%edx\n\t"				/* t >> 1 */
+		     "andl $0x55555555, %%edx\n\t"		/* t & 0x55555555 */
+		     "subl %%edx, %[w]\n"			/* w -= t */
+		     "\n\t"
+		     "movl %[w], %%edx\n\t"			/* w -> t */
+		     "shrl $2, %[w]\n\t"			/* w_tmp >> 2 */
+		     "andl $0x33333333, %%edx\n\t"		/* t & 0x33333333 */
+		     "andl $0x33333333, %[w]\n\t"		/* w_tmp & 0x33333333 */
+		     "addl %%edx, %[w]\n"			/* w = w_tmp + t */
+		     "\n\t"
+		     "movl %[w], %%edx\n\t"			/* w -> t */
+		     "shrl $4, %%edx\n\t"			/* t >> 4 */
+		     "addl %%edx, %[w]\n\t"			/* w_tmp += t */
+		     "andl  $0x0f0f0f0f, %[w]\n\t"		/* w_tmp &= 0x0f0f0f0f */
+		     "imull $0x01010101, %[w], %[w]\n\t"	/* w_tmp *= 0x01010101 */
+		     "shrl $24, %[w]\n\t"			/* w = w_tmp >> 24 */
+		     POP_DX
+		     : [w] "+r" (w));
+
+	return w;
+}
+EXPORT_SYMBOL(__sw_hweight32);
lib/Makefile +0 -5
index a65e9a861535..55ad20701dc0 100644
@@ -15,9 +15,6 @@ KCOV_INSTRUMENT_rbtree.o := n
 KCOV_INSTRUMENT_list_debug.o := n
 KCOV_INSTRUMENT_debugobjects.o := n
 KCOV_INSTRUMENT_dynamic_debug.o := n
-# Kernel does not boot if we instrument this file as it uses custom calling
-# convention (see CONFIG_ARCH_HWEIGHT_CFLAGS).
-KCOV_INSTRUMENT_hweight.o := n
 
 lib-y := ctype.o string.o vsprintf.o cmdline.o \
 	 rbtree.o radix-tree.o dump_stack.o timerqueue.o\
@@ -72,8 +69,6 @@ obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
 obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o
 obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
 
-GCOV_PROFILE_hweight.o := n
-CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS))
 obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
 
 obj-$(CONFIG_BTREE) += btree.o
lib/hweight.c +2 -0
index 9a5c1f221558..d53137a8def4 100644
@@ -9,6 +9,7 @@
  * The Hamming Weight of a number is the total number of bits set in it.
  */
 
+#ifndef __HAVE_ARCH_SW_HWEIGHT
 unsigned int __sw_hweight32(unsigned int w)
 {
 #ifdef CONFIG_ARCH_HAS_FAST_MULTIPLIER
@@ -25,6 +26,7 @@ unsigned int __sw_hweight32(unsigned int w)
 #endif
 }
 EXPORT_SYMBOL(__sw_hweight32);
+#endif
 
 unsigned int __sw_hweight16(unsigned int w)
 {
Signature · 5 lines
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 
#59 lore raw

Re: [PATCH -v2] x86/hweight: Get rid of the special calling convention

Quoted 25 lines · Borislav Petkov

#ifdef CONFIG_X86_32

# define PUSH_DX        "pushl %%edx\n\t"
# define POP_DX         "popl %%edx\n\t"
#else
# define PUSH_DX        "pushq %%rdx\n\t"
# define POP_DX         "popq %%rdx\n\t"
#endif

unsigned int __sw_hweight32(unsigned int w)

{
        asm volatile(PUSH_DX
                     "movl %[w], %%edx\n\t"                     /* w -> t */
                     "shrl %%edx\n\t"                           /* t >> 1 */
                     "andl $0x55555555, %%edx\n\t"              /* t & 0x55555555 */
                     "subl %%edx, %[w]\n"                       /* w -= t */
                     "\n\t"
                     "movl %[w], %%edx\n\t"                     /* w -> t */
                     "shrl $2, %[w]\n\t"                        /* w_tmp >> 2 */
                     "andl $0x33333333, %%edx\n\t"              /* t & 0x33333333 */
                     "andl $0x33333333, %[w]\n\t"               /* w_tmp & 0x33333333 */
                     "addl %%edx, %[w]\n"                       /* w = w_tmp + t */
                     "\n\t"
                     "movl %[w], %%edx\n\t"                     /* w -> t */
                     "shrl $4, %%edx\n\t"                       /* t >> 4 */
                     "addl %%edx, %[w]\n\t"                     /* w_tmp += t */
Quoted 8 lines
                     "andl  $0x0f0f0f0f, %[w]\n\t"              /* w_tmp &= 0x0f0f0f0f */
                     "imull $0x01010101, %[w], %[w]\n\t"        /* w_tmp *= 0x01010101 */
                     "shrl $24, %[w]\n\t"                       /* w = w_tmp >> 24 */
                     POP_DX
                     : [w] "+r" (w));

        return w;
}

But this is a C function, with C calling convention. You're now assuming GCC doesn't clobber anything with its prologue/epilogue.

I think hpa meant to put it in an .S file and avoid all that.

#60 lore raw

Re: [PATCH -v2] x86/hweight: Get rid of the special calling convention

Quoted 4 lines · Peter Zijlstra

But this is a C function, with C calling convention. You're now assuming GCC doesn't clobber anything with its prologue/epilogue.

I think hpa meant to put it in an .S file and avoid all that.

I wanted to have gcc use %[w] and this way not hardcode the reg but the ABI kinda hardcodes it to rAX. And you're right about tracing funkyness adding glue so we're probably better off doing the .S thing directly and making it more robust this way.

Signature · 5 lines
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 
#61 lore raw

Re: [PATCH -v2] x86/hweight: Get rid of the special calling convention

Quoted 4 lines · Borislav Petkov

I wanted to have gcc use %[w] and this way not hardcode the reg but the ABI kinda hardcodes it to rAX. And you're right about tracing funkyness adding glue so we're probably better off doing the .S thing directly and making it more robust this way.

Ok, here's a new version. Let me know what do you think before I hammer on it more seriously. But booting in kvm with "-popcnt" and without seems to work, no splats, corruptions or whatnot.

I've also been running POPCNT vs the asm versions in userspace and comparing results, looks good too, seems to work correctly. :)

Thanks.

---
From: Borislav Petkov <[email protected]>
Date: Wed, 4 May 2016 18:52:09 +0200
Subject: [PATCH] x86/hweight: Get rid of the special calling convention

People complained about ARCH_HWEIGHT_CFLAGS and how it throws a wrench into kcov, lto, etc, experimentation. Add asm versions for __sw_hweight{32,64}() and do explicitly saving and restoring of clobbered registers. This gets rid of the special calling convention.

We still need to hardcode POPCNT and register operands as some old gas versions which we support, do not know about POPCNT.

Btw, remove redundant REX prefix from 32-bit POPCNT because alternatives can do padding now.

---
 arch/x86/Kconfig                    |  5 ---
 arch/x86/include/asm/arch_hweight.h | 24 +++++-------
 arch/x86/kernel/i386_ksyms_32.c     |  2 +
 arch/x86/kernel/x8664_ksyms_64.c    |  3 ++
 arch/x86/lib/Makefile               |  2 +-
 arch/x86/lib/hweight.S              | 77 +++++++++++++++++++++++++++++++++++++
 lib/Makefile                        |  5 ---
 lib/hweight.c                       |  4 ++
 8 files changed, 97 insertions(+), 25 deletions(-)
 create mode 100644 arch/x86/lib/hweight.S
arch/x86/Kconfig +0 -5
index 2dc18605831f..c3a8f360683b 100644
@@ -296,11 +296,6 @@ config X86_32_LAZY_GS
 	def_bool y
 	depends on X86_32 && !CC_STACKPROTECTOR
 
-config ARCH_HWEIGHT_CFLAGS
-	string
-	default "-fcall-saved-ecx -fcall-saved-edx" if X86_32
-	default "-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" if X86_64
-
 config ARCH_SUPPORTS_UPROBES
 	def_bool y
 
arch/x86/include/asm/arch_hweight.h +10 -14
index 02e799fa43d1..e7cd63175de4 100644
@@ -4,8 +4,8 @@
 #include <asm/cpufeatures.h>
 
 #ifdef CONFIG_64BIT
-/* popcnt %edi, %eax -- redundant REX prefix for alignment */
-#define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7"
+/* popcnt %edi, %eax */
+#define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc7"
 /* popcnt %rdi, %rax */
 #define POPCNT64 ".byte 0xf3,0x48,0x0f,0xb8,0xc7"
 #define REG_IN "D"
@@ -17,19 +17,15 @@
 #define REG_OUT "a"
 #endif
 
-/*
- * __sw_hweightXX are called from within the alternatives below
- * and callee-clobbered registers need to be taken care of. See
- * ARCH_HWEIGHT_CFLAGS in <arch/x86/Kconfig> for the respective
- * compiler switches.
- */
+#define __HAVE_ARCH_SW_HWEIGHT
+
 static __always_inline unsigned int __arch_hweight32(unsigned int w)
 {
-	unsigned int res = 0;
+	unsigned int res;
 
 	asm (ALTERNATIVE("call __sw_hweight32", POPCNT32, X86_FEATURE_POPCNT)
-		     : "="REG_OUT (res)
-		     : REG_IN (w));
+			 : "="REG_OUT (res)
+			 : REG_IN (w));
 
 	return res;
 }
@@ -53,11 +49,11 @@ static inline unsigned long __arch_hweight64(__u64 w)
 #else
 static __always_inline unsigned long __arch_hweight64(__u64 w)
 {
-	unsigned long res = 0;
+	unsigned long res;
 
 	asm (ALTERNATIVE("call __sw_hweight64", POPCNT64, X86_FEATURE_POPCNT)
-		     : "="REG_OUT (res)
-		     : REG_IN (w));
+			 : "="REG_OUT (res)
+			 : REG_IN (w));
 
 	return res;
 }
arch/x86/kernel/i386_ksyms_32.c +2 -0
index 64341aa485ae..d40ee8a38fed 100644
@@ -42,3 +42,5 @@ EXPORT_SYMBOL(empty_zero_page);
 EXPORT_SYMBOL(___preempt_schedule);
 EXPORT_SYMBOL(___preempt_schedule_notrace);
 #endif
+
+EXPORT_SYMBOL(__sw_hweight32);
arch/x86/kernel/x8664_ksyms_64.c +3 -0
index cd05942bc918..f1aebfb49c36 100644
@@ -44,6 +44,9 @@ EXPORT_SYMBOL(clear_page);
 
 EXPORT_SYMBOL(csum_partial);
 
+EXPORT_SYMBOL(__sw_hweight32);
+EXPORT_SYMBOL(__sw_hweight64);
+
 /*
  * Export string functions. We normally rely on gcc builtin for most of these,
  * but gcc sometimes decides not to inline them.
arch/x86/lib/Makefile +1 -1
index 72a576752a7e..ec969cc3eb20 100644
@@ -25,7 +25,7 @@ lib-y += memcpy_$(BITS).o
 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
 lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o
 
-obj-y += msr.o msr-reg.o msr-reg-export.o
+obj-y += msr.o msr-reg.o msr-reg-export.o hweight.o
 
 ifeq ($(CONFIG_X86_32),y)
         obj-y += atomic64_32.o
arch/x86/lib/hweight.S new file +77 -0

77 lines not on this page · raw message

lib/Makefile +0 -5
index 7bd6fd436c97..08ea9f1c0c49 100644
@@ -15,9 +15,6 @@ KCOV_INSTRUMENT_rbtree.o := n
 KCOV_INSTRUMENT_list_debug.o := n
 KCOV_INSTRUMENT_debugobjects.o := n
 KCOV_INSTRUMENT_dynamic_debug.o := n
-# Kernel does not boot if we instrument this file as it uses custom calling
-# convention (see CONFIG_ARCH_HWEIGHT_CFLAGS).
-KCOV_INSTRUMENT_hweight.o := n
 
 lib-y := ctype.o string.o vsprintf.o cmdline.o \
 	 rbtree.o radix-tree.o dump_stack.o timerqueue.o\
@@ -72,8 +69,6 @@ obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
 obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o
 obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
 
-GCOV_PROFILE_hweight.o := n
-CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS))
 obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
 
 obj-$(CONFIG_BTREE) += btree.o
lib/hweight.c +4 -0
index 9a5c1f221558..43273a7d83cf 100644
@@ -9,6 +9,7 @@
  * The Hamming Weight of a number is the total number of bits set in it.
  */
 
+#ifndef __HAVE_ARCH_SW_HWEIGHT
 unsigned int __sw_hweight32(unsigned int w)
 {
 #ifdef CONFIG_ARCH_HAS_FAST_MULTIPLIER
@@ -25,6 +26,7 @@ unsigned int __sw_hweight32(unsigned int w)
 #endif
 }
 EXPORT_SYMBOL(__sw_hweight32);
+#endif
 
 unsigned int __sw_hweight16(unsigned int w)
 {
@@ -43,6 +45,7 @@ unsigned int __sw_hweight8(unsigned int w)
 }
 EXPORT_SYMBOL(__sw_hweight8);
 
+#ifndef __HAVE_ARCH_SW_HWEIGHT
 unsigned long __sw_hweight64(__u64 w)
 {
 #if BITS_PER_LONG == 32
@@ -65,3 +68,4 @@ unsigned long __sw_hweight64(__u64 w)
 #endif
 }
 EXPORT_SYMBOL(__sw_hweight64);
+#endif
Signature · 4 lines
2.7.3

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 
#62 lore raw

Re: [PATCH v2 10/30] Add x86-specific parity functions

In reply to Andi Kleen
Quoted 8 lines · On Wed, 06 Apr 2016 12:45:27 -0700 Andi Kleen <[email protected]> wrote:
Quoted 3 lines · [email protected] writes:

From: Zhaoxiu Zeng <[email protected]>

Use alternatives, lifted from arch_hweight

Is there actually anything performance critical in the kernel that uses parity?

On very low end devices some of the flash, but the implementation here is ironically pretty much worst-case for such x86 devices 8)

Alan

#63 lore raw

PATCH v2 11/30 sunrpc: use parity8

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 net/sunrpc/auth_gss/gss_krb5_keys.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
net/sunrpc/auth_gss/gss_krb5_keys.c +1 -5
index 8701331..c41b389 100644
@@ -243,16 +243,12 @@ err_return:
 	return ret;
 }
 
-#define smask(step) ((1<<step)-1)
-#define pstep(x, step) (((x)&smask(step))^(((x)>>step)&smask(step)))
-#define parity_char(x) pstep(pstep(pstep((x), 4), 2), 1)
-
 static void mit_des_fixup_key_parity(u8 key[8])
 {
 	int i;
 	for (i = 0; i < 8; i++) {
 		key[i] &= 0xfe;
-		key[i] |= 1^parity_char(key[i]);
+		key[i] |= !parity8(key[i]);
 	}
 }
 
Signature · 1 line
2.5.0
#64 lore raw

PATCH v2 12/30 mips: use parity functions in cerr-sb1.c

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 arch/mips/mm/cerr-sb1.c | 67 +++++++++++++------------------------------------
 1 file changed, 17 insertions(+), 50 deletions(-)
arch/mips/mm/cerr-sb1.c +17 -50
index ee5c1ff..2e7d660 100644
@@ -264,27 +264,6 @@ asmlinkage void sb1_cache_error(void)
 #endif
 }
 
-
-/* Parity lookup table. */
-static const uint8_t parity[256] = {
-	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
-	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
-	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
-	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
-	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
-	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
-	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
-	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
-	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
-	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
-	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
-	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
-	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
-	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
-	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
-	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0
-};
-
 /* Masks to select bits for Hamming parity, mask_72_64[i] for bit[i] */
 static const uint64_t mask_72_64[8] = {
 	0x0738C808099264FFULL,
@@ -298,34 +277,28 @@ static const uint64_t mask_72_64[8] = {
 };
 
 /* Calculate the parity on a range of bits */
-static char range_parity(uint64_t dword, int max, int min)
+static inline char range_parity(uint64_t dword, int max, int min)
 {
-	char parity = 0;
-	int i;
-	dword >>= min;
-	for (i=max-min; i>=0; i--) {
-		if (dword & 0x1)
-			parity = !parity;
-		dword >>= 1;
+	int n = max - min + 1;
+	if (__builtin_constant_p(n)) {
+		if (n <= 8)
+			return parity8((unsigned int)(dword >> min) & ((1U << n) - 1));
+		if (n <= 16)
+			return parity16((unsigned int)(dword >> min) & ((1U << n) - 1));
+		if (n <= 32)
+			return parity32((unsigned int)(dword >> min) & ((1U << n) - 1));
 	}
-	return parity;
+	return parity64((dword >> min) & ((1ULL << n) - 1));
 }
 
 /* Calculate the 4-bit even byte-parity for an instruction */
-static unsigned char inst_parity(uint32_t word)
+static inline unsigned char inst_parity(uint32_t word)
 {
-	int i, j;
-	char parity = 0;
-	for (j=0; j<4; j++) {
-		char byte_parity = 0;
-		for (i=0; i<8; i++) {
-			if (word & 0x80000000)
-				byte_parity = !byte_parity;
-			word <<= 1;
-		}
-		parity <<= 1;
-		parity |= byte_parity;
-	}
+	char parity;
+	parity  = parity8(word >> 24) << 3;
+	parity |= parity8(word >> 16) << 2;
+	parity |= parity8(word >> 8) << 1;
+	parity |= parity8(word);
 	return parity;
 }
 
@@ -436,7 +409,6 @@ static uint32_t extract_ic(unsigned short addr, int data)
 static uint8_t dc_ecc(uint64_t dword)
 {
 	uint64_t t;
-	uint32_t w;
 	uint8_t	 p;
 	int	 i;
 
@@ -445,12 +417,7 @@ static uint8_t dc_ecc(uint64_t dword)
 	{
 		p <<= 1;
 		t = dword & mask_72_64[i];
-		w = (uint32_t)(t >> 32);
-		p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF]
-		      ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]);
-		w = (uint32_t)(t & 0xFFFFFFFF);
-		p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF]
-		      ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]);
+		p |= parity64(t);
 	}
 	return p;
 }
Signature · 1 line
2.5.0
#65 lore raw

PATCH v2 13/30 bch: use parity32

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 lib/bch.c | 14 +-------------
 1 file changed, 1 insertion(+), 13 deletions(-)
lib/bch.c +1 -13
index bc89dfe4..6c6e8d4 100644
@@ -278,18 +278,6 @@ static inline int deg(unsigned int poly)
 	return fls(poly)-1;
 }
 
-static inline int parity(unsigned int x)
-{
-	/*
-	 * public domain code snippet, lifted from
-	 * http://www-graphics.stanford.edu/~seander/bithacks.html
-	 */
-	x ^= x >> 1;
-	x ^= x >> 2;
-	x = (x & 0x11111111U) * 0x11111111U;
-	return (x >> 28) & 1;
-}
-
 /* Galois field basic operations: multiply, divide, inverse, etc. */
 
 static inline unsigned int gf_mul(struct bch_control *bch, unsigned int a,
@@ -494,7 +482,7 @@ static int solve_linear_system(struct bch_control *bch, unsigned int *rows,
 		tmp = 0;
 		for (r = m-1; r >= 0; r--) {
 			mask = rows[r] & (tmp|1);
-			tmp |= parity(mask) << (m-r);
+			tmp |= parity32(mask) << (m-r);
 		}
 		sol[p] = tmp >> 1;
 	}
Signature · 1 line
2.5.0
#66 lore raw

PATCH v2 14/30 media: use parity8 in vivid-vbi-gen.c

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 drivers/media/platform/vivid/vivid-vbi-gen.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)
drivers/media/platform/vivid/vivid-vbi-gen.c +2 -7
index a2159de..d5ba0fc 100644
@@ -175,14 +175,9 @@ static const u8 vivid_cc_sequence2[30] = {
 	0x14, 0x2f,	/* End of Caption */
 };
 
-static u8 calc_parity(u8 val)
+static inline u8 calc_parity(u8 val)
 {
-	unsigned i;
-	unsigned tot = 0;
-
-	for (i = 0; i < 7; i++)
-		tot += (val & (1 << i)) ? 1 : 0;
-	return val | ((tot & 1) ? 0 : 0x80);
+	return (!parity8(val) << 7) | val;
 }
 
 static void vivid_vbi_gen_set_time_of_day(u8 *packet)
Signature · 1 line
2.5.0
#67 lore raw

PATCH v2 15/30 media: use parity functions in saa7115

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 drivers/media/i2c/saa7115.c | 17 ++---------------
 1 file changed, 2 insertions(+), 15 deletions(-)
drivers/media/i2c/saa7115.c +2 -15
index d2a1ce2..4c22df8 100644
@@ -672,15 +672,6 @@ static const unsigned char saa7115_init_misc[] = {
 	0x00, 0x00
 };
 
-static int saa711x_odd_parity(u8 c)
-{
-	c ^= (c >> 4);
-	c ^= (c >> 2);
-	c ^= (c >> 1);
-
-	return c & 1;
-}
-
 static int saa711x_decode_vps(u8 *dst, u8 *p)
 {
 	static const u8 biphase_tbl[] = {
@@ -733,7 +724,6 @@ static int saa711x_decode_wss(u8 *p)
 	static const int wss_bits[8] = {
 		0, 0, 0, 1, 0, 1, 1, 1
 	};
-	unsigned char parity;
 	int wss = 0;
 	int i;
 
@@ -745,11 +735,8 @@ static int saa711x_decode_wss(u8 *p)
 			return -1;
 		wss |= b2 << i;
 	}
-	parity = wss & 15;
-	parity ^= parity >> 2;
-	parity ^= parity >> 1;
 
-	if (!(parity & 1))
+	if (!parity4(wss))
 		return -1;
 
 	return wss;
@@ -1235,7 +1222,7 @@ static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vb
 		vbi->type = V4L2_SLICED_TELETEXT_B;
 		break;
 	case 4:
-		if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
+		if (!parity8(p[0]) || !parity8(p[1]))
 			return 0;
 		vbi->type = V4L2_SLICED_CAPTION_525;
 		break;
Signature · 1 line
2.5.0
#68 lore raw

PATCH v2 16/30 input: use parity32 in grip_mp

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 drivers/input/joystick/grip_mp.c | 16 +---------------
 1 file changed, 1 insertion(+), 15 deletions(-)
drivers/input/joystick/grip_mp.c +1 -15
index 573191d..3e29eb1 100644
@@ -112,20 +112,6 @@ static const int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5
 static int register_slot(int i, struct grip_mp *grip);
 
 /*
- * Returns whether an odd or even number of bits are on in pkt.
- */
-
-static int bit_parity(u32 pkt)
-{
-	int x = pkt ^ (pkt >> 16);
-	x ^= x >> 8;
-	x ^= x >> 4;
-	x ^= x >> 2;
-	x ^= x >> 1;
-	return x & 1;
-}
-
-/*
  * Poll gameport; return true if all bits set in 'onbits' are on and
  * all bits set in 'offbits' are off.
  */
@@ -235,7 +221,7 @@ static int mp_io(struct gameport* gameport, int sendflags, int sendcode, u32 *pa
 		pkt = (pkt >> 2) | 0xf0000000;
 	}
 
-	if (bit_parity(pkt) == 1)
+	if (parity32(pkt))
 		return IO_RESET;
 
 	/* Acknowledge packet receipt */
Signature · 1 line
2.5.0
#69 lore raw

PATCH v2 17/30 input: use parity64 in sidewinder

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 drivers/input/joystick/sidewinder.c | 24 ++++--------------------
 1 file changed, 4 insertions(+), 20 deletions(-)
drivers/input/joystick/sidewinder.c +4 -20
index 4a95b22..7ea486e 100644
@@ -259,22 +259,6 @@ static void sw_init_digital(struct gameport *gameport)
 }
 
 /*
- * sw_parity() computes parity of __u64
- */
-
-static int sw_parity(__u64 t)
-{
-	int x = t ^ (t >> 32);
-
-	x ^= x >> 16;
-	x ^= x >> 8;
-	x ^= x >> 4;
-	x ^= x >> 2;
-	x ^= x >> 1;
-	return x & 1;
-}
-
-/*
  * sw_ccheck() checks synchronization bits and computes checksum of nibbles.
  */
 
@@ -334,7 +318,7 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
 
 			for (i = 0; i < sw->number; i ++) {
 
-				if (sw_parity(GB(i*15,15)))
+				if (parity64(GB(i*15,15)))
 					return -1;
 
 				input_report_abs(sw->dev[i], ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
@@ -351,7 +335,7 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
 		case SW_ID_PP:
 		case SW_ID_FFP:
 
-			if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8)
+			if (!parity64(GB(0,48)) || (hat = GB(42,4)) > 8)
 				return -1;
 
 			dev = sw->dev[0];
@@ -372,7 +356,7 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
 
 		case SW_ID_FSP:
 
-			if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8)
+			if (!parity64(GB(0,43)) || (hat = GB(28,4)) > 8)
 				return -1;
 
 			dev = sw->dev[0];
@@ -397,7 +381,7 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
 
 		case SW_ID_FFW:
 
-			if (!sw_parity(GB(0,33)))
+			if (!parity64(GB(0,33)))
 				return -1;
 
 			dev = sw->dev[0];
Signature · 1 line
2.5.0
#70 lore raw

PATCH v2 18/30 input: use parity16 in ams_delta_serio

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 drivers/input/serio/ams_delta_serio.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)
drivers/input/serio/ams_delta_serio.c +2 -6
index 45887e3..85459b3 100644
@@ -48,13 +48,9 @@ static int check_data(int data)
 				data);
 		return SERIO_FRAME;
 	}
-	/* calculate the parity */
-	for (i = 1; i < 10; i++) {
-		if (data & (1 << i))
-			parity++;
-	}
 	/* it should be odd */
-	if (!(parity & 0x01)) {
+	parity = parity16(data & 0x3fe);
+	if (!parity) {
 		dev_warn(&ams_delta_serio->dev,
 				"paritiy check failed, data=0x%X parity=0x%X\n",
 				data, parity);
Signature · 1 line
2.5.0
#71 lore raw

PATCH v2 19/30 scsi: use parity32 in isci's phy

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 drivers/scsi/isci/phy.c | 15 +--------------
 1 file changed, 1 insertion(+), 14 deletions(-)
drivers/scsi/isci/phy.c +1 -14
index cb87b2e..a06aff6 100644
@@ -122,8 +122,6 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
 	int phy_idx = iphy->phy_index;
 	struct sci_phy_cap phy_cap;
 	u32 phy_configuration;
-	u32 parity_check = 0;
-	u32 parity_count = 0;
 	u32 llctl, link_rate;
 	u32 clksm_value = 0;
 	u32 sp_timeouts = 0;
@@ -225,18 +223,7 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
 	/* The SAS specification indicates that the phy_capabilities that
 	 * are transmitted shall have an even parity.  Calculate the parity.
 	 */
-	parity_check = phy_cap.all;
-	while (parity_check != 0) {
-		if (parity_check & 0x1)
-			parity_count++;
-		parity_check >>= 1;
-	}
-
-	/* If parity indicates there are an odd number of bits set, then
-	 * set the parity bit to 1 in the phy capabilities.
-	 */
-	if ((parity_count % 2) != 0)
-		phy_cap.parity = 1;
+	phy_cap.parity = parity32(phy_cap.all);
 
 	writel(phy_cap.all, &llr->phy_capabilities);
 
Signature · 1 line
2.5.0
#72 lore raw

PATCH v2 20/30 mtd: use parity16 in ssfdc

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

The original get_parity return even parity of the input number. So hweight of "block_address & 0x7ff" must be odd if block_address is valid.

This patch use parity16, and rearrange the code.

---
 drivers/mtd/ssfdc.c | 31 ++++++++-----------------------
 1 file changed, 8 insertions(+), 23 deletions(-)
drivers/mtd/ssfdc.c +8 -23
index daf82ba..1d55f15 100644
@@ -182,24 +182,10 @@ static int read_raw_oob(struct mtd_info *mtd, loff_t offs, uint8_t *buf)
 	return 0;
 }
 
-/* Parity calculator on a word of n bit size */
-static int get_parity(int number, int size)
-{
- 	int k;
-	int parity;
-
-	parity = 1;
-	for (k = 0; k < size; k++) {
-		parity += (number >> k);
-		parity &= 1;
-	}
-	return parity;
-}
-
 /* Read and validate the logical block address field stored in the OOB */
 static int get_logical_address(uint8_t *oob_buf)
 {
-	int block_address, parity;
+	int block_address;
 	int offset[2] = {6, 11}; /* offset of the 2 address fields within OOB */
 	int j;
 	int ok = 0;
@@ -215,18 +201,17 @@ static int get_logical_address(uint8_t *oob_buf)
 
 		/* Check for the signature bits in the address field (MSBits) */
 		if ((block_address & ~0x7FF) == 0x1000) {
-			parity = block_address & 0x01;
 			block_address &= 0x7FF;
-			block_address >>= 1;
 
-			if (get_parity(block_address, 10) != parity) {
-				pr_debug("SSFDC_RO: logical address field%d"
-					"parity error(0x%04X)\n", j+1,
-					block_address);
-			} else {
-				ok = 1;
+			ok = parity16(block_address);
+			if (ok) {
+				block_address >>= 1;
 				break;
 			}
+
+			pr_debug("SSFDC_RO: logical address field%d"
+				"parity error(0x%04X)\n", j+1,
+				block_address);
 		}
 	}
 
Signature · 1 line
2.5.0
#73 lore raw

PATCH v2 21/30 mtd: use parity functions in inftlcore

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 drivers/mtd/inftlcore.c | 17 ++++-------------
 1 file changed, 4 insertions(+), 13 deletions(-)
drivers/mtd/inftlcore.c +4 -13
index b66b541..8c9457b 100644
@@ -457,15 +457,6 @@ static u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock)
 	return INFTL_foldchain(inftl, LongestChain, pendingblock);
 }
 
-static int nrbits(unsigned int val, int bitcount)
-{
-	int i, total = 0;
-
-	for (i = 0; (i < bitcount); i++)
-		total += (((0x1 << i) & val) ? 1 : 0);
-	return total;
-}
-
 /*
  * INFTL_findwriteunit: Return the unit number into which we can write
  *                      for this block. Make it available if it isn't already.
@@ -593,10 +584,10 @@ hitused:
 		if (prev_block < inftl->nb_blocks)
 			prev_block -= inftl->firstEUN;
 
-		parity = (nrbits(thisVUC, 16) & 0x1) ? 0x1 : 0;
-		parity |= (nrbits(prev_block, 16) & 0x1) ? 0x2 : 0;
-		parity |= (nrbits(anac, 8) & 0x1) ? 0x4 : 0;
-		parity |= (nrbits(nacs, 8) & 0x1) ? 0x8 : 0;
+		parity  = parity16(thisVUC);
+		parity |= parity16(prev_block) << 1;
+		parity |= parity8(anac) << 2;
+		parity |= parity8(nacs) << 3;
 
 		oob.u.a.virtualUnitNo = cpu_to_le16(thisVUC);
 		oob.u.a.prevUnitNo = cpu_to_le16(prev_block);
Signature · 1 line
2.5.0
#74 lore raw

PATCH v2 22/30 crypto: use parity functions in qat_hal

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 drivers/crypto/qat/qat_common/qat_hal.c | 32 ++++++++++----------------------
 1 file changed, 10 insertions(+), 22 deletions(-)
drivers/crypto/qat/qat_common/qat_hal.c +10 -22
index 1e480f1..318558f 100644
@@ -546,17 +546,6 @@ static void qat_hal_disable_ctx(struct icp_qat_fw_loader_handle *handle,
 	qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx);
 }
 
-static uint64_t qat_hal_parity_64bit(uint64_t word)
-{
-	word ^= word >> 1;
-	word ^= word >> 2;
-	word ^= word >> 4;
-	word ^= word >> 8;
-	word ^= word >> 16;
-	word ^= word >> 32;
-	return word & 1;
-}
-
 static uint64_t qat_hal_set_uword_ecc(uint64_t uword)
 {
 	uint64_t bit0_mask = 0xff800007fffULL, bit1_mask = 0x1f801ff801fULL,
@@ -566,13 +555,13 @@ static uint64_t qat_hal_set_uword_ecc(uint64_t uword)
 
 	/* clear the ecc bits */
 	uword &= ~(0x7fULL << 0x2C);
-	uword |= qat_hal_parity_64bit(bit0_mask & uword) << 0x2C;
-	uword |= qat_hal_parity_64bit(bit1_mask & uword) << 0x2D;
-	uword |= qat_hal_parity_64bit(bit2_mask & uword) << 0x2E;
-	uword |= qat_hal_parity_64bit(bit3_mask & uword) << 0x2F;
-	uword |= qat_hal_parity_64bit(bit4_mask & uword) << 0x30;
-	uword |= qat_hal_parity_64bit(bit5_mask & uword) << 0x31;
-	uword |= qat_hal_parity_64bit(bit6_mask & uword) << 0x32;
+	uword |= (uint64_t)parity64(bit0_mask & uword) << 0x2C;
+	uword |= (uint64_t)parity64(bit1_mask & uword) << 0x2D;
+	uword |= (uint64_t)parity64(bit2_mask & uword) << 0x2E;
+	uword |= (uint64_t)parity64(bit3_mask & uword) << 0x2F;
+	uword |= (uint64_t)parity64(bit4_mask & uword) << 0x30;
+	uword |= (uint64_t)parity64(bit5_mask & uword) << 0x31;
+	uword |= (uint64_t)parity64(bit6_mask & uword) << 0x32;
 	return uword;
 }
 
@@ -853,15 +842,14 @@ void qat_hal_wr_umem(struct icp_qat_fw_loader_handle *handle,
 	uaddr |= UA_ECS;
 	qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, uaddr);
 	for (i = 0; i < words_num; i++) {
-		unsigned int uwrd_lo, uwrd_hi, tmp;
+		unsigned int uwrd_lo, uwrd_hi;
 
 		uwrd_lo = ((data[i] & 0xfff0000) << 4) | (0x3 << 18) |
 			  ((data[i] & 0xff00) << 2) |
 			  (0x3 << 8) | (data[i] & 0xff);
 		uwrd_hi = (0xf << 4) | ((data[i] & 0xf0000000) >> 28);
-		uwrd_hi |= (hweight32(data[i] & 0xffff) & 0x1) << 8;
-		tmp = ((data[i] >> 0x10) & 0xffff);
-		uwrd_hi |= (hweight32(tmp) & 0x1) << 9;
+		uwrd_hi |= parity16(data[i]) << 8;
+		uwrd_hi |= parity16(data[i] >> 16) << 9;
 		qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_LOWER, uwrd_lo);
 		qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_UPPER, uwrd_hi);
 	}
Signature · 1 line
2.5.0
#75 lore raw

PATCH v2 23/30 mtd: use parity16 in sm_ftl

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 drivers/mtd/sm_ftl.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/mtd/sm_ftl.c +2 -3
index b096f8b..345ff1a 100644
@@ -136,7 +136,7 @@ static int sm_get_lba(uint8_t *lba)
 		return -2;
 
 	/* check parity - endianness doesn't matter */
-	if (hweight16(*(uint16_t *)lba) & 1)
+	if (parity16(*(uint16_t *)lba))
 		return -2;
 
 	return (lba[1] >> 1) | ((lba[0] & 0x07) << 7);
@@ -183,8 +183,7 @@ static void sm_write_lba(struct sm_oob *oob, uint16_t lba)
 	tmp[0] = 0x10 | ((lba >> 7) & 0x07);
 	tmp[1] = (lba << 1) & 0xFF;
 
-	if (hweight16(*(uint16_t *)tmp) & 0x01)
-		tmp[1] |= 1;
+	tmp[1] |= parity16(*(uint16_t *)tmp);
 
 	oob->lba_copy1[0] = oob->lba_copy2[0] = tmp[0];
 	oob->lba_copy1[1] = oob->lba_copy2[1] = tmp[1];
Signature · 1 line
2.5.0
#76 lore raw

PATCH v2 24/30 ethernet: use parity8 in sun/niu.c

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 drivers/net/ethernet/sun/niu.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)
drivers/net/ethernet/sun/niu.c +2 -8
index 9cc4564..8c344ef 100644
@@ -2742,18 +2742,12 @@ static int niu_set_alt_mac_rdc_table(struct niu *np, int idx,
 
 static u64 vlan_entry_set_parity(u64 reg_val)
 {
-	u64 port01_mask;
-	u64 port23_mask;
-
-	port01_mask = 0x00ff;
-	port23_mask = 0xff00;
-
-	if (hweight64(reg_val & port01_mask) & 1)
+	if (parity8(reg_val))
 		reg_val |= ENET_VLAN_TBL_PARITY0;
 	else
 		reg_val &= ~ENET_VLAN_TBL_PARITY0;
 
-	if (hweight64(reg_val & port23_mask) & 1)
+	if (parity8((unsigned int)reg_val >> 8))
 		reg_val |= ENET_VLAN_TBL_PARITY1;
 	else
 		reg_val &= ~ENET_VLAN_TBL_PARITY1;
Signature · 1 line
2.5.0
#77 lore raw

PATCH v2 25/30 input: use parity8 in pcips2

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 drivers/input/serio/pcips2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/input/serio/pcips2.c +1 -1
index e862c6e..a51e7f0 100644
@@ -77,7 +77,7 @@ static irqreturn_t pcips2_interrupt(int irq, void *devid)
 
 		flag = (status & PS2_STAT_PARITY) ? 0 : SERIO_PARITY;
 
-		if (hweight8(scancode) & 1)
+		if (parity8(scancode))
 			flag ^= SERIO_PARITY;
 
 		serio_interrupt(ps2if->io, scancode, flag);
Signature · 1 line
2.5.0
#78 lore raw

PATCH v2 26/30 input: use parity8 in sa1111ps2

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 drivers/input/serio/sa1111ps2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/input/serio/sa1111ps2.c +1 -1
index b3e6889..324b193 100644
@@ -74,7 +74,7 @@ static irqreturn_t ps2_rxint(int irq, void *dev_id)
 
 		scancode = sa1111_readl(ps2if->base + PS2DATA) & 0xff;
 
-		if (hweight8(scancode) & 1)
+		if (parity8(scancode))
 			flag ^= SERIO_PARITY;
 
 		serio_interrupt(ps2if->io, scancode, flag);
Signature · 1 line
2.5.0
#79 lore raw

PATCH v2 27/30 iio: use parity32 in adxrs450

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 drivers/iio/gyro/adxrs450.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/iio/gyro/adxrs450.c +2 -2
index a330d42..307f55b 100644
@@ -109,7 +109,7 @@ static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev,
 	mutex_lock(&st->buf_lock);
 	tx = ADXRS450_READ_DATA | (reg_address << 17);
 
-	if (!(hweight32(tx) & 1))
+	if (!parity32(tx))
 		tx |= ADXRS450_P;
 
 	st->tx = cpu_to_be32(tx);
@@ -145,7 +145,7 @@ static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev,
 	mutex_lock(&st->buf_lock);
 	tx = ADXRS450_WRITE_DATA | (reg_address << 17) | (val << 1);
 
-	if (!(hweight32(tx) & 1))
+	if (!parity32(tx))
 		tx |= ADXRS450_P;
 
 	st->tx = cpu_to_be32(tx);
Signature · 1 line
2.5.0
maintainer Applied
#80 lore raw

Re: [PATCH v2 27/30] iio: use parity32 in adxrs450

Quoted 3 lines · On 06/04/16 11:16, [email protected] wrote:

From: Zhaoxiu Zeng <[email protected]>

Applied to the togreg branch of iio.git as you seem to have addressed Lars' comments.

Thanks,

Jonathan

Quoted 27 lines
---
 drivers/iio/gyro/adxrs450.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/iio/gyro/adxrs450.c +2 -2
index a330d42..307f55b 100644
@@ -109,7 +109,7 @@ static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev,
 	mutex_lock(&st->buf_lock);
 	tx = ADXRS450_READ_DATA | (reg_address << 17);
 
-	if (!(hweight32(tx) & 1))
+	if (!parity32(tx))
 		tx |= ADXRS450_P;
 
 	st->tx = cpu_to_be32(tx);
@@ -145,7 +145,7 @@ static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev,
 	mutex_lock(&st->buf_lock);
 	tx = ADXRS450_WRITE_DATA | (reg_address << 17) | (val << 1);
 
-	if (!(hweight32(tx) & 1))
+	if (!parity32(tx))
 		tx |= ADXRS450_P;
 
 	st->tx = cpu_to_be32(tx);
maintainer Acked-by
#82 lore raw

Re: [PATCH v2 27/30] iio: use parity32 in adxrs450

Quoted 10 lines · Lars-Peter Clausen
Quoted 6 lines · Jonathan Cameron
Quoted 3 lines · On 06/04/16 11:16, [email protected] wrote:

From: Zhaoxiu Zeng <[email protected]>

Applied to the togreg branch of iio.git as you seem to have addressed Lars' comments.

The whole series needs to go through the same tree since the new functions are introduced in the beginning.

Yeah, I just realized that when my build test failed!

Quoted 6 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

maintainer
#83 lore raw

Re: [PATCH v2 27/30] iio: use parity32 in adxrs450

Quoted 6 lines · Jonathan Cameron
Quoted 5 lines · Lars-Peter Clausen
Quoted 4 lines · Jonathan Cameron
Quoted 3 lines · On 06/04/16 11:16, [email protected] wrote:

From: Zhaoxiu Zeng <[email protected]>

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

Applied to the togreg branch of iio.git as you seem to have addressed Lars' comments.

The whole series needs to go through the same tree since the new functions are introduced in the beginning.

Yeah, I just realized that when my build test failed!

Backed out of the togreg branch of iio.git...

oops and thanks Lars!

Quoted 12 lines
Quoted 6 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#84 lore raw

PATCH v2 28/30 serial: use parity32 in max3100

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 drivers/tty/serial/max3100.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/tty/serial/max3100.c +1 -1
index 5c4c280..a0cc84a 100644
@@ -155,7 +155,7 @@ static int max3100_do_parity(struct max3100_port *s, u16 c)
 	else
 		c &= 0xff;
 
-	parity = parity ^ (hweight8(c) & 1);
+	parity ^= parity8(c);
 	return parity;
 }
 
Signature · 1 line
2.5.0
#86 lore raw

PATCH v2 29/30 input: use parity8 in elantech

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

Remove even parity table, use parity8 instead.

---
 drivers/input/mouse/elantech.c | 10 +++-------
 drivers/input/mouse/elantech.h |  1 -
 2 files changed, 3 insertions(+), 8 deletions(-)
drivers/input/mouse/elantech.c +3 -7
index 78f93cf..bbb4aa6 100644
@@ -693,9 +693,9 @@ static int elantech_packet_check_v1(struct psmouse *psmouse)
 
 	p3 = (packet[0] & 0x04) >> 2;
 
-	return etd->parity[packet[1]] == p1 &&
-	       etd->parity[packet[2]] == p2 &&
-	       etd->parity[packet[3]] == p3;
+	return parity8(packet[1]) != p1 &&
+	       parity8(packet[2]) != p2 &&
+	       parity8(packet[3]) != p3;
 }
 
 static int elantech_debounce_check_v2(struct psmouse *psmouse)
@@ -1635,10 +1635,6 @@ int elantech_init(struct psmouse *psmouse)
 
 	psmouse_reset(psmouse);
 
-	etd->parity[0] = 1;
-	for (i = 1; i < 256; i++)
-		etd->parity[i] = etd->parity[i & (i - 1)] ^ 1;
-
 	/*
 	 * Do the version query again so we can store the result
 	 */
drivers/input/mouse/elantech.h +0 -1
index e1cbf40..542c5d9 100644
@@ -141,7 +141,6 @@ struct elantech_data {
 	unsigned int y_max;
 	unsigned int width;
 	struct finger_pos mt[ETP_MAX_FINGERS];
-	unsigned char parity[256];
 	int (*send_cmd)(struct psmouse *psmouse, unsigned char c, unsigned char *param);
 	void (*original_set_rate)(struct psmouse *psmouse, unsigned int rate);
 };
Signature · 1 line
2.5.0
#87 lore raw

PATCH v2 30/30 ethernet: use parity8 in broadcom/tg3.c

In reply to Zeng Zhaoxiu

From: Zhaoxiu Zeng <[email protected]>

---
 drivers/net/ethernet/broadcom/tg3.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
drivers/net/ethernet/broadcom/tg3.c +1 -5
index 3010080..802a429 100644
@@ -12939,11 +12939,7 @@ static int tg3_test_nvram(struct tg3 *tp)
 
 		err = -EIO;
 		for (i = 0; i < NVRAM_SELFBOOT_DATA_SIZE; i++) {
-			u8 hw8 = hweight8(data[i]);
-
-			if ((hw8 & 0x1) && parity[i])
-				goto out;
-			else if (!(hw8 & 0x1) && !parity[i])
+			if (parity8(data[i]) == !!parity[i])
 				goto out;
 		}
 		err = 0;
Signature · 1 line
2.5.0