#include <ntifs.h>
#include <windef.h>
#include <ntddk.h>
#include <ntstrsafe.h>
#include <intrin.h> //VS2012编译。
#include <immintrin.h>//VS2012编译。
//#include <mmintrin.h> //WDK 编译。
//#include <emmintrin.h>//WDK 编译。
//#include <xmmintrin.h>//WDK 编译。
#pragma warning(disable:4100)
/*
CPUID.06H:EAX[bit0]
19CH 412 IA32_THERM_STATUS Core Thermal Monitor Status (R/W) See Table 35-2.
1A2H 418 MSR_TEMPERATURE_TARGET Package
15:0 Reserved.
23:16 Temperature Target (R)
The default thermal throttling or PROCHOT# activation temperature in degree C,
The effective temperature for thermal throttling or PROCHOT# activation is “Temperature Target” +“Target Offset”
29:24 Target Offset (R/W)
Specifies an offset in degrees C to adjust the throttling and PROCHOT# activation temperature from the default target specified in TEMPERATURE_TARGET (bits 23:16).
*/
#define IA32_THERM_STATUS 0x19C
#define MSR_TEMPERATURE_TARGET 0x1A2
BOOL is_support_intel()
{
BOOL B = FALSE;
char CPUString[0x20];
int CPUInfo[4] = { -1 };
unsigned nIds;
// __cpuid with an InfoType argument of 0 returns the number of valid Ids in CPUInfo[0] and the CPU identification string in the other three array elements.
// The CPU identification string is not in linear order.
// The code below arranges the information in a human readable form.
__cpuid(CPUInfo, 0);
nIds = CPUInfo[0];
memset(CPUString, 0, sizeof(CPUString));
*((int*) CPUString) = CPUInfo[1];
*((int*) (CPUString + 4)) = CPUInfo[3];
*((int*) (CPUString + 8)) = CPUInfo[2];
//printf_s("\n\nCPU String: %s\n", CPUString);//GenuineIntel
if (_stricmp(CPUString, "GenuineIntel") == 0)
{
B = TRUE;
}
return B;
}
BOOL is_support_cpuid()
/*
判断CPU是否支持CPUID指令。
*/
{
BOOL B = FALSE;
SIZE_T eflags1;
SIZE_T eflags2;
eflags1 = __readeflags();
__writeeflags(eflags1 | 0x200000);
eflags2 = __readeflags();
__writeeflags(eflags1);
if (eflags1 == eflags2) {
B = FALSE;
}
else {
B = TRUE;
}
return B;
}
//DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
}
//DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_SUCCESS;
unsigned __int64 tt = 0;
unsigned __int64 ts = 0;
int x = 0;
int to = 0;
int i = 0;
int CPUInfo[4] = { -1 };
unsigned int t = 0;
//KdBreakPoint();
//__debugbreak();
DriverObject->DriverUnload = Unload;
//识别是否支持CPUID指令。
if (!is_support_cpuid())
{
return 0;
}
//识别是不是Intel处理器。
if (!is_support_intel())
{
return 0;
}
//识别是否支持查询CPU的温度。
__cpuid(CPUInfo, 6);
t = CPUInfo[0];
//CPUID.06H:EAX[bit0] == 1
//可是下面的两个值获取的都为零。
tt = __readmsr(MSR_TEMPERATURE_TARGET);//如果这个数字为0,可以认为是在虚拟机中,有的软件叫:耐热,可能是极限。
ts = __readmsr(IA32_THERM_STATUS);
//KdPrint(("MSR_TEMPERATURE_TARGET:0x%x.\r\n", tt));
//KdPrint(("IA32_THERM_STATUS:0x%x.\r\n", ts));
x = tt & (0xFF0000);//23:16 Temperature Target (R)
to = ts & (0x7F0000);//22:16 Digital Readout (RO)
i = x - to;
i = i / 0x10000;
KdPrint(("TEMPERATURE:%d.\r\n", i));
//这个数字和别的软件有1-2度的差别。
//不过Core-Temp和hwmonitor也是相差1-2度。
return status;
}
/*
注意:测试环境最好不要用虚拟机,用真实的物理机器。
如是64位Windows,可以开启WINDBG的本机内核调试:
lkd> rdmsr 0x19C; rdmsr 0x1A2
msr[19c] = 00000000`88470000
msr[1a2] = 00000000`00691400
再计算。
注意:每个核心有个温度,不是每个CPU线程有个温度。
具体的做法有:
1.创建个设备,提供个借口供应用层用。
2.开启个定时器,在内核不停的打印消息。
made by correy
made at 2016.05.12
homepage:http://correy.webs.com
*/
没有评论:
发表评论