x86_cpuid_info.c File Reference

Include dependency graph for x86_cpuid_info.c:

Go to the source code of this file.

Data Structures

struct  _intel_cache_info

Defines

#define TLB_SIZES   3

Functions

static void init_mem_hierarchy (PAPI_mh_info_t *mh_info)
static int init_amd (PAPI_mh_info_t *mh_info, int *levels)
static short int _amd_L2_L3_assoc (unsigned short int pattern)
static int init_intel (PAPI_mh_info_t *mh_info, int *levels)
static void cpuid (unsigned int *a, unsigned int *b, unsigned int *c, unsigned int *d)
int _x86_cache_info (PAPI_mh_info_t *mh_info)
static void print_intel_cache_table ()
static void intel_decode_descriptor (struct _intel_cache_info *d, PAPI_mh_level_t *L)
static void cpuid2 (unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx, unsigned int index, unsigned int ecx_in)
static int init_intel_leaf4 (PAPI_mh_info_t *mh_info, int *num_levels)
static int init_intel_leaf2 (PAPI_mh_info_t *mh_info, int *num_levels)
int _x86_detect_hypervisor (char *vendor_name)

Variables

static struct _intel_cache_info intel_cache []

Define Documentation

#define TLB_SIZES   3

Definition at line 360 of file x86_cpuid_info.c.


Function Documentation

static short int _amd_L2_L3_assoc ( unsigned short int  pattern  )  [static]

Definition at line 116 of file x86_cpuid_info.c.

00117 {
00118     /* From "CPUID Specification" #25481 Rev 2.28, April 2008 */
00119     short int assoc[16] =
00120         { 0, 1, 2, -1, 4, -1, 8, -1, 16, -1, 32, 48, 64, 96, 128, SHRT_MAX };
00121     if ( pattern > 0xF )
00122         return -1;
00123     return ( assoc[pattern] );
00124 }

Here is the caller graph for this function:

int _x86_cache_info ( PAPI_mh_info_t mh_info  ) 

Definition at line 51 of file x86_cpuid_info.c.

00052 {
00053     int retval = 0;
00054     union
00055     {
00056         struct
00057         {
00058             unsigned int ax, bx, cx, dx;
00059         } e;
00060         char vendor[20];               /* leave room for terminator bytes */
00061     } reg;
00062 
00063     /* Don't use cpu_type to determine the processor.
00064      * get the information directly from the chip.
00065      */
00066     reg.e.ax = 0;            /* function code 0: vendor string */
00067     /* The vendor string is composed of EBX:EDX:ECX.
00068      * by swapping the register addresses in the call below,
00069      * the string is correctly composed in the char array.
00070      */
00071     cpuid( &reg.e.ax, &reg.e.bx, &reg.e.dx, &reg.e.cx );
00072     reg.vendor[16] = 0;
00073     MEMDBG( "Vendor: %s\n", &reg.vendor[4] );
00074 
00075     init_mem_hierarchy( mh_info );
00076 
00077     if ( !strncmp( "GenuineIntel", &reg.vendor[4], 12 ) ) {
00078             init_intel( mh_info, &mh_info->levels);
00079     } else if ( !strncmp( "AuthenticAMD", &reg.vendor[4], 12 ) ) {
00080       init_amd( mh_info, &mh_info->levels );
00081     } else {
00082         MEMDBG( "Unsupported cpu type; Not Intel or AMD x86\n" );
00083         return PAPI_ENOIMPL;
00084     }
00085 
00086     /* This works only because an empty cache element is initialized to 0 */
00087     MEMDBG( "Detected L1: %d L2: %d  L3: %d\n",
00088             mh_info->level[0].cache[0].size + mh_info->level[0].cache[1].size,
00089             mh_info->level[1].cache[0].size + mh_info->level[1].cache[1].size,
00090             mh_info->level[2].cache[0].size + mh_info->level[2].cache[1].size );
00091     return retval;
00092 }

Here is the call graph for this function:

int _x86_detect_hypervisor ( char *  vendor_name  ) 

Definition at line 1508 of file x86_cpuid_info.c.

