免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 7922 | 回复: 7
打印 上一主题 下一主题

[内核同步] 哪位大牛懂smp_processor_id的原理? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-08-26 16:23 |只看该作者 |倒序浏览
我看的代码是2.6.32,smp_processor_id的定义过程是:
# define smp_processor_id() raw_smp_processor_id()
接下来:
#define raw_smp_processor_id() (percpu_read(cpu_number))
后面最终调用了:
percpu_from_op("mov", per_cpu__##var, "m" (per_cpu__##var))
这个宏展开后,实质上等价于:
#define percpu_from_op(op, var, constraint)       
({                                                       
        typeof(var) ret__;
        switch (sizeof(var)) {
        case 1:
            asm(“movb  %%fs:%P1, %0"
                : "=q" (ret__)
                : constraint);
           break;
        ...
})

后续的线索没了。。。。这里fs寄存器里面是什么东西?为什么这里就可以获取到cpu的id?请牛人指点!!

论坛徽章:
22
丑牛
日期:2014-08-15 14:32:0015-16赛季CBA联赛之同曦
日期:2017-12-14 15:28:14黑曼巴
日期:2017-08-10 08:14:342017金鸡报晓
日期:2017-02-08 10:39:42黑曼巴
日期:2016-11-15 15:48:38CU十四周年纪念徽章
日期:2016-11-09 13:19:1015-16赛季CBA联赛之同曦
日期:2016-04-08 18:00:03平安夜徽章
日期:2015-12-26 00:06:30程序设计版块每日发帖之星
日期:2015-12-03 06:20:002015七夕节徽章
日期:2015-08-21 11:06:17IT运维版块每日发帖之星
日期:2015-08-09 06:20:002015亚冠之吉达阿赫利
日期:2015-07-03 08:39:42
2 [报告]
发表于 2012-08-26 17:54 |只看该作者
不同的arch不一样,mips是这样定义的
#define raw_smp_processor_id() (current_thread_info()->cpu)

X86的汇编我不是非常熟悉,看起来就是从某段:偏移量的一个内存地址读出来而已。或许,你应该找找cpu初始化的地方看看是怎么初始化这个内存吧

论坛徽章:
0
3 [报告]
发表于 2012-08-27 16:25 |只看该作者
初始化 :
setup_per_cpu_areas()
{
    per_cpu(cpu_number, cpu) = cpu;
}      

段选择子 fs 初始化:
static inline void setup_percpu_segment(int cpu)
{
#ifdef CONFIG_X86_32
        struct desc_struct gdt;

        pack_descriptor(&gdt, per_cpu_offset(cpu), 0xFFFFF,
                        0x2 | DESCTYPE_S, 0x;
        gdt.s = 1;
        write_gdt_entry(get_cpu_gdt_table(cpu),
                        GDT_ENTRY_PERCPU, &gdt, DESCTYPE_S);
#endif
}
设置 GDT 描述符在 GDT 表中的偏移 GDT_ENTRY_PERCPU ,将相应 cpu 的每 cpu 变量写到 GDT 描述符地址字段
其实就是 fs 对应 per_cpu_offset[cpu],一切尽在不言中 GDTR,GDT ......


化简如下:
asm("movb %%fs:%P1, %0"
        :"=q"(ret__)
        :"m"(per_cpu__cpu_number));

每个 cpu 的 fs 的内容都不同,此时 fs:
GDT-> GDT_ENTRY_PERCPU-> 偏移
per_cpu_offset[cpu] + &per_cpu__cpu_number 便得到了相应 cpu 的每 per_cpu__cpu_number,关于 per_cpu_offset 请参考 setup_per_cpu_areas 函数

大致就是这样, hope useful for you ~

论坛徽章:
0
4 [报告]
发表于 2012-08-29 17:57 |只看该作者
但是boot_cpu_init在这些函数之前调用的,在这个函数里面,已经在使用smp_processor_id了!这是怎么回事?回复 3# zd零


   

论坛徽章:
0
5 [报告]
发表于 2012-08-29 20:37 |只看该作者
回复 4# dingyujie


此时 AP 还没有启动,BP 完成启动,所以就是 cpu 0

Details plz reference this  :
http://comments.gmane.org/gmane.linux.kernel.kernelnewbies/40924

论坛徽章:
0
6 [报告]
发表于 2012-08-30 10:56 |只看该作者
谢谢zd零大牛的解答,懂了!回复 5# zd零


   

论坛徽章:
0
7 [报告]
发表于 2012-08-30 11:24 |只看该作者
在x86/kernel/head_32.S中:

movl $(__KERNEL_PERCPU), %eax
movl %eax,%fs

而__KERNEL_PERCPU是per-CPU GDT的一项:

*  ------- start of kernel segments:
*
*  12 - kernel code segment                <==== new cacheline
*  13 - kernel data segment
*  14 - default user CS
*  15 - default user DS
*  16 - TSS
*  17 - LDT
*  18 - PNPBIOS support (16->32 gate)
*  19 - PNPBIOS support
*  20 - PNPBIOS support
*  21 - PNPBIOS support
*  22 - PNPBIOS support
*  23 - APM BIOS support
*  24 - APM BIOS support
*  25 - APM BIOS support
*
*  26 - ESPFIX small SS
*  27 - per-cpu                        [ offset to per-cpu data area ]
*  28 - stack_canary-20                [ for stack protector ]
*  29 - unused
*  30 - unused
*  31 - TSS for double fault handler

在BP运行时,这个27项,也就是per-cpu项中的值,是如何设置的呢?

因为在start_kernel的开始调用boot_cpu_init的时候,就会调用smp_processor_id了,这里面会使用%%fs:cpu_number来获取cpu id。。。
那说明这个fs在之前肯定需要设置妥当!

有人帮忙解答下这个问题吗?


   

论坛徽章:
0
8 [报告]
发表于 2012-11-24 23:53 |只看该作者
大概流程如下:
1.BP:kernel_init->smp_init->cpu_up->native_cpu_up->do_boot_cpu->
early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
将AP:cpu的gdt(之前由BP为每个AP初始化好了)写入early_gdt_descr中。

2.AP:trampoline_data->startup_32_smp->
lgdt early_gdt_descr
...
movl $(__KERNEL_PERCPU), %eax
movl %eax,%fs                       
将AP cpu对应的PER_CPU段的首地址读入到fs中。

3.AP:start_secondary->cpu_init->smp_processor_id读取设置在fs段中的cpu number值。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP