Merge tag 'v6.8-rc4' into x86/percpu, to resolve conflicts and refresh the branch
[sfrench/cifs-2.6.git] / arch / x86 / include / asm / percpu.h
index 5e01883eb51ee8e576e70db0577bfbe0c20c2e4f..44958ebaf626e20c970acaacaad012f93cba2671 100644 (file)
@@ -4,17 +4,21 @@
 
 #ifdef CONFIG_X86_64
 #define __percpu_seg           gs
+#define __percpu_rel           (%rip)
 #else
 #define __percpu_seg           fs
+#define __percpu_rel
 #endif
 
 #ifdef __ASSEMBLY__
 
 #ifdef CONFIG_SMP
-#define PER_CPU_VAR(var)       %__percpu_seg:var
-#else /* ! SMP */
-#define PER_CPU_VAR(var)       var
-#endif /* SMP */
+#define __percpu               %__percpu_seg:
+#else
+#define __percpu
+#endif
+
+#define PER_CPU_VAR(var)       __percpu(var)__percpu_rel
 
 #ifdef CONFIG_X86_64_SMP
 #define INIT_PER_CPU_VAR(var)  init_per_cpu__##var
 
 #else /* ...!ASSEMBLY */
 
+#include <linux/build_bug.h>
 #include <linux/stringify.h>
 #include <asm/asm.h>
 
 #ifdef CONFIG_SMP
+
+#ifdef CONFIG_CC_HAS_NAMED_AS
+
+#ifdef __CHECKER__
+#define __seg_gs               __attribute__((address_space(__seg_gs)))
+#define __seg_fs               __attribute__((address_space(__seg_fs)))
+#endif
+
+#ifdef CONFIG_X86_64
+#define __percpu_seg_override  __seg_gs
+#else
+#define __percpu_seg_override  __seg_fs
+#endif
+
+#define __percpu_prefix                ""
+
+#else /* CONFIG_CC_HAS_NAMED_AS */
+
+#define __percpu_seg_override
 #define __percpu_prefix                "%%"__stringify(__percpu_seg)":"
+
+#endif /* CONFIG_CC_HAS_NAMED_AS */
+
+#define __force_percpu_prefix  "%%"__stringify(__percpu_seg)":"
 #define __my_cpu_offset                this_cpu_read(this_cpu_off)
 
+#ifdef CONFIG_USE_X86_SEG_SUPPORT
+/*
+ * Efficient implementation for cases in which the compiler supports
+ * named address spaces.  Allows the compiler to perform additional
+ * optimizations that can save more instructions.
+ */
+#define arch_raw_cpu_ptr(ptr)                                  \
+({                                                             \
+       unsigned long tcp_ptr__;                                \
+       tcp_ptr__ = __raw_cpu_read(, this_cpu_off);             \
+                                                               \
+       tcp_ptr__ += (unsigned long)(ptr);                      \
+       (typeof(*(ptr)) __kernel __force *)tcp_ptr__;           \
+})
+#else /* CONFIG_USE_X86_SEG_SUPPORT */
 /*
  * Compared to the generic __my_cpu_offset version, the following
  * saves one instruction and avoids clobbering a temp register.
  */
