Home | History | Annotate | Download | only in core
      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