Reading CPU model specific registers on linux

4

I am running Ubuntu 15.10 but testes it also on Debian. I have Intel i5-5675C processor. I am using msr-tools-1.3 to do it. I am able to read register 0x00001a2 with the following command:

rdmsr 0x00001a2

It gives me some good output according to the datasheet. However I can't do anything handy with this value.

I would like to read some model-specific registers from my CPU associated with temperature or voltage or something useful. Datasheet info:

Datasheet Vol 1

Datasheet Vol 2

From datasheet Vol 2: 5.2.52 IA32-IA32_THERM_STATUS,

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

I get an error like this. I have tried running it on all 4 CPU cores and have enabled modprobe and files are present in /dev/cpu/{CPU_ID}/msr:

sudo modprobe msr

Here is strace output:

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 +++

Zwierzak

Posted 2016-04-23T08:00:05.763

Reputation: 151

What does uname -r show and what arguments are you passing to rdmsr? – tijko – 2016-11-27T19:02:48.653

There is no MSR 0x59c0. You cannot read what is not there. – MSR – 2017-09-20T16:19:57.513

Answers

1

Notice the line:

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

where 22976 = 0x59c0, which is the MSR address you are trying to read. The EIO error appears when in msr_read function the call to rdmsr_safe_on_cpu leading to rdmsr_safe macro calling the native_read_msr_safe function results in #GP exception on executing the RDMSR instruction.

So, your CPU doesn't support the MSR you're trying to read.

But, as pointed out in the answer by duskwuff, you're reading the wrong datasheet. The offset 0x59c0 is the offset relative to MCHBAR, which points to the memory space – it's not an address of any MSR. To find the correct MSR address you should read Volume 3B of the Intel's manual – System Programming Guide, namely, its chapter 14.4. There it's said that IA32_THERM_STATUS (note, not IA32—IA32_THERM_STATUS) MSR has address 0x19c.

Ruslan

Posted 2016-04-23T08:00:05.763

Reputation: 1 168

You are right, that means that the register doesn't exist. – abu_bua – 2018-07-25T19:38:26.867

1

You have misread the datasheet.

IA32—IA32_THERM_STATUS is a configuration register in the platform PCI device, not a CPU MSR. It cannot be read using rdmsr.

duskwuff -inactive-

Posted 2016-04-23T08:00:05.763

Reputation: 3 824

That is wrong! You can of course read the IA32_THERM_STATUS (in most cases address 0x19c). But you have to load the msr kernel before. – abu_bua – 2018-07-25T19:37:41.840

@abu_bua Context is important. The OP was specifically referring to a register described in the datasheet with offset 59c0h; this register is part of the platform PCI device. It's on page 144 of https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/5th-gen-core-family-datasheet-vol-2.pdf

– duskwuff -inactive- – 2018-07-25T19:41:29.760

@abu_bua actually this is right, and it nicely complements my answer. IA32—IA32_THERM_STATUS is at MCHBAR+0x59c0 in the memory space. Although it's indeed possible to read IA32_THERM_STATUS via the MSR interface at address 0x19c, the offset 0x59c0 found by the OP is related to MMIO, not MSRs. So definitely, the OP has misunderstood the datasheet. – Ruslan – 2018-07-25T21:38:37.250

Sorry, I missread the op' question! – abu_bua – 2018-07-25T22:33:58.933

0

Two things jump out

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

Open passed returning the file descriptor with value 3

The msr registers can only be read/written with Root. The man page makes this clear.

SUDO used to stand for SuperUser DO. On modern Linux is more like Substitute User DO. SUDO doesn't mean the user executing the task is necessarily Root. Often it temporarily elevates a user's status to do things things as that user. So while you may have root permissions you can still fail the UserID == 0 check.

Try the same command in a root shell and see if it fails.

Valarauca

Posted 2016-04-23T08:00:05.763

Reputation: 109

If the problem were with permissions, you'd fail to open the file. The actual problem happens later, on pread, which returns EIO. – Ruslan – 2018-05-16T10:44:44.283