[OS64][033] 源码阅读:程序8-2 物理机器 CPUID 查询处理器固件信息

学习笔记

使用教材(配书源码以及使用方法)
《一个64位操作系统的设计与实现》
http://www.ituring.com.cn/book/2450
https://www.jianshu.com/p/28f9713a9171

源码结构

  • 配书代码包 :第8章 \ 程序 \ 程序8-2

实验操作

1、虚拟机:生成boot.bin 、loader.bin以及kernel.bin 并复制到U盘

[anno@localhost 32MB-bootloader]$ 
sudo dd if=boot.bin of=/dev/sdb bs=512 count=1 conv=notrunc

[anno@localhost 物理平台]$ cd kernel
[anno@localhost kernel]$ make
gcc -E head.S > head.s
as --64 -o head.o head.s
gcc -E entry.S > entry.s
as --64 -o entry.o entry.s
gcc  -mcmodel=large -fno-builtin -m64 -c main.c
gcc  -mcmodel=large -fno-builtin -m64 -c printk.c
gcc  -mcmodel=large -fno-builtin -m64 -c trap.c
gcc  -mcmodel=large -fno-builtin -m64 -c memory.c
gcc  -mcmodel=large -fno-builtin -m64 -c interrupt.c
gcc  -mcmodel=large -fno-builtin -m64 -c task.c 
gcc  -mcmodel=large -fno-builtin -m64 -c cpu.c
ld -b elf64-x86-64 -z muldefs -o system head.o entry.o main.o printk.o trap.o memory.o interrupt.o task.o cpu.o -T Kernel.lds 
objcopy -I elf64-x86-64 -S -R ".eh_frame" -R ".comment" -O binary system kernel.bin

根据自己使用的U盘,修改bootloader部分源码的方法参见
[OS64][031]实验操作:程序7-3 移植到物理平台 U盘启动
https://www.jianshu.com/p/a84b45ae3219

  • 其实程序8-2程序7-3使用的bootloader代码是一致的,如果在程序7-3的实验中已经按照自己的U盘规格制作好了boot.binloader.bin可以直接拿来用了

2、物理机器:插上U盘,显示运行画面

程序8-2 运行画面

源码阅读

get_cpuid 用于获取处理器固件信息

CPUID指令将通过EAX寄存器输入查询的主功能号,如果有需要,则再向ECX寄存器输入查询的子功能号。
当这条汇编指令执行结束后,查询的返回值将保存在EAX、EBX、ECX和EDX寄存器

代码清单8-4 第8章\程序\程序8-2\物理平台\kernel\cpu.h

inline void get_cpuid(unsigned int Mop,
    unsigned int Sop,
    unsigned int * a,
    unsigned int * b,
    unsigned int * c,
    unsigned int * d)
{
    __asm__ __volatile__    (    "cpuid    \n\t"
                                 :"=a"(*a),"=b"(*b),"=c"(*c),"=d"(*d)
                                 :"0"(Mop),"2"(Sop)
                            );
}

  • CPUID汇编指令封装成get_cpuid函数
  • MopSop参数用于向CPUID指令传递主功能号子功能号
  • 将查询的返回值保存到指针变量a、b、c和d指向的内存

init_cpu() 中调用 get_cpuid(...)

