MSR 这种寄存器专门用于调试、程序执行跟踪、计算机性能监控、简化软件编程、电源控制等等各种实验性功能。
什么是 MSR
MSR 的概念是不易理解,所以这一节只说一些 MSR 的外在,比如形容和指令等,然后展开说说,看完整篇文章你应该就能明白了。
MSR 是一组寄存器,主要可用于操作系统或执行过程(即在特权级别0下运行的代码),这些寄存器的数量和功能因处理器不同,可能也不同。
实际上所有的 MSR 处理系统相关的函数,并且不能被应用程序访问,读取和写入 MSR 需要使用WRMSR
和RDMSR
两个系统指令。而本文的 TSC 是一个例外(使用rdtsc
等指令也可以读取)。
为什么要设计这样的一种寄存器呢?
为什么要设计出这样的一种寄存器呢?这与常见的EAX
通用寄存器太不一样了。
首先需要了解一下 MSR 的来历。从 80386 开始,英特尔给每一代处理器都会引入了一些“实验性”功能,这些功能不一定会出现在未来的处理器中。这就会导致一些指令无效。
比如在新一代处理器中新增了了几个测试功能的寄存器,然后设计了一个mov
变体(假设叫movx
)来读取这几个寄存器,但是后续处理器没有这几个测试寄存器,那么这个movx
指令就失效了。但是有些程序或者编译器等是使用movx
的话,就需要重新编写。加大了开发工作量和兼容难度。
为了解决这个问题,从奔腾处理器开始,英特尔开始提供WRMSR
和RDMSR
这对指令来访问当前和未来会出现的“特定模块的寄存器”。比如说,这里读取一个测试代码的寄存器,我们不用操心具体使用哪个指令来读取具体的寄存器,而是使用RDMSR
来读取这个测试代码模型下使用的寄存器,具体如何读取是RDMSR
去实现的。这样就避免了寄存器未来不使用后,指令也不能用了的问题。
如果你在 Intel SDM 中搜索 MSR,会发现 MSR 出现的地方都是一些比较实验性的内容。而且最后的第 4 卷标题就是 Model-Specific Registers,可见这个技术还蛮重要的。
是不是有点像高级语言的感觉,所以有些人会把 MSR 当做一个虚拟寄存器。但是这是个实际存在的寄存器,只不过这个实际存在的寄存器在每一代可能都不同,因为加上了这样一层所以感觉有点“虚”。
为什么你说应用程序不能访问,又说WRMSR
和RDMSR
两个系统指令可以读写 MSR 呢?
因为除了 TSC 可以使用rdtsc
等指令外,你只能通过设置ECX
寄存器的值,再使用RDMSR
将其写入EDX:EAX
两个寄存器中,然后使用mov
等指令来读取EAX
和EDX
的值。而不能直接用mov
或者其变体读取 TSC 的寄存器。
关于使用rdtsc
读取 TSC 可以看我的这篇文章:如何使用rdtsc和C/C++来测量运行时间(如何使用内联汇编和获取CPU的TSC时钟频率),这篇文章使用了内联汇编,可以作为一个例子帮助理解。
什么叫体系结构 MSR
让我们来想一个问题:现在指令是没有失效的风险了,但要是模型不用了咋办?随着技术的发展,一些技术可能就不用了,那么模型就被淘汰了。
这个没有 MSR 这么神奇的方法,所以只能依照约定和惯例。
在文档中提及:如果是体系结构 MSR(Architectural MSRs),那么未来可预期的会出现,但要不是,可能就没了。这就靠开发者了。
MSR 的一个子集和相关的比特字段在未来几代处理器中不会改变,现在被称为“体系结构MSR”。由于历史原因(从奔腾 4 处理器开始),这些“体系结构 MSR”的前缀为IA32_
。
名称/地址
每个寄存器都有自己的名称和地址,具体请见 Intel® 64 and IA-32 Architectures Software Developer’s Manual
Volume 4: Model-Specific Registers,整个第 4 卷 500 多页全是列出的 MSR。
如下图就是一个寄存器地址和体系结构 MSR 名称(Architectural MSR Name)的对应:
MSR地址范围在4000000H到4000FFFFH之间被标记为特别保留的范围。所有现有和未来的处理器都不会使用该范围内的任何MSR来实现任何功能。
希望能帮到有需要的人~
参考资料
Intel® 64 and IA-32 Architectures Software Developer Manuals:Intel 处理器的官方文档,比较详细的介绍了 MSR 以及一个长长长长的列表。
Model-specific register - Wikipedia:这个维基百科其实写的不详细,也是别人根据自己的研究编写的。重点是附带资料不错,推荐看看。