From e4920d79b0de818d92aa5ebf39001784302be649 Mon Sep 17 00:00:00 2001 From: Veselin Georgiev Date: Wed, 30 Sep 2009 17:20:52 +0000 Subject: [PATCH] Added cpu_msrinfo() function and implemented a few test info entries git-svn-id: https://svn.code.sf.net/p/libcpuid/code/HEAD/libcpuid@71 3b4be424-7ac5-41d7-8526-f4ddcb85d872 --- cpuid_tool/cpuid_tool.c | 6 ++-- libcpuid/libcpuid.h | 32 +++++++++++++++++++++ libcpuid/rdmsr.c | 62 ++++++++++++++++++++++++----------------- 3 files changed, 72 insertions(+), 28 deletions(-) diff --git a/cpuid_tool/cpuid_tool.c b/cpuid_tool/cpuid_tool.c index 41eacbe..bbfffae 100644 --- a/cpuid_tool/cpuid_tool.c +++ b/cpuid_tool/cpuid_tool.c @@ -317,7 +317,6 @@ static void print_info(output_data_switch query, struct cpu_raw_data_t* raw, { int i; struct msr_driver_t* handle; - uint64_t value; switch (query) { case NEED_CPUID_PRESENT: fprintf(fout, "%d\n", cpuid_present()); @@ -410,8 +409,9 @@ static void print_info(output_data_switch query, struct cpu_raw_data_t* raw, if ((handle = cpu_msr_driver_open()) == NULL) { fprintf(fout, "Cannot open MSR driver: %s\n", cpuid_error()); } else { - cpu_rdmsr(handle, 0x10, &value); - fprintf(fout, "%I64d\n", value); + fprintf(fout, "mperf = %d\n", cpu_msrinfo(handle, INFO_MPERF)); + fprintf(fout, "aperf = %d\n", cpu_msrinfo(handle, INFO_APERF)); + fprintf(fout, "cpu:fsb = %.1f\n", cpu_msrinfo(handle, INFO_CUR_MULTIPLIER) / 100.0f); cpu_msr_driver_close(handle); } break; diff --git a/libcpuid/libcpuid.h b/libcpuid/libcpuid.h index f1de2b9..fa1ac15 100644 --- a/libcpuid/libcpuid.h +++ b/libcpuid/libcpuid.h @@ -741,6 +741,38 @@ struct msr_driver_t* cpu_msr_driver_open(void); */ int cpu_rdmsr(struct msr_driver_t* handle, int msr_index, uint64_t* result); + +typedef enum { + INFO_MPERF, /*!< Maximum performance frequency clock. This + is a counter, which increments as a + proportion of the actual processor speed */ + INFO_APERF, /*!< Actual performance frequency clock. This + accumulates the core clock counts when the + core is active. */ + INFO_CUR_MULTIPLIER, /*!< Current CPU:FSB ratio, multiplied by 100. + e.g., a CPU:FSB value of 18.5 reads as + 1850. */ + INFO_MAX_MULTIPLIER, /*!< Maxumum CPU:FSB ratio for this CPU, + multiplied by 100 */ + INFO_TEMPERATURE, /*!< The current core temperature in Celsius */ + INFO_THROTTLING, /*!< 1 if the current logical processor is + throttling. 0 if it is running normally. */ +} cpu_msrinfo_request_t; + +/** + * @brief Reads extended CPU information from Model-Specific Registers. + * @param handle - a handle to an open MSR driver, @see cpu_msr_driver_open + * @param which - which info field should be returned. A list of + * available information entities is listed in the + * cpu_msrinfo_request_t enum. + * @retval - if the requested information is available for the current + * processor model, the respective value is returned. + * if no information is available, or the CPU doesn't support + * the query, the special value CPU_INVALID_VALUE is returned + */ +int cpu_msrinfo(struct msr_driver_t* handle, cpu_msrinfo_request_t which); +#define CPU_INVALID_VALUE 0x3fffffff + /** * @brief Closes an open MSR driver * diff --git a/libcpuid/rdmsr.c b/libcpuid/rdmsr.c index b7d2130..918b970 100644 --- a/libcpuid/rdmsr.c +++ b/libcpuid/rdmsr.c @@ -215,31 +215,7 @@ static int load_driver(struct msr_driver_t* drv) debugf(1, "Create driver service failed: %d\n", dwLastError); break; } - } /*else { - switch(getImageType(lpszDriverFilePath)){ - case IMAGE_FILE_MACHINE_AMD64: - if(!isRunning_x64()){ - if(!DeleteFile(lpszDriverFilePath)){ - addLastErrorMessageMsgEx(g_hLogEdit, __TEXT("Error deleting driver file(due to binary incompatibility):"), GetLastError()); - goto clean_up; - } - if(!extractDriver(lpszDriverFilePath)) - goto clean_up; - } - break; - case IMAGE_FILE_MACHINE_I386: - if(isRunning_x64()){ - if(!DeleteFile(lpszDriverFilePath)){ - addLastErrorMessageMsgEx(g_hLogEdit, __TEXT("Error deleting driver file(due to binary incompatibility):"), GetLastError()); - goto clean_up; - } - if(!extractDriver(lpszDriverFilePath)) - goto clean_up; - } - break; - } - }*/ - + } if(drv->scDriver != NULL){ if(StartService(drv->scDriver, 0, NULL)){ if(!wait_for_service_state(drv->scDriver, SERVICE_RUNNING, &srvStatus)){ @@ -312,6 +288,7 @@ int cpu_rdmsr(struct msr_driver_t* driver, int msr_index, uint64_t* result) int cpu_msr_driver_close(struct msr_driver_t* drv) { SERVICE_STATUS srvStatus = {0}; + if (drv == NULL) return 0; if(drv->scDriver != NULL){ if (drv->hhDriver) CancelIo(drv->hhDriver); if(drv->ovl.hEvent != NULL) @@ -328,4 +305,39 @@ int cpu_msr_driver_close(struct msr_driver_t* drv) return 0; } +int cpu_msrinfo(struct msr_driver_t* handle, cpu_msrinfo_request_t which) +{ + uint64_t r; + int err; + + if (handle == NULL) + return set_error(ERR_HANDLE); + switch (which) { + case INFO_MPERF: + { + err = cpu_rdmsr(handle, 0xe7, &r); + if (err) return CPU_INVALID_VALUE; + return (int) (r & 0x7fffffff); + } + case INFO_APERF: + { + err = cpu_rdmsr(handle, 0xe8, &r); + if (err) return CPU_INVALID_VALUE; + return (int) (r & 0x7fffffff); + } + case INFO_CUR_MULTIPLIER: + { + err = cpu_rdmsr(handle, 0x2a, &r); + if (err) return CPU_INVALID_VALUE; + return (int) ((r >> 22) & 0x3f) * 100; + } + case INFO_MAX_MULTIPLIER: + case INFO_TEMPERATURE: + case INFO_THROTTLING: + default: + return CPU_INVALID_VALUE; + } +} + + #endif /* _WIN32 */