void init_cpu(void)
{
    int i,j;
    unsigned int CpuFacName[4] = {0,0,0,0};
    char    FactoryName[17] = {0};

    //vendor_string
    get_cpuid(0,0,&CpuFacName[0],&CpuFacName[1],&CpuFacName[2],&CpuFacName[3]);

    *(unsigned int*)&FactoryName[0] = CpuFacName[1];

    *(unsigned int*)&FactoryName[4] = CpuFacName[3];

    *(unsigned int*)&FactoryName[8] = CpuFacName[2];    

    FactoryName[12] = '\0';
    color_printk(YELLOW,BLACK,"%s\t%#010x\t%#010x\t%#010x\n",FactoryName,CpuFacName[1],CpuFacName[3],CpuFacName[2]);
    
    //brand_string
    for(i = 0x80000002;i < 0x80000005;i++)
    {
        get_cpuid(i,0,&CpuFacName[0],&CpuFacName[1],&CpuFacName[2],&CpuFacName[3]);

        *(unsigned int*)&FactoryName[0] = CpuFacName[0];

        *(unsigned int*)&FactoryName[4] = CpuFacName[1];

        *(unsigned int*)&FactoryName[8] = CpuFacName[2];

        *(unsigned int*)&FactoryName[12] = CpuFacName[3];

        FactoryName[16] = '\0';
        color_printk(YELLOW,BLACK,"%s",FactoryName);
    }
    color_printk(YELLOW,BLACK,"\n");

    //Version Informatin Type,Family,Model,and Stepping ID
    get_cpuid(1,0,&CpuFacName[0],&CpuFacName[1],&CpuFacName[2],&CpuFacName[3]);
    color_printk(YELLOW,BLACK,"Family Code:%#010x,Extended Family:%#010x,Model Number:%#010x,Extended Model:%#010x,Processor Type:%#010x,Stepping ID:%#010x\n",(CpuFacName[0] >> 8 & 0xf),(CpuFacName[0] >> 20 & 0xff),(CpuFacName[0] >> 4 & 0xf),(CpuFacName[0] >> 16 & 0xf),(CpuFacName[0] >> 12 & 0x3),(CpuFacName[0] & 0xf));

    //get Linear/Physical Address size
    get_cpuid(0x80000008,0,&CpuFacName[0],&CpuFacName[1],&CpuFacName[2],&CpuFacName[3]);
    color_printk(YELLOW,BLACK,"Physical Address size:%08d,Linear Address size:%08d\n",(CpuFacName[0] & 0xff),(CpuFacName[0] >> 8 & 0xff));

    //max cpuid operation code
    get_cpuid(0,0,&CpuFacName[0],&CpuFacName[1],&CpuFacName[2],&CpuFacName[3]);
    color_printk(WHITE,BLACK,"MAX Basic Operation Code :%#010x\t",CpuFacName[0]);

    get_cpuid(0x80000000,0,&CpuFacName[0],&CpuFacName[1],&CpuFacName[2],&CpuFacName[3]);
    color_printk(WHITE,BLACK,"MAX Extended Operation Code :%#010x\n",CpuFacName[0]);


}

功能号 0x00 获取处理器的供应商标识

功能号 0x00 获取处理器的供应商标识
  • get_cpuid(0,0,&CpuFacName[0],&CpuFacName[1],&CpuFacName[2],&CpuFacName[3]); 传入的功能号0x00
  • *(unsigned int*)&FactoryName[0] = CpuFacName[1];
    其中 CpuFacName[1] = 0x756e6547 代表 "Genu"
  • *(unsigned int*)&FactoryName[0] 先取FactoryName[0]的地址,然后就是将 0x756e6547 填入FactoryName[0] FactoryName[1] FactoryName[2] FactoryName[3]
  • color_printk(YELLOW,BLACK,"%s\t%#010x\t%#010x\t%#010x\n",FactoryName,CpuFacName[1],CpuFacName[3],CpuFacName[2]); 其中 %s0x756e6547 看做字符串 Genu输出,%#010x直接输出数值0x756e6547

功能号0x80002~0x80004 获取处理器商标信息

功能号0x80002~0x80004 获取处理器商标信息
  • for(i = 0x80000002;i < 0x80000005;i++) { }

init_cpu() 在何处被调用 ?

通常情况下,这些数据(处理器固件信息),应该最先被操作系统捕获,随后操作系统再根据处理器的固件信息来确定处理器支持的功能,以便进一步初始化处理器。
因此,将init_cpu函数插入到系统异常处理功能的初始化函数( sys_vector_init();)之后会更妥当一些

代码清单8-6 第8章\程序\程序8-2\物理平台\kernel\main.c

void Start_Kernel(void)
{
    ……
    sys_vector_init();

    init_cpu();
    ……
}

参考资料

[ATT汇编]程序举例:xxx.S 编译、链接、运行、调试 (CPUID命令 显示处理器厂商信息)
https://www.jianshu.com/p/91506500523a

[内联汇编]扩展asm:格式、占位符、跳转、内联汇编宏函数
https://www.jianshu.com/p/76fda24ee7f7

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容