From 9b038c94c45abf81a805ed8813af2f8aaac32eda Mon Sep 17 00:00:00 2001 From: Xorg Date: Thu, 9 Feb 2017 20:55:28 +0100 Subject: [PATCH] Add a msr_serialize_raw_data() function --- cpuid_tool/cpuid_tool.c | 12 ++++++ libcpuid/exports.def | 1 + libcpuid/libcpuid.h | 19 ++++++++++ libcpuid/libcpuid.sym | 1 + libcpuid/rdmsr.c | 81 ++++++++++++++++++++++++++++++++++++++++- 5 files changed, 113 insertions(+), 1 deletion(-) diff --git a/cpuid_tool/cpuid_tool.c b/cpuid_tool/cpuid_tool.c index c87635a..7ef03f9 100644 --- a/cpuid_tool/cpuid_tool.c +++ b/cpuid_tool/cpuid_tool.c @@ -89,6 +89,7 @@ typedef enum { NEED_CLOCK_RDTSC, NEED_CLOCK_IC, NEED_RDMSR, + NEED_RDMSR_RAW, NEED_SSE_UNIT_SIZE, } output_data_switch; @@ -146,6 +147,7 @@ matchtable[] = { { NEED_CLOCK_RDTSC , "--clock-rdtsc" , 1}, { NEED_CLOCK_IC , "--clock-ic" , 1}, { NEED_RDMSR , "--rdmsr" , 0}, + { NEED_RDMSR_RAW , "--rdmsr-raw" , 0}, { NEED_SSE_UNIT_SIZE, "--sse-size" , 1}, }; @@ -460,6 +462,16 @@ static void print_info(output_data_switch query, struct cpu_raw_data_t* raw, } break; } + case NEED_RDMSR_RAW: + { + if ((handle = cpu_msr_driver_open()) == NULL) { + fprintf(fout, "Cannot open MSR driver: %s\n", cpuid_error()); + } else { + msr_serialize_raw_data(handle, ""); + cpu_msr_driver_close(handle); + } + break; + } case NEED_SSE_UNIT_SIZE: { fprintf(fout, "%d (%s)\n", data->sse_size, diff --git a/libcpuid/exports.def b/libcpuid/exports.def index 9bda55b..b680d9e 100644 --- a/libcpuid/exports.def +++ b/libcpuid/exports.def @@ -32,3 +32,4 @@ cpu_msr_driver_open_core @28 cpuid_get_vendor @29 cpu_rdmsr_range @30 cpuid_get_epc @31 +msr_serialize_raw_data @32 diff --git a/libcpuid/libcpuid.h b/libcpuid/libcpuid.h index 866c0e8..5ce4b89 100644 --- a/libcpuid/libcpuid.h +++ b/libcpuid/libcpuid.h @@ -1104,6 +1104,25 @@ int cpu_rdmsr_range(struct msr_driver_t* handle, uint32_t msr_index, uint8_t hig int cpu_msrinfo(struct msr_driver_t* handle, cpu_msrinfo_request_t which); #define CPU_INVALID_VALUE 0x3fffffff +/** + * @brief Writes the raw MSR data to a text file + * @param data - a pointer to msr_driver_t structure + * @param filename - the path of the file, where the serialized data should be + * written. If empty, stdout will be used. + * @note This is intended primarily for debugging. On some processor, which is + * not currently supported or not completely recognized by cpu_identify, + * one can still successfully get the raw data and write it to a file. + * libcpuid developers can later import this file and debug the detection + * code as if running on the actual hardware. + * The file is simple text format of "something=value" pairs. Version info + * is also written, but the format is not intended to be neither backward- + * nor forward compatible. + * @returns zero if successful, and some negative number on error. + * The error message can be obtained by calling \ref cpuid_error. + * @see cpu_error_t + */ +int msr_serialize_raw_data(struct msr_driver_t* handle, const char* filename); + /** * @brief Closes an open MSR driver * diff --git a/libcpuid/libcpuid.sym b/libcpuid/libcpuid.sym index 64869a0..a55f753 100644 --- a/libcpuid/libcpuid.sym +++ b/libcpuid/libcpuid.sym @@ -29,3 +29,4 @@ cpu_msr_driver_open_core cpuid_get_vendor cpu_rdmsr_range cpuid_get_epc +msr_serialize_raw_data diff --git a/libcpuid/rdmsr.c b/libcpuid/rdmsr.c index a27e939..c63cf15 100644 --- a/libcpuid/rdmsr.c +++ b/libcpuid/rdmsr.c @@ -26,6 +26,7 @@ #define _XOPEN_SOURCE 500 #include #include +#include #include "libcpuid.h" #include "asm-bits.h" #include "libcpuid_util.h" @@ -502,6 +503,11 @@ int cpu_msrinfo(struct msr_driver_t* driver, cpu_msrinfo_request_t which) return set_error(ERR_NOT_IMP); } +int msr_serialize_raw_data(struct msr_driver_t* handle, const char* filename) +{ + return set_error(ERR_NOT_IMP); +} + #endif /* Unsupported OS */ #ifndef RDMSR_UNSUPPORTED_OS @@ -537,7 +543,26 @@ int cpu_msrinfo(struct msr_driver_t* driver, cpu_msrinfo_request_t which) #define MSR_PSTATE_L 0xC0010061 #define MSR_PSTATE_S 0xC0010063 #define MSR_PSTATE_0 0xC0010064 +#define MSR_PSTATE_1 0xC0010065 +#define MSR_PSTATE_2 0xC0010066 +#define MSR_PSTATE_3 0xC0010067 +#define MSR_PSTATE_4 0xC0010068 +#define MSR_PSTATE_5 0xC0010069 +#define MSR_PSTATE_6 0xC001006A #define MSR_PSTATE_7 0xC001006B +static const uint32_t amd_msr[] = { + MSR_PSTATE_L, + MSR_PSTATE_S, + MSR_PSTATE_0, + MSR_PSTATE_1, + MSR_PSTATE_2, + MSR_PSTATE_3, + MSR_PSTATE_4, + MSR_PSTATE_5, + MSR_PSTATE_6, + MSR_PSTATE_7, + CPU_INVALID_VALUE +}; /* Intel MSRs addresses */ #define IA32_MPERF 0xE7 @@ -549,7 +574,18 @@ int cpu_msrinfo(struct msr_driver_t* driver, cpu_msrinfo_request_t which) #define MSR_TEMPERATURE_TARGET 0x1A2 #define MSR_PERF_STATUS 0x198 #define MSR_PLATFORM_INFO 0xCE - +static const uint32_t intel_msr[] = { + IA32_MPERF, + IA32_APERF, + IA32_PERF_STATUS, + IA32_THERM_STATUS, + MSR_EBL_CR_POWERON, + MSR_TURBO_RATIO_LIMIT, + MSR_TEMPERATURE_TARGET, + MSR_PERF_STATUS, + MSR_PLATFORM_INFO, + CPU_INVALID_VALUE +}; static int rdmsr_supported(void) { @@ -919,4 +955,47 @@ int cpu_msrinfo(struct msr_driver_t* handle, cpu_msrinfo_request_t which) } } +int msr_serialize_raw_data(struct msr_driver_t* handle, const char* filename) +{ + int i, j; + FILE *f; + uint64_t reg; + const uint32_t *msr; + struct cpu_raw_data_t raw; + struct cpu_id_t id; + struct internal_id_info_t internal; + + if (handle == NULL) + return set_error(ERR_HANDLE); + + if (!strcmp(filename, "")) + f = stdout; + else + f = fopen(filename, "wt"); + if (!f) return set_error(ERR_OPEN); + + if (cpuid_get_raw_data(&raw) || cpu_ident_internal(&raw, &id, &internal)) + return -1; + + fprintf(f, "CPU is %s %s, stock clock is %dMHz.\n", id.vendor_str, id.brand_str, cpu_clock_measure(100, 1)); + if (id.vendor == VENDOR_INTEL) + msr = intel_msr; + else if (id.vendor == VENDOR_AMD) + msr = amd_msr; + else + return set_error(ERR_CPU_UNKN); + + for (i = 0; msr[i] != CPU_INVALID_VALUE; i++) { + cpu_rdmsr(handle, msr[i], ®); + fprintf(f, "msr[%#08x]=", msr[i]); + for (j = 56; j >= 0; j -= 8) + fprintf(f, "%02x ", (int) (reg >> j) & 0xff); + printf("\n"); + } + + if (strcmp(filename, "")) + fclose(f); + return set_error(ERR_OK); +} + #endif // RDMSR_UNSUPPORTED_OS