Blame src/x86_cpuid_info.c

Packit 577717
/****************************/
Packit 577717
/* THIS IS OPEN SOURCE CODE */
Packit 577717
/****************************/
Packit 577717
Packit 577717
/* 
Packit 577717
* File:    x86_cpuid_info.c
Packit 577717
* Author:  Dan Terpstra
Packit 577717
*          terpstra@eecs.utk.edu
Packit 577717
*          complete rewrite of linux-memory.c to conform to latest docs
Packit 577717
*          and convert Intel to a table driven implementation.
Packit 577717
*          Now also supports multiple TLB descriptors
Packit 577717
*/
Packit 577717
Packit 577717
#include <string.h>
Packit 577717
#include <stdio.h>
Packit 577717
#include "papi.h"
Packit 577717
#include "papi_internal.h"
Packit 577717
Packit 577717
static void init_mem_hierarchy( PAPI_mh_info_t * mh_info );
Packit 577717
static int init_amd( PAPI_mh_info_t * mh_info, int *levels );
Packit 577717
static short int _amd_L2_L3_assoc( unsigned short int pattern );
Packit 577717
static int init_intel( PAPI_mh_info_t * mh_info , int *levels);
Packit 577717
Packit 577717
#if defined( __amd64__ ) || defined (__x86_64__)
Packit 577717
static inline void
Packit 577717
cpuid( unsigned int *a, unsigned int *b, unsigned int *c, unsigned int *d )
Packit 577717
{
Packit 577717
	unsigned int op = *a;
Packit 577717
	__asm__("cpuid;"
Packit 577717
		: "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d)
Packit 577717
		: "a" (op) );
Packit 577717
}
Packit 577717
#else
Packit 577717
static inline void
Packit 577717
cpuid( unsigned int *a, unsigned int *b, unsigned int *c, unsigned int *d )
Packit 577717
{
Packit 577717
	unsigned int op = *a;
Packit 577717
	// .byte 0x53 == push ebx. it's universal for 32 and 64 bit
Packit 577717
	// .byte 0x5b == pop ebx.
Packit 577717
	// Some gcc's (4.1.2 on Core2) object to pairing push/pop and ebx in 64 bit mode.
Packit 577717
	// Using the opcode directly avoids this problem.
Packit 577717
  __asm__ __volatile__( ".byte 0x53\n\tcpuid\n\tmovl %%ebx, %%esi\n\t.byte 0x5b":"=a"( *a ), "=S"( *b ), "=c"( *c ),
Packit 577717
						  "=d"
Packit 577717
						  ( *d )
Packit 577717
  :					  "a"( op ) );
Packit 577717
}
Packit 577717
#endif
Packit 577717
Packit 577717
int
Packit 577717
_x86_cache_info( PAPI_mh_info_t * mh_info )
Packit 577717
{
Packit 577717
	int retval = 0;
Packit 577717
	union
Packit 577717
	{
Packit 577717
		struct
Packit 577717
		{
Packit 577717
			unsigned int ax, bx, cx, dx;
Packit 577717
		} e;
Packit 577717
		char vendor[20];			   /* leave room for terminator bytes */
Packit 577717
	} reg;
Packit 577717
Packit 577717
	/* Don't use cpu_type to determine the processor.
Packit 577717
	 * get the information directly from the chip.
Packit 577717
	 */
Packit 577717
	reg.e.ax = 0;			 /* function code 0: vendor string */
Packit 577717
	/* The vendor string is composed of EBX:EDX:ECX.
Packit 577717
	 * by swapping the register addresses in the call below,
Packit 577717
	 * the string is correctly composed in the char array.
Packit 577717
	 */
Packit 577717
	cpuid( &reg.e.ax, &reg.e.bx, &reg.e.dx, &reg.e.cx );
Packit 577717
	reg.vendor[16] = 0;
Packit 577717
	MEMDBG( "Vendor: %s\n", &reg.vendor[4] );
Packit 577717
Packit 577717
	init_mem_hierarchy( mh_info );
Packit 577717
Packit 577717
	if ( !strncmp( "GenuineIntel", &reg.vendor[4], 12 ) ) {
Packit 577717
	        init_intel( mh_info, &mh_info->levels);
Packit 577717
	} else if ( !strncmp( "AuthenticAMD", &reg.vendor[4], 12 ) ) {
Packit 577717
	  init_amd( mh_info, &mh_info->levels );
Packit 577717
	} else {
Packit 577717
		MEMDBG( "Unsupported cpu type; Not Intel or AMD x86\n" );
Packit 577717
		return PAPI_ENOIMPL;
Packit 577717
	}
Packit 577717
Packit 577717
	/* This works only because an empty cache element is initialized to 0 */
Packit 577717
	MEMDBG( "Detected L1: %d L2: %d  L3: %d\n",
Packit 577717
			mh_info->level[0].cache[0].size + mh_info->level[0].cache[1].size,
Packit 577717
			mh_info->level[1].cache[0].size + mh_info->level[1].cache[1].size,
Packit 577717
			mh_info->level[2].cache[0].size + mh_info->level[2].cache[1].size );
Packit 577717
	return retval;
Packit 577717
}
Packit 577717
Packit 577717
static void
Packit 577717
init_mem_hierarchy( PAPI_mh_info_t * mh_info )
Packit 577717
{
Packit 577717
	int i, j;
Packit 577717
	PAPI_mh_level_t *L = mh_info->level;
Packit 577717
Packit 577717
	/* initialize entire memory hierarchy structure to benign values */
Packit 577717
	for ( i = 0; i < PAPI_MAX_MEM_HIERARCHY_LEVELS; i++ ) {
Packit 577717
		for ( j = 0; j < PAPI_MH_MAX_LEVELS; j++ ) {
Packit 577717
			L[i].tlb[j].type = PAPI_MH_TYPE_EMPTY;
Packit 577717
			L[i].tlb[j].num_entries = 0;
Packit 577717
			L[i].tlb[j].associativity = 0;
Packit 577717
			L[i].cache[j].type = PAPI_MH_TYPE_EMPTY;
Packit 577717
			L[i].cache[j].size = 0;
Packit 577717
			L[i].cache[j].line_size = 0;
Packit 577717
			L[i].cache[j].num_lines = 0;
Packit 577717
			L[i].cache[j].associativity = 0;
Packit 577717
		}
Packit 577717
	}
Packit 577717
}
Packit 577717
Packit 577717
static short int
Packit 577717
_amd_L2_L3_assoc( unsigned short int pattern )
Packit 577717
{
Packit 577717
	/* From "CPUID Specification" #25481 Rev 2.28, April 2008 */
Packit 577717
	short int assoc[16] =
Packit 577717
		{ 0, 1, 2, -1, 4, -1, 8, -1, 16, -1, 32, 48, 64, 96, 128, SHRT_MAX };
Packit 577717
	if ( pattern > 0xF )
Packit 577717
		return -1;
Packit 577717
	return ( assoc[pattern] );
Packit 577717
}
Packit 577717
Packit 577717
/* Cache configuration for AMD Athlon/Duron */
Packit 577717
static int
Packit 577717
init_amd( PAPI_mh_info_t * mh_info, int *num_levels )
Packit 577717
{
Packit 577717
	union
Packit 577717
	{
Packit 577717
		struct
Packit 577717
		{
Packit 577717
			unsigned int ax, bx, cx, dx;
Packit 577717
		} e;
Packit 577717
		unsigned char byt[16];
Packit 577717
	} reg;
Packit 577717
	int i, j, levels = 0;
Packit 577717
	PAPI_mh_level_t *L = mh_info->level;
Packit 577717
Packit 577717
	/*
Packit 577717
	 * Layout of CPU information taken from :
Packit 577717
	 * "CPUID Specification" #25481 Rev 2.28, April 2008 for most current info.
Packit 577717
	 */
Packit 577717
Packit 577717
	MEMDBG( "Initializing AMD memory info\n" );
Packit 577717
	/* AMD level 1 cache info */
Packit 577717
	reg.e.ax = 0x80000005;	 /* extended function code 5: L1 Cache and TLB Identifiers */
Packit 577717
	cpuid( &reg.e.ax, &reg.e.bx, &reg.e.cx, &reg.e.dx );
Packit 577717
Packit 577717
	MEMDBG( "e.ax=%#8.8x e.bx=%#8.8x e.cx=%#8.8x e.dx=%#8.8x\n",
Packit 577717
			reg.e.ax, reg.e.bx, reg.e.cx, reg.e.dx );
Packit 577717
	MEMDBG
Packit 577717
		( ":\neax: %#x %#x %#x %#x\nebx: %#x %#x %#x %#x\necx: %#x %#x %#x %#x\nedx: %#x %#x %#x %#x\n",
Packit 577717
		  reg.byt[0], reg.byt[1], reg.byt[2], reg.byt[3], reg.byt[4],
Packit 577717
		  reg.byt[5], reg.byt[6], reg.byt[7], reg.byt[8], reg.byt[9],
Packit 577717
		  reg.byt[10], reg.byt[11], reg.byt[12], reg.byt[13], reg.byt[14],
Packit 577717
		  reg.byt[15] );
Packit 577717
Packit 577717
	/* NOTE: We assume L1 cache and TLB always exists */
Packit 577717
	/* L1 TLB info */
Packit 577717
Packit 577717
	/* 4MB memory page information; half the number of entries as 2MB */
Packit 577717
	L[0].tlb[0].type = PAPI_MH_TYPE_INST;
Packit 577717
	L[0].tlb[0].num_entries = reg.byt[0] / 2;
Packit 577717
	L[0].tlb[0].page_size = 4096 << 10;
Packit 577717
	L[0].tlb[0].associativity = reg.byt[1];
Packit 577717
Packit 577717
	L[0].tlb[1].type = PAPI_MH_TYPE_DATA;
Packit 577717
	L[0].tlb[1].num_entries = reg.byt[2] / 2;
Packit 577717
	L[0].tlb[1].page_size = 4096 << 10;
Packit 577717
	L[0].tlb[1].associativity = reg.byt[3];
Packit 577717
Packit 577717
	/* 2MB memory page information */
Packit 577717
	L[0].tlb[2].type = PAPI_MH_TYPE_INST;
Packit 577717
	L[0].tlb[2].num_entries = reg.byt[0];
Packit 577717
	L[0].tlb[2].page_size = 2048 << 10;
Packit 577717
	L[0].tlb[2].associativity = reg.byt[1];
Packit 577717
Packit 577717
	L[0].tlb[3].type = PAPI_MH_TYPE_DATA;
Packit 577717
	L[0].tlb[3].num_entries = reg.byt[2];
Packit 577717
	L[0].tlb[3].page_size = 2048 << 10;
Packit 577717
	L[0].tlb[3].associativity = reg.byt[3];
Packit 577717
Packit 577717
	/* 4k page information */
Packit 577717
	L[0].tlb[4].type = PAPI_MH_TYPE_INST;
Packit 577717
	L[0].tlb[4].num_entries = reg.byt[4];
Packit 577717
	L[0].tlb[4].page_size = 4 << 10;
Packit 577717
	L[0].tlb[4].associativity = reg.byt[5];
Packit 577717
Packit 577717
	L[0].tlb[5].type = PAPI_MH_TYPE_DATA;
Packit 577717
	L[0].tlb[5].num_entries = reg.byt[6];
Packit 577717
	L[0].tlb[5].page_size = 4 << 10;
Packit 577717
	L[0].tlb[5].associativity = reg.byt[7];
Packit 577717
Packit 577717
	for ( i = 0; i < PAPI_MH_MAX_LEVELS; i++ ) {
Packit 577717
		if ( L[0].tlb[i].associativity == 0xff )
Packit 577717
			L[0].tlb[i].associativity = SHRT_MAX;
Packit 577717
	}
Packit 577717
Packit 577717
	/* L1 D-cache info */
Packit 577717
	L[0].cache[0].type =
Packit 577717
		PAPI_MH_TYPE_DATA | PAPI_MH_TYPE_WB | PAPI_MH_TYPE_PSEUDO_LRU;
Packit 577717
	L[0].cache[0].size = reg.byt[11] << 10;
Packit 577717
	L[0].cache[0].associativity = reg.byt[10];
Packit 577717
	L[0].cache[0].line_size = reg.byt[8];
Packit 577717
	/* Byt[9] is "Lines per tag" */
Packit 577717
	/* Is that == lines per cache? */
Packit 577717
	/* L[0].cache[1].num_lines = reg.byt[9]; */
Packit 577717
	if ( L[0].cache[0].line_size )
Packit 577717
		L[0].cache[0].num_lines = L[0].cache[0].size / L[0].cache[0].line_size;
Packit 577717
	MEMDBG( "D-Cache Line Count: %d; Computed: %d\n", reg.byt[9],
Packit 577717
			L[0].cache[0].num_lines );
Packit 577717
Packit 577717
	/* L1 I-cache info */
Packit 577717
	L[0].cache[1].type = PAPI_MH_TYPE_INST;
Packit 577717
	L[0].cache[1].size = reg.byt[15] << 10;
Packit 577717
	L[0].cache[1].associativity = reg.byt[14];
Packit 577717
	L[0].cache[1].line_size = reg.byt[12];
Packit 577717
	/* Byt[13] is "Lines per tag" */
Packit 577717
	/* Is that == lines per cache? */
Packit 577717
	/* L[0].cache[1].num_lines = reg.byt[13]; */
Packit 577717
	if ( L[0].cache[1].line_size )
Packit 577717
		L[0].cache[1].num_lines = L[0].cache[1].size / L[0].cache[1].line_size;
Packit 577717
	MEMDBG( "I-Cache Line Count: %d; Computed: %d\n", reg.byt[13],
Packit 577717
			L[0].cache[1].num_lines );
Packit 577717
Packit 577717
	for ( i = 0; i < 2; i++ ) {
Packit 577717
		if ( L[0].cache[i].associativity == 0xff )
Packit 577717
			L[0].cache[i].associativity = SHRT_MAX;
Packit 577717
	}
Packit 577717
Packit 577717
	/* AMD L2/L3 Cache and L2 TLB info */
Packit 577717
	/* NOTE: For safety we assume L2 and L3 cache and TLB may not exist */
Packit 577717
Packit 577717
	reg.e.ax = 0x80000006;	 /* extended function code 6: L2/L3 Cache and L2 TLB Identifiers */
Packit 577717
	cpuid( &reg.e.ax, &reg.e.bx, &reg.e.cx, &reg.e.dx );
Packit 577717
Packit 577717
	MEMDBG( "e.ax=%#8.8x e.bx=%#8.8x e.cx=%#8.8x e.dx=%#8.8x\n",
Packit 577717
			reg.e.ax, reg.e.bx, reg.e.cx, reg.e.dx );
Packit 577717
	MEMDBG
Packit 577717
		( ":\neax: %#x %#x %#x %#x\nebx: %#x %#x %#x %#x\necx: %#x %#x %#x %#x\nedx: %#x %#x %#x %#x\n",
Packit 577717
		  reg.byt[0], reg.byt[1], reg.byt[2], reg.byt[3], reg.byt[4],
Packit 577717
		  reg.byt[5], reg.byt[6], reg.byt[7], reg.byt[8], reg.byt[9],
Packit 577717
		  reg.byt[10], reg.byt[11], reg.byt[12], reg.byt[13], reg.byt[14],
Packit 577717
		  reg.byt[15] );
Packit 577717
Packit 577717
	/* L2 TLB info */
Packit 577717
Packit 577717
	if ( reg.byt[0] | reg.byt[1] ) {	/* Level 2 ITLB exists */
Packit 577717
		/* 4MB ITLB page information; half the number of entries as 2MB */
Packit 577717
		L[1].tlb[0].type = PAPI_MH_TYPE_INST;
Packit 577717
		L[1].tlb[0].num_entries =
Packit 577717
			( ( ( short ) ( reg.byt[1] & 0xF ) << 8 ) + reg.byt[0] ) / 2;
Packit 577717
		L[1].tlb[0].page_size = 4096 << 10;
Packit 577717
		L[1].tlb[0].associativity =
Packit 577717
			_amd_L2_L3_assoc( ( reg.byt[1] & 0xF0 ) >> 4 );
Packit 577717
Packit 577717
		/* 2MB ITLB page information */
Packit 577717
		L[1].tlb[2].type = PAPI_MH_TYPE_INST;
Packit 577717
		L[1].tlb[2].num_entries = L[1].tlb[0].num_entries * 2;
Packit 577717
		L[1].tlb[2].page_size = 2048 << 10;
Packit 577717
		L[1].tlb[2].associativity = L[1].tlb[0].associativity;
Packit 577717
	}
Packit 577717
Packit 577717
	if ( reg.byt[2] | reg.byt[3] ) {	/* Level 2 DTLB exists */
Packit 577717
		/* 4MB DTLB page information; half the number of entries as 2MB */
Packit 577717
		L[1].tlb[1].type = PAPI_MH_TYPE_DATA;
Packit 577717
		L[1].tlb[1].num_entries =
Packit 577717
			( ( ( short ) ( reg.byt[3] & 0xF ) << 8 ) + reg.byt[2] ) / 2;
Packit 577717
		L[1].tlb[1].page_size = 4096 << 10;
Packit 577717
		L[1].tlb[1].associativity =
Packit 577717
			_amd_L2_L3_assoc( ( reg.byt[3] & 0xF0 ) >> 4 );
Packit 577717
Packit 577717
		/* 2MB DTLB page information */
Packit 577717
		L[1].tlb[3].type = PAPI_MH_TYPE_DATA;
Packit 577717
		L[1].tlb[3].num_entries = L[1].tlb[1].num_entries * 2;
Packit 577717
		L[1].tlb[3].page_size = 2048 << 10;
Packit 577717
		L[1].tlb[3].associativity = L[1].tlb[1].associativity;
Packit 577717
	}
Packit 577717
Packit 577717
	/* 4k page information */
Packit 577717
	if ( reg.byt[4] | reg.byt[5] ) {	/* Level 2 ITLB exists */
Packit 577717
		L[1].tlb[4].type = PAPI_MH_TYPE_INST;
Packit 577717
		L[1].tlb[4].num_entries =
Packit 577717
			( ( short ) ( reg.byt[5] & 0xF ) << 8 ) + reg.byt[4];
Packit 577717
		L[1].tlb[4].page_size = 4 << 10;
Packit 577717
		L[1].tlb[4].associativity =
Packit 577717
			_amd_L2_L3_assoc( ( reg.byt[5] & 0xF0 ) >> 4 );
Packit 577717
	}
Packit 577717
	if ( reg.byt[6] | reg.byt[7] ) {	/* Level 2 DTLB exists */
Packit 577717
		L[1].tlb[5].type = PAPI_MH_TYPE_DATA;
Packit 577717
		L[1].tlb[5].num_entries =
Packit 577717
			( ( short ) ( reg.byt[7] & 0xF ) << 8 ) + reg.byt[6];
Packit 577717
		L[1].tlb[5].page_size = 4 << 10;
Packit 577717
		L[1].tlb[5].associativity =
Packit 577717
			_amd_L2_L3_assoc( ( reg.byt[7] & 0xF0 ) >> 4 );
Packit 577717
	}
Packit 577717
Packit 577717
	/* AMD Level 2 cache info */
Packit 577717
	if ( reg.e.cx ) {
Packit 577717
		L[1].cache[0].type =
Packit 577717
			PAPI_MH_TYPE_UNIFIED | PAPI_MH_TYPE_WT | PAPI_MH_TYPE_PSEUDO_LRU;
Packit 577717
		L[1].cache[0].size = ( int ) ( ( reg.e.cx & 0xffff0000 ) >> 6 );	/* right shift by 16; multiply by 2^10 */
Packit 577717
		L[1].cache[0].associativity =
Packit 577717
			_amd_L2_L3_assoc( ( reg.byt[9] & 0xF0 ) >> 4 );
Packit 577717
		L[1].cache[0].line_size = reg.byt[8];
Packit 577717
/*		L[1].cache[0].num_lines = reg.byt[9]&0xF; */
Packit 577717
		if ( L[1].cache[0].line_size )
Packit 577717
			L[1].cache[0].num_lines =
Packit 577717
				L[1].cache[0].size / L[1].cache[0].line_size;
Packit 577717
		MEMDBG( "U-Cache Line Count: %d; Computed: %d\n", reg.byt[9] & 0xF,
Packit 577717
				L[1].cache[0].num_lines );
Packit 577717
	}
Packit 577717
Packit 577717
	/* AMD Level 3 cache info (shared across cores) */
Packit 577717
	if ( reg.e.dx ) {
Packit 577717
		L[2].cache[0].type =
Packit 577717
			PAPI_MH_TYPE_UNIFIED | PAPI_MH_TYPE_WT | PAPI_MH_TYPE_PSEUDO_LRU;
Packit 577717
		L[2].cache[0].size = ( int ) ( reg.e.dx & 0xfffc0000 ) << 1;	/* in blocks of 512KB (2^19) */
Packit 577717
		L[2].cache[0].associativity =
Packit 577717
			_amd_L2_L3_assoc( ( reg.byt[13] & 0xF0 ) >> 4 );
Packit 577717
		L[2].cache[0].line_size = reg.byt[12];
Packit 577717
/*		L[2].cache[0].num_lines = reg.byt[13]&0xF; */
Packit 577717
		if ( L[2].cache[0].line_size )
Packit 577717
			L[2].cache[0].num_lines =
Packit 577717
				L[2].cache[0].size / L[2].cache[0].line_size;
Packit 577717
		MEMDBG( "U-Cache Line Count: %d; Computed: %d\n", reg.byt[13] & 0xF,
Packit 577717
				L[1].cache[0].num_lines );
Packit 577717
	}
Packit 577717
	for ( i = 0; i < PAPI_MAX_MEM_HIERARCHY_LEVELS; i++ ) {
Packit 577717
		for ( j = 0; j < PAPI_MH_MAX_LEVELS; j++ ) {
Packit 577717
			/* Compute the number of levels of hierarchy actually used */
Packit 577717
			if ( L[i].tlb[j].type != PAPI_MH_TYPE_EMPTY ||
Packit 577717
				 L[i].cache[j].type != PAPI_MH_TYPE_EMPTY )
Packit 577717
				levels = i + 1;
Packit 577717
		}
Packit 577717
	}
Packit 577717
	*num_levels = levels;
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
   /*
Packit 577717
    * The data from this table now comes from figure 3-17 in
Packit 577717
    *  the Intel Architectures Software Reference Manual 2A
Packit 577717
    *  (cpuid instruction section)
Packit 577717
    * 
Packit 577717
    * Pretviously the information was provided by
Packit 577717
    * "Intel® Processor Identification and the CPUID Instruction",
Packit 577717
    * Application Note, AP-485, Nov 2008, 241618-033
Packit 577717
    * Updated to AP-485, Aug 2009, 241618-036
Packit 577717
    *
Packit 577717
    * The following data structure and its instantiation trys to
Packit 577717
    * capture all the information in Section 2.1.3 of the above
Packit 577717
    * document. Not all of it is used by PAPI, but it could be.
Packit 577717
    * As the above document is revised, this table should be
Packit 577717
    * updated.
Packit 577717
    */
Packit 577717
Packit 577717
#define TLB_SIZES 3			 /* number of different page sizes for a single TLB descriptor */
Packit 577717
struct _intel_cache_info
Packit 577717
{
Packit 577717
	int descriptor;					   /* 0x00 - 0xFF: register descriptor code */
Packit 577717
	int level;						   /* 1 to PAPI_MH_MAX_LEVELS */
Packit 577717
	int type;						   /* Empty, instr, data, vector, unified | TLB */
Packit 577717
	int size[TLB_SIZES];			   /* cache or  TLB page size(s) in kB */
Packit 577717
	int associativity;				   /* SHRT_MAX == fully associative */
Packit 577717
	int sector;						   /* 1 if cache is sectored; else 0 */
Packit 577717
	int line_size;					   /* for cache */
Packit 577717
	int entries;					   /* for TLB */
Packit 577717
};
Packit 577717
Packit 577717
static struct _intel_cache_info intel_cache[] = {
Packit 577717
// 0x01
Packit 577717
	{.descriptor = 0x01,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_INST,
Packit 577717
	 .size[0] = 4,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .entries = 32,
Packit 577717
	 },
Packit 577717
// 0x02
Packit 577717
	{.descriptor = 0x02,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_INST,
Packit 577717
	 .size[0] = 4096,
Packit 577717
	 .associativity = SHRT_MAX,
Packit 577717
	 .entries = 2,
Packit 577717
	 },
Packit 577717
// 0x03
Packit 577717
	{.descriptor = 0x03,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 4,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .entries = 64,
Packit 577717
	 },
Packit 577717
// 0x04
Packit 577717
	{.descriptor = 0x04,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 4096,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .entries = 8,
Packit 577717
	 },
Packit 577717
// 0x05
Packit 577717
	{.descriptor = 0x05,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 4096,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .entries = 32,
Packit 577717
	 },
Packit 577717
// 0x06
Packit 577717
	{.descriptor = 0x06,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_INST,
Packit 577717
	 .size[0] = 8,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .line_size = 32,
Packit 577717
	 },
Packit 577717
// 0x08
Packit 577717
	{.descriptor = 0x08,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_INST,
Packit 577717
	 .size[0] = 16,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .line_size = 32,
Packit 577717
	 },
Packit 577717
// 0x09
Packit 577717
	{.descriptor = 0x09,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_INST,
Packit 577717
	 .size[0] = 32,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x0A
Packit 577717
	{.descriptor = 0x0A,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 8,
Packit 577717
	 .associativity = 2,
Packit 577717
	 .line_size = 32,
Packit 577717
	 },
Packit 577717
// 0x0B
Packit 577717
	{.descriptor = 0x0B,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_INST,
Packit 577717
	 .size[0] = 4096,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .entries = 4,
Packit 577717
	 },   
Packit 577717
// 0x0C
Packit 577717
	{.descriptor = 0x0C,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 16,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .line_size = 32,
Packit 577717
	 },
Packit 577717
// 0x0D
Packit 577717
	{.descriptor = 0x0D,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 16,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x0E
Packit 577717
	{.descriptor = 0x0E,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 24,
Packit 577717
	 .associativity = 6,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },   
Packit 577717
// 0x21
Packit 577717
	{.descriptor = 0x21,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 256,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x22
Packit 577717
	{.descriptor = 0x22,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 512,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x23
Packit 577717
	{.descriptor = 0x23,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 1024,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x25
Packit 577717
	{.descriptor = 0x25,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 2048,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x29
Packit 577717
	{.descriptor = 0x29,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 4096,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x2C
Packit 577717
	{.descriptor = 0x2C,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 32,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x30
Packit 577717
	{.descriptor = 0x30,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_INST,
Packit 577717
	 .size[0] = 32,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x39
Packit 577717
	{.descriptor = 0x39,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 128,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x3A
Packit 577717
	{.descriptor = 0x3A,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 192,
Packit 577717
	 .associativity = 6,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x3B
Packit 577717
	{.descriptor = 0x3B,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 128,
Packit 577717
	 .associativity = 2,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x3C
Packit 577717
	{.descriptor = 0x3C,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 256,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x3D
Packit 577717
	{.descriptor = 0x3D,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 384,
Packit 577717
	 .associativity = 6,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x3E
Packit 577717
	{.descriptor = 0x3E,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 512,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x40: no last level cache (??)
Packit 577717
// 0x41
Packit 577717
	{.descriptor = 0x41,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 128,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .line_size = 32,
Packit 577717
	 },
Packit 577717
// 0x42
Packit 577717
	{.descriptor = 0x42,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 256,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .line_size = 32,
Packit 577717
	 },
Packit 577717
// 0x43
Packit 577717
	{.descriptor = 0x43,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 512,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .line_size = 32,
Packit 577717
	 },
Packit 577717
// 0x44
Packit 577717
	{.descriptor = 0x44,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 1024,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .line_size = 32,
Packit 577717
	 },
Packit 577717
// 0x45
Packit 577717
	{.descriptor = 0x45,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 2048,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .line_size = 32,
Packit 577717
	 },
Packit 577717
// 0x46
Packit 577717
	{.descriptor = 0x46,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 4096,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x47
Packit 577717
	{.descriptor = 0x47,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 8192,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x48
Packit 577717
	{.descriptor = 0x48,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 3072,
Packit 577717
	 .associativity = 12,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x49 NOTE: for family 0x0F model 0x06 this is level 3
Packit 577717
	{.descriptor = 0x49,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 4096,
Packit 577717
	 .associativity = 16,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x4A
Packit 577717
	{.descriptor = 0x4A,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 6144,
Packit 577717
	 .associativity = 12,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x4B
Packit 577717
	{.descriptor = 0x4B,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 8192,
Packit 577717
	 .associativity = 16,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x4C
Packit 577717
	{.descriptor = 0x4C,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 12288,
Packit 577717
	 .associativity = 12,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x4D
Packit 577717
	{.descriptor = 0x4D,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 16384,
Packit 577717
	 .associativity = 16,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x4E
Packit 577717
	{.descriptor = 0x4E,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 6144,
Packit 577717
	 .associativity = 24,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x4F
Packit 577717
	{.descriptor = 0x4F,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_INST,
Packit 577717
	 .size[0] = 4,
Packit 577717
	 .associativity = SHRT_MAX,
Packit 577717
	 .entries = 32,
Packit 577717
	 },
Packit 577717
// 0x50
Packit 577717
	{.descriptor = 0x50,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_INST,
Packit 577717
	 .size = {4, 2048, 4096},
Packit 577717
	 .associativity = SHRT_MAX,
Packit 577717
	 .entries = 64,
Packit 577717
	 },
Packit 577717
// 0x51
Packit 577717
	{.descriptor = 0x51,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_INST,
Packit 577717
	 .size = {4, 2048, 4096},
Packit 577717
	 .associativity = SHRT_MAX,
Packit 577717
	 .entries = 128,
Packit 577717
	 },
Packit 577717
// 0x52
Packit 577717
	{.descriptor = 0x52,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_INST,
Packit 577717
	 .size = {4, 2048, 4096},
Packit 577717
	 .associativity = SHRT_MAX,
Packit 577717
	 .entries = 256,
Packit 577717
	 },
Packit 577717
// 0x55
Packit 577717
	{.descriptor = 0x55,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_INST,
Packit 577717
	 .size = {2048, 4096, 0},
Packit 577717
	 .associativity = SHRT_MAX,
Packit 577717
	 .entries = 7,
Packit 577717
	 },
Packit 577717
// 0x56
Packit 577717
	{.descriptor = 0x56,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 4096,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .entries = 16,
Packit 577717
	 },
Packit 577717
// 0x57
Packit 577717
	{.descriptor = 0x57,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 4,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .entries = 16,
Packit 577717
	 },
Packit 577717
// 0x59
Packit 577717
	{.descriptor = 0x59,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 4,
Packit 577717
	 .associativity = SHRT_MAX,
Packit 577717
	 .entries = 16,
Packit 577717
	 },   
Packit 577717
// 0x5A
Packit 577717
	{.descriptor = 0x5A,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_DATA,
Packit 577717
	 .size = {2048, 4096, 0},
Packit 577717
	 .associativity = 4,
Packit 577717
	 .entries = 32,
Packit 577717
	 },
Packit 577717
// 0x5B
Packit 577717
	{.descriptor = 0x5B,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_DATA,
Packit 577717
	 .size = {4, 4096, 0},
Packit 577717
	 .associativity = SHRT_MAX,
Packit 577717
	 .entries = 64,
Packit 577717
	 },
Packit 577717
// 0x5C
Packit 577717
	{.descriptor = 0x5C,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_DATA,
Packit 577717
	 .size = {4, 4096, 0},
Packit 577717
	 .associativity = SHRT_MAX,
Packit 577717
	 .entries = 128,
Packit 577717
	 },
Packit 577717
// 0x5D
Packit 577717
	{.descriptor = 0x5D,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_DATA,
Packit 577717
	 .size = {4, 4096, 0},
Packit 577717
	 .associativity = SHRT_MAX,
Packit 577717
	 .entries = 256,
Packit 577717
	 },
Packit 577717
// 0x60
Packit 577717
	{.descriptor = 0x60,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 16,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x66
Packit 577717
	{.descriptor = 0x66,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 8,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x67
Packit 577717
	{.descriptor = 0x67,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 16,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x68
Packit 577717
	{.descriptor = 0x68,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 32,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x70
Packit 577717
	{.descriptor = 0x70,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TRACE,
Packit 577717
	 .size[0] = 12,
Packit 577717
	 .associativity = 8,
Packit 577717
	 },
Packit 577717
// 0x71
Packit 577717
	{.descriptor = 0x71,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TRACE,
Packit 577717
	 .size[0] = 16,
Packit 577717
	 .associativity = 8,
Packit 577717
	 },
Packit 577717
// 0x72
Packit 577717
	{.descriptor = 0x72,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TRACE,
Packit 577717
	 .size[0] = 32,
Packit 577717
	 .associativity = 8,
Packit 577717
	 },
Packit 577717
// 0x73
Packit 577717
	{.descriptor = 0x73,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TRACE,
Packit 577717
	 .size[0] = 64,
Packit 577717
	 .associativity = 8,
Packit 577717
	 },
Packit 577717
// 0x78
Packit 577717
	{.descriptor = 0x78,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 1024,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x79
Packit 577717
	{.descriptor = 0x79,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 128,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x7A
Packit 577717
	{.descriptor = 0x7A,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 256,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x7B
Packit 577717
	{.descriptor = 0x7B,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 512,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x7C
Packit 577717
	{.descriptor = 0x7C,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 1024,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .sector = 1,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x7D
Packit 577717
	{.descriptor = 0x7D,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 2048,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x7F
Packit 577717
	{.descriptor = 0x7F,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 512,
Packit 577717
	 .associativity = 2,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x80
Packit 577717
	{.descriptor = 0x80,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 512,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },   
Packit 577717
// 0x82
Packit 577717
	{.descriptor = 0x82,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 256,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .line_size = 32,
Packit 577717
	 },
Packit 577717
// 0x83
Packit 577717
	{.descriptor = 0x83,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 512,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .line_size = 32,
Packit 577717
	 },
Packit 577717
// 0x84
Packit 577717
	{.descriptor = 0x84,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 1024,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .line_size = 32,
Packit 577717
	 },
Packit 577717
// 0x85
Packit 577717
	{.descriptor = 0x85,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 2048,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .line_size = 32,
Packit 577717
	 },
Packit 577717
// 0x86
Packit 577717
	{.descriptor = 0x86,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 512,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0x87
Packit 577717
	{.descriptor = 0x87,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 1024,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0xB0
Packit 577717
	{.descriptor = 0xB0,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_INST,
Packit 577717
	 .size[0] = 4,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .entries = 128,
Packit 577717
	 },
Packit 577717
// 0xB1 NOTE: This is currently the only instance where .entries
Packit 577717
//      is dependent on .size. It's handled as a code exception.
Packit 577717
//      If other instances appear in the future, the structure
Packit 577717
//      should probably change to accomodate it.
Packit 577717
	{.descriptor = 0xB1,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_INST,
Packit 577717
	 .size = {2048, 4096, 0},
Packit 577717
	 .associativity = 4,
Packit 577717
	 .entries = 8,			 /* or 4 if size = 4096 */
Packit 577717
	 },
Packit 577717
// 0xB2
Packit 577717
	{.descriptor = 0xB2,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_INST,
Packit 577717
	 .size[0] = 4,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .entries = 64,
Packit 577717
	 },
Packit 577717
// 0xB3
Packit 577717
	{.descriptor = 0xB3,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 4,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .entries = 128,
Packit 577717
	 },
Packit 577717
// 0xB4
Packit 577717
	{.descriptor = 0xB4,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 4,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .entries = 256,
Packit 577717
	 },
Packit 577717
// 0xBA
Packit 577717
	{.descriptor = 0xBA,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_DATA,
Packit 577717
	 .size[0] = 4,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .entries = 64,
Packit 577717
	 },   
Packit 577717
// 0xC0
Packit 577717
	{.descriptor = 0xBA,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_DATA,
Packit 577717
	 .size = {4,4096},
Packit 577717
	 .associativity = 4,
Packit 577717
	 .entries = 8,
Packit 577717
	 },      
Packit 577717
// 0xCA
Packit 577717
	{.descriptor = 0xCA,
Packit 577717
	 .level = 2,
Packit 577717
	 .type = PAPI_MH_TYPE_TLB | PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 4,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .entries = 512,
Packit 577717
	 },
Packit 577717
// 0xD0
Packit 577717
	{.descriptor = 0xD0,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 512,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0xD1
Packit 577717
	{.descriptor = 0xD1,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 1024,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0xD2
Packit 577717
	{.descriptor = 0xD2,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 2048,
Packit 577717
	 .associativity = 4,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0xD6
Packit 577717
	{.descriptor = 0xD6,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 1024,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0xD7
Packit 577717
	{.descriptor = 0xD7,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 2048,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0xD8
Packit 577717
	{.descriptor = 0xD8,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 4096,
Packit 577717
	 .associativity = 8,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0xDC
Packit 577717
	{.descriptor = 0xDC,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 1536,
Packit 577717
	 .associativity = 12,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0xDD
Packit 577717
	{.descriptor = 0xDD,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 3072,
Packit 577717
	 .associativity = 12,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0xDE
Packit 577717
	{.descriptor = 0xDE,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 6144,
Packit 577717
	 .associativity = 12,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0xE2
Packit 577717
	{.descriptor = 0xE2,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 2048,
Packit 577717
	 .associativity = 16,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0xE3
Packit 577717
	{.descriptor = 0xE3,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 4096,
Packit 577717
	 .associativity = 16,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0xE4
Packit 577717
	{.descriptor = 0xE4,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 8192,
Packit 577717
	 .associativity = 16,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0xEA
Packit 577717
	{.descriptor = 0xEA,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 12288,
Packit 577717
	 .associativity = 24,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0xEB
Packit 577717
	{.descriptor = 0xEB,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 18432,
Packit 577717
	 .associativity = 24,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0xEC
Packit 577717
	{.descriptor = 0xEC,
Packit 577717
	 .level = 3,
Packit 577717
	 .type = PAPI_MH_TYPE_UNIFIED,
Packit 577717
	 .size[0] = 24576,
Packit 577717
	 .associativity = 24,
Packit 577717
	 .line_size = 64,
Packit 577717
	 },
Packit 577717
// 0xF0
Packit 577717
	{.descriptor = 0xF0,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_PREF,
Packit 577717
	 .size[0] = 64,
Packit 577717
	 },
Packit 577717
// 0xF1
Packit 577717
	{.descriptor = 0xF1,
Packit 577717
	 .level = 1,
Packit 577717
	 .type = PAPI_MH_TYPE_PREF,
Packit 577717
	 .size[0] = 128,
Packit 577717
	 },
Packit 577717
};
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
static void
Packit 577717
print_intel_cache_table(  )
Packit 577717
{
Packit 577717
	int i, j, k =
Packit 577717
		( int ) ( sizeof ( intel_cache ) /
Packit 577717
				  sizeof ( struct _intel_cache_info ) );
Packit 577717
	for ( i = 0; i < k; i++ ) {
Packit 577717
		printf( "%d.\tDescriptor: %#x\n", i, intel_cache[i].descriptor );
Packit 577717
		printf( "\t  Level:     %d\n", intel_cache[i].level );
Packit 577717
		printf( "\t  Type:      %d\n", intel_cache[i].type );
Packit 577717
		printf( "\t  Size(s):   " );
Packit 577717
		for ( j = 0; j < TLB_SIZES; j++ )
Packit 577717
			printf( "%d, ", intel_cache[i].size[j] );
Packit 577717
		printf( "\n" );
Packit 577717
		printf( "\t  Assoc:     %d\n", intel_cache[i].associativity );
Packit 577717
		printf( "\t  Sector:    %d\n", intel_cache[i].sector );
Packit 577717
		printf( "\t  Line Size: %d\n", intel_cache[i].line_size );
Packit 577717
		printf( "\t  Entries:   %d\n", intel_cache[i].entries );
Packit 577717
		printf( "\n" );
Packit 577717
	}
Packit 577717
}
Packit 577717
#endif
Packit 577717
Packit 577717
/* Given a specific cache descriptor, this routine decodes the information from a table
Packit 577717
 * of such descriptors and fills out one or more records in a PAPI data structure.
Packit 577717
 * Called only by init_intel()
Packit 577717
 */
Packit 577717
static void
Packit 577717
intel_decode_descriptor( struct _intel_cache_info *d, PAPI_mh_level_t * L )
Packit 577717
{
Packit 577717
	int i, next;
Packit 577717
	int level = d->level - 1;
Packit 577717
	PAPI_mh_tlb_info_t *t;
Packit 577717
	PAPI_mh_cache_info_t *c;
Packit 577717
Packit 577717
	if ( d->descriptor == 0x49 ) {	/* special case */
Packit 577717
		unsigned int r_eax, r_ebx, r_ecx, r_edx;
Packit 577717
		r_eax = 0x1;		 /* function code 1: family & model */
Packit 577717
		cpuid( &r_eax, &r_ebx, &r_ecx, &r_edx );
Packit 577717
		/* override table for Family F, model 6 only */
Packit 577717
		if ( ( r_eax & 0x0FFF3FF0 ) == 0xF60 )
Packit 577717
			level = 3;
Packit 577717
	}
Packit 577717
	if ( d->type & PAPI_MH_TYPE_TLB ) {
Packit 577717
		for ( next = 0; next < PAPI_MH_MAX_LEVELS - 1; next++ ) {
Packit 577717
			if ( L[level].tlb[next].type == PAPI_MH_TYPE_EMPTY )
Packit 577717
				break;
Packit 577717
		}
Packit 577717
		/* expand TLB entries for multiple possible page sizes */
Packit 577717
		for ( i = 0; i < TLB_SIZES && next < PAPI_MH_MAX_LEVELS && d->size[i];
Packit 577717
			  i++, next++ ) {
Packit 577717
//          printf("Level %d Descriptor: %#x TLB type %#x next: %d, i: %d\n", level, d->descriptor, d->type, next, i);
Packit 577717
			t = &L[level].tlb[next];
Packit 577717
			t->type = PAPI_MH_CACHE_TYPE( d->type );
Packit 577717
			t->num_entries = d->entries;
Packit 577717
			t->page_size = d->size[i] << 10;	/* minimum page size in KB */
Packit 577717
			t->associativity = d->associativity;
Packit 577717
			/* another special case */
Packit 577717
			if ( d->descriptor == 0xB1 && d->size[i] == 4096 )
Packit 577717
				t->num_entries = d->entries / 2;
Packit 577717
		}
Packit 577717
	} else {
Packit 577717
		for ( next = 0; next < PAPI_MH_MAX_LEVELS - 1; next++ ) {
Packit 577717
			if ( L[level].cache[next].type == PAPI_MH_TYPE_EMPTY )
Packit 577717
				break;
Packit 577717
		}
Packit 577717
//      printf("Level %d Descriptor: %#x Cache type %#x next: %d\n", level, d->descriptor, d->type, next);
Packit 577717
		c = &L[level].cache[next];
Packit 577717
		c->type = PAPI_MH_CACHE_TYPE( d->type );
Packit 577717
		c->size = d->size[0] << 10;	/* convert from KB to bytes */
Packit 577717
		c->associativity = d->associativity;
Packit 577717
		if ( d->line_size ) {
Packit 577717
			c->line_size = d->line_size;
Packit 577717
			c->num_lines = c->size / c->line_size;
Packit 577717
		}
Packit 577717
	}
Packit 577717
}
Packit 577717
Packit 577717
#if defined(__amd64__) || defined(__x86_64__)
Packit 577717
static inline void
Packit 577717
cpuid2( unsigned int*eax, unsigned int* ebx,
Packit 577717
		unsigned int*ecx, unsigned int *edx,
Packit 577717
		unsigned int index, unsigned int ecx_in )
Packit 577717
{
Packit 577717
	__asm__ __volatile__ ("cpuid;"
Packit 577717
		: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
Packit 577717
		: "0" (index), "2"(ecx_in) );
Packit 577717
}
Packit 577717
#else
Packit 577717
static inline void
Packit 577717
cpuid2 ( unsigned int* eax, unsigned int* ebx, 
Packit 577717
                    unsigned int* ecx, unsigned int* edx, 
Packit 577717
                    unsigned int index, unsigned int ecx_in )
Packit 577717
{
Packit 577717
  unsigned int a,b,c,d;
Packit 577717
  __asm__ __volatile__ (".byte 0x53\n\tcpuid\n\tmovl %%ebx, %%esi\n\t.byte 0x5b"
Packit 577717
		: "=a" (a), "=S" (b), "=c" (c), "=d" (d) \
Packit 577717
		: "0" (index), "2"(ecx_in) );
Packit 577717
  *eax = a; *ebx = b; *ecx = c; *edx = d;
Packit 577717
}
Packit 577717
#endif
Packit 577717
Packit 577717
Packit 577717
static int
Packit 577717
init_intel_leaf4( PAPI_mh_info_t * mh_info, int *num_levels )
Packit 577717
{
Packit 577717
Packit 577717
  unsigned int eax, ebx, ecx, edx;
Packit 577717
  unsigned int maxidx, ecx_in;
Packit 577717
  int next;
Packit 577717
Packit 577717
  int cache_type,cache_level,cache_selfinit,cache_fullyassoc;
Packit 577717
  int cache_linesize,cache_partitions,cache_ways,cache_sets;
Packit 577717
Packit 577717
  PAPI_mh_cache_info_t *c;
Packit 577717
Packit 577717
  *num_levels=0;
Packit 577717
Packit 577717
  cpuid2(&eax,&ebx,&ecx,&edx, 0, 0);
Packit 577717
  maxidx = eax;
Packit 577717
  
Packit 577717
  if (maxidx<4) {
Packit 577717
    MEMDBG("Warning!  CPUID Index 4 not supported!\n");
Packit 577717
    return PAPI_ENOSUPP;
Packit 577717
  }
Packit 577717
Packit 577717
  ecx_in=0;
Packit 577717
  while(1) {
Packit 577717
    cpuid2(&eax,&ebx,&ecx,&edx, 4, ecx_in);
Packit 577717
Packit 577717
Packit 577717
    
Packit 577717
    /* decoded as per table 3-12 in Intel Software Developer's Manual Volume 2A */
Packit 577717
     
Packit 577717
    cache_type=eax&0x1f;
Packit 577717
    if (cache_type==0) break;     
Packit 577717
     
Packit 577717
    cache_level=(eax>>5)&0x3;
Packit 577717
    cache_selfinit=(eax>>8)&0x1;
Packit 577717
    cache_fullyassoc=(eax>>9)&0x1;
Packit 577717
Packit 577717
    cache_linesize=(ebx&0xfff)+1;
Packit 577717
    cache_partitions=((ebx>>12)&0x3ff)+1;
Packit 577717
    cache_ways=((ebx>>22)&0x3ff)+1;
Packit 577717
       
Packit 577717
    cache_sets=(ecx)+1;
Packit 577717
Packit 577717
    /* should we export this info?
Packit 577717
Packit 577717
    cache_maxshare=((eax>>14)&0xfff)+1;
Packit 577717
    cache_maxpackage=((eax>>26)&0x3f)+1;
Packit 577717
     
Packit 577717
    cache_wb=(edx)&1;
Packit 577717
    cache_inclusive=(edx>>1)&1;
Packit 577717
    cache_indexing=(edx>>2)&1;
Packit 577717
    */
Packit 577717
Packit 577717
    if (cache_level>*num_levels) *num_levels=cache_level;
Packit 577717
Packit 577717
    /* find next slot available to hold cache info */
Packit 577717
    for ( next = 0; next < PAPI_MH_MAX_LEVELS - 1; next++ ) {
Packit 577717
        if ( mh_info->level[cache_level-1].cache[next].type == PAPI_MH_TYPE_EMPTY ) break;
Packit 577717
    }
Packit 577717
Packit 577717
    c=&(mh_info->level[cache_level-1].cache[next]);
Packit 577717
Packit 577717
    switch(cache_type) {
Packit 577717
      case 1: MEMDBG("L%d Data Cache\n",cache_level); 
Packit 577717
	c->type=PAPI_MH_TYPE_DATA;
Packit 577717
	break;
Packit 577717
      case 2: MEMDBG("L%d Instruction Cache\n",cache_level); 
Packit 577717
	c->type=PAPI_MH_TYPE_INST;
Packit 577717
	break;
Packit 577717
      case 3: MEMDBG("L%d Unified Cache\n",cache_level); 
Packit 577717
	c->type=PAPI_MH_TYPE_UNIFIED;
Packit 577717
	break;
Packit 577717
    }
Packit 577717
     
Packit 577717
    if (cache_selfinit) { MEMDBG("\tSelf-init\n"); }
Packit 577717
    if (cache_fullyassoc) { MEMDBG("\tFully Associtative\n"); }
Packit 577717
     
Packit 577717
    //MEMDBG("\tMax logical processors sharing cache: %d\n",cache_maxshare);
Packit 577717
    //MEMDBG("\tMax logical processors sharing package: %d\n",cache_maxpackage);
Packit 577717
     
Packit 577717
    MEMDBG("\tCache linesize: %d\n",cache_linesize);
Packit 577717
Packit 577717
    MEMDBG("\tCache partitions: %d\n",cache_partitions);
Packit 577717
    MEMDBG("\tCache associaticity: %d\n",cache_ways);
Packit 577717
Packit 577717
    MEMDBG("\tCache sets: %d\n",cache_sets);
Packit 577717
    MEMDBG("\tCache size = %dkB\n",
Packit 577717
	   (cache_ways*cache_partitions*cache_linesize*cache_sets)/1024);
Packit 577717
Packit 577717
    //MEMDBG("\tWBINVD/INVD acts on lower caches: %d\n",cache_wb);
Packit 577717
    //MEMDBG("\tCache is not inclusive: %d\n",cache_inclusive);
Packit 577717
    //MEMDBG("\tComplex cache indexing: %d\n",cache_indexing);
Packit 577717
Packit 577717
    c->line_size=cache_linesize;
Packit 577717
    if (cache_fullyassoc) {
Packit 577717
       c->associativity=SHRT_MAX;
Packit 577717
    }
Packit 577717
    else {
Packit 577717
       c->associativity=cache_ways;
Packit 577717
    }
Packit 577717
    c->size=(cache_ways*cache_partitions*cache_linesize*cache_sets);
Packit 577717
    c->num_lines=cache_ways*cache_partitions*cache_sets;
Packit 577717
     
Packit 577717
    ecx_in++;
Packit 577717
  }
Packit 577717
  return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
init_intel_leaf2( PAPI_mh_info_t * mh_info , int *num_levels)
Packit 577717
{
Packit 577717
	/* cpuid() returns memory copies of 4 32-bit registers
Packit 577717
	 * this union allows them to be accessed as either registers
Packit 577717
	 * or individual bytes. Remember that Intel is little-endian.
Packit 577717
	 */
Packit 577717
	union
Packit 577717
	{
Packit 577717
		struct
Packit 577717
		{
Packit 577717
			unsigned int ax, bx, cx, dx;
Packit 577717
		} e;
Packit 577717
		unsigned char descrip[16];
Packit 577717
	} reg;
Packit 577717
Packit 577717
	int r;							   /* register boundary index */
Packit 577717
	int b;							   /* byte index into a register */
Packit 577717
	int i;							   /* byte index into the descrip array */
Packit 577717
	int t;							   /* table index into the static descriptor table */
Packit 577717
	int count;						   /* how many times to call cpuid; from eax:lsb */
Packit 577717
	int size;						   /* size of the descriptor table */
Packit 577717
	int last_level = 0;				   /* how many levels in the cache hierarchy */
Packit 577717
Packit 577717
	/* All of Intel's cache info is in 1 call to cpuid
Packit 577717
	 * however it is a table lookup :(
Packit 577717
	 */
Packit 577717
	MEMDBG( "Initializing Intel Cache and TLB descriptors\n" );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	if ( ISLEVEL( DEBUG_MEMORY ) )
Packit 577717
		print_intel_cache_table(  );
Packit 577717
#endif
Packit 577717
Packit 577717
	reg.e.ax = 0x2;			 /* function code 2: cache descriptors */
Packit 577717
	cpuid( &reg.e.ax, &reg.e.bx, &reg.e.cx, &reg.e.dx );
Packit 577717
Packit 577717
	MEMDBG( "e.ax=%#8.8x e.bx=%#8.8x e.cx=%#8.8x e.dx=%#8.8x\n",
Packit 577717
			reg.e.ax, reg.e.bx, reg.e.cx, reg.e.dx );
Packit 577717
	MEMDBG
Packit 577717
		( ":\nd0: %#x %#x %#x %#x\nd1: %#x %#x %#x %#x\nd2: %#x %#x %#x %#x\nd3: %#x %#x %#x %#x\n",
Packit 577717
		  reg.descrip[0], reg.descrip[1], reg.descrip[2], reg.descrip[3],
Packit 577717
		  reg.descrip[4], reg.descrip[5], reg.descrip[6], reg.descrip[7],
Packit 577717
		  reg.descrip[8], reg.descrip[9], reg.descrip[10], reg.descrip[11],
Packit 577717
		  reg.descrip[12], reg.descrip[13], reg.descrip[14], reg.descrip[15] );
Packit 577717
Packit 577717
	count = reg.descrip[0];	 /* # times to repeat CPUID call. Not implemented. */
Packit 577717
Packit 577717
	/* Knights Corner at least returns 0 here */
Packit 577717
	if (count==0) goto early_exit;
Packit 577717
Packit 577717
	size = ( sizeof ( intel_cache ) / sizeof ( struct _intel_cache_info ) );	/* # descriptors */
Packit 577717
	MEMDBG( "Repeat cpuid(2,...) %d times. If not 1, code is broken.\n",
Packit 577717
			count );
Packit 577717
	if (count!=1) {
Packit 577717
	   fprintf(stderr,"Warning: Unhandled cpuid count of %d\n",count);
Packit 577717
	}
Packit 577717
Packit 577717
	for ( r = 0; r < 4; r++ ) {	/* walk the registers */
Packit 577717
		if ( ( reg.descrip[r * 4 + 3] & 0x80 ) == 0 ) {	/* only process if high order bit is 0 */
Packit 577717
			for ( b = 3; b >= 0; b-- ) {	/* walk the descriptor bytes from high to low */
Packit 577717
				i = r * 4 + b;	/* calculate an index into the array of descriptors */
Packit 577717
				if ( i ) {	 /* skip the low order byte in eax [0]; it's the count (see above) */
Packit 577717
				   if ( reg.descrip[i] == 0xff ) {
Packit 577717
				      MEMDBG("Warning! PAPI x86_cache: must implement cpuid leaf 4\n");
Packit 577717
				      return PAPI_ENOSUPP;
Packit 577717
				      /* we might continue instead */
Packit 577717
				      /* in order to get TLB info  */
Packit 577717
				      /* continue;                 */
Packit 577717
				   }
Packit 577717
					for ( t = 0; t < size; t++ ) {	/* walk the descriptor table */					   
Packit 577717
						if ( reg.descrip[i] == intel_cache[t].descriptor ) {	/* find match */
Packit 577717
							if ( intel_cache[t].level > last_level )
Packit 577717
								last_level = intel_cache[t].level;
Packit 577717
							intel_decode_descriptor( &intel_cache[t],
Packit 577717
													 mh_info->level );
Packit 577717
						}
Packit 577717
					}
Packit 577717
				}
Packit 577717
			}
Packit 577717
		}
Packit 577717
	}
Packit 577717
early_exit:
Packit 577717
	MEMDBG( "# of Levels: %d\n", last_level );
Packit 577717
	*num_levels=last_level;
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
static int
Packit 577717
init_intel( PAPI_mh_info_t * mh_info, int *levels )
Packit 577717
{
Packit 577717
Packit 577717
  int result;
Packit 577717
  int num_levels;
Packit 577717
Packit 577717
  /* try using the oldest leaf2 method first */
Packit 577717
  result=init_intel_leaf2(mh_info, &num_levels);
Packit 577717
  
Packit 577717
  if (result!=PAPI_OK) {
Packit 577717
     /* All Core2 and newer also support leaf4 detection */
Packit 577717
     /* Starting with Westmere *only* leaf4 is supported */
Packit 577717
     result=init_intel_leaf4(mh_info, &num_levels);
Packit 577717
  }
Packit 577717
Packit 577717
  *levels=num_levels;
Packit 577717
  return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/* Returns 1 if hypervisor detected */
Packit 577717
/* Returns 0 if none found.         */
Packit 577717
int 
Packit 577717
_x86_detect_hypervisor(char *vendor_name)
Packit 577717
{
Packit 577717
  unsigned int eax, ebx, ecx, edx;
Packit 577717
  char hyper_vendor_id[13];
Packit 577717
Packit 577717
  cpuid2(&eax, &ebx, &ecx, &edx,0x1,0);
Packit 577717
  /* This is the hypervisor bit, ecx bit 31 */
Packit 577717
  if  (ecx&0x80000000) {
Packit 577717
    /* There are various values in the 0x4000000X range */
Packit 577717
    /* It is questionable how standard they are         */
Packit 577717
    /* For now we just return the name.                 */
Packit 577717
    cpuid2(&eax, &ebx, &ecx, &edx, 0x40000000,0);
Packit 577717
    memcpy(hyper_vendor_id + 0, &ebx, 4);
Packit 577717
    memcpy(hyper_vendor_id + 4, &ecx, 4);
Packit 577717
    memcpy(hyper_vendor_id + 8, &edx, 4);
Packit 577717
    hyper_vendor_id[12] = '\0';
Packit 577717
    strncpy(vendor_name,hyper_vendor_id,PAPI_MAX_STR_LEN);
Packit 577717
    return 1;
Packit 577717
  }
Packit 577717
  else {
Packit 577717
    strncpy(vendor_name,"none",PAPI_MAX_STR_LEN);
Packit 577717
  }
Packit 577717
  return 0;
Packit 577717
}