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:piotr.roszaty...@gmail.com `. `' mailto:dex...@debian.org `-
#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); }