在 Linux 上读取 CPU 模型特定的寄存器

在 Linux 上读取 CPU 模型特定的寄存器

我正在运行 Ubuntu 15.10,但也在 Debian 上测试它。我有英特尔i5-5675C处理器。我正在使用msr-工具-1.3做到这一点。我可以读取寄存器0x00001a2使用以下命令:

rdmsr 0x00001a2

根据数据表,它给出了一些不错的输出。但是我无法用这个值做任何有用的事情。

我想从我的 CPU 中读取一些与温度或电压或某些有用信息相关的特定于模型的寄存器。数据表信息:

数据表第 1 卷

数据表第 2 卷

来自数据表第 2 卷: 5.2.52 IA32-IA32_THERM_STATUS

 rdmsr 0x000059c0
 rdmsr: CPU 0 cannot read MSR 0x000059c0

我遇到了这样的错误。我尝试在所有 4 个 CPU 核心上运行它,并启用了 modprobe,文件存在于/dev/cpu/{CPU_ID}/msr

sudo modprobe msr

以下是 strace 的输出:

sudo strace rdmsr 0x59c0
execve("/usr/sbin/rdmsr", ["rdmsr", "0x59c0"], [/* 25 vars */]) = 0
brk(0)                                  = 0x84d000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe87cb3f000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=92026, ...}) = 0
mmap(NULL, 92026, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe87cb28000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\v\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1869392, ...}) = 0
mmap(NULL, 3972864, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fe87c554000
mprotect(0x7fe87c714000, 2097152, PROT_NONE) = 0
mmap(0x7fe87c914000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c0000) = 0x7fe87c914000
mmap(0x7fe87c91a000, 16128, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fe87c91a000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe87cb27000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe87cb26000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe87cb25000
arch_prctl(ARCH_SET_FS, 0x7fe87cb26700) = 0
mprotect(0x7fe87c914000, 16384, PROT_READ) = 0
mprotect(0x602000, 4096, PROT_READ)     = 0
mprotect(0x7fe87cb41000, 4096, PROT_READ) = 0
munmap(0x7fe87cb28000, 92026)           = 0
open("/dev/cpu/0/msr", O_RDONLY)        = 3
pread(3, 0x7ffcd2bddf78, 8, 22976)      = -1 EIO (Input/output error)
write(2, "rdmsr: CPU 0 cannot read MSR 0x0"..., 40rdmsr: CPU 0 cannot read MSR 0x000059c0
) = 40
exit_group(4)                           = ?
+++ exited with 4 +++

答案1

请注意这一行:

pread(3, 0x7ffcd2bddf78, 8, 22976)      = -1 EIO (Input/output error)

其中22976 = 0x59c0,即您尝试读取的 MSR 地址。EIO在以下情况下会出现错误:msr_读取函数调用rdmsr_safe_on_cpu导致rdmsr_safe宏调用native_read_msr_safe函数在执行指令时导致#GP 异常RDMSR

因此,您的 CPU 不支持您尝试读取的 MSR。

但正如duskwuff 的回答,你读错了数据表。偏移量 0x59c0 是相对于 的偏移量MCHBAR,它指向记忆空间——它不是任何 MSR 的地址。要找到正确的 MSR 地址,您应该阅读Intel 手册第 3B 卷 – 系统编程指南,即其第 14.4 章。那里说IA32_THERM_STATUS(注意,不是IA32—IA32_THERM_STATUS)MSR 的地址为 0x19c。

答案2

您误读了数据表。

IA32—IA32_THERM_STATUS是平台 PCI 设备中的配置寄存器,而不是 CPU MSR。无法使用 读取rdmsr

答案3

有两件事引人注目

open("/dev/cpu/0/msr", O_RDONLY) = 3

Open 已通过,返回值为 3 的文件描述符

仅可msr registers使用 Root 进行读取/写入。手册页使这一点变得清晰。

SUDO 过去代表年代上层驅動在现代 Linux 上更像是年代替代驅動。SUDO 并不意味着执行任务的用户一定是 Root。通常,它会暂时提升用户的身份来执行某些操作作为该用户。因此,当你可能拥有root权限仍然未能通过UserID == 0检查。

在 root shell 中尝试相同的命令,看看是否失败。

相关内容