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);
}

Reply via email to