1 #include <stdint.h> 2 #include <string.h> 3 #include <cpu.h> 4 5 /** @file 6 * 7 * CPU identification 8 * 9 */ 10 11 /** 12 * Test to see if CPU flag is changeable 13 * 14 * @v flag Flag to test 15 * @ret can_change Flag is changeable 16 */ 17 static inline int flag_is_changeable ( unsigned int flag ) { 18 uint32_t f1, f2; 19 20 __asm__ ( "pushfl\n\t" 21 "pushfl\n\t" 22 "popl %0\n\t" 23 "movl %0,%1\n\t" 24 "xorl %2,%0\n\t" 25 "pushl %0\n\t" 26 "popfl\n\t" 27 "pushfl\n\t" 28 "popl %0\n\t" 29 "popfl\n\t" 30 : "=&r" ( f1 ), "=&r" ( f2 ) 31 : "ir" ( flag ) ); 32 33 return ( ( ( f1 ^ f2 ) & flag ) != 0 ); 34 } 35 36 /** 37 * Get CPU information 38 * 39 * @v cpu CPU information structure to fill in 40 */ 41 void get_cpuinfo ( struct cpuinfo_x86 *cpu ) { 42 unsigned int cpuid_level; 43 unsigned int cpuid_extlevel; 44 unsigned int discard_1, discard_2, discard_3; 45 46 memset ( cpu, 0, sizeof ( *cpu ) ); 47 48 /* Check for CPUID instruction */ 49 if ( ! flag_is_changeable ( X86_EFLAGS_ID ) ) { 50 DBG ( "CPUID not supported\n" ); 51 return; 52 } 53 54 /* Get features, if present */ 55 cpuid ( 0x00000000, &cpuid_level, &discard_1, 56 &discard_2, &discard_3 ); 57 if ( cpuid_level >= 0x00000001 ) { 58 cpuid ( 0x00000001, &discard_1, &discard_2, 59 &discard_3, &cpu->features ); 60 } else { 61 DBG ( "CPUID cannot return capabilities\n" ); 62 } 63 64 /* Get 64-bit features, if present */ 65 cpuid ( 0x80000000, &cpuid_extlevel, &discard_1, 66 &discard_2, &discard_3 ); 67 if ( ( cpuid_extlevel & 0xffff0000 ) == 0x80000000 ) { 68 if ( cpuid_extlevel >= 0x80000001 ) { 69 cpuid ( 0x80000001, &discard_1, &discard_2, 70 &discard_3, &cpu->amd_features ); 71 } 72 } 73 } 74