
来源
内容提取
1. 从文件节点获取
OS在启动时,会将底层硬件信息载入到相应的文件节点中,这样,位于EL0
层的用户就可以通过读取这些文件节点来获取这些信息,比较常用的有两个:
-
/sys/devices/system/cpu:
该文件夹下保存了较全的CPU信息文件,并按单个CPU进行区分,读取其中某一个的regs
文件目录就可以获得相应的CPU详情信息,如我们尝试获取CPU0的相关信息:可以看到,我们读取的仍然是
MIDR_EL1
寄存器相对应的信息,并且是未解析的数据,需要对应上文介绍的方法进行解析。并且目前没有在这个文件夹下找到CPU Flags
的相关的信息,如果后续找到其所在位置,会刷新。 -
/proc/cpuinfo:
通过读取cpuinfo可以看到,通过这种方法获取的CPU详情,是进行过解析的,对原始数据进行了拆分,并且是包含了
CPU Flag
信息的,但仍与X86下的结果有较大不同,各个key所对应的信息仍然需要根据表单进行解析才能转变为人为可读的信息。 -
使用LSCPU命令读取
Linux内核的开发者显然也发现了上文介绍的两种方法获取信息不够全面且需要二次解析的问题,因此在Linux外围工具组
util-linux/lscpu
(wiki)中进行了改进,从2.32版本开始增加了对ARM平台CPU信息的解析,从而提供人为可读的内容(由于2019年11月才合入相关Patch,HiSilicon芯片的解析需要手动编译最新主干代码才能实现)。 -
使用内联汇编和辅助向量直接解析
上文介绍的两种方法相对来说比较简单,但需要进行读取文件、运行外部命令等操作;当想在自己的程序中引用上述信息时,速度会相对较慢且会引入新的依赖(lscpu)。因此最快速的方法是通过内联汇编直接读取并解析相应的寄存器;
上文中已经提到,用户在
EL0
无法直接读取到位于EL1
的寄存器内的内容,那么该如何去做呢?ARM已经为我们准备好了一切,用户可以通过
MRS
指令将程序状态寄存器的内容传送到通用寄存器中,再进行进一步的解析,因此我们可以这样做:1
2
3
4
5
6
7
8
9/* read the cpuid data from MIDR_EL1 register */
asm("mrs %0, MIDR_EL1" : "=r" (cpuid));
VIR_DEBUG("CPUID read from register: 0x%016lx", cpuid);
/* parse the coresponding part_id bits */
data->pvr = cpuid>>4&0xFFF;
/* parse the coresponding vendor_id bits */
data->vendor_id = cpuid>>24&0xFF;
这样就可以快速的获取CPUID相关的具体内容,在根据表格进行映射即可获得Vendor和Model信息;
5.不想看了