|
Packit |
577717 |
/* $Id: x86_cpuinfo.c,v 1.1 2004/05/22 20:59:58 mikpe Exp $
|
|
Packit |
577717 |
* Copyright (C) 2004 Mikael Pettersson
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
#include "x86_cpuinfo.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
struct cpuid { /* The field order must not be changed. */
|
|
Packit |
577717 |
unsigned int eax, ebx, edx, ecx;
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef __x86_64__
|
|
Packit |
577717 |
static void get_cpuid(unsigned int op, struct cpuid *cpuid)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
__asm__("cpuid"
|
|
Packit |
577717 |
: "=a"(cpuid->eax),
|
|
Packit |
577717 |
"=b"(cpuid->ebx),
|
|
Packit |
577717 |
"=c"(cpuid->ecx),
|
|
Packit |
577717 |
"=d"(cpuid->edx)
|
|
Packit |
577717 |
: "0"(op));
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#else
|
|
Packit |
577717 |
/* Many versions of gcc fail on x86 if an asm() clobbers %ebx when
|
|
Packit |
577717 |
-fPIC is specified. So we do the cpuid in hand-written assembly code. */
|
|
Packit |
577717 |
extern void get_cpuid(unsigned int, struct cpuid*); /* x86_cpuid.S */
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static const struct {
|
|
Packit |
577717 |
const char vendor_string[12];
|
|
Packit |
577717 |
unsigned int vendor_code;
|
|
Packit |
577717 |
} vendors[] = {
|
|
Packit |
577717 |
{ "GenuineIntel", X86_VENDOR_INTEL },
|
|
Packit |
577717 |
{ "AuthenticAMD", X86_VENDOR_AMD },
|
|
Packit |
577717 |
{ "CyrixInstead", X86_VENDOR_CYRIX },
|
|
Packit |
577717 |
{ "CentaurHauls", X86_VENDOR_CENTAUR },
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static unsigned int check_vendor(const char cpuid_vendor[12])
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i = 0; i < sizeof vendors / sizeof(vendors[0]); ++i)
|
|
Packit |
577717 |
if (memcmp(cpuid_vendor, vendors[i].vendor_string, 12) == 0)
|
|
Packit |
577717 |
return vendors[i].vendor_code;
|
|
Packit |
577717 |
return X86_VENDOR_UNKNOWN;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
void identify_cpu(struct cpuinfo *cpuinfo)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
struct cpuid cpuid[2];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Skip EFLAGS.ID check. We will only get here if
|
|
Packit |
577717 |
the kernel has created a perfctr state for us,
|
|
Packit |
577717 |
and that will never happen on pre-CPUID CPUs. */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
get_cpuid(0, &cpuid[0]);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Quirk for Intel A-step Pentium. */
|
|
Packit |
577717 |
if ((cpuid[0].eax & 0xFFFFFF00) == 0x0500) {
|
|
Packit |
577717 |
cpuinfo->vendor = X86_VENDOR_INTEL;
|
|
Packit |
577717 |
cpuinfo->signature = cpuid[0].eax;
|
|
Packit |
577717 |
cpuinfo->features = 0x1BF; /* CX8,MCE,MSR,TSC,PSE,DE,VME,FPU */
|
|
Packit |
577717 |
return;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
cpuinfo->vendor = check_vendor((const char*)&cpuid[0].ebx);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (cpuid[0].eax == 0) {
|
|
Packit |
577717 |
cpuinfo->signature = 0;
|
|
Packit |
577717 |
cpuinfo->features = 0;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
get_cpuid(1, &cpuid[1]);
|
|
Packit |
577717 |
cpuinfo->signature = cpuid[1].eax;
|
|
Packit |
577717 |
cpuinfo->features = cpuid[1].edx;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|