From 2d453e612cdd0cc5afcd7f5a0dabf3b5a1c934b4 Mon Sep 17 00:00:00 2001 From: Veselin Georgiev Date: Mon, 10 Nov 2008 16:04:29 +0000 Subject: [PATCH] Initial detection working git-svn-id: https://svn.code.sf.net/p/libcpuid/code/HEAD/libcpuid@5 3b4be424-7ac5-41d7-8526-f4ddcb85d872 --- Makefile.am | 2 +- configure.ac | 1 + cpuid_tool/Makefile.am | 8 ++ cpuid_tool/cpuid_tool.c | 44 +++++++ libcpuid/asm-bits.c | 192 +++++++++++++++++++++++++++++ libcpuid/asm-bits.h | 33 +++++ libcpuid/cpuid_main.c | 265 +++++++++++++++++++++++++++++++++++++--- libcpuid/libcpuid.h | 13 +- libcpuid/recog_amd.c | 7 ++ libcpuid/recog_intel.c | 7 ++ 10 files changed, 547 insertions(+), 25 deletions(-) create mode 100644 cpuid_tool/Makefile.am create mode 100644 cpuid_tool/cpuid_tool.c create mode 100644 libcpuid/asm-bits.c create mode 100644 libcpuid/asm-bits.h diff --git a/Makefile.am b/Makefile.am index 1d35bdd..d34b461 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = libcpuid +SUBDIRS = libcpuid cpuid_tool pkgconfigdir = $(libdir)/pkgconfig diff --git a/configure.ac b/configure.ac index 8ecda75..ea0e5e8 100644 --- a/configure.ac +++ b/configure.ac @@ -41,6 +41,7 @@ AC_CONFIG_FILES([ Makefile libcpuid.pc libcpuid/Makefile + cpuid_tool/Makefile ]) AC_OUTPUT diff --git a/cpuid_tool/Makefile.am b/cpuid_tool/Makefile.am new file mode 100644 index 0000000..1d8b79b --- /dev/null +++ b/cpuid_tool/Makefile.am @@ -0,0 +1,8 @@ +bin_PROGRAMS = cpuid_tool + +cpuid_tool_SOURCES = cpuid_tool.c + +EXTRA_INCLUDE_PATHS = -I$(top_srcdir)/libcpuid +AM_CPPFLAGS = $(all_includes) $(EXTRA_INCLUDE_PATHS) + +cpuid_tool_LDADD = $(top_builddir)/libcpuid/libcpuid.la diff --git a/cpuid_tool/cpuid_tool.c b/cpuid_tool/cpuid_tool.c new file mode 100644 index 0000000..881e9b1 --- /dev/null +++ b/cpuid_tool/cpuid_tool.c @@ -0,0 +1,44 @@ +#include +#include "libcpuid.h" + +int main(void) +{ + if (!cpuid_present()) { + printf("No CPUID on this CPU, sorry!\n"); + return -1; + } + printf("CPUID is present\n"); + struct cpu_raw_data_t raw; + struct cpu_id_t data; + if (cpuid_get_raw_data(&raw) < 0) + printf("Error obtaining raw data: %s\n", cpuid_error()); + if (cpu_identify(&raw, &data) < 0) + printf("Error identifying the CPU: %s\n", cpuid_error()); + printf("CPU Info:\n------------------\n"); + printf(" vendor_str: `%s'\n", data.vendor_str); + printf(" vendor id : %d\n", (int) data.vendor); + printf(" brand_str : `%s'\n", data.brand_str); + printf(" family : %d\n", data.family); + printf(" model : %d\n", data.model); + printf(" stepping : %d\n", data.stepping); + printf(" ext_family: %d\n", data.ext_family); + printf(" ext_model : %d\n", data.ext_model); + printf(" num_cores : %d\n", data.num_cores); + printf(" num_logcpu: %d\n", data.num_logical_cpus); + printf(" total_cpus: %d\n", data.total_cpus); + printf(" L1 D cache: %d KB\n", data.l1_data_cache); + printf(" L1 I cache: %d KB\n", data.l1_instruction_cache); + printf(" L2 cache : %d KB\n", data.l2_cache); + printf(" L3 cache : %d KB\n", data.l3_cache); + printf(" L1 assoc. : %d-way\n", data.l1_assoc); + printf(" L2 assoc. : %d-way\n", data.l2_assoc); + printf(" L3 assoc. : %d-way\n", data.l3_assoc); + printf(" code name : `%s'\n", data.cpu_codename); + printf(" flags:"); + int i; + for (i = 0; i < CPU_FEATURE_END; i++) + if (data.flags[i]) + printf(" %s", cpu_feature_str(i)); + printf("\n"); + return 0; +} diff --git a/libcpuid/asm-bits.c b/libcpuid/asm-bits.c new file mode 100644 index 0000000..ce073fe --- /dev/null +++ b/libcpuid/asm-bits.c @@ -0,0 +1,192 @@ +/* + * Copyright 2008 Veselin Georgiev, + * anrieffNOSPAM @ mgail_DOT.com (convert to gmail) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "libcpuid.h" +#include "asm-bits.h" + +int cpuid_exists_by_eflags(void) +{ +#ifdef __x86_64__ + return 1; // CPUID is always present on the x86_64 +#else +# ifdef __GNUC__ + int result; + __asm __volatile( + " pushfl\n" + " pop %%eax\n" + " mov %%eax, %%ecx\n" + " xor $0x200000, %%eax\n" + " push %%eax\n" + " popfl\n" + " pushfl\n" + " pop %%eax\n" + " xor %%ecx, %%eax\n" + " mov %%eax, %0\n" + " push %%ecx\n" + " popfl\n" + : "=m"(result) + : :"eax", "ecx", "memory"); + return (result != 0); +# else +# ifdef _MSC_VER + int result; + __asm { + pushfd + pop eax + mov ecx, eax + xor eax, 0x200000 + push eax + popfd + pushfd + pop eax + xor eax, ecx + mov result, eax + push ecx + popfd + }; + return (result != 0); +# else +# error "Unsupported compiler" +# endif // _MSC_VER +# endif // __GNUC__ +#endif // __x86_64__ +} + +void exec_cpiud(uint32_t *regs) +{ +#ifdef __GNUC__ +# ifdef __x86_64__ + __asm __volatile( + " push %%rbx\n" + " push %%rcx\n" + " push %%rdx\n" + " push %%rdi\n" + + " mov %0, %%rdi\n" + + " mov (%%rdi), %%eax\n" + " mov 4(%%rdi), %%ebx\n" + " mov 8(%%rdi), %%ecx\n" + " mov 12(%%rdi), %%edx\n" + + " cpuid\n" + + " movl %%eax, (%%rdi)\n" + " movl %%ebx, 4(%%rdi)\n" + " movl %%ecx, 8(%%rdi)\n" + " movl %%edx, 12(%%rdi)\n" + " pop %%rdi\n" + " pop %%rdx\n" + " pop %%rcx\n" + " pop %%rbx\n" + : + :"rdi"(regs) + :"memory", "eax" + ); +# else + __asm __volatile( + " push %%ebx\n" + " push %%ecx\n" + " push %%edx\n" + " push %%edi\n" + " mov %0, %%edi\n" + + " mov (%%edi), %%eax\n" + " mov 4(%%edi), %%ebx\n" + " mov 8(%%edi), %%ecx\n" + " mov 12(%%edi), %%edx\n" + + " cpuid\n" + + " mov %%eax, (%%edi)\n" + " mov %%ebx, 4(%%edi)\n" + " mov %%ecx, 8(%%edi)\n" + " mov %%edx, 12(%%edi)\n" + " pop %%edi\n" + " pop %%edx\n" + " pop %%ecx\n" + " pop %%ebx\n" + : + :"m"(regs) + :"memory", "eax" + ); +# endif // __x86_64__ +#else +# ifdef _MSC_VER + __asm { + push ebx + push ecx + push edx + push edi + mov edi, regs + + mov eax, [edi] + mov ebx, [edi+4] + mov ecx, [edi+8] + mov edx, [edi+12] + + cpuid + + mov [edi], eax + mov [edi+4], ebx + mov [edi+8], ecx + mov [edi+12], edx + + pop edi + pop edx + pop ecx + pop ebx + } +# else +# error "Unsupported compiler" +# endif // _MSC_VER +#endif + +} + +void cpu_rdtsc(uint64_t* result) +{ + uint32_t low_part, hi_part; +#ifdef __GNUC__ + __asm __volatile ( + " rdtsc\n" + " mov %%eax, %0\n" + " mov %%edx, %1\n" + :"=m"(low_part), "=m"(hi_part)::"memory", "eax", "edx" + ); +#else +# ifdef _MSC_VER + __asm { + rdtsc + mov low_part, eax + mov hi_part, edx + }; +# else +# error "Unsupported compiler" +# endif // _MSC_VER +#endif // __GNUC__ + *result = (uint64_t)low_part + (((uint64_t) hi_part) << 32); +} diff --git a/libcpuid/asm-bits.h b/libcpuid/asm-bits.h new file mode 100644 index 0000000..f286e49 --- /dev/null +++ b/libcpuid/asm-bits.h @@ -0,0 +1,33 @@ +/* + * Copyright 2008 Veselin Georgiev, + * anrieffNOSPAM @ mgail_DOT.com (convert to gmail) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __ASM_BITS_H__ +#define __ASM_BITS_H__ +#include "libcpuid.h" + +int cpuid_exists_by_eflags(void); +void exec_cpiud(uint32_t *regs); + +#endif // __ASM_BITS_H__ diff --git a/libcpuid/cpuid_main.c b/libcpuid/cpuid_main.c index 1a9502b..5c61583 100644 --- a/libcpuid/cpuid_main.c +++ b/libcpuid/cpuid_main.c @@ -33,6 +33,8 @@ #include #include +#define COUNT_OF(array) (sizeof(array) / sizeof(array[0])) + /* Implementation: */ static int _libcpiud_errno = ERR_OK; @@ -50,17 +52,19 @@ static int set_error(cpuid_error_t err) return (int) err; } -static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data) -{ - return ERR_OK; -} - -static void initialize_defaults(struct cpu_raw_data_t* raw) +static void raw_data_t_constructor(struct cpu_raw_data_t* raw) { memset(raw, 0, sizeof(struct cpu_raw_data_t)); } -static int parse_token(const char* expected_token, const char *token, +static void cpu_id_t_constructor(struct cpu_id_t* id) +{ + memset(id, 0, sizeof(struct cpu_id_t)); + id->l1_data_cache = id->l1_instruction_cache = id->l2_cache = id->l3_cache = -1; + id->l1_assoc = id->l2_assoc = id->l3_assoc = -1; +} + +static int parse_token(const char* expected_token, const char *token, const char *value, uint32_t array[][4], int limit, int *recognized) { char format[32]; @@ -83,6 +87,127 @@ static int parse_token(const char* expected_token, const char *token, return 0; } +struct feature_map_t { + unsigned bit; + cpu_feature_t feature; +}; + +static void match_features(const struct feature_map_t* matchtable, int count, uint32_t reg, struct cpu_id_t* data) +{ + int i; + for (i = 0; i < count; i++) + if (reg & (1 << matchtable[i].bit)) + data->flags[matchtable[i].feature] = 1; +} + +static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* data) +{ + const struct feature_map_t matchtable_edx1[] = { + { 0, CPU_FEATURE_FPU }, + { 1, CPU_FEATURE_VME }, + { 2, CPU_FEATURE_DEBUG }, + { 3, CPU_FEATURE_PSE }, + { 4, CPU_FEATURE_TSC }, + { 5, CPU_FEATURE_MSR }, + { 6, CPU_FEATURE_PAE }, + { 7, CPU_FEATURE_MCE }, + { 8, CPU_FEATURE_CX8 }, + { 9, CPU_FEATURE_APIC }, + { 12, CPU_FEATURE_MTRR }, + { 13, CPU_FEATURE_PGE }, + { 14, CPU_FEATURE_MCA }, + { 15, CPU_FEATURE_CMOV }, + { 16, CPU_FEATURE_PAT }, + { 17, CPU_FEATURE_PSE36 }, + { 19, CPU_FEATURE_CLFLUSH }, + { 23, CPU_FEATURE_MMX }, + { 24, CPU_FEATURE_FXSR }, + { 25, CPU_FEATURE_SSE }, + { 26, CPU_FEATURE_SSE2 }, + { 28, CPU_FEATURE_HT }, + }; + const struct feature_map_t matchtable_ecx1[] = { + { 0, CPU_FEATURE_SSE3 }, + { 3, CPU_FEATURE_MON }, + { 9, CPU_FEATURE_SSSE3 }, + { 13, CPU_FEATURE_CX16 }, + { 19, CPU_FEATURE_SSE41 }, + }; + const struct feature_map_t matchtable_edx81[] = { + { 29, CPU_FEATURE_LM }, + }; + const struct feature_map_t matchtable_ecx81[] = { + { 0, CPU_FEATURE_LAHFSAHF }, + }; + if (raw->basic_cpuid[0][0] >= 1) { + match_features(matchtable_edx1, COUNT_OF(matchtable_edx1), raw->basic_cpuid[1][3], data); + match_features(matchtable_ecx1, COUNT_OF(matchtable_ecx1), raw->basic_cpuid[1][2], data); + } + if (raw->ext_cpuid[0][0] >= 1) { + match_features(matchtable_edx81, COUNT_OF(matchtable_edx81), raw->ext_cpuid[1][3], data); + match_features(matchtable_ecx81, COUNT_OF(matchtable_ecx81), raw->ext_cpuid[1][2], data); + } +} + +static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data) +{ + int i, j; + + memcpy(data->vendor_str + 0, &raw->basic_cpuid[0][1], 4); + memcpy(data->vendor_str + 4, &raw->basic_cpuid[0][3], 4); + memcpy(data->vendor_str + 8, &raw->basic_cpuid[0][2], 4); + data->vendor_str[12] = 0; + /* Determine vendor: */ + const struct { cpu_vendor_t vendor; char match[16]; } + matchtable[NUM_VENDORS] = { + /* source: http://www.sandpile.org/ia32/cpuid.htm */ + { INTEL , "GenuineIntel" }, + { AMD , "AuthenticAMD" }, + { CYRIX , "CyrixInstead" }, + { NEXGEN , "NexGenDriven" }, + { TRANSMETA , "GenuineTMx86" }, + { UMC , "UMC UMC UMC " }, + { CENTAUR , "CentaurHauls" }, + { RISE , "RiseRiseRise" }, + { SIS , "SiS SiS SiS " }, + { NSC , "Geode by NSC" }, + }; + data->vendor = UNKNOWN; + for (i = 0; i < NUM_VENDORS; i++) + if (!strcmp(data->vendor_str, matchtable[i].match)) { + data->vendor = matchtable[i].vendor; + break; + } + if (data->vendor == UNKNOWN) + return set_error(ERR_CPU_UNKN); + int basic = raw->basic_cpuid[0][0]; + if (basic >= 1) { + data->family = (raw->basic_cpuid[1][0] >> 8) & 0xf; + data->model = (raw->basic_cpuid[1][0] >> 4) & 0xf; + data->stepping = raw->basic_cpuid[1][0] & 0xf; + data->ext_model = (raw->basic_cpuid[1][0] >> 16) & 0xf; + data->ext_family = (raw->basic_cpuid[1][0] >> 20) & 0xff; + } + int ext = raw->ext_cpuid[0][0] - 0x8000000; + + /* obtain the brand string, if present: */ + char brandstr[64] = {0}; + if (ext >= 4) { + for (i = 0; i < 3; i++) + for (j = 0; j < 4; j++) + memcpy(brandstr + i * 16 + j * 4, + &raw->ext_cpuid[2 + i][j], 4); + brandstr[48] = 0; + i = 0; + while (brandstr[i] == ' ') i++; + strncpy(data->brand_str, brandstr + i, sizeof(data->brand_str)); + data->brand_str[48] = 0; + } + load_features_common(raw, data); + return set_error(ERR_OK); +} + + /* Interface: */ int cpuid_present(void) @@ -110,7 +235,7 @@ int cpuid_get_raw_data(struct cpu_raw_data_t* data) for (i = 0; i < 32; i++) cpu_exec_cpuid(i, data->basic_cpuid[i]); for (i = 0; i < 32; i++) - cpu_exec_cpuid(0x8000000 + i, data->ext_cpuid[i]); + cpu_exec_cpuid(0x80000000 + i, data->ext_cpuid[i]); for (i = 0; i < 4; i++) { memset(data->intel_fn4[i], 0, sizeof(data->intel_fn4[i])); data->intel_fn4[i][0] = 4; @@ -128,17 +253,17 @@ int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename) f = fopen(filename, "wt"); if (!f) return set_error(ERR_OPEN); - fprintf(f, "version = %s\n", VERSION); + fprintf(f, "version=%s\n", VERSION); for (i = 0; i < MAX_CPUID_LEVEL; i++) - fprintf(f, "basic_cpuid[%d] = %08x %08x %08x %08x", i, + fprintf(f, "basic_cpuid[%d]=%08x %08x %08x %08x\n", i, data->basic_cpuid[i][0], data->basic_cpuid[i][1], data->basic_cpuid[i][2], data->basic_cpuid[i][3]); for (i = 0; i < MAX_EXT_CPUID_LEVEL; i++) - fprintf(f, "ext_cpuid[%d] = %08x %08x %08x %08x", i, + fprintf(f, "ext_cpuid[%d]=%08x %08x %08x %08x\n", i, data->ext_cpuid[i][0], data->ext_cpuid[i][1], data->ext_cpuid[i][2], data->ext_cpuid[i][3]); for (i = 0; i < MAX_INTELFN4_LEVEL; i++) - fprintf(f, "intel_fn4[%d] = %08x %08x %08x %08x", i, + fprintf(f, "intel_fn4[%d]=%08x %08x %08x %08x\n", i, data->intel_fn4[i][0], data->intel_fn4[i][1], data->intel_fn4[i][2], data->intel_fn4[i][3]); @@ -158,7 +283,7 @@ int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename int recognized; FILE *f; - initialize_defaults(data); + raw_data_t_constructor(data); f = fopen(filename, "rt"); if (!f) return set_error(ERR_OPEN); @@ -169,13 +294,13 @@ int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename if (line[len - 1] == '\n') line[--len] = '\0'; for (i = 0; i < len && line[i] != '='; i++) - if (i >= len && i < 2 && len - i - 2 <= 0) { + if (i >= len && i < 1 && len - i - 1 <= 0) { fclose(f); return set_error(ERR_BADFMT); } - strncpy(token, line, i - 1); - token[i - 1] = '\0'; - value = &line[i + 2]; + strncpy(token, line, i); + token[i] = '\0'; + value = &line[i + 1]; // try to recognize the line recognized = 0; if (!strcmp(token, "version")) { @@ -206,6 +331,12 @@ int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data) { int r; + struct cpu_raw_data_t myraw; + if (!raw) { + cpuid_get_raw_data(&myraw); + raw = &myraw; + } + cpu_id_t_constructor(data); if ((r = cpuid_basic_identify(raw, data)) < 0) return set_error(r); switch (data->vendor) { @@ -223,12 +354,102 @@ int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data) const char* cpu_feature_str(cpu_feature_t feature) { - return ""; // FIXME + const struct { cpu_feature_t feature; const char* name; } + matchtable[] = { + { CPU_FEATURE_FPU, "fpu" }, + { CPU_FEATURE_VME, "vme" }, + { CPU_FEATURE_DEBUG, "debug" }, + { CPU_FEATURE_PSE, "pse" }, + { CPU_FEATURE_TSC, "tsc" }, + { CPU_FEATURE_MSR, "msr" }, + { CPU_FEATURE_PAE, "pae" }, + { CPU_FEATURE_MCE, "mce" }, + { CPU_FEATURE_CX8, "cx8" }, + { CPU_FEATURE_APIC, "apic" }, + { CPU_FEATURE_MTRR, "mtrr" }, + { CPU_FEATURE_PGE, "pge" }, + { CPU_FEATURE_MCA, "mca" }, + { CPU_FEATURE_CMOV, "cmov" }, + { CPU_FEATURE_PAT, "pat" }, + { CPU_FEATURE_PSE36, "pse36" }, + { CPU_FEATURE_PSN, "psn" }, + { CPU_FEATURE_CLFLUSH, "clflush" }, + { CPU_FEATURE_DTS, "dts" }, + { CPU_FEATURE_ACPI, "acpi" }, + { CPU_FEATURE_MMX, "mmx" }, + { CPU_FEATURE_FXSR, "fxsr" }, + { CPU_FEATURE_SSE, "sse" }, + { CPU_FEATURE_SSE2, "sse2" }, + { CPU_FEATURE_SS, "ss" }, + { CPU_FEATURE_HT, "ht" }, + { CPU_FEATURE_TM, "tm" }, + { CPU_FEATURE_IA64, "ia64" }, + { CPU_FEATURE_PBE, "pbe" }, + { CPU_FEATURE_SSE3, "sse3" }, + { CPU_FEATURE_PCLMUL, "pclmul" }, + { CPU_FEATURE_DTS64, "dts64" }, + { CPU_FEATURE_MON, "mon" }, + { CPU_FEATURE_DSCPL, "dscpl" }, + { CPU_FEATURE_VMX, "vmx" }, + { CPU_FEATURE_SMX, "smx" }, + { CPU_FEATURE_EST, "est" }, + { CPU_FEATURE_TM2, "tm2" }, + { CPU_FEATURE_SSSE3, "ssse3" }, + { CPU_FEATURE_CID, "cid" }, + { CPU_FEATURE_CX16, "cx16" }, + { CPU_FEATURE_ETPRD, "etprd" }, + { CPU_FEATURE_PDCM, "pdcm" }, + { CPU_FEATURE_DCA, "dca" }, + { CPU_FEATURE_SSE41, "sse41" }, + { CPU_FEATURE_SSE42, "sse42" }, + { CPU_FEATURE_MOVBE, "movbe" }, + { CPU_FEATURE_POPCNT, "popcnt" }, + { CPU_FEATURE_AES, "aes" }, + { CPU_FEATURE_XSAVE, "xsave" }, + { CPU_FEATURE_OSXSAVE, "osxsave" }, + { CPU_FEATURE_AVX, "avx" }, + { CPU_FEATURE_MMXEXT, "mmxext" }, + { CPU_FEATURE_3DNOW, "3dnow" }, + { CPU_FEATURE_3DNOWEXT, "3dnowext" }, + { CPU_FEATURE_NX, "nx" }, + { CPU_FEATURE_RDTSCP, "rdtscp" }, + { CPU_FEATURE_LM, "lm" }, + { CPU_FEATURE_LAHFSAHF, "lahfsahf" }, + { CPU_FEATURE_SVM, "svm" }, + { CPU_FEATURE_LZCNT, "lzcnt" }, + { CPU_FEATURE_3DNOWPREFETCH, "3dnowprefetch" }, + { CPU_FEATURE_OSVW, "osvw" }, + { CPU_FEATURE_IBS, "ibs" }, + { CPU_FEATURE_SSE51, "sse51" }, + { CPU_FEATURE_SKINIT, "skinit" }, + { CPU_FEATURE_WDT, "wdt" }, + { CPU_FEATURE_CONST_TSC, "const_tsc" }, + }; + unsigned i; + for (i = 0; i < COUNT_OF(matchtable); i++) + if (matchtable[i].feature == feature) + return matchtable[i].name; + return ""; } const char* cpuid_error(void) { - return ""; // FIXME + const struct { cpuid_error_t error; const char *description; } + matchtable[] = { + { ERR_OK , "No error"}, + { ERR_NO_CPUID , "CPUID instruction is not supported"}, + { ERR_NO_RDTSC , "RDTSC instruction is not supported"}, + { ERR_NO_MEM , "Memory allocation failed"}, + { ERR_OPEN , "File open operation failed"}, + { ERR_BADFMT , "Bad file format"}, + { ERR_NOT_IMP , "Not implemented"}, + { ERR_CPU_UNKN , "Unsupported processor"}, + }; + unsigned i; + for (i = 0; i < COUNT_OF(matchtable); i++) + if (_libcpiud_errno == matchtable[i].error) + return matchtable[i].description; + return "Unknown error"; } @@ -236,3 +457,9 @@ const char* cpuid_lib_version(void) { return VERSION; } + +void set_warn_function(void (*warn_fun) (const char* msg)) +{ + _warn = warn_fun; +} + diff --git a/libcpuid/libcpuid.h b/libcpuid/libcpuid.h index 4432748..e4fa456 100644 --- a/libcpuid/libcpuid.h +++ b/libcpuid/libcpuid.h @@ -55,8 +55,7 @@ enum _cpu_vendor_t { INTEL = 0, AMD, CYRIX, - VIA, - NEXTGEN, + NEXGEN, TRANSMETA, UMC, CENTAUR, @@ -67,6 +66,7 @@ enum _cpu_vendor_t { NUM_VENDORS, UNKNOWN = -1, }; +#define NUM_VENDORS NUM_VENDORS typedef enum _cpu_vendor_t cpu_vendor_t; /** @@ -217,7 +217,6 @@ enum _cpu_feature_t { CPU_FEATURE_MCE, /*!< Machine check exception */ CPU_FEATURE_CX8, /*!< CMPXCHG8B instruction supported */ CPU_FEATURE_APIC, /*!< APIC support */ - CPU_FEATURE_SEP, /*!< SYSCALL / SYSEXIT supported */ CPU_FEATURE_MTRR, /*!< Memory type range registers */ CPU_FEATURE_PGE, /*!< Page global enable */ CPU_FEATURE_MCA, /*!< Machine check architecture */ @@ -276,6 +275,9 @@ enum _cpu_feature_t { CPU_FEATURE_SSE51, /*!< SSE 5.1 instructions supported */ CPU_FEATURE_SKINIT, /*!< SKINIT / STGI supported */ CPU_FEATURE_WDT, /*!< Watchdog timer support */ + CPU_FEATURE_CONST_TSC, /*!< Constant TSC */ + // termination: + CPU_FEATURE_END, }; typedef enum _cpu_feature_t cpu_feature_t; @@ -289,7 +291,8 @@ enum _cpuid_error_t { ERR_NO_MEM = -3, /*!< "Memory allocation failed" */ ERR_OPEN = -4, /*!< "File open operation failed" */ ERR_BADFMT = -5, /*!< "Bad file format" */ - ERR_NOT_IMP = -6, /*!< "Not implemented" */ + ERR_NOT_IMP = -6, /*!< "Not implemented" */ + ERR_CPU_UNKN = -7, /*!< "Unsupported processor" */ }; typedef enum _cpuid_error_t cpuid_error_t; @@ -336,7 +339,7 @@ int cpu_clock(void); const char* cpuid_lib_version(void); -void set_warn_function(void (*fun) (const char * msg)); +void set_warn_function(void (*warn_fun) (const char* msg)); #ifdef __cplusplus }; // extern "C" diff --git a/libcpuid/recog_amd.c b/libcpuid/recog_amd.c index c9b4b66..ce07a2a 100644 --- a/libcpuid/recog_amd.c +++ b/libcpuid/recog_amd.c @@ -23,3 +23,10 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "libcpuid.h" +#include "recog_amd.h" + +int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data) +{ + return 0; +} diff --git a/libcpuid/recog_intel.c b/libcpuid/recog_intel.c index c9b4b66..fec6613 100644 --- a/libcpuid/recog_intel.c +++ b/libcpuid/recog_intel.c @@ -23,3 +23,10 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "libcpuid.h" +#include "recog_intel.h" + +int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data) +{ + return 0; +}