162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _ASM_X86_PERCPU_H
362306a36Sopenharmony_ci#define _ASM_X86_PERCPU_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#ifdef CONFIG_X86_64
662306a36Sopenharmony_ci#define __percpu_seg		gs
762306a36Sopenharmony_ci#else
862306a36Sopenharmony_ci#define __percpu_seg		fs
962306a36Sopenharmony_ci#endif
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#ifdef __ASSEMBLY__
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#ifdef CONFIG_SMP
1462306a36Sopenharmony_ci#define PER_CPU_VAR(var)	%__percpu_seg:var
1562306a36Sopenharmony_ci#else /* ! SMP */
1662306a36Sopenharmony_ci#define PER_CPU_VAR(var)	var
1762306a36Sopenharmony_ci#endif	/* SMP */
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#ifdef CONFIG_X86_64_SMP
2062306a36Sopenharmony_ci#define INIT_PER_CPU_VAR(var)  init_per_cpu__##var
2162306a36Sopenharmony_ci#else
2262306a36Sopenharmony_ci#define INIT_PER_CPU_VAR(var)  var
2362306a36Sopenharmony_ci#endif
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#else /* ...!ASSEMBLY */
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include <linux/kernel.h>
2862306a36Sopenharmony_ci#include <linux/stringify.h>
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#ifdef CONFIG_SMP
3162306a36Sopenharmony_ci#define __percpu_prefix		"%%"__stringify(__percpu_seg)":"
3262306a36Sopenharmony_ci#define __my_cpu_offset		this_cpu_read(this_cpu_off)
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/*
3562306a36Sopenharmony_ci * Compared to the generic __my_cpu_offset version, the following
3662306a36Sopenharmony_ci * saves one instruction and avoids clobbering a temp register.
3762306a36Sopenharmony_ci */
3862306a36Sopenharmony_ci#define arch_raw_cpu_ptr(ptr)				\
3962306a36Sopenharmony_ci({							\
4062306a36Sopenharmony_ci	unsigned long tcp_ptr__;			\
4162306a36Sopenharmony_ci	asm ("add " __percpu_arg(1) ", %0"		\
4262306a36Sopenharmony_ci	     : "=r" (tcp_ptr__)				\
4362306a36Sopenharmony_ci	     : "m" (this_cpu_off), "0" (ptr));		\
4462306a36Sopenharmony_ci	(typeof(*(ptr)) __kernel __force *)tcp_ptr__;	\
4562306a36Sopenharmony_ci})
4662306a36Sopenharmony_ci#else
4762306a36Sopenharmony_ci#define __percpu_prefix		""
4862306a36Sopenharmony_ci#endif
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci#define __percpu_arg(x)		__percpu_prefix "%" #x
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/*
5362306a36Sopenharmony_ci * Initialized pointers to per-cpu variables needed for the boot
5462306a36Sopenharmony_ci * processor need to use these macros to get the proper address
5562306a36Sopenharmony_ci * offset from __per_cpu_load on SMP.
5662306a36Sopenharmony_ci *
5762306a36Sopenharmony_ci * There also must be an entry in vmlinux_64.lds.S
5862306a36Sopenharmony_ci */
5962306a36Sopenharmony_ci#define DECLARE_INIT_PER_CPU(var) \
6062306a36Sopenharmony_ci       extern typeof(var) init_per_cpu_var(var)
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci#ifdef CONFIG_X86_64_SMP
6362306a36Sopenharmony_ci#define init_per_cpu_var(var)  init_per_cpu__##var
6462306a36Sopenharmony_ci#else
6562306a36Sopenharmony_ci#define init_per_cpu_var(var)  var
6662306a36Sopenharmony_ci#endif
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/* For arch-specific code, we can use direct single-insn ops (they
6962306a36Sopenharmony_ci * don't give an lvalue though). */
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci#define __pcpu_type_1 u8
7262306a36Sopenharmony_ci#define __pcpu_type_2 u16
7362306a36Sopenharmony_ci#define __pcpu_type_4 u32
7462306a36Sopenharmony_ci#define __pcpu_type_8 u64
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci#define __pcpu_cast_1(val) ((u8)(((unsigned long) val) & 0xff))
7762306a36Sopenharmony_ci#define __pcpu_cast_2(val) ((u16)(((unsigned long) val) & 0xffff))
7862306a36Sopenharmony_ci#define __pcpu_cast_4(val) ((u32)(((unsigned long) val) & 0xffffffff))
7962306a36Sopenharmony_ci#define __pcpu_cast_8(val) ((u64)(val))
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci#define __pcpu_op1_1(op, dst) op "b " dst
8262306a36Sopenharmony_ci#define __pcpu_op1_2(op, dst) op "w " dst
8362306a36Sopenharmony_ci#define __pcpu_op1_4(op, dst) op "l " dst
8462306a36Sopenharmony_ci#define __pcpu_op1_8(op, dst) op "q " dst
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci#define __pcpu_op2_1(op, src, dst) op "b " src ", " dst
8762306a36Sopenharmony_ci#define __pcpu_op2_2(op, src, dst) op "w " src ", " dst
8862306a36Sopenharmony_ci#define __pcpu_op2_4(op, src, dst) op "l " src ", " dst
8962306a36Sopenharmony_ci#define __pcpu_op2_8(op, src, dst) op "q " src ", " dst
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci#define __pcpu_reg_1(mod, x) mod "q" (x)
9262306a36Sopenharmony_ci#define __pcpu_reg_2(mod, x) mod "r" (x)
9362306a36Sopenharmony_ci#define __pcpu_reg_4(mod, x) mod "r" (x)
9462306a36Sopenharmony_ci#define __pcpu_reg_8(mod, x) mod "r" (x)
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci#define __pcpu_reg_imm_1(x) "qi" (x)
9762306a36Sopenharmony_ci#define __pcpu_reg_imm_2(x) "ri" (x)
9862306a36Sopenharmony_ci#define __pcpu_reg_imm_4(x) "ri" (x)
9962306a36Sopenharmony_ci#define __pcpu_reg_imm_8(x) "re" (x)
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci#define percpu_to_op(size, qual, op, _var, _val)			\
10262306a36Sopenharmony_cido {									\
10362306a36Sopenharmony_ci	__pcpu_type_##size pto_val__ = __pcpu_cast_##size(_val);	\
10462306a36Sopenharmony_ci	if (0) {		                                        \
10562306a36Sopenharmony_ci		typeof(_var) pto_tmp__;					\
10662306a36Sopenharmony_ci		pto_tmp__ = (_val);					\
10762306a36Sopenharmony_ci		(void)pto_tmp__;					\
10862306a36Sopenharmony_ci	}								\
10962306a36Sopenharmony_ci	asm qual(__pcpu_op2_##size(op, "%[val]", __percpu_arg([var]))	\
11062306a36Sopenharmony_ci	    : [var] "+m" (_var)						\
11162306a36Sopenharmony_ci	    : [val] __pcpu_reg_imm_##size(pto_val__));			\
11262306a36Sopenharmony_ci} while (0)
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci#define percpu_unary_op(size, qual, op, _var)				\
11562306a36Sopenharmony_ci({									\
11662306a36Sopenharmony_ci	asm qual (__pcpu_op1_##size(op, __percpu_arg([var]))		\
11762306a36Sopenharmony_ci	    : [var] "+m" (_var));					\
11862306a36Sopenharmony_ci})
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci/*
12162306a36Sopenharmony_ci * Generate a percpu add to memory instruction and optimize code
12262306a36Sopenharmony_ci * if one is added or subtracted.
12362306a36Sopenharmony_ci */
12462306a36Sopenharmony_ci#define percpu_add_op(size, qual, var, val)				\
12562306a36Sopenharmony_cido {									\
12662306a36Sopenharmony_ci	const int pao_ID__ = (__builtin_constant_p(val) &&		\
12762306a36Sopenharmony_ci			      ((val) == 1 || (val) == -1)) ?		\
12862306a36Sopenharmony_ci				(int)(val) : 0;				\
12962306a36Sopenharmony_ci	if (0) {							\
13062306a36Sopenharmony_ci		typeof(var) pao_tmp__;					\
13162306a36Sopenharmony_ci		pao_tmp__ = (val);					\
13262306a36Sopenharmony_ci		(void)pao_tmp__;					\
13362306a36Sopenharmony_ci	}								\
13462306a36Sopenharmony_ci	if (pao_ID__ == 1)						\
13562306a36Sopenharmony_ci		percpu_unary_op(size, qual, "inc", var);		\
13662306a36Sopenharmony_ci	else if (pao_ID__ == -1)					\
13762306a36Sopenharmony_ci		percpu_unary_op(size, qual, "dec", var);		\
13862306a36Sopenharmony_ci	else								\
13962306a36Sopenharmony_ci		percpu_to_op(size, qual, "add", var, val);		\
14062306a36Sopenharmony_ci} while (0)
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci#define percpu_from_op(size, qual, op, _var)				\
14362306a36Sopenharmony_ci({									\
14462306a36Sopenharmony_ci	__pcpu_type_##size pfo_val__;					\
14562306a36Sopenharmony_ci	asm qual (__pcpu_op2_##size(op, __percpu_arg([var]), "%[val]")	\
14662306a36Sopenharmony_ci	    : [val] __pcpu_reg_##size("=", pfo_val__)			\
14762306a36Sopenharmony_ci	    : [var] "m" (_var));					\
14862306a36Sopenharmony_ci	(typeof(_var))(unsigned long) pfo_val__;			\
14962306a36Sopenharmony_ci})
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci#define percpu_stable_op(size, op, _var)				\
15262306a36Sopenharmony_ci({									\
15362306a36Sopenharmony_ci	__pcpu_type_##size pfo_val__;					\
15462306a36Sopenharmony_ci	asm(__pcpu_op2_##size(op, __percpu_arg(P[var]), "%[val]")	\
15562306a36Sopenharmony_ci	    : [val] __pcpu_reg_##size("=", pfo_val__)			\
15662306a36Sopenharmony_ci	    : [var] "p" (&(_var)));					\
15762306a36Sopenharmony_ci	(typeof(_var))(unsigned long) pfo_val__;			\
15862306a36Sopenharmony_ci})
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci/*
16162306a36Sopenharmony_ci * Add return operation
16262306a36Sopenharmony_ci */
16362306a36Sopenharmony_ci#define percpu_add_return_op(size, qual, _var, _val)			\
16462306a36Sopenharmony_ci({									\
16562306a36Sopenharmony_ci	__pcpu_type_##size paro_tmp__ = __pcpu_cast_##size(_val);	\
16662306a36Sopenharmony_ci	asm qual (__pcpu_op2_##size("xadd", "%[tmp]",			\
16762306a36Sopenharmony_ci				     __percpu_arg([var]))		\
16862306a36Sopenharmony_ci		  : [tmp] __pcpu_reg_##size("+", paro_tmp__),		\
16962306a36Sopenharmony_ci		    [var] "+m" (_var)					\
17062306a36Sopenharmony_ci		  : : "memory");					\
17162306a36Sopenharmony_ci	(typeof(_var))(unsigned long) (paro_tmp__ + _val);		\
17262306a36Sopenharmony_ci})
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci/*
17562306a36Sopenharmony_ci * xchg is implemented using cmpxchg without a lock prefix. xchg is
17662306a36Sopenharmony_ci * expensive due to the implied lock prefix.  The processor cannot prefetch
17762306a36Sopenharmony_ci * cachelines if xchg is used.
17862306a36Sopenharmony_ci */
17962306a36Sopenharmony_ci#define percpu_xchg_op(size, qual, _var, _nval)				\
18062306a36Sopenharmony_ci({									\
18162306a36Sopenharmony_ci	__pcpu_type_##size pxo_old__;					\
18262306a36Sopenharmony_ci	__pcpu_type_##size pxo_new__ = __pcpu_cast_##size(_nval);	\
18362306a36Sopenharmony_ci	asm qual (__pcpu_op2_##size("mov", __percpu_arg([var]),		\
18462306a36Sopenharmony_ci				    "%[oval]")				\
18562306a36Sopenharmony_ci		  "\n1:\t"						\
18662306a36Sopenharmony_ci		  __pcpu_op2_##size("cmpxchg", "%[nval]",		\
18762306a36Sopenharmony_ci				    __percpu_arg([var]))		\
18862306a36Sopenharmony_ci		  "\n\tjnz 1b"						\
18962306a36Sopenharmony_ci		  : [oval] "=&a" (pxo_old__),				\
19062306a36Sopenharmony_ci		    [var] "+m" (_var)					\
19162306a36Sopenharmony_ci		  : [nval] __pcpu_reg_##size(, pxo_new__)		\
19262306a36Sopenharmony_ci		  : "memory");						\
19362306a36Sopenharmony_ci	(typeof(_var))(unsigned long) pxo_old__;			\
19462306a36Sopenharmony_ci})
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci/*
19762306a36Sopenharmony_ci * cmpxchg has no such implied lock semantics as a result it is much
19862306a36Sopenharmony_ci * more efficient for cpu local operations.
19962306a36Sopenharmony_ci */
20062306a36Sopenharmony_ci#define percpu_cmpxchg_op(size, qual, _var, _oval, _nval)		\
20162306a36Sopenharmony_ci({									\
20262306a36Sopenharmony_ci	__pcpu_type_##size pco_old__ = __pcpu_cast_##size(_oval);	\
20362306a36Sopenharmony_ci	__pcpu_type_##size pco_new__ = __pcpu_cast_##size(_nval);	\
20462306a36Sopenharmony_ci	asm qual (__pcpu_op2_##size("cmpxchg", "%[nval]",		\
20562306a36Sopenharmony_ci				    __percpu_arg([var]))		\
20662306a36Sopenharmony_ci		  : [oval] "+a" (pco_old__),				\
20762306a36Sopenharmony_ci		    [var] "+m" (_var)					\
20862306a36Sopenharmony_ci		  : [nval] __pcpu_reg_##size(, pco_new__)		\
20962306a36Sopenharmony_ci		  : "memory");						\
21062306a36Sopenharmony_ci	(typeof(_var))(unsigned long) pco_old__;			\
21162306a36Sopenharmony_ci})
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci#if defined(CONFIG_X86_32) && !defined(CONFIG_UML)
21462306a36Sopenharmony_ci#define percpu_cmpxchg64_op(size, qual, _var, _oval, _nval)		\
21562306a36Sopenharmony_ci({									\
21662306a36Sopenharmony_ci	union {								\
21762306a36Sopenharmony_ci		u64 var;						\
21862306a36Sopenharmony_ci		struct {						\
21962306a36Sopenharmony_ci			u32 low, high;					\
22062306a36Sopenharmony_ci		};							\
22162306a36Sopenharmony_ci	} old__, new__;							\
22262306a36Sopenharmony_ci									\
22362306a36Sopenharmony_ci	old__.var = _oval;						\
22462306a36Sopenharmony_ci	new__.var = _nval;						\
22562306a36Sopenharmony_ci									\
22662306a36Sopenharmony_ci	asm qual (ALTERNATIVE("leal %P[var], %%esi; call this_cpu_cmpxchg8b_emu", \
22762306a36Sopenharmony_ci			      "cmpxchg8b " __percpu_arg([var]), X86_FEATURE_CX8) \
22862306a36Sopenharmony_ci		  : [var] "+m" (_var),					\
22962306a36Sopenharmony_ci		    "+a" (old__.low),					\
23062306a36Sopenharmony_ci		    "+d" (old__.high)					\
23162306a36Sopenharmony_ci		  : "b" (new__.low),					\
23262306a36Sopenharmony_ci		    "c" (new__.high)					\
23362306a36Sopenharmony_ci		  : "memory", "esi");					\
23462306a36Sopenharmony_ci									\
23562306a36Sopenharmony_ci	old__.var;							\
23662306a36Sopenharmony_ci})
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci#define raw_cpu_cmpxchg64(pcp, oval, nval)	percpu_cmpxchg64_op(8,         , pcp, oval, nval)
23962306a36Sopenharmony_ci#define this_cpu_cmpxchg64(pcp, oval, nval)	percpu_cmpxchg64_op(8, volatile, pcp, oval, nval)
24062306a36Sopenharmony_ci#endif
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci#ifdef CONFIG_X86_64
24362306a36Sopenharmony_ci#define raw_cpu_cmpxchg64(pcp, oval, nval)	percpu_cmpxchg_op(8,         , pcp, oval, nval);
24462306a36Sopenharmony_ci#define this_cpu_cmpxchg64(pcp, oval, nval)	percpu_cmpxchg_op(8, volatile, pcp, oval, nval);
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci#define percpu_cmpxchg128_op(size, qual, _var, _oval, _nval)		\
24762306a36Sopenharmony_ci({									\
24862306a36Sopenharmony_ci	union {								\
24962306a36Sopenharmony_ci		u128 var;						\
25062306a36Sopenharmony_ci		struct {						\
25162306a36Sopenharmony_ci			u64 low, high;					\
25262306a36Sopenharmony_ci		};							\
25362306a36Sopenharmony_ci	} old__, new__;							\
25462306a36Sopenharmony_ci									\
25562306a36Sopenharmony_ci	old__.var = _oval;						\
25662306a36Sopenharmony_ci	new__.var = _nval;						\
25762306a36Sopenharmony_ci									\
25862306a36Sopenharmony_ci	asm qual (ALTERNATIVE("leaq %P[var], %%rsi; call this_cpu_cmpxchg16b_emu", \
25962306a36Sopenharmony_ci			      "cmpxchg16b " __percpu_arg([var]), X86_FEATURE_CX16) \
26062306a36Sopenharmony_ci		  : [var] "+m" (_var),					\
26162306a36Sopenharmony_ci		    "+a" (old__.low),					\
26262306a36Sopenharmony_ci		    "+d" (old__.high)					\
26362306a36Sopenharmony_ci		  : "b" (new__.low),					\
26462306a36Sopenharmony_ci		    "c" (new__.high)					\
26562306a36Sopenharmony_ci		  : "memory", "rsi");					\
26662306a36Sopenharmony_ci									\
26762306a36Sopenharmony_ci	old__.var;							\
26862306a36Sopenharmony_ci})
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci#define raw_cpu_cmpxchg128(pcp, oval, nval)	percpu_cmpxchg128_op(16,         , pcp, oval, nval)
27162306a36Sopenharmony_ci#define this_cpu_cmpxchg128(pcp, oval, nval)	percpu_cmpxchg128_op(16, volatile, pcp, oval, nval)
27262306a36Sopenharmony_ci#endif
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci/*
27562306a36Sopenharmony_ci * this_cpu_read() makes gcc load the percpu variable every time it is
27662306a36Sopenharmony_ci * accessed while this_cpu_read_stable() allows the value to be cached.
27762306a36Sopenharmony_ci * this_cpu_read_stable() is more efficient and can be used if its value
27862306a36Sopenharmony_ci * is guaranteed to be valid across cpus.  The current users include
27962306a36Sopenharmony_ci * get_current() and get_thread_info() both of which are actually
28062306a36Sopenharmony_ci * per-thread variables implemented as per-cpu variables and thus
28162306a36Sopenharmony_ci * stable for the duration of the respective task.
28262306a36Sopenharmony_ci */
28362306a36Sopenharmony_ci#define this_cpu_read_stable_1(pcp)	percpu_stable_op(1, "mov", pcp)
28462306a36Sopenharmony_ci#define this_cpu_read_stable_2(pcp)	percpu_stable_op(2, "mov", pcp)
28562306a36Sopenharmony_ci#define this_cpu_read_stable_4(pcp)	percpu_stable_op(4, "mov", pcp)
28662306a36Sopenharmony_ci#define this_cpu_read_stable_8(pcp)	percpu_stable_op(8, "mov", pcp)
28762306a36Sopenharmony_ci#define this_cpu_read_stable(pcp)	__pcpu_size_call_return(this_cpu_read_stable_, pcp)
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci#define raw_cpu_read_1(pcp)		percpu_from_op(1, , "mov", pcp)
29062306a36Sopenharmony_ci#define raw_cpu_read_2(pcp)		percpu_from_op(2, , "mov", pcp)
29162306a36Sopenharmony_ci#define raw_cpu_read_4(pcp)		percpu_from_op(4, , "mov", pcp)
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci#define raw_cpu_write_1(pcp, val)	percpu_to_op(1, , "mov", (pcp), val)
29462306a36Sopenharmony_ci#define raw_cpu_write_2(pcp, val)	percpu_to_op(2, , "mov", (pcp), val)
29562306a36Sopenharmony_ci#define raw_cpu_write_4(pcp, val)	percpu_to_op(4, , "mov", (pcp), val)
29662306a36Sopenharmony_ci#define raw_cpu_add_1(pcp, val)		percpu_add_op(1, , (pcp), val)
29762306a36Sopenharmony_ci#define raw_cpu_add_2(pcp, val)		percpu_add_op(2, , (pcp), val)
29862306a36Sopenharmony_ci#define raw_cpu_add_4(pcp, val)		percpu_add_op(4, , (pcp), val)
29962306a36Sopenharmony_ci#define raw_cpu_and_1(pcp, val)		percpu_to_op(1, , "and", (pcp), val)
30062306a36Sopenharmony_ci#define raw_cpu_and_2(pcp, val)		percpu_to_op(2, , "and", (pcp), val)
30162306a36Sopenharmony_ci#define raw_cpu_and_4(pcp, val)		percpu_to_op(4, , "and", (pcp), val)
30262306a36Sopenharmony_ci#define raw_cpu_or_1(pcp, val)		percpu_to_op(1, , "or", (pcp), val)
30362306a36Sopenharmony_ci#define raw_cpu_or_2(pcp, val)		percpu_to_op(2, , "or", (pcp), val)
30462306a36Sopenharmony_ci#define raw_cpu_or_4(pcp, val)		percpu_to_op(4, , "or", (pcp), val)
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci/*
30762306a36Sopenharmony_ci * raw_cpu_xchg() can use a load-store since it is not required to be
30862306a36Sopenharmony_ci * IRQ-safe.
30962306a36Sopenharmony_ci */
31062306a36Sopenharmony_ci#define raw_percpu_xchg_op(var, nval)					\
31162306a36Sopenharmony_ci({									\
31262306a36Sopenharmony_ci	typeof(var) pxo_ret__ = raw_cpu_read(var);			\
31362306a36Sopenharmony_ci	raw_cpu_write(var, (nval));					\
31462306a36Sopenharmony_ci	pxo_ret__;							\
31562306a36Sopenharmony_ci})
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci#define raw_cpu_xchg_1(pcp, val)	raw_percpu_xchg_op(pcp, val)
31862306a36Sopenharmony_ci#define raw_cpu_xchg_2(pcp, val)	raw_percpu_xchg_op(pcp, val)
31962306a36Sopenharmony_ci#define raw_cpu_xchg_4(pcp, val)	raw_percpu_xchg_op(pcp, val)
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci#define this_cpu_read_1(pcp)		percpu_from_op(1, volatile, "mov", pcp)
32262306a36Sopenharmony_ci#define this_cpu_read_2(pcp)		percpu_from_op(2, volatile, "mov", pcp)
32362306a36Sopenharmony_ci#define this_cpu_read_4(pcp)		percpu_from_op(4, volatile, "mov", pcp)
32462306a36Sopenharmony_ci#define this_cpu_write_1(pcp, val)	percpu_to_op(1, volatile, "mov", (pcp), val)
32562306a36Sopenharmony_ci#define this_cpu_write_2(pcp, val)	percpu_to_op(2, volatile, "mov", (pcp), val)
32662306a36Sopenharmony_ci#define this_cpu_write_4(pcp, val)	percpu_to_op(4, volatile, "mov", (pcp), val)
32762306a36Sopenharmony_ci#define this_cpu_add_1(pcp, val)	percpu_add_op(1, volatile, (pcp), val)
32862306a36Sopenharmony_ci#define this_cpu_add_2(pcp, val)	percpu_add_op(2, volatile, (pcp), val)
32962306a36Sopenharmony_ci#define this_cpu_add_4(pcp, val)	percpu_add_op(4, volatile, (pcp), val)
33062306a36Sopenharmony_ci#define this_cpu_and_1(pcp, val)	percpu_to_op(1, volatile, "and", (pcp), val)
33162306a36Sopenharmony_ci#define this_cpu_and_2(pcp, val)	percpu_to_op(2, volatile, "and", (pcp), val)
33262306a36Sopenharmony_ci#define this_cpu_and_4(pcp, val)	percpu_to_op(4, volatile, "and", (pcp), val)
33362306a36Sopenharmony_ci#define this_cpu_or_1(pcp, val)		percpu_to_op(1, volatile, "or", (pcp), val)
33462306a36Sopenharmony_ci#define this_cpu_or_2(pcp, val)		percpu_to_op(2, volatile, "or", (pcp), val)
33562306a36Sopenharmony_ci#define this_cpu_or_4(pcp, val)		percpu_to_op(4, volatile, "or", (pcp), val)
33662306a36Sopenharmony_ci#define this_cpu_xchg_1(pcp, nval)	percpu_xchg_op(1, volatile, pcp, nval)
33762306a36Sopenharmony_ci#define this_cpu_xchg_2(pcp, nval)	percpu_xchg_op(2, volatile, pcp, nval)
33862306a36Sopenharmony_ci#define this_cpu_xchg_4(pcp, nval)	percpu_xchg_op(4, volatile, pcp, nval)
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci#define raw_cpu_add_return_1(pcp, val)		percpu_add_return_op(1, , pcp, val)
34162306a36Sopenharmony_ci#define raw_cpu_add_return_2(pcp, val)		percpu_add_return_op(2, , pcp, val)
34262306a36Sopenharmony_ci#define raw_cpu_add_return_4(pcp, val)		percpu_add_return_op(4, , pcp, val)
34362306a36Sopenharmony_ci#define raw_cpu_cmpxchg_1(pcp, oval, nval)	percpu_cmpxchg_op(1, , pcp, oval, nval)
34462306a36Sopenharmony_ci#define raw_cpu_cmpxchg_2(pcp, oval, nval)	percpu_cmpxchg_op(2, , pcp, oval, nval)
34562306a36Sopenharmony_ci#define raw_cpu_cmpxchg_4(pcp, oval, nval)	percpu_cmpxchg_op(4, , pcp, oval, nval)
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci#define this_cpu_add_return_1(pcp, val)		percpu_add_return_op(1, volatile, pcp, val)
34862306a36Sopenharmony_ci#define this_cpu_add_return_2(pcp, val)		percpu_add_return_op(2, volatile, pcp, val)
34962306a36Sopenharmony_ci#define this_cpu_add_return_4(pcp, val)		percpu_add_return_op(4, volatile, pcp, val)
35062306a36Sopenharmony_ci#define this_cpu_cmpxchg_1(pcp, oval, nval)	percpu_cmpxchg_op(1, volatile, pcp, oval, nval)
35162306a36Sopenharmony_ci#define this_cpu_cmpxchg_2(pcp, oval, nval)	percpu_cmpxchg_op(2, volatile, pcp, oval, nval)
35262306a36Sopenharmony_ci#define this_cpu_cmpxchg_4(pcp, oval, nval)	percpu_cmpxchg_op(4, volatile, pcp, oval, nval)
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci/*
35562306a36Sopenharmony_ci * Per cpu atomic 64 bit operations are only available under 64 bit.
35662306a36Sopenharmony_ci * 32 bit must fall back to generic operations.
35762306a36Sopenharmony_ci */
35862306a36Sopenharmony_ci#ifdef CONFIG_X86_64
35962306a36Sopenharmony_ci#define raw_cpu_read_8(pcp)			percpu_from_op(8, , "mov", pcp)
36062306a36Sopenharmony_ci#define raw_cpu_write_8(pcp, val)		percpu_to_op(8, , "mov", (pcp), val)
36162306a36Sopenharmony_ci#define raw_cpu_add_8(pcp, val)			percpu_add_op(8, , (pcp), val)
36262306a36Sopenharmony_ci#define raw_cpu_and_8(pcp, val)			percpu_to_op(8, , "and", (pcp), val)
36362306a36Sopenharmony_ci#define raw_cpu_or_8(pcp, val)			percpu_to_op(8, , "or", (pcp), val)
36462306a36Sopenharmony_ci#define raw_cpu_add_return_8(pcp, val)		percpu_add_return_op(8, , pcp, val)
36562306a36Sopenharmony_ci#define raw_cpu_xchg_8(pcp, nval)		raw_percpu_xchg_op(pcp, nval)
36662306a36Sopenharmony_ci#define raw_cpu_cmpxchg_8(pcp, oval, nval)	percpu_cmpxchg_op(8, , pcp, oval, nval)
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci#define this_cpu_read_8(pcp)			percpu_from_op(8, volatile, "mov", pcp)
36962306a36Sopenharmony_ci#define this_cpu_write_8(pcp, val)		percpu_to_op(8, volatile, "mov", (pcp), val)
37062306a36Sopenharmony_ci#define this_cpu_add_8(pcp, val)		percpu_add_op(8, volatile, (pcp), val)
37162306a36Sopenharmony_ci#define this_cpu_and_8(pcp, val)		percpu_to_op(8, volatile, "and", (pcp), val)
37262306a36Sopenharmony_ci#define this_cpu_or_8(pcp, val)			percpu_to_op(8, volatile, "or", (pcp), val)
37362306a36Sopenharmony_ci#define this_cpu_add_return_8(pcp, val)		percpu_add_return_op(8, volatile, pcp, val)
37462306a36Sopenharmony_ci#define this_cpu_xchg_8(pcp, nval)		percpu_xchg_op(8, volatile, pcp, nval)
37562306a36Sopenharmony_ci#define this_cpu_cmpxchg_8(pcp, oval, nval)	percpu_cmpxchg_op(8, volatile, pcp, oval, nval)
37662306a36Sopenharmony_ci#endif
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_cistatic __always_inline bool x86_this_cpu_constant_test_bit(unsigned int nr,
37962306a36Sopenharmony_ci                        const unsigned long __percpu *addr)
38062306a36Sopenharmony_ci{
38162306a36Sopenharmony_ci	unsigned long __percpu *a =
38262306a36Sopenharmony_ci		(unsigned long __percpu *)addr + nr / BITS_PER_LONG;
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci#ifdef CONFIG_X86_64
38562306a36Sopenharmony_ci	return ((1UL << (nr % BITS_PER_LONG)) & raw_cpu_read_8(*a)) != 0;
38662306a36Sopenharmony_ci#else
38762306a36Sopenharmony_ci	return ((1UL << (nr % BITS_PER_LONG)) & raw_cpu_read_4(*a)) != 0;
38862306a36Sopenharmony_ci#endif
38962306a36Sopenharmony_ci}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_cistatic inline bool x86_this_cpu_variable_test_bit(int nr,
39262306a36Sopenharmony_ci                        const unsigned long __percpu *addr)
39362306a36Sopenharmony_ci{
39462306a36Sopenharmony_ci	bool oldbit;
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	asm volatile("btl "__percpu_arg(2)",%1"
39762306a36Sopenharmony_ci			CC_SET(c)
39862306a36Sopenharmony_ci			: CC_OUT(c) (oldbit)
39962306a36Sopenharmony_ci			: "m" (*(unsigned long __percpu *)addr), "Ir" (nr));
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	return oldbit;
40262306a36Sopenharmony_ci}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci#define x86_this_cpu_test_bit(nr, addr)			\
40562306a36Sopenharmony_ci	(__builtin_constant_p((nr))			\
40662306a36Sopenharmony_ci	 ? x86_this_cpu_constant_test_bit((nr), (addr))	\
40762306a36Sopenharmony_ci	 : x86_this_cpu_variable_test_bit((nr), (addr)))
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci#include <asm-generic/percpu.h>
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci/* We can use this directly for local CPU (faster). */
41362306a36Sopenharmony_ciDECLARE_PER_CPU_READ_MOSTLY(unsigned long, this_cpu_off);
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci#endif /* !__ASSEMBLY__ */
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci#ifdef CONFIG_SMP
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci/*
42062306a36Sopenharmony_ci * Define the "EARLY_PER_CPU" macros.  These are used for some per_cpu
42162306a36Sopenharmony_ci * variables that are initialized and accessed before there are per_cpu
42262306a36Sopenharmony_ci * areas allocated.
42362306a36Sopenharmony_ci */
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci#define	DEFINE_EARLY_PER_CPU(_type, _name, _initvalue)			\
42662306a36Sopenharmony_ci	DEFINE_PER_CPU(_type, _name) = _initvalue;			\
42762306a36Sopenharmony_ci	__typeof__(_type) _name##_early_map[NR_CPUS] __initdata =	\
42862306a36Sopenharmony_ci				{ [0 ... NR_CPUS-1] = _initvalue };	\
42962306a36Sopenharmony_ci	__typeof__(_type) *_name##_early_ptr __refdata = _name##_early_map
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci#define DEFINE_EARLY_PER_CPU_READ_MOSTLY(_type, _name, _initvalue)	\
43262306a36Sopenharmony_ci	DEFINE_PER_CPU_READ_MOSTLY(_type, _name) = _initvalue;		\
43362306a36Sopenharmony_ci	__typeof__(_type) _name##_early_map[NR_CPUS] __initdata =	\
43462306a36Sopenharmony_ci				{ [0 ... NR_CPUS-1] = _initvalue };	\
43562306a36Sopenharmony_ci	__typeof__(_type) *_name##_early_ptr __refdata = _name##_early_map
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci#define EXPORT_EARLY_PER_CPU_SYMBOL(_name)			\
43862306a36Sopenharmony_ci	EXPORT_PER_CPU_SYMBOL(_name)
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci#define DECLARE_EARLY_PER_CPU(_type, _name)			\
44162306a36Sopenharmony_ci	DECLARE_PER_CPU(_type, _name);				\
44262306a36Sopenharmony_ci	extern __typeof__(_type) *_name##_early_ptr;		\
44362306a36Sopenharmony_ci	extern __typeof__(_type)  _name##_early_map[]
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci#define DECLARE_EARLY_PER_CPU_READ_MOSTLY(_type, _name)		\
44662306a36Sopenharmony_ci	DECLARE_PER_CPU_READ_MOSTLY(_type, _name);		\
44762306a36Sopenharmony_ci	extern __typeof__(_type) *_name##_early_ptr;		\
44862306a36Sopenharmony_ci	extern __typeof__(_type)  _name##_early_map[]
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci#define	early_per_cpu_ptr(_name) (_name##_early_ptr)
45162306a36Sopenharmony_ci#define	early_per_cpu_map(_name, _idx) (_name##_early_map[_idx])
45262306a36Sopenharmony_ci#define	early_per_cpu(_name, _cpu) 				\
45362306a36Sopenharmony_ci	*(early_per_cpu_ptr(_name) ?				\
45462306a36Sopenharmony_ci		&early_per_cpu_ptr(_name)[_cpu] :		\
45562306a36Sopenharmony_ci		&per_cpu(_name, _cpu))
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci#else	/* !CONFIG_SMP */
45862306a36Sopenharmony_ci#define	DEFINE_EARLY_PER_CPU(_type, _name, _initvalue)		\
45962306a36Sopenharmony_ci	DEFINE_PER_CPU(_type, _name) = _initvalue
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci#define DEFINE_EARLY_PER_CPU_READ_MOSTLY(_type, _name, _initvalue)	\
46262306a36Sopenharmony_ci	DEFINE_PER_CPU_READ_MOSTLY(_type, _name) = _initvalue
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci#define EXPORT_EARLY_PER_CPU_SYMBOL(_name)			\
46562306a36Sopenharmony_ci	EXPORT_PER_CPU_SYMBOL(_name)
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci#define DECLARE_EARLY_PER_CPU(_type, _name)			\
46862306a36Sopenharmony_ci	DECLARE_PER_CPU(_type, _name)
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci#define DECLARE_EARLY_PER_CPU_READ_MOSTLY(_type, _name)		\
47162306a36Sopenharmony_ci	DECLARE_PER_CPU_READ_MOSTLY(_type, _name)
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci#define	early_per_cpu(_name, _cpu) per_cpu(_name, _cpu)
47462306a36Sopenharmony_ci#define	early_per_cpu_ptr(_name) NULL
47562306a36Sopenharmony_ci/* no early_per_cpu_map() */
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci#endif	/* !CONFIG_SMP */
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci#endif /* _ASM_X86_PERCPU_H */
480