I need to read the value of a MSR on an Intel Conroe (Core 2 Duo) CPU. After smacking my head against the wall for two days I think I have come to the conclusion that it has to be done with some in-line assembly code inserted into my C++ application. Unfortunately, I have prectically no experience with asm and am hoping for some assistance with a few questions:
1) Is assembly truly the only way to access a MSR?
2) If so, is reading the value of the MSR and passing it back to my C++ application a difficult task to code?
3) If not, could anyone throw me a bone and help point me in the right direction?
While flailing around for a solution I did learn about the instruction "rdmsr" documented in http://www.cs.inf.ethz.ch/stricker/lab/doc/intel-part1.pdf and it looks like it would do exactly what I want. However, I tried using it but I believe I am hitting a protected mode exception because my code isn't running at privilege level 0 and I don't think running at level 0 is an option.
From what (very) little I know, it seems like directly reading a register would be about as simple a task as you can get in assembly but at this point I may as well try to speak Swahili. If it helps any, I am trying to read the register at address 19CH hex (412 decimal).
Thanks in advance for your patience and any assistance you can provide...
Steve
SAK,
What you need to find out is the privelege level required to access the instruction. If its ring0 you will need to write a driver for it that is specific to the OS version you are running.
Thank you for responding Hutch, I appreciate it. Since the rdmsr instruction must be run in Ring0, I have blundered into the same conclusion and I was just reading about writing device drivers at OSROnline. Would the idea basically be to write an ultra-simple driver with a function that invokes the rdmsr instruction and returns the information to a calling application? Is it really that simple?
Thanks again for taking the time to help!
Steve
I know bumping old threads is frowned upon, but this topic is exactly what I'm trying to do: read MSR 19CH (412 dec) - IA32_THERM_STATUS. My end goal is to get the CPU temperature. I'm assuming reading that register (via RDMSR) is the way to do it, unless someone has a better idea?
Does anyone have any advice on creating the driver? Is there a simple MASM example that I could easily modify?
I'm guessing I need a 64-bit driver since I use 64-bit. I've downloaded the WDK and browsed around but it's a bit over my head.
uzig,
I think you are in trouble there, you will need 64 bit drivers for a 64 bit OS version and from memory they must be digitally signed to run in 64 bit. Is there an existing system driver that will do what you are after ?
There may be a driver available.. I'm not entirely sure. The signing issue can be overcome by disabling signed driver enforcement; F8 each boot, or via this command: bcdedit /set loadoptions DDISABLE_INTEGRITY_CHECKS
It's not ideal, but it works. Anyway, I'm just exploring the possiblity of coding/compiling this myself. It seems odd that it's so difficult to read the CPU temp.
If you are trying to get an intel cpu's temperature, you are in for a battle (something about tjunction? or tdelta?).
They finally released some info, but it only applied to core2 cpu's. ::)
edit: I think that cpuz has a dll api you can use. There is also winio but I think it's for 32-bit.
Reading the register seems to be the hardest part since it requires a driver. The math/logic looks to be fairly straight-forward.
This link explains it a bit:
http://www.alcpu.com/CoreTemp/howitworks.html
I'll have to look into the various CPU monitoring progs to see what their redistribution rules are, since I may eventually want to share it with others (non-profit).
i never tried using the dll in my app from http://www.alcpu.com/CoreTemp/main_data/GetCoreTempInfo.zip , even though they include the .lib im not sure if i can use in my project
this what i have so far:
invoke LoadLibrary,CTEXT("GetCoreTempInfo.dll")
.if eax==NULL
invoke MessageBox,hWin,CTEXT("no worky"),CTEXT("Fail."),0
.else
invoke MessageBox,hWin,CTEXT("it worked."),CTEXT("yay!"),0
invoke GetProcAddress, eax,CTEXT("fnGetCoreTempInfo")
mov GetCoreTempInfo, eax
.endif
how do i call the rest to get the cpu temp etc
Quote from: ChillyWilly on September 26, 2009, 10:53:52 PM
how do i call the rest to get the cpu temp etc
It seems like it only works if the program "Core Temp.exe" runs. If it runs (some time it crash!) the temperatures are the same as shown in the program it self ("Core Temp.exe"). Here is my try:
include masm32rt.inc
CORE_TEMP_SHARED_DATA struct
uiLoad DWORD 256 dup (?)
uiTjMax DWORD 128 dup (?)
uiCoreCnt DWORD ?
uiCPUCnt DWORD ?
fTemp REAL4 256 dup (?)
fVID REAL4 ?
fCPUSpeed REAL4 ?
fFSBSpeed REAL4 ?
fMultipier REAL4 ?
sCPUName BYTE 100 dup (?)
ucFahrenheit BYTE ?
ucDeltaToTjMax BYTE ?
CORE_TEMP_SHARED_DATA ends
prc1 typedef PROTO C :DWORD
pfnGetCoreTempInfo typedef ptr prc1
.data?
hMod dd ?
hFileMap dd ?
fnGetCoreTempInfo pfnGetCoreTempInfo ?
core0 real4 ?
.code
start:
mov hMod,rv(LoadLibrary,"GetCoreTempInfo.dll")
mov fnGetCoreTempInfo,rv(GetProcAddress,hMod,"fnGetCoreTempInfo")
mov hFileMap,rv(CreateFileMapping,-1,0,PAGE_READWRITE or SEC_COMMIT,0,SIZEOF CORE_TEMP_SHARED_DATA,"CoreTempMappingObject")
invoke MapViewOfFile,hFileMap,FILE_MAP_WRITE or FILE_MAP_READ,0,0,SIZEOF CORE_TEMP_SHARED_DATA
push eax
invoke fnGetCoreTempInfo,eax
mov eax,DWORD ptr [esp]
assume eax: ptr CORE_TEMP_SHARED_DATA
m2m core0,[eax].fTemp
fn MessageBox,0,real4$(core0),"core0",MB_OK
pop eax
invoke UnmapViewOfFile,eax
invoke CloseHandle,hFileMap
invoke ExitProcess,0
end start