点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-CSDN博客
3.4.2 __ipipe_init_early之fixup_percpu_data()
这个函数只有在CPU是SMP对称多core的情况下,才会真正运作,否则就是个空函数。
#ifdef CONFIG_SMP
static inline void fixup_percpu_data(void)
{
struct ipipe_percpu_data *p;
int cpu;
/*
* ipipe_percpu.curr cannot be assigned statically to
* &ipipe_percpu.root, due to the dynamic nature of percpu
* data. So we make ipipe_percpu.curr refer to a temporary
* boot up context in static memory, until we can fixup all
* context pointers in this routine, after per-cpu areas have
* been eventually set up. The temporary context data is
* copied to per_cpu(ipipe_percpu, 0).root in the same move.
*
* Obviously, this code must run over the boot CPU, before SMP
* operations start.
*/
BUG_ON(smp_processor_id() || !irqs_disabled());
per_cpu(ipipe_percpu, 0).root = bootup_context; //这一句感觉是多余的:-)
for_each_possible_cpu(cpu) {
p = &per_cpu(ipipe_percpu, cpu);
p->curr = &p->root;
}
}
#else /* !CONFIG_SMP */
static inline void fixup_percpu_data(void) { }
#endif /* CONFIG_SMP */
在Linux处于启动过程中,而实时内核还没有注册到IPIPE中时,ipipe_percpu.curr应该指向ipipe_percpu.root。但是,ipipe_percpu是per cpu变量,在静态定义时是无法让ipipe_percpu.curr指向ipipe_percpu.root的。
为什么?
既然ipipe_percpu是per cpu变量,所以每个CPU core都有一份独有的ipipe_percpu。在Linux没有启动的情况下,你咋知道CPU有多少个core呢?所以,静态定义的per cpu变量在编译阶段只有一份,只有当Linux启动后,才会为每个CPU core分配一个独有的per cpu变量。
怎么办?
IPIPE的解决办法是这样的。静态定义的时候,只要保证通过ipipe_percpu.curr访问到的struct ipipe_percpu_domain_data结构的内容和ipipe_percpu.root的内容一致,不就可以了吗。
于是,IPIPE想到了一个规避的方法,定义了一个bootup_context,它的内容和ipipe_percpu.root完全一致。同时,让ipipe_percpu.curr指向bootup_context。所以,从start_kernel执行到__ipipe_init_early,如果访问ipipe_percpu.curr,得到的内容一定是正确的。
当代码走到__ipipe_init_early->fixup_percpu_data,此时per cpu变量已经根据CPU SMP完成初始化了,是时候最终修复问题了。此时,只需要遍历每个CPU core的ipipe_percpu变量,让ipipe_percpu.curr指向ipipe_percpu.root即可!
点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-CSDN博客
原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!