Merge branch 'rwonce/rework' of git://git.kernel.org/pub/scm/linux/kernel/git/will...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 10 Jun 2020 21:46:54 +0000 (14:46 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 10 Jun 2020 21:46:54 +0000 (14:46 -0700)
Pull READ/WRITE_ONCE rework from Will Deacon:
 "This the READ_ONCE rework I've been working on for a while, which
  bumps the minimum GCC version and improves code-gen on arm64 when
  stack protector is enabled"

[ Side note: I'm _really_ tempted to raise the minimum gcc version to
  4.9, so that we can just say that we require _Generic() support.

  That would allow us to more cleanly handle a lot of the cases where we
  depend on very complex macros with 'sizeof' or __builtin_choose_expr()
  with __builtin_types_compatible_p() etc.

  This branch has a workaround for sparse not handling _Generic(),
  either, but that was already fixed in the sparse development branch,
  so it's really just gcc-4.9 that we'd require.   - Linus ]

* 'rwonce/rework' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux:
  compiler_types.h: Use unoptimized __unqual_scalar_typeof for sparse
  compiler_types.h: Optimize __unqual_scalar_typeof compilation time
  compiler.h: Enforce that READ_ONCE_NOCHECK() access size is sizeof(long)
  compiler-types.h: Include naked type in __pick_integer_type() match
  READ_ONCE: Fix comment describing 2x32-bit atomicity
  gcov: Remove old GCC 3.4 support
  arm64: barrier: Use '__unqual_scalar_typeof' for acquire/release macros
  locking/barriers: Use '__unqual_scalar_typeof' for load-acquire macros
  READ_ONCE: Drop pointer qualifiers when reading from scalar types
  READ_ONCE: Enforce atomicity for {READ,WRITE}_ONCE() memory accesses
  READ_ONCE: Simplify implementations of {READ,WRITE}_ONCE()
  arm64: csum: Disable KASAN for do_csum()
  fault_inject: Don't rely on "return value" from WRITE_ONCE()
  net: tls: Avoid assigning 'const' pointer to non-const pointer
  netfilter: Avoid assigning 'const' pointer to non-const pointer
  compiler/gcc: Raise minimum GCC version for kernel builds to 4.8

18 files changed:
Documentation/process/changes.rst
arch/arm/crypto/Kconfig
arch/arm64/include/asm/barrier.h
arch/arm64/lib/csum.c
crypto/Kconfig
drivers/xen/time.c
include/asm-generic/barrier.h
include/linux/compiler-gcc.h
include/linux/compiler.h
include/linux/compiler_types.h
init/Kconfig
kernel/gcov/Kconfig
kernel/gcov/Makefile
kernel/gcov/gcc_3_4.c [deleted file]
lib/fault-inject.c
net/netfilter/core.c
net/tls/tls_main.c
scripts/gcc-plugins/Kconfig

index 91c5ff8..5cfb54c 100644 (file)
@@ -29,7 +29,7 @@ you probably needn't concern yourself with pcmciautils.
 ====================== ===============  ========================================
         Program        Minimal version       Command to check the version
 ====================== ===============  ========================================
-GNU C                  4.6              gcc --version
+GNU C                  4.8              gcc --version
 GNU make               3.81             make --version
 binutils               2.23             ld -v
 flex                   2.5.35           flex --version
index 2674de6..c9bf2df 100644 (file)
@@ -30,7 +30,7 @@ config CRYPTO_SHA1_ARM_NEON
 
 config CRYPTO_SHA1_ARM_CE
        tristate "SHA1 digest algorithm (ARM v8 Crypto Extensions)"
-       depends on KERNEL_MODE_NEON && (CC_IS_CLANG || GCC_VERSION >= 40800)
+       depends on KERNEL_MODE_NEON
        select CRYPTO_SHA1_ARM
        select CRYPTO_HASH
        help
@@ -39,7 +39,7 @@ config CRYPTO_SHA1_ARM_CE
 
 config CRYPTO_SHA2_ARM_CE
        tristate "SHA-224/256 digest algorithm (ARM v8 Crypto Extensions)"
-       depends on KERNEL_MODE_NEON && (CC_IS_CLANG || GCC_VERSION >= 40800)
+       depends on KERNEL_MODE_NEON
        select CRYPTO_SHA256_ARM
        select CRYPTO_HASH
        help
@@ -96,7 +96,7 @@ config CRYPTO_AES_ARM_BS
 
 config CRYPTO_AES_ARM_CE
        tristate "Accelerated AES using ARMv8 Crypto Extensions"
-       depends on KERNEL_MODE_NEON && (CC_IS_CLANG || GCC_VERSION >= 40800)
+       depends on KERNEL_MODE_NEON
        select CRYPTO_SKCIPHER
        select CRYPTO_LIB_AES
        select CRYPTO_SIMD
@@ -106,7 +106,7 @@ config CRYPTO_AES_ARM_CE
 
 config CRYPTO_GHASH_ARM_CE
        tristate "PMULL-accelerated GHASH using NEON/ARMv8 Crypto Extensions"
-       depends on KERNEL_MODE_NEON && (CC_IS_CLANG || GCC_VERSION >= 40800)
+       depends on KERNEL_MODE_NEON
        select CRYPTO_HASH
        select CRYPTO_CRYPTD
        select CRYPTO_GF128MUL
@@ -118,13 +118,13 @@ config CRYPTO_GHASH_ARM_CE
 
 config CRYPTO_CRCT10DIF_ARM_CE
        tristate "CRCT10DIF digest algorithm using PMULL instructions"
-       depends on KERNEL_MODE_NEON && (CC_IS_CLANG || GCC_VERSION >= 40800)
+       depends on KERNEL_MODE_NEON
        depends on CRC_T10DIF
        select CRYPTO_HASH
 
 config CRYPTO_CRC32_ARM_CE
        tristate "CRC32(C) digest algorithm using CRC and/or PMULL instructions"
