linux/include/asm-x86/percpu.h
<<
>>
Prefs
   1#ifndef _ASM_X86_PERCPU_H_
   2#define _ASM_X86_PERCPU_H_
   3
   4#ifdef CONFIG_X86_64
   5#include <linux/compiler.h>
   6
   7/* Same as asm-generic/percpu.h, except that we store the per cpu offset
   8   in the PDA. Longer term the PDA and every per cpu variable
   9   should be just put into a single section and referenced directly
  10   from %gs */
  11
  12#ifdef CONFIG_SMP
  13#include <asm/pda.h>
  14
  15#define __per_cpu_offset(cpu) (cpu_pda(cpu)->data_offset)
  16#define __my_cpu_offset read_pda(data_offset)
  17
  18#define per_cpu_offset(x) (__per_cpu_offset(x))
  19
  20#endif
  21#include <asm-generic/percpu.h>
  22
  23DECLARE_PER_CPU(struct x8664_pda, pda);
  24
  25#else /* CONFIG_X86_64 */
  26
  27#ifdef __ASSEMBLY__
  28
  29/*
  30 * PER_CPU finds an address of a per-cpu variable.
  31 *
  32 * Args:
  33 *    var - variable name
  34 *    reg - 32bit register
  35 *
  36 * The resulting address is stored in the "reg" argument.
  37 *
  38 * Example:
  39 *    PER_CPU(cpu_gdt_descr, %ebx)
  40 */
  41#ifdef CONFIG_SMP
  42#define PER_CPU(var, reg)                               \
  43        movl %fs:per_cpu__##this_cpu_off, reg;          \
  44        lea per_cpu__##var(reg), reg
  45#define PER_CPU_VAR(var)        %fs:per_cpu__##var
  46#else /* ! SMP */
  47#define PER_CPU(var, reg)                       \
  48        movl $per_cpu__##var, reg
  49#define PER_CPU_VAR(var)        per_cpu__##var
  50#endif  /* SMP */
  51
  52#else /* ...!ASSEMBLY */
  53
  54/*
  55 * PER_CPU finds an address of a per-cpu variable.
  56 *
  57 * Args:
  58 *    var - variable name
  59 *    cpu - 32bit register containing the current CPU number
  60 *
  61 * The resulting address is stored in the "cpu" argument.
  62 *
  63 * Example:
  64 *    PER_CPU(cpu_gdt_descr, %ebx)
  65 */
  66#ifdef CONFIG_SMP
  67
  68#define __my_cpu_offset x86_read_percpu(this_cpu_off)
  69
  70/* fs segment starts at (positive) offset == __per_cpu_offset[cpu] */
  71#define __percpu_seg "%%fs:"
  72
  73#else  /* !SMP */
  74
  75#define __percpu_seg ""
  76
  77#endif  /* SMP */
  78
  79#include <asm-generic/percpu.h>
  80
  81/* We can use this directly for local CPU (faster). */
  82DECLARE_PER_CPU(unsigned long, this_cpu_off);
  83
  84/* For arch-specific code, we can use direct single-insn ops (they
  85 * don't give an lvalue though). */
  86extern void __bad_percpu_size(void);
  87
  88#define percpu_to_op(op,var,val)                                \
  89        do {                                                    \
  90                typedef typeof(var) T__;                        \
  91                if (0) { T__ tmp__; tmp__ = (val); }            \
  92                switch (sizeof(var)) {                          \
  93                case 1:                                         \
  94                        asm(op "b %1,"__percpu_seg"%0"          \
  95                            : "+m" (var)                        \
  96                            :"ri" ((T__)val));                  \
  97                        break;                                  \
  98                case 2:                                         \
  99                        asm(op "w %1,"__percpu_seg"%0"          \
 100                            : "+m" (var)                        \
 101                            :"ri" ((T__)val));                  \
 102                        break;                                  \
 103                case 4:                                         \
 104                        asm(op "l %1,"__percpu_seg"%0"          \
 105                            : "+m" (var)                        \
 106                            :"ri" ((T__)val));                  \
 107                        break;                                  \
 108                default: __bad_percpu_size();                   \
 109                }                                               \
 110        } while (0)
 111
 112#define percpu_from_op(op,var)                                  \
 113        ({                                                      \
 114                typeof(var) ret__;                              \
 115                switch (sizeof(var)) {                          \
 116                case 1:                                         \
 117                        asm(op "b "__percpu_seg"%1,%0"          \
 118                            : "=r" (ret__)                      \
 119                            : "m" (var));                       \
 120                        break;                                  \
 121                case 2:                                         \
 122                        asm(op "w "__percpu_seg"%1,%0"          \
 123                            : "=r" (ret__)                      \
 124                            : "m" (var));                       \
 125                        break;                                  \
 126                case 4:                                         \
 127                        asm(op "l "__percpu_seg"%1,%0"          \
 128                            : "=r" (ret__)                      \
 129                            : "m" (var));                       \
 130                        break;                                  \
 131                default: __bad_percpu_size();                   \
 132                }                                               \
 133                ret__; })
 134
 135#define x86_read_percpu(var) percpu_from_op("mov", per_cpu__##var)
 136#define x86_write_percpu(var,val) percpu_to_op("mov", per_cpu__##var, val)
 137#define x86_add_percpu(var,val) percpu_to_op("add", per_cpu__##var, val)
 138#define x86_sub_percpu(var,val) percpu_to_op("sub", per_cpu__##var, val)
 139#define x86_or_percpu(var,val) percpu_to_op("or", per_cpu__##var, val)
 140#endif /* !__ASSEMBLY__ */
 141#endif /* !CONFIG_X86_64 */
 142#endif /* _ASM_X86_PERCPU_H_ */
 143
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.