CPU detection macro now usable even if you don't have /proc/cpuinfo... thank Nach for the hard work.

This commit is contained in:
grinvader
2005-10-25 20:10:27 +00:00
parent e076248109
commit 11c92d0803

View File

@@ -244,7 +244,8 @@ dnl When copying, include from Begin to End custom cpu detection autoconf macro,
dnl including those tags, so others can easily copy it too. dnl including those tags, so others can easily copy it too.
dnl dnl
dnl AM_CPU_DETECT([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) dnl AM_CPU_DETECT([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
dnl Tests and reads the first entry in /proc/cpuinfo, outputs CPU_INFO dnl Reads the first entry in /proc/cpuinfo or uses cpuid to grab what is needed,
dnl outputs CPU_INFO
AC_DEFUN([AM_CPU_DETECT], AC_DEFUN([AM_CPU_DETECT],
[ [
CPU_INFO="" CPU_INFO=""
@@ -257,13 +258,58 @@ if test x$enable_cpucheck != xno; then
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h>
int main() #define cpuid(in, a, b, c, d) asm volatile("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in));
char *x86_flags[] =
{ "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
"cx8", "apic", 0, "sep", "mtrr", "pge", "mca", "cmov",
"pat", "pse36", "pn", "clflush", 0, "dts", "acpi", "mmx",
"fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, "syscall", 0, 0, 0, 0,
0, 0, 0, "mp", "nx", 0, "mmxext", 0,
0, "fxsr_opt", 0, 0, 0, "lm", "3dnowext", "3dnow",
"recovery", "longrun", 0, "lrti", 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
"pni", 0, 0, "monitor", "ds_cpl", 0, 0, "est",
"tm2", 0, "cid", 0, 0, 0, "xtpr", 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, "rng", "rng_en", 0, 0, "ace", "ace_en",
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
"lahf_lm", "cmp_legacy", 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
void add_flags(char *flags, unsigned int reg, unsigned int offset)
{ {
char line[256], key[40], arg[216], *cpu = 0; unsigned int i;
const char *pattern = " %39[^:]: %215[ -~]"; // for sscanf for (i = 0; i < 32; i++)
{
if ((reg & (1 << i)) && x86_flags[i+offset])
{
strcat(flags, x86_flags[i+offset]);
strcat(flags, " ");
}
}
}
char model_name[216], flags[216], cpu_family[216], vendor_id[216], model[216]; int main(int argc, char *argv[])
{
char *cpu = 0, model_name[216], flags[216];
char cpu_family[216], vendor_id[216], model[216];
FILE *fp; FILE *fp;
@@ -275,6 +321,9 @@ if test x$enable_cpucheck != xno; then
if ((fp = fopen("/proc/cpuinfo", "r"))) if ((fp = fopen("/proc/cpuinfo", "r")))
{ {
char line[256], key[40], arg[216];
const char *pattern = " %39[^:]: %215[ -~]"; // for sscanf
while (fgets(line, sizeof(line), fp) && sscanf(line, pattern, key, arg) == 2) while (fgets(line, sizeof(line), fp) && sscanf(line, pattern, key, arg) == 2)
{ {
if (!strncmp(key, "model name", strlen("model name")) && !*model_name) if (!strncmp(key, "model name", strlen("model name")) && !*model_name)
@@ -289,6 +338,62 @@ if test x$enable_cpucheck != xno; then
{ strcpy(model, arg); } { strcpy(model, arg); }
} }
fclose(fp); fclose(fp);
}
else
{
unsigned int maxei, eax, ebx, ecx, edx, unused, i;
cpuid(0, unused, ebx, ecx, edx);
strncat(vendor_id, (char *)&ebx, 4);
strncat(vendor_id, (char *)&edx, 4);
strncat(vendor_id, (char *)&ecx, 4);
cpuid(1, eax, ebx, ecx, edx);
sprintf(model, "%u", (eax >> 4) & 0xf);
sprintf(cpu_family, "%u", (eax >> 8) & 0xf);
add_flags(flags, edx, 0);
add_flags(flags, ecx, 96);
cpuid(0x80000000, maxei, unused, unused, unused);
if(maxei >= 0x80000001)
{
cpuid(0x80000001, unused, unused, ecx, edx);
add_flags(flags, edx, 32);
add_flags(flags, ecx, 160);
}
//Transmeta
cpuid(0x80860000, eax, unused, unused, unused);
if (((eax & 0xffff0000) == 0x80860000) && (eax > 0x80860001))
{
cpuid(0x80860001, unused, unused, unused, edx);
add_flags(flags, edx, 64);
}
//Centaur
cpuid(0xC0000000, eax, unused, unused, unused);
if (eax >= 0xC0000001)
{
cpuid(0xC0000001, unused, unused, unused, edx);
add_flags(flags, edx, 128);
}
if(maxei >= 0x80000002)
{
for (i = 0x80000002; i <= 0x80000004; i++)
{
cpuid(i, eax, ebx, ecx, edx);
strncat(model_name, (char *)&eax, 4);
strncat(model_name, (char *)&ebx, 4);
strncat(model_name, (char *)&ecx, 4);
strncat(model_name, (char *)&edx, 4);
}
while (isspace(*model_name))
{ memmove(model_name, model_name+1, strlen(model_name)); }
}
}
if (!strcmp(vendor_id, "AuthenticAMD") || strstr(model_name, "AMD")) if (!strcmp(vendor_id, "AuthenticAMD") || strstr(model_name, "AMD"))
{ {
@@ -306,10 +411,9 @@ if test x$enable_cpucheck != xno; then
if (strstr(flags, "sse2") && strstr(flags, "lm")) //Need two checks to protect Semprons if (strstr(flags, "sse2") && strstr(flags, "lm")) //Need two checks to protect Semprons
{ {
if (strstr(model_name, "Opteron")) { cpu = "opteron"; } if (strstr(model_name, "Opteron")) { cpu = "opteron"; }
else { cpu = (strstr(model_name, "Athlon(tm) 64")) ? cpu = "athlon64" : "k8"; } else { cpu = (strstr(model_name, "Athlon(tm) 64")) ? "athlon64" : "k8"; }
} } //Athlon64, also athlon-fx
#endif #endif
if (!cpu) if (!cpu)
{ {
if (strstr(model_name, "Athlon(tm) 4")) { cpu = "athlon-4"; } if (strstr(model_name, "Athlon(tm) 4")) { cpu = "athlon-4"; }
@@ -420,12 +524,12 @@ if test x$enable_cpucheck != xno; then
if ((fp = fopen("conf.cpuchk", "a"))) if ((fp = fopen("conf.cpuchk", "a")))
{ {
fprintf(fp, "%s", (cpu) ? cpu : ""); fprintf(fp, "%s", cpu);
fclose(fp); fclose(fp);
return 0; return(0);
} }
}
return 1; return(1);
} }
],cpu_found=yes) ],cpu_found=yes)