-       depends on KERNEL_MODE_NEON && (CC_IS_CLANG || GCC_VERSION >= 40800)
+       depends on KERNEL_MODE_NEON
        depends on CRC32
        select CRYPTO_HASH
 
index 7d9cc5e..fb4c275 100644 (file)
@@ -76,8 +76,8 @@ static inline unsigned long array_index_mask_nospec(unsigned long idx,
 #define __smp_store_release(p, v)                                      \
 do {                                                                   \
        typeof(p) __p = (p);                                            \
-       union { typeof(*p) __val; char __c[1]; } __u =                  \
-               { .__val = (__force typeof(*p)) (v) };                  \
+       union { __unqual_scalar_typeof(*p) __val; char __c[1]; } __u =  \
+               { .__val = (__force __unqual_scalar_typeof(*p)) (v) };  \
        compiletime_assert_atomic_type(*p);                             \
        kasan_check_write(__p, sizeof(*p));                             \
        switch (sizeof(*p)) {                                           \
@@ -110,7 +110,7 @@ do {                                                                        \
 
 #define __smp_load_acquire(p)                                          \
 ({                                                                     \
-       union { typeof(*p) __val; char __c[1]; } __u;                   \
+       union { __unqual_scalar_typeof(*p) __val; char __c[1]; } __u;   \
        typeof(p) __p = (p);                                            \
        compiletime_assert_atomic_type(*p);                             \
        kasan_check_read(__p, sizeof(*p));                              \
@@ -136,33 +136,33 @@ do {                                                                      \
                        : "Q" (*__p) : "memory");                       \
                break;                                                  \
        }                                                               \
-       __u.__val;                                                      \
+       (typeof(*p))__u.__val;                                          \
 })
 
 #define smp_cond_load_relaxed(ptr, cond_expr)                          \
 ({                                                                     \
        typeof(ptr) __PTR = (ptr);                                      \
-       typeof(*ptr) VAL;                                               \
+       __unqual_scalar_typeof(*ptr) VAL;                               \
        for (;;) {                                                      \
                VAL = READ_ONCE(*__PTR);                                \
                if (cond_expr)                                          \
                        break;                                          \
                __cmpwait_relaxed(__PTR, VAL);                          \
        }                                                               \
-       VAL;                                                            \
+       (typeof(*ptr))VAL;                                              \
 })
 
 #define smp_cond_load_acquire(ptr, cond_expr)                          \
 ({                                                                     \
        typeof(ptr) __PTR = (ptr);                                      \
-       typeof(*ptr) VAL;                                               \
+       __unqual_scalar_typeof(*ptr) VAL;                               \
        for (;;) {                                                      \
                VAL = smp_load_acquire(__PTR);                          \
                if (cond_expr)                                          \
                        break;                                          \
                __cmpwait_relaxed(__PTR, VAL);                          \
        }                                                               \
-       VAL;                                                            \
+       (typeof(*ptr))VAL;                                              \
 })
 
 #include <asm-generic/barrier.h>
index 60eccae..78b87a6 100644 (file)
@@ -14,7 +14,11 @@ static u64 accumulate(u64 sum, u64 data)
        return tmp + (tmp >> 64);
 }
 
-unsigned int do_csum(const unsigned char *buff, int len)
+/*
+ * We over-read the buffer and this makes KASAN unhappy. Instead, disable
+ * instrumentation and call kasan explicitly.
+ */
+unsigned int __no_sanitize_address do_csum(const unsigned char *buff, int len)
 {
        unsigned int offset, shift, sum;
        const u64 *ptr;
@@ -42,7 +46,7 @@ unsigned int do_csum(const unsigned char *buff, int len)
         * odd/even alignment, and means we can ignore it until the very end.
         */
        shift = offset * 8;
-       data = READ_ONCE_NOCHECK(*ptr++);
+       data = *ptr++;
 #ifdef __LITTLE_ENDIAN
        data = (data >> shift) << shift;
 #else
@@ -58,10 +62,10 @@ unsigned int do_csum(const unsigned char *buff, int len)
        while (unlikely(len > 64)) {
                __uint128_t tmp1, tmp2, tmp3, tmp4;
 
-               tmp1 = READ_ONCE_NOCHECK(*(__uint128_t *)ptr);
-               tmp2 = READ_ONCE_NOCHECK(*(__uint128_t *)(ptr + 2));
-               tmp3 = READ_ONCE_NOCHECK(*(__uint128_t *)(ptr + 4));
-               tmp4 = READ_ONCE_NOCHECK(*(__uint128_t *)(ptr + 6));
+               tmp1 = *(__uint128_t *)ptr;
+               tmp2 = *(__uint128_t *)(ptr + 2);
+               tmp3 = *(__uint128_t *)(ptr + 4);
+               tmp4 = *(__uint128_t *)(ptr + 6);
 
                len -= 64;
                ptr += 8;
@@ -85,7 +89,7 @@ unsigned int do_csum(const unsigned char *buff, int len)
                __uint128_t tmp;
 
                sum64 = accumulate(sum64, data);
-               tmp = READ_ONCE_NOCHECK(*(__uint128_t *)ptr);
+               tmp = *(__uint128_t *)ptr;
 
                len -= 16;
                ptr += 2;
@@ -100,7 +104,7 @@ unsigned int do_csum(const unsigned char *buff, int len)
        }
        if (len > 0) {
                sum64 = accumulate(sum64, data);
-               data = READ_ONCE_NOCHECK(*ptr);
+               data = *ptr;
                len -= 8;
        }
        /*
index d5daf35..091c0a0 100644 (file)
@@ -316,7 +316,6 @@ config CRYPTO_AEGIS128
 config CRYPTO_AEGIS128_SIMD
        bool "Support SIMD acceleration for AEGIS-128"
        depends on CRYPTO_AEGIS128 && ((ARM || ARM64) && KERNEL_MODE_NEON)
-       depends on !ARM || CC_IS_CLANG || GCC_VERSION >= 40800
        default y
 
 config CRYPTO_AEGIS128_AESNI_SSE2
index 0968859..108edbc 100644 (file)
@@ -64,7 +64,7 @@ static void xen_get_runstate_snapshot_cpu_delta(
        do {
                state_time = get64(&state->state_entry_time);
                rmb();  /* Hypervisor might update data. */
-               *res = READ_ONCE(*state);
+               *res = __READ_ONCE(*state);
                rmb();  /* Hypervisor might update data. */
        } while (get64(&state->state_entry_time) != state_time ||
                 (state_time & XEN_RUNSTATE_UPDATE));
index 85b28eb..2eacaf7 100644 (file)
@@ -128,10 +128,10 @@ do {                                                                      \
 #ifndef __smp_load_acquire
 #define __smp_load_acquire(p)                                          \
 ({                                                                     \
-       typeof(*p) ___p1 = READ_ONCE(*p);                               \
+       __unqual_scalar_typeof(*p) ___p1 = READ_ONCE(*p);               \
        compiletime_assert_atomic_type(*p);                             \
        __smp_mb();                                                     \
-       ___p1;                                                          \
+       (typeof(*p))___p1;                                              \
 })
 #endif
 
@@ -183,10 +183,10 @@ do {                                                                      \
 #ifndef smp_load_acquire
 #define smp_load_acquire(p)                                            \
 ({                                                                     \
-       typeof(*p) ___p1 = READ_ONCE(*p);                               \
+       __unqual_scalar_typeof(*p) ___p1 = READ_ONCE(*p);               \
        compiletime_assert_atomic_type(*p);                             \
        barrier();                                                      \
-       ___p1;                                                          \
+       (typeof(*p))___p1;                                              \
 })
 #endif
 
@@ -229,14 +229,14 @@ do {                                                                      \
 #ifndef smp_cond_load_relaxed
 #define smp_cond_load_relaxed(ptr, cond_expr) ({               \
        typeof(ptr) __PTR = (ptr);                              \
-       typeof(*ptr) VAL;                                       \
+       __unqual_scalar_typeof(*ptr) VAL;                       \
        for (;;) {                                              \
                VAL = READ_ONCE(*__PTR);                        \
                if (cond_expr)                                  \
                        break;                                  \
                cpu_relax();                                    \
        }                                                       \
-       VAL;                                                    \
+       (typeof(*ptr))VAL;                                      \
 })
 #endif
 
@@ -250,10 +250,10 @@ do {                                                                      \
  */
 #ifndef smp_cond_load_acquire
 #define smp_cond_load_acquire(ptr, cond_expr) ({               \
-       typeof(*ptr) _val;                                      \
+       __unqual_scalar_typeof(*ptr) _val;                      \
        _val = smp_cond_load_relaxed(ptr, cond_expr);           \
        smp_acquire__after_ctrl_dep();                          \
-       _val;                                                   \
+       (typeof(*ptr))_val;                                     \
 })
 #endif
 
index d7ee4c6..e2f7252 100644 (file)
@@ -10,7 +10,8 @@
                     + __GNUC_MINOR__ * 100     \
                     + __GNUC_PATCHLEVEL__)
 
-#if GCC_VERSION < 40600
+/* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145 */
+#if GCC_VERSION < 40800
 # error Sorry, your compiler is too old - please upgrade it.
 #endif
 
 #if defined(CONFIG_ARCH_USE_BUILTIN_BSWAP) && !defined(__CHECKER__)
 #define __HAVE_BUILTIN_BSWAP32__
 #define __HAVE_BUILTIN_BSWAP64__
-#if GCC_VERSION >= 40800
 #define __HAVE_BUILTIN_BSWAP16__
-#endif
 #endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP && !__CHECKER__ */
 
 #if GCC_VERSION >= 70000
index 6325d64..33d3a2e 100644 (file)
@@ -230,60 +230,6 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
 # define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __LINE__)
 #endif
 
-#include <uapi/linux/types.h>
-
-#define __READ_ONCE_SIZE                                               \
-({                                                                     \
-       switch (size) {                                                 \
-       case 1: *(__u8 *)res = *(volatile __u8 *)p; break;              \
-       case 2: *(__u16 *)res = *(volatile __u16 *)p; break;            \
-       case 4: *(__u32 *)res = *(volatile __u32 *)p; break;            \
-       case 8: *(__u64 *)res = *(volatile __u64 *)p; break;            \
-       default:                                                        \
-               barrier();                                              \
-               __builtin_memcpy((void *)res, (const void *)p, size);   \
-               barrier();                                              \
-       }                                                               \
-})
-
-static __always_inline
-void __read_once_size(const volatile void *p, void *res, int size)
-{
-       __READ_ONCE_SIZE;
-}
-
-#ifdef CONFIG_KASAN
-/*
- * We can't declare function 'inline' because __no_sanitize_address confilcts
- * with inlining. Attempt to inline it may cause a build failure.
- *     https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
- * '__maybe_unused' allows us to avoid defined-but-not-used warnings.
- */
-# define __no_kasan_or_inline __no_sanitize_address notrace __maybe_unused
-#else
-# define __no_kasan_or_inline __always_inline
-#endif
-
-static __no_kasan_or_inline
-void __read_once_size_nocheck(const volatile void *p, void *res, int size)
-{
-       __READ_ONCE_SIZE;
-}
-
-static __always_inline void __write_once_size(volatile void *p, void *res, int size)
-{
-       switch (size) {
-       case 1: *(volatile __u8 *)p = *(__u8 *)res; break;
-       case 2: *(volatile __u16 *)p = *(__u16 *)res; break;
-       case 4: *(volatile __u32 *)p = *(__u32 *)res; break;
-       case 8: *(volatile __u64 *)p = *(__u64 *)res; break;
-       default:
-               barrier();
-               __builtin_memcpy((void *)p, (const void *)res, size);
-               barrier();
-       }
-}
-
 /*
  * Prevent the compiler from merging or refetching reads or writes. The
  * compiler is also forbidden from reordering successive instances of
@@ -293,11 +239,7 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
  * statements.
  *
  * These two macros will also work on aggregate data types like structs or
- * unions. If the size of the accessed data type exceeds the word size of
- * the machine (e.g., 32 bits or 64 bits) READ_ONCE() and WRITE_ONCE() will
- * fall back to memcpy(). There's at least two memcpy()s: one for the
- * __builtin_memcpy() and then one for the macro doing the copy of variable
- * - '__u' allocated on the stack.
+ * unions.
  *
  * Their two major use cases are: (1) Mediating communication between
  * process-level code and irq/NMI handlers, all running on the same CPU,
@@ -309,23 +251,69 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 #include <asm/barrier.h>
 #include <linux/kasan-checks.h>
 
-#define __READ_ONCE(x, check)                                          \
+/*
+ * Use __READ_ONCE() instead of READ_ONCE() if you do not require any
+ * atomicity or dependency ordering guarantees. Note that this may result
+ * in tears!
+ */
+#define __READ_ONCE(x) (*(const volatile __unqual_scalar_typeof(x) *)&(x))
+
+#define __READ_ONCE_SCALAR(x)                                          \
 ({                                                                     \
-       union { typeof(x) __val; char __c[1]; } __u;                    \
-       if (check)                                                      \
-               __read_once_size(&(x), __u.__c, sizeof(x));             \
-       else                                                            \
-               __read_once_size_nocheck(&(x), __u.__c, sizeof(x));     \
-       smp_read_barrier_depends(); /* Enforce dependency ordering from x */ \
-       __u.__val;                                                      \
+       __unqual_scalar_typeof(x) __x = __READ_ONCE(x);                 \
+       smp_read_barrier_depends();                                     \
+       (typeof(x))__x;                                                 \
 })
-#define READ_ONCE(x) __READ_ONCE(x, 1)
 
+#define READ_ONCE(x)                                                   \
+({                                                                     \
+       compiletime_assert_rwonce_type(x);                              \
+       __READ_ONCE_SCALAR(x);                                          \
+})
+
+#define __WRITE_ONCE(x, val)                           \
+do {                                                   \
+       *(volatile typeof(x) *)&(x) = (val);            \
+} while (0)
+
+#define WRITE_ONCE(x, val)                             \
+do {                                                   \
+       compiletime_assert_rwonce_type(x);              \
+       __WRITE_ONCE(x, val);                           \
+} while (0)
+
+#ifdef CONFIG_KASAN
 /*
- * Use READ_ONCE_NOCHECK() instead of READ_ONCE() if you need
- * to hide memory access from KASAN.
+ * We can't declare function 'inline' because __no_sanitize_address conflicts
+ * with inlining. Attempt to inline it may cause a build failure.
+ *     https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
+ * '__maybe_unused' allows us to avoid defined-but-not-used warnings.
  */
-#define READ_ONCE_NOCHECK(x) __READ_ONCE(x, 0)
+# define __no_kasan_or_inline __no_sanitize_address notrace __maybe_unused
+#else
+# define __no_kasan_or_inline __always_inline
+#endif
+
+static __no_kasan_or_inline
+unsigned long __read_once_word_nocheck(const void *addr)
+{
+       return __READ_ONCE(*(unsigned long *)addr);
+}
+
+/*
+ * Use READ_ONCE_NOCHECK() instead of READ_ONCE() if you need to load a
+ * word from memory atomically but without telling KASAN. This is usually
+ * used by unwinding code when walking the stack of a running process.
+ */
+#define READ_ONCE_NOCHECK(x)                                           \
+({                                                                     \
+       unsigned long __x;                                              \
+       compiletime_assert(sizeof(x) == sizeof(__x),                    \
+               "Unsupported access size for READ_ONCE_NOCHECK().");    \
+       __x = __read_once_word_nocheck(&(x));                           \
+       smp_read_barrier_depends();                                     \
+       (typeof(x))__x;                                                 \
+})
 
 static __no_kasan_or_inline
 unsigned long read_word_at_a_time(const void *addr)
@@ -334,14 +322,6 @@ unsigned long read_word_at_a_time(const void *addr)
        return *(unsigned long *)addr;
 }
 
