I read the source for kernel 2.6.24 and found that it uses similar
technic for CPUID detection. I've copied to one simple test program
(attached) and I worried why it doesn't work on Vortex correcty:
$ ./cpuid
This CPU has CPUID opcode
Illegal instruction
> Any ideas? Would anyone be so kind and compare it to the Linux code?
--
.''`. Piotr Roszatycki
: :' : mailto:[email protected]
`. `' mailto:[email protected]
`-
#include <stdio.h>
#define __cold __attribute__((__cold__))
#define __section(S) __attribute__ ((__section__(#S)))
#define __cpuinit __section(.cpuinit.text) __cold
#define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */
typedef unsigned int u32;
/* Standard macro to see if a specific flag is changeable */
static inline int flag_is_changeable_p(u32 flag)
{
u32 f1, f2;
asm("pushfl\n\t"
"pushfl\n\t"
"popl %0\n\t"
"movl %0,%1\n\t"
"xorl %2,%0\n\t"
"pushl %0\n\t"
"popfl\n\t"
"pushfl\n\t"
"popl %0\n\t"
"popfl\n\t"
: "=&r" (f1), "=&r" (f2)
: "ir" (flag));
return ((f1^f2) & flag) != 0;
}
/* Probe for the CPUID instruction */
static int __cpuinit have_cpuid_p(void)
{
return flag_is_changeable_p(X86_EFLAGS_ID);
}
/* Generix CPUID */
static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
{
__asm__("cpuid"
: "=a" (*eax),
"=b" (*ebx),
"=c" (*ecx),
"=d" (*edx)
: "0" (op), "c"(0));
}
int main() {
int id0, id1, id2, id3;
printf("This CPU %s CPUID opcode\n", (have_cpuid_p ? "has" : "has not"));
/* Get vendor name and crash on Vortex86SX */
cpuid(0x00000000, &id0, (int *)&id1, (int *)&id2, (int *)&id3);
}