比如我们读取或者写入一个per cpu变量
cnten_val = per_cpu(cntenset_val, cpu);
其实就是求这个per cpu 变量的地址
#define per_cpu(var, cpu) (*per_cpu_ptr(&(var), cpu))
#define per_cpu_ptr(ptr, cpu) \
({ \
__verify_pcpu_ptr(ptr); \
SHIFT_PERCPU_PTR((ptr), per_cpu_offset((cpu))); \
})
per_cpu_offset(cpu)这里由cpu number 转换成 cpu offset
#define SHIFT_PERCPU_PTR(__p, __offset) \
RELOC_HIDE((typeof(*(__p)) __kernel __force *)(__p), (__offset))
#define RELOC_HIDE(ptr, off) \
({ unsigned long __ptr; \
__ptr = (unsigned long) (ptr); \
(typeof(ptr)) (__ptr + (off)); })
弄了半天,就是基地址+offset
(typeof(ptr)) (__ptr + (off)); })
我们来看看这个offset 如何得到
per_cpu_offset(cpu)
#define per_cpu_offset(x) (__per_cpu_offset[x])
extern unsigned long __per_cpu_offset[NR_CPUS];
静态设置,只有知道cpu number 就可以得到cpu offser
我们看看如何得到cpu id
# define smp_processor_id() raw_smp_processor_id()
#define raw_smp_processor_id() (*raw_cpu_ptr(&cpu_number))
DECLARE_PER_CPU_READ_MOSTLY(int, cpu_number);
#define raw_cpu_ptr(ptr) \
({ \
__verify_pcpu_ptr(ptr); \
arch_raw_cpu_ptr(ptr); \
})
#define arch_raw_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, __my_cpu_offset)
static inline unsigned long __my_cpu_offset(void)
{
unsigned long off;
/*
* We want to allow caching the value, so avoid using volatile and
* instead use a fake stack read to hazard against barrier().
*/
asm("mrs %0, tpidr_el1" : "=r" (off) :
"Q" (*(const unsigned long *)current_stack_pointer));
return off;
}
最后读取了 本cpu 的 tpidr_el1 将采取
看看arm 怎么定义的:
其实就是cpu提供一个寄存器,可以写入一下信息。
是由下面函数,在core 启动时间写入的
static inline void set_my_cpu_offset(unsigned long off)
{
asm volatile("msr tpidr_el1, %0" :: "r" (off) : "memory");
}