-#define WRITE_ONCE(x, val) \
-({                                                     \
-       union { typeof(x) __val; char __c[1]; } __u =   \
-               { .__val = (__force typeof(x)) (val) }; \
-       __write_once_size(&(x), __u.__c, sizeof(x));    \
-       __u.__val;                                      \
-})
-
 #endif /* __KERNEL__ */
 
 /*
@@ -406,6 +386,16 @@ static inline void *offset_to_ptr(const int *off)
        compiletime_assert(__native_word(t),                            \
                "Need native word sized stores/loads for atomicity.")
 
+/*
+ * Yes, this permits 64-bit accesses on 32-bit architectures. These will
+ * actually be atomic in some cases (namely Armv7 + LPAE), but for others we
+ * rely on the access being split into 2x32-bit accesses for a 32-bit quantity
+ * (e.g. a virtual address) and a strong prevailing wind.
+ */
+#define compiletime_assert_rwonce_type(t)                                      \
+       compiletime_assert(__native_word(t) || sizeof(t) == sizeof(long long),  \
+               "Unsupported access size for {READ,WRITE}_ONCE().")
+
 /* &a[0] degrades to a pointer: a different type from an array */
 #define __must_be_array(a)     BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
 
index 6fcf732..d4e1956 100644 (file)
@@ -218,6 +218,53 @@ struct ftrace_likely_data {
 /* Are two types/vars the same type (ignoring qualifiers)? */
 #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
 
+/*
+ * __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving
+ *                            non-scalar types unchanged.
+ */
+#if (defined(CONFIG_CC_IS_GCC) && CONFIG_GCC_VERSION < 40900) || defined(__CHECKER__)
+/*
+ * We build this out of a couple of helper macros in a vain attempt to
+ * help you keep your lunch down while reading it.
+ */
+#define __pick_scalar_type(x, type, otherwise)                                 \
+       __builtin_choose_expr(__same_type(x, type), (type)0, otherwise)
+
+/*
+ * 'char' is not type-compatible with either 'signed char' or 'unsigned char',
+ * so we include the naked type here as well as the signed/unsigned variants.
+ */
+#define __pick_integer_type(x, type, otherwise)                                        \
+       __pick_scalar_type(x, type,                                             \
+               __pick_scalar_type(x, unsigned type,                            \
+                       __pick_scalar_type(x, signed type, otherwise)))
+
+#define __unqual_scalar_typeof(x) typeof(                                      \
+       __pick_integer_type(x, char,                                            \
+               __pick_integer_type(x, short,                                   \
+                       __pick_integer_type(x, int,                             \
+                               __pick_integer_type(x, long,                    \
+                                       __pick_integer_type(x, long long, x))))))
+#else
+/*
+ * If supported, prefer C11 _Generic for better compile-times. As above, 'char'
+ * is not type-compatible with 'signed char', and we define a separate case.
+ */
+#define __scalar_type_to_expr_cases(type)                              \
+               unsigned type:  (unsigned type)0,                       \
+               signed type:    (signed type)0
+
+#define __unqual_scalar_typeof(x) typeof(                              \
+               _Generic((x),                                           \
+                        char:  (char)0,                                \
+                        __scalar_type_to_expr_cases(char),             \
+                        __scalar_type_to_expr_cases(short),            \
+                        __scalar_type_to_expr_cases(int),              \
+                        __scalar_type_to_expr_cases(long),             \
+                        __scalar_type_to_expr_cases(long long),        \
+                        default: (x)))
+#endif
+
 /* Is this type a native word size -- useful for atomic operations */
 #define __native_word(t) \
        (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || \
index 58a4b70..49eb7a3 100644 (file)
@@ -1293,7 +1293,6 @@ config LD_DEAD_CODE_DATA_ELIMINATION
        bool "Dead code and data elimination (EXPERIMENTAL)"
        depends on HAVE_LD_DEAD_CODE_DATA_ELIMINATION
        depends on EXPERT
-       depends on !(FUNCTION_TRACER && CC_IS_GCC && GCC_VERSION < 40800)
        depends on $(cc-option,-ffunction-sections -fdata-sections)
        depends on $(ld-option,--gc-sections)
        help
index 3941a9c..feaad59 100644 (file)
@@ -51,28 +51,4 @@ config GCOV_PROFILE_ALL
        larger and run slower. Also be sure to exclude files from profiling
        which are not linked to the kernel image to prevent linker errors.
 
-choice
-       prompt "Specify GCOV format"
-       depends on GCOV_KERNEL
-       depends on CC_IS_GCC
-       ---help---
-       The gcov format is usually determined by the GCC version, and the
-       default is chosen according to your GCC version. However, there are
-       exceptions where format changes are integrated in lower-version GCCs.
-       In such a case, change this option to adjust the format used in the
-       kernel accordingly.
-
-config GCOV_FORMAT_3_4
-       bool "GCC 3.4 format"
-       depends on GCC_VERSION < 40700
-       ---help---
-       Select this option to use the format defined by GCC 3.4.
-
-config GCOV_FORMAT_4_7
-       bool "GCC 4.7 format"
-       ---help---
-       Select this option to use the format defined by GCC 4.7.
-
-endchoice
-
 endmenu
index d66a74b..16f8ecc 100644 (file)
@@ -2,6 +2,5 @@
 ccflags-y := -DSRCTREE='"$(srctree)"' -DOBJTREE='"$(objtree)"'
 
 obj-y := base.o fs.o
-obj-$(CONFIG_GCOV_FORMAT_3_4) += gcc_base.o gcc_3_4.o
-obj-$(CONFIG_GCOV_FORMAT_4_7) += gcc_base.o gcc_4_7.o
+obj-$(CONFIG_CC_IS_GCC) += gcc_base.o gcc_4_7.o
 obj-$(CONFIG_CC_IS_CLANG) += clang.o
diff --git a/kernel/gcov/gcc_3_4.c b/kernel/gcov/gcc_3_4.c
deleted file mode 100644 (file)
index acb8355..0000000
+++ /dev/null
@@ -1,573 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *  This code provides functions to handle gcc's profiling data format
- *  introduced with gcc 3.4. Future versions of gcc may change the gcov
- *  format (as happened before), so all format-specific information needs
- *  to be kept modular and easily exchangeable.
- *
- *  This file is based on gcc-internal definitions. Functions and data
- *  structures are defined to be compatible with gcc counterparts.
- *  For a better understanding, refer to gcc source: gcc/gcov-io.h.
- *
- *    Copyright IBM Corp. 2009
- *    Author(s): Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
- *
- *    Uses gcc-internal data definitions.
- */
-
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/seq_file.h>
-#include <linux/vmalloc.h>
-#include "gcov.h"
-
-#define GCOV_COUNTERS          5
-
-static struct gcov_info *gcov_info_head;
-
-/**
- * struct gcov_fn_info - profiling meta data per function
- * @ident: object file-unique function identifier
- * @checksum: function checksum
- * @n_ctrs: number of values per counter type belonging to this function
- *
- * This data is generated by gcc during compilation and doesn't change
- * at run-time.
- */
-struct gcov_fn_info {
-       unsigned int ident;
-       unsigned int checksum;
-       unsigned int n_ctrs[];
-};
-
-/**
- * struct gcov_ctr_info - profiling data per counter type
- * @num: number of counter values for this type
- * @values: array of counter values for this type
- * @merge: merge function for counter values of this type (unused)
- *
- * This data is generated by gcc during compilation and doesn't change
- * at run-time with the exception of the values array.
- */
-struct gcov_ctr_info {
-       unsigned int    num;
-       gcov_type       *values;
-       void            (*merge)(gcov_type *, unsigned int);
-};
-
-/**
- * struct gcov_info - profiling data per object file
- * @version: gcov version magic indicating the gcc version used for compilation
- * @next: list head for a singly-linked list
- * @stamp: time stamp
- * @filename: name of the associated gcov data file
- * @n_functions: number of instrumented functions
- * @functions: function data
- * @ctr_mask: mask specifying which counter types are active
- * @counts: counter data per counter type
- *
- * This data is generated by gcc during compilation and doesn't change
- * at run-time with the exception of the next pointer.
- */
-struct gcov_info {
-       unsigned int                    version;
-       struct gcov_info                *next;
-       unsigned int                    stamp;
-       const char                      *filename;
-       unsigned int                    n_functions;
-       const struct gcov_fn_info       *functions;
-       unsigned int                    ctr_mask;
-       struct gcov_ctr_info            counts[];
-};
-
-/**
- * gcov_info_filename - return info filename
- * @info: profiling data set
- */
-const char *gcov_info_filename(struct gcov_info *info)
-{
-       return info->filename;
-}
-
-/**
- * gcov_info_version - return info version
- * @info: profiling data set
- */
-unsigned int gcov_info_version(struct gcov_info *info)
-{
-       return info->version;
-}
-
-/**
- * gcov_info_next - return next profiling data set
- * @info: profiling data set
- *
- * Returns next gcov_info following @info or first gcov_info in the chain if
- * @info is %NULL.
- */
-struct gcov_info *gcov_info_next(struct gcov_info *info)
-{
-       if (!info)
-               return gcov_info_head;
-
-       return info->next;
-}
-
-/**
- * gcov_info_link - link/add profiling data set to the list
- * @info: profiling data set
- */
-void gcov_info_link(struct gcov_info *info)
-{
-       info->next = gcov_info_head;
-       gcov_info_head = info;
-}
-
-/**
- * gcov_info_unlink - unlink/remove profiling data set from the list
- * @prev: previous profiling data set
- * @info: profiling data set
- */
-void gcov_info_unlink(struct gcov_info *prev, struct gcov_info *info)
-{
-       if (prev)
-               prev->next = info->next;
-       else
-               gcov_info_head = info->next;
-}
-
-/**
- * gcov_info_within_module - check if a profiling data set belongs to a module
- * @info: profiling data set
- * @mod: module
- *
- * Returns true if profiling data belongs module, false otherwise.
- */
-bool gcov_info_within_module(struct gcov_info *info, struct module *mod)
-{
-       return within_module((unsigned long)info, mod);
-}
-
-/* Symbolic links to be created for each profiling data file. */
-const struct gcov_link gcov_link[] = {
-       { OBJ_TREE, "gcno" },   /* Link to .gcno file in $(objtree). */
-       { 0, NULL},
-};
-
-/*
- * Determine whether a counter is active. Based on gcc magic. Doesn't change
- * at run-time.
- */
-static int counter_active(struct gcov_info *info, unsigned int type)
-{
-       return (1 << type) & info->ctr_mask;
-}
-
-/* Determine number of active counters. Based on gcc magic. */
-static unsigned int num_counter_active(struct gcov_info *info)
-{
-       unsigned int i;
-       unsigned int result = 0;
-
-       for (i = 0; i < GCOV_COUNTERS; i++) {
-               if (counter_active(info, i))
-                       result++;
-       }
-       return result;
-}
-
-/**
- * gcov_info_reset - reset profiling data to zero
- * @info: profiling data set
- */
-void gcov_info_reset(struct gcov_info *info)
-{
-       unsigned int active = num_counter_active(info);
-       unsigned int i;
-
-       for (i = 0; i < active; i++) {
-               memset(info->counts[i].values, 0,
-                      info->counts[i].num * sizeof(gcov_type));
-       }
-}
-
-/**
- * gcov_info_is_compatible - check if profiling data can be added
- * @info1: first profiling data set
- * @info2: second profiling data set
- *
- * Returns non-zero if profiling data can be added, zero otherwise.
- */
-int gcov_info_is_compatible(struct gcov_info *info1, struct gcov_info *info2)
-{
-       return (info1->stamp == info2->stamp);
-}
-
-/**
- * gcov_info_add - add up profiling data
- * @dest: profiling data set to which data is added
- * @source: profiling data set which is added
- *
- * Adds profiling counts of @source to @dest.
- */
-void gcov_info_add(struct gcov_info *dest, struct gcov_info *source)
-{
-       unsigned int i;
-       unsigned int j;
-
-       for (i = 0; i < num_counter_active(dest); i++) {
-               for (j = 0; j < dest->counts[i].num; j++) {
-                       dest->counts[i].values[j] +=
-                               source->counts[i].values[j];
-               }
-       }
-}
-
-/* Get size of function info entry. Based on gcc magic. */
-static size_t get_fn_size(struct gcov_info *info)
-{
-       size_t size;
-
-       size = sizeof(struct gcov_fn_info) + num_counter_active(info) *
-              sizeof(unsigned int);
-       if (__alignof__(struct gcov_fn_info) > sizeof(unsigned int))
-               size = ALIGN(size, __alignof__(struct gcov_fn_info));
-       return size;
-}
-
-/* Get address of function info entry. Based on gcc magic. */
-static struct gcov_fn_info *get_fn_info(struct gcov_info *info, unsigned int fn)
-{
-       return (struct gcov_fn_info *)
-               ((char *) info->functions + fn * get_fn_size(info));
-}
-
-/**
- * gcov_info_dup - duplicate profiling data set
- * @info: profiling data set to duplicate
- *
- * Return newly allocated duplicate on success, %NULL on error.
- */
-struct gcov_info *gcov_info_dup(struct gcov_info *info)
-{
-       struct gcov_info *dup;
-       unsigned int i;
-       unsigned int active;
-
-       /* Duplicate gcov_info. */
-       active = num_counter_active(info);
-       dup = kzalloc(struct_size(dup, counts, active), GFP_KERNEL);
-       if (!dup)
-               return NULL;
-       dup->version            = info->version;
-       dup->stamp              = info->stamp;
-       dup->n_functions        = info->n_functions;
-       dup->ctr_mask           = info->ctr_mask;
-       /* Duplicate filename. */
-       dup->filename           = kstrdup(info->filename, GFP_KERNEL);
-       if (!dup->filename)
-               goto err_free;
-       /* Duplicate table of functions. */
-       dup->functions = kmemdup(info->functions, info->n_functions *
-                                get_fn_size(info), GFP_KERNEL);
-       if (!dup->functions)
-               goto err_free;
-       /* Duplicate counter arrays. */
-       for (i = 0; i < active ; i++) {
-               struct gcov_ctr_info *ctr = &info->counts[i];
-               size_t size = ctr->num * sizeof(gcov_type);
-
-               dup->counts[i].num = ctr->num;
-               dup->counts[i].merge = ctr->merge;
-               dup->counts[i].values = vmalloc(size);
-               if (!dup->counts[i].values)
-                       goto err_free;
-               memcpy(dup->counts[i].values, ctr->values, size);
-       }
-       return dup;
-
-err_free:
-       gcov_info_free(dup);
-       return NULL;
-}
-
-/**
- * gcov_info_free - release memory for profiling data set duplicate
- * @info: profiling data set duplicate to free
- */
-void gcov_info_free(struct gcov_info *info)
-{
-       unsigned int active = num_counter_active(info);
-       unsigned int i;
-
-       for (i = 0; i < active ; i++)
-               vfree(info->counts[i].values);
-       kfree(info->functions);
-       kfree(info->filename);
-       kfree(info);
-}
-
-/**
- * struct type_info - iterator helper array
- * @ctr_type: counter type
- * @offset: index of the first value of the current function for this type
- *
- * This array is needed to convert the in-memory data format into the in-file
- * data format:
- *
- * In-memory:
- *   for each counter type
- *     for each function
- *       values
- *
- * In-file:
- *   for each function
- *     for each counter type
- *       values
- *
- * See gcc source gcc/gcov-io.h for more information on data organization.
- */
-struct type_info {
-       int ctr_type;
-       unsigned int offset;
-};
-
-/**
- * struct gcov_iterator - specifies current file position in logical records
- * @info: associated profiling data
- * @record: record type
- * @function: function number
- * @type: counter type
- * @count: index into values array
- * @num_types: number of counter types
- * @type_info: helper array to get values-array offset for current function
- */
-struct gcov_iterator {
-       struct gcov_info *info;
-
-       int record;
-       unsigned int function;
-       unsigned int type;
-       unsigned int count;
-
-       int num_types;
-       struct type_info type_info[];
-};
-
-static struct gcov_fn_info *get_func(struct gcov_iterator *iter)
-{
-       return get_fn_info(iter->info, iter->function);
-}
-
-static struct type_info *get_type(struct gcov_iterator *iter)
-{
-       return &iter->type_info[iter->type];
-}
-
-/**
- * gcov_iter_new - allocate and initialize profiling data iterator
- * @info: profiling data set to be iterated
- *
- * Return file iterator on success, %NULL otherwise.
- */
-struct gcov_iterator *gcov_iter_new(struct gcov_info *info)
-{
-       struct gcov_iterator *iter;
-
-       iter = kzalloc(struct_size(iter, type_info, num_counter_active(info)),
-                      GFP_KERNEL);
-       if (iter)
-               iter->info = info;
-
-       return iter;
-}
-
-/**
- * gcov_iter_free - release memory for iterator
- * @iter: file iterator to free
- */
-void gcov_iter_free(struct gcov_iterator *iter)
-{
-       kfree(iter);
-}
-
-/**
- * gcov_iter_get_info - return profiling data set for given file iterator
- * @iter: file iterator
- */
-struct gcov_info *gcov_iter_get_info(struct gcov_iterator *iter)
-{
-       return iter->info;
-}
-
-/**
- * gcov_iter_start - reset file iterator to starting position
- * @iter: file iterator
- */
-void gcov_iter_start(struct gcov_iterator *iter)
-{
-       int i;
-
-       iter->record = 0;
-       iter->function = 0;
-       iter->type = 0;
-       iter->count = 0;
-       iter->num_types = 0;
-       for (i = 0; i < GCOV_COUNTERS; i++) {
-               if (counter_active(iter->info, i)) {
-                       iter->type_info[iter->num_types].ctr_type = i;
-                       iter->type_info[iter->num_types++].offset = 0;
-               }
-       }
-}
-
-/* Mapping of logical record number to actual file content. */
-#define RECORD_FILE_MAGIC      0
-#define RECORD_GCOV_VERSION    1
-#define RECORD_TIME_STAMP      2
-#define RECORD_FUNCTION_TAG    3
-#define RECORD_FUNCTON_TAG_LEN 4
-#define RECORD_FUNCTION_IDENT  5
-#define RECORD_FUNCTION_CHECK  6
-#define RECORD_COUNT_TAG       7
-#define RECORD_COUNT_LEN       8
-#define RECORD_COUNT           9
-
-/**
- * gcov_iter_next - advance file iterator to next logical record
- * @iter: file iterator
- *
- * Return zero if new position is valid, non-zero if iterator has reached end.
- */
-int gcov_iter_next(struct gcov_iterator *iter)
-{
-       switch (iter->record) {
-       case RECORD_FILE_MAGIC:
-       case RECORD_GCOV_VERSION:
-       case RECORD_FUNCTION_TAG:
-       case RECORD_FUNCTON_TAG_LEN:
-       case RECORD_FUNCTION_IDENT:
-       case RECORD_COUNT_TAG:
-               /* Advance to next record */
-               iter->record++;
-               break;
-       case RECORD_COUNT:
-               /* Advance to next count */
-               iter->count++;
-               /* fall through */
-       case RECORD_COUNT_LEN:
-               if (iter->count < get_func(iter)->n_ctrs[iter->type]) {
-                       iter->record = 9;
-                       break;
-               }
-               /* Advance to next counter type */
-               get_type(iter)->offset += iter->count;
-               iter->count = 0;
-               iter->type++;
-               /* fall through */
-       case RECORD_FUNCTION_CHECK:
-               if (iter->type < iter->num_types) {
-                       iter->record = 7;
-                       break;
-               }
-               /* Advance to next function */
-               iter->type = 0;
-               iter->function++;
-               /* fall through */
-       case RECORD_TIME_STAMP:
-               if (iter->function < iter->info->n_functions)
-                       iter->record = 3;
-               else
-                       iter->record = -1;
-               break;
-       }
-       /* Check for EOF. */
-       if (iter->record == -1)
-               return -EINVAL;
-       else
-               return 0;
-}
-
-/**
- * seq_write_gcov_u32 - write 32 bit number in gcov format to seq_file
- * @seq: seq_file handle
- * @v: value to be stored
- *
- * Number format defined by gcc: numbers are recorded in the 32 bit
- * unsigned binary form of the endianness of the machine generating the
- * file.
- */
-static int seq_write_gcov_u32(struct seq_file *seq, u32 v)
-{
-       return seq_write(seq, &v, sizeof(v));
-}
-
-/**
- * seq_write_gcov_u64 - write 64 bit number in gcov format to seq_file
- * @seq: seq_file handle
- * @v: value to be stored
- *
- * Number format defined by gcc: numbers are recorded in the 32 bit
- * unsigned binary form of the endianness of the machine generating the
- * file. 64 bit numbers are stored as two 32 bit numbers, the low part
- * first.
- */
-static int seq_write_gcov_u64(struct seq_file *seq, u64 v)
-{
-       u32 data[2];
-
-       data[0] = (v & 0xffffffffUL);
-       data[1] = (v >> 32);
-       return seq_write(seq, data, sizeof(data));
-}
-
-/**
- * gcov_iter_write - write data for current pos to seq_file
- * @iter: file iterator
- * @seq: seq_file handle
- *
- * Return zero on success, non-zero otherwise.
- */
-int gcov_iter_write(struct gcov_iterator *iter, struct seq_file *seq)
-{
-       int rc = -EINVAL;
-
-       switch (iter->record) {
-       case RECORD_FILE_MAGIC:
-               rc = seq_write_gcov_u32(seq, GCOV_DATA_MAGIC);
-               break;
-       case RECORD_GCOV_VERSION:
-               rc = seq_write_gcov_u32(seq, iter->info->version);
-               break;
-       case RECORD_TIME_STAMP:
-               rc = seq_write_gcov_u32(seq, iter->info->stamp);
-               break;
-       case RECORD_FUNCTION_TAG:
-               rc = seq_write_gcov_u32(seq, GCOV_TAG_FUNCTION);
-               break;
-       case RECORD_FUNCTON_TAG_LEN:
-               rc = seq_write_gcov_u32(seq, 2);
-               break;
-       case RECORD_FUNCTION_IDENT:
-               rc = seq_write_gcov_u32(seq, get_func(iter)->ident);
-               break;
-       case RECORD_FUNCTION_CHECK:
-               rc = seq_write_gcov_u32(seq, get_func(iter)->checksum);
-               break;
-       case RECORD_COUNT_TAG:
-               rc = seq_write_gcov_u32(seq,
-                       GCOV_TAG_FOR_COUNTER(get_type(iter)->ctr_type));
-               break;
-       case RECORD_COUNT_LEN:
-               rc = seq_write_gcov_u32(seq,
-                               get_func(iter)->n_ctrs[iter->type] * 2);
-               break;
-       case RECORD_COUNT:
-               rc = seq_write_gcov_u64(seq,
-                       iter->info->counts[iter->type].
-                               values[iter->count + get_type(iter)->offset]);
-               break;
-       }
-       return rc;
-}
index 8186ca8..ce12621 100644 (file)
@@ -106,7 +106,9 @@ bool should_fail(struct fault_attr *attr, ssize_t size)
                unsigned int fail_nth = READ_ONCE(current->fail_nth);
 
                if (fail_nth) {
-                       if (!WRITE_ONCE(current->fail_nth, fail_nth - 1))
+                       fail_nth--;
+                       WRITE_ONCE(current->fail_nth, fail_nth);
+                       if (!fail_nth)
                                goto fail;
 
                        return false;
index 78f046e..3ac7c8c 100644 (file)
@@ -376,7 +376,7 @@ static bool nf_remove_net_hook(struct nf_hook_entries *old,
                if (orig_ops[i] != unreg)
                        continue;
                WRITE_ONCE(old->hooks[i].hook, accept_all);
-               WRITE_ONCE(orig_ops[i], &dummy_ops);
+               WRITE_ONCE(orig_ops[i], (void *)&dummy_ops);
                return true;
        }
 
index 0e98900..ec10041 100644 (file)
@@ -629,7 +629,7 @@ struct tls_context *tls_ctx_create(struct sock *sk)
 static void tls_build_proto(struct sock *sk)
 {
        int ip_ver = sk->sk_family == AF_INET6 ? TLSV6 : TLSV4;
-       const struct proto *prot = READ_ONCE(sk->sk_prot);
+       struct proto *prot = READ_ONCE(sk->sk_prot);
 
        /* Build IPv6 TLS whenever the address of tcpv6 _prot changes */
        if (ip_ver == TLSV6 &&
index 013ba3a..ce0b99f 100644 (file)
@@ -8,7 +8,7 @@ config HAVE_GCC_PLUGINS
 menuconfig GCC_PLUGINS
        bool "GCC plugins"
        depends on HAVE_GCC_PLUGINS
-       depends on CC_IS_GCC && GCC_VERSION >= 40800
+       depends on CC_IS_GCC
        depends on $(success,$(srctree)/scripts/gcc-plugin.sh $(CC))
        default y
        help