On 2009-03-12 Piotr Roszatycki <dex...@debian.org> wrote: > 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? There is a second, slightly diffeent instance of the same code in boot/cpucheck.c. Does this one also prodecue the Illegal instruction error? cu and- doesn't speak ASM -reas -- `What a good friend you are to him, Dr. Maturin. His other friends are so grateful to you.' `I sew his ears on from time to time, sure'
#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; static int has_eflag(u32 mask) { u32 f0, f1; asm("pushfl ; " "pushfl ; " "popl %0 ; " "movl %0,%1 ; " "xorl %2,%1 ; " "pushl %1 ; " "popfl ; " "pushfl ; " "popl %1 ; " "popfl" : "=&r" (f0), "=&r" (f1) : "ri" (mask)); return !!((f0^f1) & mask); } /* Probe for the CPUID instruction */ static int __cpuinit have_cpuid_p(void) { return has_eflag(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); printf("%d %d %d\n", id0 , id1 , id2); }