-#define arch_raw_cpu_ptr(ptr)                          \
-({                                                     \
-       unsigned long tcp_ptr__;                        \
-       asm ("add " __percpu_arg(1) ", %0"              \
-            : "=r" (tcp_ptr__)                         \
-            : "m" (this_cpu_off), "0" (ptr));          \
-       (typeof(*(ptr)) __kernel __force *)tcp_ptr__;   \
+#define arch_raw_cpu_ptr(ptr)                                  \
+({                                                             \
+       unsigned long tcp_ptr__;                                \
+       asm ("mov " __percpu_arg(1) ", %0"                      \
+            : "=r" (tcp_ptr__)                                 \
+            : "m" (__my_cpu_var(this_cpu_off)));               \
+                                                               \
+       tcp_ptr__ += (unsigned long)(ptr);                      \
+       (typeof(*(ptr)) __kernel __force *)tcp_ptr__;           \
 })
-#else
+#endif /* CONFIG_USE_X86_SEG_SUPPORT */
+
+#define PER_CPU_VAR(var)       %__percpu_seg:(var)__percpu_rel
+
+#else /* CONFIG_SMP */
+#define __percpu_seg_override
 #define __percpu_prefix                ""
-#endif
+#define __force_percpu_prefix  ""
+
+#define PER_CPU_VAR(var)       (var)__percpu_rel
 
+#endif /* CONFIG_SMP */
+
+#define __my_cpu_type(var)     typeof(var) __percpu_seg_override
+#define __my_cpu_ptr(ptr)      (__my_cpu_type(*ptr) *)(uintptr_t)(ptr)
+#define __my_cpu_var(var)      (*__my_cpu_ptr(&var))
 #define __percpu_arg(x)                __percpu_prefix "%" #x
+#define __force_percpu_arg(x)  __force_percpu_prefix "%" #x
 
 /*
  * Initialized pointers to per-cpu variables needed for the boot
@@ -107,14 +165,14 @@ do {                                                                      \
                (void)pto_tmp__;                                        \
        }                                                               \
        asm qual(__pcpu_op2_##size(op, "%[val]", __percpu_arg([var]))   \
-           : [var] "+m" (_var)                                         \
+           : [var] "+m" (__my_cpu_var(_var))                           \
            : [val] __pcpu_reg_imm_##size(pto_val__));                  \
 } while (0)
 
 #define percpu_unary_op(size, qual, op, _var)                          \
 ({                                                                     \
        asm qual (__pcpu_op1_##size(op, __percpu_arg([var]))            \
-           : [var] "+m" (_var));                                       \
+           : [var] "+m" (__my_cpu_var(_var)));                         \
 })
 
 /*
@@ -144,16 +202,16 @@ do {                                                                      \
        __pcpu_type_##size pfo_val__;                                   \
        asm qual (__pcpu_op2_##size(op, __percpu_arg([var]), "%[val]")  \
            : [val] __pcpu_reg_##size("=", pfo_val__)                   \
-           : [var] "m" (_var));                                        \
+           : [var] "m" (__my_cpu_var(_var)));                          \
        (typeof(_var))(unsigned long) pfo_val__;                        \
 })
 
 #define percpu_stable_op(size, op, _var)                               \
 ({                                                                     \
        __pcpu_type_##size pfo_val__;                                   \
-       asm(__pcpu_op2_##size(op, __percpu_arg(P[var]), "%[val]")       \
+       asm(__pcpu_op2_##size(op, __force_percpu_arg(a[var]), "%[val]") \
            : [val] __pcpu_reg_##size("=", pfo_val__)                   \
-           : [var] "p" (&(_var)));                                     \
+           : [var] "i" (&(_var)));                                     \
        (typeof(_var))(unsigned long) pfo_val__;                        \
 })
 
@@ -166,7 +224,7 @@ do {                                                                        \
        asm qual (__pcpu_op2_##size("xadd", "%[tmp]",                   \
                                     __percpu_arg([var]))               \
                  : [tmp] __pcpu_reg_##size("+", paro_tmp__),           \
-                   [var] "+m" (_var)                                   \
+                   [var] "+m" (__my_cpu_var(_var))                     \
                  : : "memory");                                        \
        (typeof(_var))(unsigned long) (paro_tmp__ + _val);              \
 })
@@ -187,7 +245,7 @@ do {                                                                        \
                                    __percpu_arg([var]))                \
                  "\n\tjnz 1b"                                          \
                  : [oval] "=&a" (pxo_old__),                           \
-                   [var] "+m" (_var)                                   \
+                   [var] "+m" (__my_cpu_var(_var))                     \
                  : [nval] __pcpu_reg_##size(, pxo_new__)               \
                  : "memory");                                          \
        (typeof(_var))(unsigned long) pxo_old__;                        \
@@ -204,7 +262,7 @@ do {                                                                        \
        asm qual (__pcpu_op2_##size("cmpxchg", "%[nval]",               \
                                    __percpu_arg([var]))                \
                  : [oval] "+a" (pco_old__),                            \
-                   [var] "+m" (_var)                                   \
+                   [var] "+m" (__my_cpu_var(_var))                     \
                  : [nval] __pcpu_reg_##size(, pco_new__)               \
                  : "memory");                                          \
        (typeof(_var))(unsigned long) pco_old__;                        \
@@ -221,7 +279,7 @@ do {                                                                        \
                  CC_SET(z)                                             \
                  : CC_OUT(z) (success),                                \
                    [oval] "+a" (pco_old__),                            \
-                   [var] "+m" (_var)                                   \
+                   [var] "+m" (__my_cpu_var(_var))                     \
                  : [nval] __pcpu_reg_##size(, pco_new__)               \
                  : "memory");                                          \
        if (unlikely(!success))                                         \
@@ -244,7 +302,7 @@ do {                                                                        \
                                                                        \
        asm qual (ALTERNATIVE("call this_cpu_cmpxchg8b_emu",            \
                              "cmpxchg8b " __percpu_arg([var]), X86_FEATURE_CX8) \
-                 : [var] "+m" (_var),                                  \
+                 : [var] "+m" (__my_cpu_var(_var)),                    \
                    "+a" (old__.low),                                   \
                    "+d" (old__.high)                                   \
                  : "b" (new__.low),                                    \
@@ -276,7 +334,7 @@ do {                                                                        \
                              "cmpxchg8b " __percpu_arg([var]), X86_FEATURE_CX8) \
                  CC_SET(z)                                             \
                  : CC_OUT(z) (success),                                \
-                   [var] "+m" (_var),                                  \
+                   [var] "+m" (__my_cpu_var(_var)),                    \
                    "+a" (old__.low),                                   \
                    "+d" (old__.high)                                   \
                  : "b" (new__.low),                                    \
@@ -313,7 +371,7 @@ do {                                                                        \
                                                                        \
        asm qual (ALTERNATIVE("call this_cpu_cmpxchg16b_emu",           \
                              "cmpxchg16b " __percpu_arg([var]), X86_FEATURE_CX16) \
-                 : [var] "+m" (_var),                                  \
+                 : [var] "+m" (__my_cpu_var(_var)),                    \
                    "+a" (old__.low),                                   \
                    "+d" (old__.high)                                   \
                  : "b" (new__.low),                                    \
@@ -345,7 +403,7 @@ do {                                                                        \
                              "cmpxchg16b " __percpu_arg([var]), X86_FEATURE_CX16) \
                  CC_SET(z)                                             \
                  : CC_OUT(z) (success),                                \
-                   [var] "+m" (_var),                                  \
+                   [var] "+m" (__my_cpu_var(_var)),                    \
                    "+a" (old__.low),                                   \
                    "+d" (old__.high)                                   \
                  : "b" (new__.low),                                    \
@@ -366,9 +424,9 @@ do {                                                                        \
  * accessed while this_cpu_read_stable() allows the value to be cached.
  * this_cpu_read_stable() is more efficient and can be used if its value
  * is guaranteed to be valid across cpus.  The current users include
- * get_current() and get_thread_info() both of which are actually
- * per-thread variables implemented as per-cpu variables and thus
- * stable for the duration of the respective task.
+ * pcpu_hot.current_task and pcpu_hot.top_of_stack, both of which are
+ * actually per-thread variables implemented as per-CPU variables and
+ * thus stable for the duration of the respective task.
  */
 #define this_cpu_read_stable_1(pcp)    percpu_stable_op(1, "mov", pcp)
 #define this_cpu_read_stable_2(pcp)    percpu_stable_op(2, "mov", pcp)
@@ -376,13 +434,72 @@ do {                                                                      \
 #define this_cpu_read_stable_8(pcp)    percpu_stable_op(8, "mov", pcp)
 #define this_cpu_read_stable(pcp)      __pcpu_size_call_return(this_cpu_read_stable_, pcp)
 
+#ifdef CONFIG_USE_X86_SEG_SUPPORT
+
+#define __raw_cpu_read(qual, pcp)                                      \
+({                                                                     \
+       *(qual __my_cpu_type(pcp) *)__my_cpu_ptr(&(pcp));               \
+})
+
+#define __raw_cpu_write(qual, pcp, val)                                        \
+do {                                                                   \
+       *(qual __my_cpu_type(pcp) *)__my_cpu_ptr(&(pcp)) = (val);       \
+} while (0)
+
+#define raw_cpu_read_1(pcp)            __raw_cpu_read(, pcp)
+#define raw_cpu_read_2(pcp)            __raw_cpu_read(, pcp)
+#define raw_cpu_read_4(pcp)            __raw_cpu_read(, pcp)
+#define raw_cpu_write_1(pcp, val)      __raw_cpu_write(, pcp, val)
+#define raw_cpu_write_2(pcp, val)      __raw_cpu_write(, pcp, val)
+#define raw_cpu_write_4(pcp, val)      __raw_cpu_write(, pcp, val)
+
+#define this_cpu_read_1(pcp)           __raw_cpu_read(volatile, pcp)
+#define this_cpu_read_2(pcp)           __raw_cpu_read(volatile, pcp)
+#define this_cpu_read_4(pcp)           __raw_cpu_read(volatile, pcp)
+#define this_cpu_write_1(pcp, val)     __raw_cpu_write(volatile, pcp, val)
+#define this_cpu_write_2(pcp, val)     __raw_cpu_write(volatile, pcp, val)
+#define this_cpu_write_4(pcp, val)     __raw_cpu_write(volatile, pcp, val)
+
+#ifdef CONFIG_X86_64
+#define raw_cpu_read_8(pcp)            __raw_cpu_read(, pcp)
+#define raw_cpu_write_8(pcp, val)      __raw_cpu_write(, pcp, val)
+
+#define this_cpu_read_8(pcp)           __raw_cpu_read(volatile, pcp)
+#define this_cpu_write_8(pcp, val)     __raw_cpu_write(volatile, pcp, val)
+#endif
+
+#define this_cpu_read_const(pcp)       __raw_cpu_read(, pcp)
+#else /* CONFIG_USE_X86_SEG_SUPPORT */
+
 #define raw_cpu_read_1(pcp)            percpu_from_op(1, , "mov", pcp)
 #define raw_cpu_read_2(pcp)            percpu_from_op(2, , "mov", pcp)
 #define raw_cpu_read_4(pcp)            percpu_from_op(4, , "mov", pcp)
-
 #define raw_cpu_write_1(pcp, val)      percpu_to_op(1, , "mov", (pcp), val)
 #define raw_cpu_write_2(pcp, val)      percpu_to_op(2, , "mov", (pcp), val)
 #define raw_cpu_write_4(pcp, val)      percpu_to_op(4, , "mov", (pcp), val)
+
+#define this_cpu_read_1(pcp)           percpu_from_op(1, volatile, "mov", pcp)
+#define this_cpu_read_2(pcp)           percpu_from_op(2, volatile, "mov", pcp)
+#define this_cpu_read_4(pcp)           percpu_from_op(4, volatile, "mov", pcp)
+#define this_cpu_write_1(pcp, val)     percpu_to_op(1, volatile, "mov", (pcp), val)
+#define this_cpu_write_2(pcp, val)     percpu_to_op(2, volatile, "mov", (pcp), val)
+#define this_cpu_write_4(pcp, val)     percpu_to_op(4, volatile, "mov", (pcp), val)
+
+#ifdef CONFIG_X86_64
+#define raw_cpu_read_8(pcp)            percpu_from_op(8, , "mov", pcp)
+#define raw_cpu_write_8(pcp, val)      percpu_to_op(8, , "mov", (pcp), val)
+
+#define this_cpu_read_8(pcp)           percpu_from_op(8, volatile, "mov", pcp)
+#define this_cpu_write_8(pcp, val)     percpu_to_op(8, volatile, "mov", (pcp), val)
+#endif
+
+/*
+ * The generic per-cpu infrastrucutre is not suitable for
+ * reading const-qualified variables.
+ */
+#define this_cpu_read_const(pcp)       ({ BUILD_BUG(); (typeof(pcp))0; })
+#endif /* CONFIG_USE_X86_SEG_SUPPORT */
+
 #define raw_cpu_add_1(pcp, val)                percpu_add_op(1, , (pcp), val)
 #define raw_cpu_add_2(pcp, val)                percpu_add_op(2, , (pcp), val)
 #define raw_cpu_add_4(pcp, val)                percpu_add_op(4, , (pcp), val)
@@ -408,12 +525,6 @@ do {                                                                       \
 #define raw_cpu_xchg_2(pcp, val)       raw_percpu_xchg_op(pcp, val)
 #define raw_cpu_xchg_4(pcp, val)       raw_percpu_xchg_op(pcp, val)
 
-#define this_cpu_read_1(pcp)           percpu_from_op(1, volatile, "mov", pcp)
-#define this_cpu_read_2(pcp)           percpu_from_op(2, volatile, "mov", pcp)
-#define this_cpu_read_4(pcp)           percpu_from_op(4, volatile, "mov", pcp)
-#define this_cpu_write_1(pcp, val)     percpu_to_op(1, volatile, "mov", (pcp), val)
-#define this_cpu_write_2(pcp, val)     percpu_to_op(2, volatile, "mov", (pcp), val)
-#define this_cpu_write_4(pcp, val)     percpu_to_op(4, volatile, "mov", (pcp), val)
 #define this_cpu_add_1(pcp, val)       percpu_add_op(1, volatile, (pcp), val)
 #define this_cpu_add_2(pcp, val)       percpu_add_op(2, volatile, (pcp), val)
 #define this_cpu_add_4(pcp, val)       percpu_add_op(4, volatile, (pcp), val)
@@ -452,8 +563,6 @@ do {                                                                        \
  * 32 bit must fall back to generic operations.
  */
 #ifdef CONFIG_X86_64
-#define raw_cpu_read_8(pcp)                    percpu_from_op(8, , "mov", pcp)
-#define raw_cpu_write_8(pcp, val)              percpu_to_op(8, , "mov", (pcp), val)
 #define raw_cpu_add_8(pcp, val)                        percpu_add_op(8, , (pcp), val)
 #define raw_cpu_and_8(pcp, val)                        percpu_to_op(8, , "and", (pcp), val)
 #define raw_cpu_or_8(pcp, val)                 percpu_to_op(8, , "or", (pcp), val)
@@ -462,8 +571,6 @@ do {                                                                        \
 #define raw_cpu_cmpxchg_8(pcp, oval, nval)     percpu_cmpxchg_op(8, , pcp, oval, nval)
 #define raw_cpu_try_cmpxchg_8(pcp, ovalp, nval)        percpu_try_cmpxchg_op(8, , pcp, ovalp, nval)
 
-#define this_cpu_read_8(pcp)                   percpu_from_op(8, volatile, "mov", pcp)
-#define this_cpu_write_8(pcp, val)             percpu_to_op(8, volatile, "mov", (pcp), val)
 #define this_cpu_add_8(pcp, val)               percpu_add_op(8, volatile, (pcp), val)
 #define this_cpu_and_8(pcp, val)               percpu_to_op(8, volatile, "and", (pcp), val)
 #define this_cpu_or_8(pcp, val)                        percpu_to_op(8, volatile, "or", (pcp), val)
@@ -494,7 +601,7 @@ static inline bool x86_this_cpu_variable_test_bit(int nr,
        asm volatile("btl "__percpu_arg(2)",%1"
                        CC_SET(c)
                        : CC_OUT(c) (oldbit)
-                       : "m" (*(unsigned long __percpu *)addr), "Ir" (nr));
+                       : "m" (*__my_cpu_ptr((unsigned long __percpu *)(addr))), "Ir" (nr));
 
        return oldbit;
 }