01509 {
01510   unsigned int eax, ebx, ecx, edx;
01511   char hyper_vendor_id[13];
01512 
01513   cpuid2(&eax, &ebx, &ecx, &edx,0x1,0);
01514   /* This is the hypervisor bit, ecx bit 31 */
01515   if  (ecx&0x80000000) {
01516     /* There are various values in the 0x4000000X range */
01517     /* It is questionable how standard they are         */
01518     /* For now we just return the name.                 */
01519     cpuid2(&eax, &ebx, &ecx, &edx, 0x40000000,0);
01520     memcpy(hyper_vendor_id + 0, &ebx, 4);
01521     memcpy(hyper_vendor_id + 4, &ecx, 4);
01522     memcpy(hyper_vendor_id + 8, &edx, 4);
01523     hyper_vendor_id[12] = '\0';
01524     strncpy(vendor_name,hyper_vendor_id,PAPI_MAX_STR_LEN);
01525     return 1;
01526   }
01527   else {
01528     strncpy(vendor_name,"none",PAPI_MAX_STR_LEN);
01529   }
01530   return 0;
01531 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void cpuid ( unsigned int *  a,
unsigned int *  b,
unsigned int *  c,
unsigned int *  d 
) [inline, static]

Definition at line 36 of file x86_cpuid_info.c.

00037 {
00038     unsigned int op = *a;
00039     // .byte 0x53 == push ebx. it's universal for 32 and 64 bit
00040     // .byte 0x5b == pop ebx.
00041     // Some gcc's (4.1.2 on Core2) object to pairing push/pop and ebx in 64 bit mode.
00042     // Using the opcode directly avoids this problem.
00043   __asm__ __volatile__( ".byte 0x53\n\tcpuid\n\tmovl %%ebx, %%esi\n\t.byte 0x5b":"=a"( *a ), "=S"( *b ), "=c"( *c ),
00044                           "=d"
00045                           ( *d )
00046   :                   "a"( op ) );
00047 }

Here is the caller graph for this function:

static void cpuid2 ( unsigned int *  eax,
unsigned int *  ebx,
unsigned int *  ecx,
unsigned int *  edx,
unsigned int  index,
unsigned int  ecx_in 
) [inline, static]

Definition at line 1273 of file x86_cpuid_info.c.

01276 {
01277   unsigned int a,b,c,d;
01278   __asm__ __volatile__ (".byte 0x53\n\tcpuid\n\tmovl %%ebx, %%esi\n\t.byte 0x5b"
01279         : "=a" (a), "=S" (b), "=c" (c), "=d" (d) \
01280         : "0" (index), "2"(ecx_in) );
01281   *eax = a; *ebx = b; *ecx = c; *edx = d;
01282 }

Here is the caller graph for this function:

static int init_amd ( PAPI_mh_info_t mh_info,
int *  levels 
) [static]

Definition at line 128 of file x86_cpuid_info.c.

00129 {
00130     union
00131     {
00132         struct
00133         {
00134             unsigned int ax, bx, cx, dx;
00135         } e;
00136         unsigned char byt[16];
00137     } reg;
00138     int i, j, levels = 0;
00139     PAPI_mh_level_t *L = mh_info->level;
00140 
00141     /*
00142      * Layout of CPU information taken from :
00143      * "CPUID Specification" #25481 Rev 2.28, April 2008 for most current info.
00144      */
00145 
00146     MEMDBG( "Initializing AMD memory info\n" );
00147     /* AMD level 1 cache info */
00148     reg.e.ax = 0x80000005;   /* extended function code 5: L1 Cache and TLB Identifiers */
00149     cpuid( &reg.e.ax, &reg.e.bx, &reg.e.cx, &reg.e.dx );
00150 
00151     MEMDBG( "e.ax=%#8.8x e.bx=%#8.8x e.cx=%#8.8x e.dx=%#8.8x\n",
00152             reg.e.ax, reg.e.bx, reg.e.cx, reg.e.dx );
00153     MEMDBG
00154         ( ":\neax: %#x %#x %#x %#x\nebx: %#x %#x %#x %#x\necx: %#x %#x %#x %#x\nedx: %#x %#x %#x %#x\n",
00155           reg.byt[0], reg.byt[1], reg.byt[2], reg.byt[3], reg.byt[4],
00156           reg.byt[5], reg.byt[6], reg.byt[7], reg.byt[8], reg.byt[9],
00157           reg.byt[10], reg.byt[11], reg.byt[12], reg.byt[13], reg.byt[14],
00158           reg.byt[15] );
00159 
00160     /* NOTE: We assume L1 cache and TLB always exists */
00161     /* L1 TLB info */
00162 
00163     /* 4MB memory page information; half the number of entries as 2MB */
00164     L[0].tlb[0].type = PAPI_MH_TYPE_INST;
00165     L[0].tlb[0].num_entries = reg.byt[0] / 2;
00166     L[0].tlb[0].page_size = 4096 << 10;
00167     L[0].tlb[0].associativity = reg.byt[1];
00168 
00169     L[0].tlb[1].type = PAPI_MH_TYPE_DATA;
00170     L[0].tlb[1].num_entries = reg.byt[2] / 2;
00171     L[0].tlb[1].page_size = 4096 << 10;
00172     L[0].tlb[1].associativity = reg.byt[3];
00173 
00174     /* 2MB memory page information */
00175     L[0].tlb[2].type = PAPI_MH_TYPE_INST;
00176     L[0].tlb[2].num_entries = reg.byt[0];
00177     L[0].tlb[2].page_size = 2048 << 10;
00178     L[0].tlb[2].associativity = reg.byt[1];
00179 
00180     L[0].tlb[3].type = PAPI_MH_TYPE_DATA;
00181     L[0].tlb[3].num_entries = reg.byt[2];
00182     L[0].tlb[3].page_size = 2048 << 10;
00183     L[0].tlb[3].associativity = reg.byt[3];
00184 
00185     /* 4k page information */
00186     L[0].tlb[4].type = PAPI_MH_TYPE_INST;
00187     L[0].tlb[4].num_entries = reg.byt[4];
00188     L[0].tlb[4].page_size = 4 << 10;
00189     L[0].tlb[4].associativity = reg.byt[5];
00190 
00191     L[0].tlb[5].type = PAPI_MH_TYPE_DATA;
00192     L[0].tlb[5].num_entries = reg.byt[6];
00193     L[0].tlb[5].page_size = 4 << 10;
00194     L[0].tlb[5].associativity = reg.byt[7];
00195 
00196     for ( i = 0; i < PAPI_MH_MAX_LEVELS; i++ ) {
00197         if ( L[0].tlb[i].associativity == 0xff )
00198             L[0].tlb[i].associativity = SHRT_MAX;
00199     }
00200 
00201     /* L1 D-cache info */
00202     L[0].cache[0].type =
00203         PAPI_MH_TYPE_DATA | PAPI_MH_TYPE_WB | PAPI_MH_TYPE_PSEUDO_LRU;
00204     L[0].cache[0].size = reg.byt[11] << 10;
00205     L[0].cache[0].associativity = reg.byt[10];
00206     L[0].cache[0].line_size = reg.byt[8];
00207     /* Byt[9] is "Lines per tag" */
00208     /* Is that == lines per cache? */
00209     /* L[0].cache[1].num_lines = reg.byt[9]; */
00210     if ( L[0].cache[0].line_size )
00211         L[0].cache[0].num_lines = L[0].cache[0].size / L[0].cache[0].line_size;
00212     MEMDBG( "D-Cache Line Count: %d; Computed: %d\n", reg.byt[9],
00213             L[0].cache[0].num_lines );
00214 
00215     /* L1 I-cache info */
00216     L[0].cache[1].type = PAPI_MH_TYPE_INST;
00217     L[0].cache[1].size = reg.byt[15] << 10;
00218     L[0].cache[1].associativity = reg.byt[14];
00219     L[0].cache[1].line_size = reg.byt[12];
00220     /* Byt[13] is "Lines per tag" */
00221     /* Is that == lines per cache? */
00222     /* L[0].cache[1].num_lines = reg.byt[13]; */
00223     if ( L[0].cache[1].line_size )
00224         L[0].cache[1].num_lines = L[0].cache[1].size / L[0].cache[1].line_size;
00225     MEMDBG( "I-Cache Line Count: %d; Computed: %d\n", reg.byt[13],
00226             L[0].cache[1].num_lines );
00227 
00228     for ( i = 0; i < 2; i++ ) {
00229         if ( L[0].cache[i].associativity == 0xff )
00230             L[0].cache[i].associativity = SHRT_MAX;
00231     }
00232 
00233     /* AMD L2/L3 Cache and L2 TLB info */
00234     /* NOTE: For safety we assume L2 and L3 cache and TLB may not exist */
00235 
00236     reg.e.ax = 0x80000006;   /* extended function code 6: L2/L3 Cache and L2 TLB Identifiers */
00237     cpuid( &reg.e.ax, &reg.e.bx, &reg.e.cx, &reg.e.dx );
00238 
00239     MEMDBG( "e.ax=%#8.8x e.bx=%#8.8x e.cx=%#8.8x e.dx=%#8.8x\n",
00240             reg.e.ax, reg.e.bx, reg.e.cx, reg.e.dx );
00241     MEMDBG
00242         ( ":\neax: %#x %#x %#x %#x\nebx: %#x %#x %#x %#x\necx: %#x %#x %#x %#x\nedx: %#x %#x %#x %#x\n",
00243           reg.byt[0], reg.byt[1], reg.byt[2], reg.byt[3], reg.byt[4],
00244           reg.byt[5], reg.byt[6], reg.byt[7], reg.byt[8], reg.byt[9],
00245           reg.byt[10], reg.byt[11], reg.byt[12], reg.byt[13], reg.byt[14],
00246           reg.byt[15] );
00247 
00248     /* L2 TLB info */
00249 
00250     if ( reg.byt[0] | reg.byt[1] ) {    /* Level 2 ITLB exists */
00251         /* 4MB ITLB page information; half the number of entries as 2MB */
00252         L[1].tlb[0].type = PAPI_MH_TYPE_INST;
00253         L[1].tlb[0].num_entries =
00254             ( ( ( short ) ( reg.byt[1] & 0xF ) << 8 ) + reg.byt[0] ) / 2;
00255         L[1].tlb[0].page_size = 4096 << 10;
00256         L[1].tlb[0].associativity =
00257             _amd_L2_L3_assoc( ( reg.byt[1] & 0xF0 ) >> 4 );
00258 
00259         /* 2MB ITLB page information */
00260         L[1].tlb[2].type = PAPI_MH_TYPE_INST;
00261         L[1].tlb[2].num_entries = L[1].tlb[0].num_entries * 2;
00262         L[1].tlb[2].page_size = 2048 << 10;
00263         L[1].tlb[2].associativity = L[1].tlb[0].associativity;
00264     }
00265 
00266     if ( reg.byt[2] | reg.byt[3] ) {    /* Level 2 DTLB exists */
00267         /* 4MB DTLB page information; half the number of entries as 2MB */
00268         L[1].tlb[1].type = PAPI_MH_TYPE_DATA;
00269         L[1].tlb[1].num_entries =
00270             ( ( ( short ) ( reg.byt[3] & 0xF ) << 8 ) + reg.byt[2] ) / 2;
00271         L[1].tlb[1].page_size = 4096 << 10;
00272         L[1].tlb[1].associativity =
00273             _amd_L2_L3_assoc( ( reg.byt[3] & 0xF0 ) >> 4 );
00274 
00275         /* 2MB DTLB page information */
00276         L[1].tlb[3].type = PAPI_MH_TYPE_DATA;
00277         L[1].tlb[3].num_entries = L[1].tlb[1].num_entries * 2;
00278         L[1].tlb[3].page_size = 2048 << 10;
00279         L[1].tlb[3].associativity = L[1].tlb[1].associativity;
00280     }
00281 
00282     /* 4k page information */
00283     if ( reg.byt[4] | reg.byt[5] ) {    /* Level 2 ITLB exists */
00284         L[1].tlb[4].type = PAPI_MH_TYPE_INST;
00285         L[1].tlb[4].num_entries =
00286             ( ( short ) ( reg.byt[5] & 0xF ) << 8 ) + reg.byt[4];
00287         L[1].tlb[4].page_size = 4 << 10;
00288         L[1].tlb[4].associativity =
00289             _amd_L2_L3_assoc( ( reg.byt[5] & 0xF0 ) >> 4 );
00290     }
00291     if ( reg.byt[6] | reg.byt[7] ) {    /* Level 2 DTLB exists */
00292         L[1].tlb[5].type = PAPI_MH_TYPE_DATA;
00293         L[1].tlb[5].num_entries =
00294             ( ( short ) ( reg.byt[7] & 0xF ) << 8 ) + reg.byt[6];
00295         L[1].tlb[5].page_size = 4 << 10;
00296         L[1].tlb[5].associativity =
00297             _amd_L2_L3_assoc( ( reg.byt[7] & 0xF0 ) >> 4 );
00298     }
00299 
00300     /* AMD Level 2 cache info */
00301     if ( reg.e.cx ) {
00302         L[1].cache[0].type =
00303             PAPI_MH_TYPE_UNIFIED | PAPI_MH_TYPE_WT | PAPI_MH_TYPE_PSEUDO_LRU;
00304         L[1].cache[0].size = ( int ) ( ( reg.e.cx & 0xffff0000 ) >> 6 );    /* right shift by 16; multiply by 2^10 */
00305         L[1].cache[0].associativity =
00306             _amd_L2_L3_assoc( ( reg.byt[9] & 0xF0 ) >> 4 );
00307         L[1].cache[0].line_size = reg.byt[8];
00308 /*      L[1].cache[0].num_lines = reg.byt[9]&0xF; */
00309         if ( L[1].cache[0].line_size )
00310             L[1].cache[0].num_lines =
00311                 L[1].cache[0].size / L[1].cache[0].line_size;
00312         MEMDBG( "U-Cache Line Count: %d; Computed: %d\n", reg.byt[9] & 0xF,
00313                 L[1].cache[0].num_lines );
00314     }
00315 
00316     /* AMD Level 3 cache info (shared across cores) */
00317     if ( reg.e.dx ) {
00318         L[2].cache[0].type =
00319             PAPI_MH_TYPE_UNIFIED | PAPI_MH_TYPE_WT | PAPI_MH_TYPE_PSEUDO_LRU;
00320         L[2].cache[0].size = ( int ) ( reg.e.dx & 0xfffc0000 ) << 1;    /* in blocks of 512KB (2^19) */
00321         L[2].cache[0].associativity =
00322             _amd_L2_L3_assoc( ( reg.byt[13] & 0xF0 ) >> 4 );
00323         L[2].cache[0].line_size = reg.byt[12];
00324 /*      L[2].cache[0].num_lines = reg.byt[13]&0xF; */
00325         if ( L[2].cache[0].line_size )
00326             L[2].cache[0].num_lines =
00327                 L[2].cache[0].size / L[2].cache[0].line_size;
00328         MEMDBG( "U-Cache Line Count: %d; Computed: %d\n", reg.byt[13] & 0xF,
00329                 L[1].cache[0].num_lines );
00330     }
00331     for ( i = 0; i < PAPI_MAX_MEM_HIERARCHY_LEVELS; i++ ) {
00332         for ( j = 0; j < PAPI_MH_MAX_LEVELS; j++ ) {
00333             /* Compute the number of levels of hierarchy actually used */
00334             if ( L[i].tlb[j].type != PAPI_MH_TYPE_EMPTY ||
00335                  L[i].cache[j].type != PAPI_MH_TYPE_EMPTY )
00336                 levels = i + 1;
00337         }
00338     }
00339     *num_levels = levels;
00340     return PAPI_OK;
00341 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int init_intel ( PAPI_mh_info_t mh_info,
int *  levels 
) [static]

Definition at line 1485 of file x86_cpuid_info.c.

01486 {
01487 
01488   int result;
01489   int num_levels;
01490 
01491   /* try using the oldest leaf2 method first */
01492   result=init_intel_leaf2(mh_info, &num_levels);
01493   
01494   if (result!=PAPI_OK) {
01495      /* All Core2 and newer also support leaf4 detection */
01496      /* Starting with Westmere *only* leaf4 is supported */
01497      result=init_intel_leaf4(mh_info, &num_levels);
01498   }
01499 
01500   *levels=num_levels;
01501   return PAPI_OK;
01502 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int init_intel_leaf2 ( PAPI_mh_info_t mh_info,
int *  num_levels 
) [static]

Definition at line 1396 of file x86_cpuid_info.c.

01397 {
01398     /* cpuid() returns memory copies of 4 32-bit registers
01399      * this union allows them to be accessed as either registers
01400      * or individual bytes. Remember that Intel is little-endian.
01401      */
01402     union
01403     {
01404         struct
01405         {
01406             unsigned int ax, bx, cx, dx;
01407         } e;
01408         unsigned char descrip[16];
01409     } reg;
01410 
01411     int r;                             /* register boundary index */
01412     int b;                             /* byte index into a register */
01413     int i;                             /* byte index into the descrip array */
01414     int t;                             /* table index into the static descriptor table */
01415     int count;                         /* how many times to call cpuid; from eax:lsb */
01416     int size;                          /* size of the descriptor table */
01417     int last_level = 0;                /* how many levels in the cache hierarchy */
01418 
01419     /* All of Intel's cache info is in 1 call to cpuid
01420      * however it is a table lookup :(
01421      */
01422     MEMDBG( "Initializing Intel Cache and TLB descriptors\n" );
01423 
01424 #ifdef DEBUG
01425     if ( ISLEVEL( DEBUG_MEMORY ) )
01426         print_intel_cache_table(  );
01427 #endif
01428 
01429     reg.e.ax = 0x2;          /* function code 2: cache descriptors */
01430     cpuid( &reg.e.ax, &reg.e.bx, &reg.e.cx, &reg.e.dx );
01431 
01432     MEMDBG( "e.ax=%#8.8x e.bx=%#8.8x e.cx=%#8.8x e.dx=%#8.8x\n",
01433             reg.e.ax, reg.e.bx, reg.e.cx, reg.e.dx );
01434     MEMDBG
01435         ( ":\nd0: %#x %#x %#x %#x\nd1: %#x %#x %#x %#x\nd2: %#x %#x %#x %#x\nd3: %#x %#x %#x %#x\n",
01436           reg.descrip[0], reg.descrip[1], reg.descrip[2], reg.descrip[3],
01437           reg.descrip[4], reg.descrip[5], reg.descrip[6], reg.descrip[7],
01438           reg.descrip[8], reg.descrip[9], reg.descrip[10], reg.descrip[11],
01439           reg.descrip[12], reg.descrip[13], reg.descrip[14], reg.descrip[15] );
01440 
01441     count = reg.descrip[0];  /* # times to repeat CPUID call. Not implemented. */
01442 
01443     /* Knights Corner at least returns 0 here */
01444     if (count==0) goto early_exit;
01445 
01446     size = ( sizeof ( intel_cache ) / sizeof ( struct _intel_cache_info ) );    /* # descriptors */
01447     MEMDBG( "Repeat cpuid(2,...) %d times. If not 1, code is broken.\n",
01448             count );
01449     if (count!=1) {
01450        fprintf(stderr,"Warning: Unhandled cpuid count of %d\n",count);
01451     }
01452 
01453     for ( r = 0; r < 4; r++ ) { /* walk the registers */
01454         if ( ( reg.descrip[r * 4 + 3] & 0x80 ) == 0 ) { /* only process if high order bit is 0 */
01455             for ( b = 3; b >= 0; b-- ) {    /* walk the descriptor bytes from high to low */
01456                 i = r * 4 + b;  /* calculate an index into the array of descriptors */
01457                 if ( i ) {   /* skip the low order byte in eax [0]; it's the count (see above) */
01458                    if ( reg.descrip[i] == 0xff ) {
01459                       MEMDBG("Warning! PAPI x86_cache: must implement cpuid leaf 4\n");
01460                       return PAPI_ENOSUPP;
01461                       /* we might continue instead */
01462                       /* in order to get TLB info  */
01463                       /* continue;                 */
01464                    }
01465                     for ( t = 0; t < size; t++ ) {  /* walk the descriptor table */                    
01466                         if ( reg.descrip[i] == intel_cache[t].descriptor ) {    /* find match */
01467                             if ( intel_cache[t].level > last_level )
01468                                 last_level = intel_cache[t].level;
01469                             intel_decode_descriptor( &intel_cache[t],
01470                                                      mh_info->level );
01471                         }
01472                     }
01473                 }
01474             }
01475         }
01476     }
01477 early_exit:
01478     MEMDBG( "# of Levels: %d\n", last_level );
01479     *num_levels=last_level;
01480     return PAPI_OK;
01481 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int init_intel_leaf4 ( PAPI_mh_info_t mh_info,
int *  num_levels 
) [static]

Definition at line 1287 of file x86_cpuid_info.c.

01288 {
01289 
01290   unsigned int eax, ebx, ecx, edx;
01291   unsigned int maxidx, ecx_in;
01292   int next;
01293 
01294   int cache_type,cache_level,cache_selfinit,cache_fullyassoc;
01295   int cache_linesize,cache_partitions,cache_ways,cache_sets;
01296 
01297   PAPI_mh_cache_info_t *c;
01298 
01299   *num_levels=0;
01300 
01301   cpuid2(&eax,&ebx,&ecx,&edx, 0, 0);
01302   maxidx = eax;
01303   
01304   if (maxidx<4) {
01305     MEMDBG("Warning!  CPUID Index 4 not supported!\n");
01306     return PAPI_ENOSUPP;
01307   }
01308 
01309   ecx_in=0;
01310   while(1) {
01311     cpuid2(&eax,&ebx,&ecx,&edx, 4, ecx_in);
01312 
01313 
01314     
01315     /* decoded as per table 3-12 in Intel Software Developer's Manual Volume 2A */
01316      
01317     cache_type=eax&0x1f;
01318     if (cache_type==0) break;     
01319      
01320     cache_level=(eax>>5)&0x3;
01321     cache_selfinit=(eax>>8)&0x1;
01322     cache_fullyassoc=(eax>>9)&0x1;
01323 
01324     cache_linesize=(ebx&0xfff)+1;
01325     cache_partitions=((ebx>>12)&0x3ff)+1;
01326     cache_ways=((ebx>>22)&0x3ff)+1;
01327        
01328     cache_sets=(ecx)+1;
01329 
01330     /* should we export this info?
01331 
01332     cache_maxshare=((eax>>14)&0xfff)+1;
01333     cache_maxpackage=((eax>>26)&0x3f)+1;
01334      
01335     cache_wb=(edx)&1;
01336     cache_inclusive=(edx>>1)&1;
01337     cache_indexing=(edx>>2)&1;
01338     */
01339 
01340     if (cache_level>*num_levels) *num_levels=cache_level;
01341 
01342     /* find next slot available to hold cache info */
01343     for ( next = 0; next < PAPI_MH_MAX_LEVELS - 1; next++ ) {
01344         if ( mh_info->level[cache_level-1].cache[next].type == PAPI_MH_TYPE_EMPTY ) break;
01345     }
01346 
01347     c=&(mh_info->level[cache_level-1].cache[next]);
01348 
01349     switch(cache_type) {
01350       case 1: MEMDBG("L%d Data Cache\n",cache_level); 
01351     c->type=PAPI_MH_TYPE_DATA;
01352     break;
01353       case 2: MEMDBG("L%d Instruction Cache\n",cache_level); 
01354     c->type=PAPI_MH_TYPE_INST;
01355     break;
01356       case 3: MEMDBG("L%d Unified Cache\n",cache_level); 
01357     c->type=PAPI_MH_TYPE_UNIFIED;
01358     break;
01359     }
01360      
01361     if (cache_selfinit) { MEMDBG("\tSelf-init\n"); }
01362     if (cache_fullyassoc) { MEMDBG("\tFully Associtative\n"); }
01363      
01364     //MEMDBG("\tMax logical processors sharing cache: %d\n",cache_maxshare);
01365     //MEMDBG("\tMax logical processors sharing package: %d\n",cache_maxpackage);
01366      
01367     MEMDBG("\tCache linesize: %d\n",cache_linesize);
01368 
01369     MEMDBG("\tCache partitions: %d\n",cache_partitions);
01370     MEMDBG("\tCache associaticity: %d\n",cache_ways);
01371 
01372     MEMDBG("\tCache sets: %d\n",cache_sets);
01373     MEMDBG("\tCache size = %dkB\n",
01374        (cache_ways*cache_partitions*cache_linesize*cache_sets)/1024);
01375 
01376     //MEMDBG("\tWBINVD/INVD acts on lower caches: %d\n",cache_wb);
01377     //MEMDBG("\tCache is not inclusive: %d\n",cache_inclusive);
01378     //MEMDBG("\tComplex cache indexing: %d\n",cache_indexing);
01379 
01380     c->line_size=cache_linesize;
01381     if (cache_fullyassoc) {
01382        c->associativity=SHRT_MAX;
01383     }
01384     else {
01385        c->associativity=cache_ways;
01386     }
01387     c->size=(cache_ways*cache_partitions*cache_linesize*cache_sets);
01388     c->num_lines=cache_ways*cache_partitions*cache_sets;
01389      
01390     ecx_in++;
01391   }
01392   return PAPI_OK;
01393 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void init_mem_hierarchy ( PAPI_mh_info_t mh_info  )  [static]

Definition at line 95 of file x86_cpuid_info.c.

00096 {
00097     int i, j;
00098     PAPI_mh_level_t *L = mh_info->level;
00099 
00100     /* initialize entire memory hierarchy structure to benign values */
00101     for ( i = 0; i < PAPI_MAX_MEM_HIERARCHY_LEVELS; i++ ) {
00102         for ( j = 0; j < PAPI_MH_MAX_LEVELS; j++ ) {
00103             L[i].tlb[j].type = PAPI_MH_TYPE_EMPTY;
00104             L[i].tlb[j].num_entries = 0;
00105             L[i].tlb[j].associativity = 0;
00106             L[i].cache[j].type = PAPI_MH_TYPE_EMPTY;
00107             L[i].cache[j].size = 0;
00108             L[i].cache[j].line_size = 0;
00109             L[i].cache[j].num_lines = 0;
00110             L[i].cache[j].associativity = 0;
00111         }
00112     }
00113 }

Here is the caller graph for this function:

static void intel_decode_descriptor ( struct _intel_cache_info d,
PAPI_mh_level_t L 
) [static]

Definition at line 1211 of file x86_cpuid_info.c.

01212 {
01213     int i, next;
01214     int level = d->level - 1;
01215     PAPI_mh_tlb_info_t *t;
01216     PAPI_mh_cache_info_t *c;
01217 
01218     if ( d->descriptor == 0x49 ) {  /* special case */
01219         unsigned int r_eax, r_ebx, r_ecx, r_edx;
01220         r_eax = 0x1;         /* function code 1: family & model */
01221         cpuid( &r_eax, &r_ebx, &r_ecx, &r_edx );
01222         /* override table for Family F, model 6 only */
01223         if ( ( r_eax & 0x0FFF3FF0 ) == 0xF60 )
01224             level = 3;
01225     }
01226     if ( d->type & PAPI_MH_TYPE_TLB ) {
01227         for ( next = 0; next < PAPI_MH_MAX_LEVELS - 1; next++ ) {
01228             if ( L[level].tlb[next].type == PAPI_MH_TYPE_EMPTY )
01229                 break;
01230         }
01231         /* expand TLB entries for multiple possible page sizes */
01232         for ( i = 0; i < TLB_SIZES && next < PAPI_MH_MAX_LEVELS && d->size[i];
01233               i++, next++ ) {
01234 //          printf("Level %d Descriptor: %#x TLB type %#x next: %d, i: %d\n", level, d->descriptor, d->type, next, i);
01235             t = &L[level].tlb[next];
01236             t->type = PAPI_MH_CACHE_TYPE( d->type );
01237             t->num_entries = d->entries;
01238             t->page_size = d->size[i] << 10;    /* minimum page size in KB */
01239             t->associativity = d->associativity;
01240             /* another special case */
01241             if ( d->descriptor == 0xB1 && d->size[i] == 4096 )
01242                 t->num_entries = d->entries / 2;
01243         }
01244     } else {
01245         for ( next = 0; next < PAPI_MH_MAX_LEVELS - 1; next++ ) {
01246             if ( L[level].cache[next].type == PAPI_MH_TYPE_EMPTY )
01247                 break;
01248         }
01249 //      printf("Level %d Descriptor: %#x Cache type %#x next: %d\n", level, d->descriptor, d->type, next);
01250         c = &L[level].cache[next];
01251         c->type = PAPI_MH_CACHE_TYPE( d->type );
01252         c->size = d->size[0] << 10; /* convert from KB to bytes */
01253         c->associativity = d->associativity;
01254         if ( d->line_size ) {
01255             c->line_size = d->line_size;
01256             c->num_lines = c->size / c->line_size;
01257         }
01258     }
01259 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_intel_cache_table (  )  [static]

Definition at line 1184 of file x86_cpuid_info.c.

01185 {
01186     int i, j, k =
01187         ( int ) ( sizeof ( intel_cache ) /
01188                   sizeof ( struct _intel_cache_info ) );
01189     for ( i = 0; i < k; i++ ) {
01190         printf( "%d.\tDescriptor: %#x\n", i, intel_cache[i].descriptor );
01191         printf( "\t  Level:     %d\n", intel_cache[i].level );
01192         printf( "\t  Type:      %d\n", intel_cache[i].type );
01193         printf( "\t  Size(s):   " );
01194         for ( j = 0; j < TLB_SIZES; j++ )
01195             printf( "%d, ", intel_cache[i].size[j] );
01196         printf( "\n" );
01197         printf( "\t  Assoc:     %d\n", intel_cache[i].associativity );
01198         printf( "\t  Sector:    %d\n", intel_cache[i].sector );
01199         printf( "\t  Line Size: %d\n", intel_cache[i].line_size );
01200         printf( "\t  Entries:   %d\n", intel_cache[i].entries );
01201         printf( "\n" );
01202     }
01203 }

Here is the caller graph for this function:


Variable Documentation

struct _intel_cache_info intel_cache[] [static]

Definition at line 373 of file x86_cpuid_info.c.


Generated on 8 Sep 2016 for PAPI by  doxygen 1.6.1