mirror of
https://github.com/anrieff/libcpuid
synced 2024-11-20 23:01:51 +00:00
Initial detection working
git-svn-id: https://svn.code.sf.net/p/libcpuid/code/HEAD/libcpuid@5 3b4be424-7ac5-41d7-8526-f4ddcb85d872
This commit is contained in:
parent
a8e3645176
commit
2d453e612c
10 changed files with 547 additions and 25 deletions
|
@ -1,4 +1,4 @@
|
|||
SUBDIRS = libcpuid
|
||||
SUBDIRS = libcpuid cpuid_tool
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ AC_CONFIG_FILES([
|
|||
Makefile
|
||||
libcpuid.pc
|
||||
libcpuid/Makefile
|
||||
cpuid_tool/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
||||
|
|
8
cpuid_tool/Makefile.am
Normal file
8
cpuid_tool/Makefile.am
Normal file
|
@ -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
|
44
cpuid_tool/cpuid_tool.c
Normal file
44
cpuid_tool/cpuid_tool.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include <stdio.h>
|
||||
#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;
|
||||
}
|
192
libcpuid/asm-bits.c
Normal file
192
libcpuid/asm-bits.c
Normal file
|
@ -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);
|
||||
}
|
33
libcpuid/asm-bits.h
Normal file
33
libcpuid/asm-bits.h
Normal file
|
@ -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__
|
|
@ -33,6 +33,8 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue