2008-01-30 15:32:53 +03:00
# ifndef _ASM_X86_PERCPU_H_
# define _ASM_X86_PERCPU_H_
# ifdef CONFIG_X86_64
# include <linux/compiler.h>
/* Same as asm-generic/percpu.h, except that we store the per cpu offset
in the PDA . Longer term the PDA and every per cpu variable
should be just put into a single section and referenced directly
from % gs */
# ifdef CONFIG_SMP
# include <asm/pda.h>
# define __per_cpu_offset(cpu) (cpu_pda(cpu)->data_offset)
# define __my_cpu_offset read_pda(data_offset)
# define per_cpu_offset(x) (__per_cpu_offset(x))
2007-10-11 13:20:03 +04:00
# endif
2008-01-30 15:32:53 +03:00
# include <asm-generic/percpu.h>
DECLARE_PER_CPU ( struct x8664_pda , pda ) ;
# else /* CONFIG_X86_64 */
# ifdef __ASSEMBLY__
/*
* PER_CPU finds an address of a per - cpu variable .
*
* Args :
* var - variable name
* reg - 32 bit register
*
* The resulting address is stored in the " reg " argument .
*
* Example :
* PER_CPU ( cpu_gdt_descr , % ebx )
*/
# ifdef CONFIG_SMP
# define PER_CPU(var, reg) \
movl % fs : per_cpu__ # # this_cpu_off , reg ; \
lea per_cpu__ # # var ( reg ) , reg
# define PER_CPU_VAR(var) %fs:per_cpu__##var
# else /* ! SMP */
# define PER_CPU(var, reg) \
movl $ per_cpu__ # # var , reg
# define PER_CPU_VAR(var) per_cpu__##var
# endif /* SMP */
# else /* ...!ASSEMBLY */
/*
* PER_CPU finds an address of a per - cpu variable .
*
* Args :
* var - variable name
* cpu - 32 bit register containing the current CPU number
*
* The resulting address is stored in the " cpu " argument .
*
* Example :
* PER_CPU ( cpu_gdt_descr , % ebx )
*/
# ifdef CONFIG_SMP
# define __my_cpu_offset x86_read_percpu(this_cpu_off)
/* fs segment starts at (positive) offset == __per_cpu_offset[cpu] */
# define __percpu_seg "%%fs:"
# else /* !SMP */
# define __percpu_seg ""
# endif /* SMP */
# include <asm-generic/percpu.h>
/* We can use this directly for local CPU (faster). */
DECLARE_PER_CPU ( unsigned long , this_cpu_off ) ;
/* For arch-specific code, we can use direct single-insn ops (they
* don ' t give an lvalue though ) . */
extern void __bad_percpu_size ( void ) ;
2008-03-23 11:03:06 +03:00
# define percpu_to_op(op, var, val) \
do { \
typedef typeof ( var ) T__ ; \
if ( 0 ) { \
T__ tmp__ ; \
tmp__ = ( val ) ; \
} \
switch ( sizeof ( var ) ) { \
case 1 : \
asm ( op " b %1, " __percpu_seg " %0 " \
: " +m " ( var ) \
: " ri " ( ( T__ ) val ) ) ; \
break ; \
case 2 : \
asm ( op " w %1, " __percpu_seg " %0 " \
: " +m " ( var ) \
: " ri " ( ( T__ ) val ) ) ; \
break ; \
case 4 : \
asm ( op " l %1, " __percpu_seg " %0 " \
: " +m " ( var ) \
: " ri " ( ( T__ ) val ) ) ; \
break ; \
default : __bad_percpu_size ( ) ; \
} \
} while ( 0 )
# define percpu_from_op(op, var) \
( { \
typeof ( var ) ret__ ; \
switch ( sizeof ( var ) ) { \
case 1 : \
asm ( op " b " __percpu_seg " %1,%0 " \
: " =r " ( ret__ ) \
: " m " ( var ) ) ; \
break ; \
case 2 : \
asm ( op " w " __percpu_seg " %1,%0 " \
: " =r " ( ret__ ) \
: " m " ( var ) ) ; \
break ; \
case 4 : \
asm ( op " l " __percpu_seg " %1,%0 " \
: " =r " ( ret__ ) \
: " m " ( var ) ) ; \
break ; \
default : __bad_percpu_size ( ) ; \
} \
ret__ ; \
} )
2008-01-30 15:32:53 +03:00
# define x86_read_percpu(var) percpu_from_op("mov", per_cpu__##var)
2008-03-23 11:03:06 +03:00
# define x86_write_percpu(var, val) percpu_to_op("mov", per_cpu__##var, val)
# define x86_add_percpu(var, val) percpu_to_op("add", per_cpu__##var, val)
# define x86_sub_percpu(var, val) percpu_to_op("sub", per_cpu__##var, val)
# define x86_or_percpu(var, val) percpu_to_op("or", per_cpu__##var, val)
2008-01-30 15:32:53 +03:00
# endif /* !__ASSEMBLY__ */
# endif /* !CONFIG_X86_64 */
# endif /* _ASM_X86_PERCPU_H_ */