PAPI 7.1.0.0
Loading...
Searching...
No Matches
x86_cpu_utils.c File Reference
Include dependency graph for x86_cpu_utils.c:

Go to the source code of this file.

Data Structures

struct  apic_subid_mask_t
 
struct  apic_subid_t
 
struct  cpuid_reg_t
 

Functions

static int cpuid_get_vendor (char *vendor)
 
static int cpuid_get_name (char *name)
 
static int cpuid_get_attribute (CPU_attr_e attr, int *value)
 
static int cpuid_get_attribute_at (CPU_attr_e attr, int loc, int *value)
 
static int cpuid_get_topology_info (CPU_attr_e attr, int *value)
 
static int cpuid_get_cache_info (CPU_attr_e attr, int level, int *value)
 
static int intel_get_cache_info (CPU_attr_e attr, int level, int *value)
 
static int amd_get_cache_info (CPU_attr_e attr, int level, int *value)
 
static int cpuid_supports_leaves_4_11 (void)
 
static int enum_cpu_resources (int num_mappings, apic_subid_mask_t *mask, apic_subid_t *subids, int *sockets, int *cores, int *threads)
 
static int cpuid_get_versioning_info (CPU_attr_e attr, int *value)
 
static int cpuid_parse_id_foreach_thread (unsigned int num_mappings, apic_subid_mask_t *mask, apic_subid_t *subid)
 
static int cpuid_parse_ids (int os_proc_count, apic_subid_mask_t *mask, apic_subid_t *subid)
 
static int cpuid_get_mask (apic_subid_mask_t *mask)
 
static int cpuid_get_leaf11_mask (apic_subid_mask_t *mask)
 
static int cpuid_get_leaf4_mask (apic_subid_mask_t *mask)
 
static unsigned int cpuid_get_x2apic_id (void)
 
static unsigned int cpuid_get_apic_id (void)
 
static unsigned int bit_width (unsigned int x)
 
static void cpuid (cpuid_reg_t *reg, const unsigned int func)
 
static void cpuid2 (cpuid_reg_t *reg, const unsigned int func, const unsigned int subfunc)
 
int x86_cpu_init (void)
 
int x86_cpu_finalize (void)
 
int x86_cpu_get_vendor (char *vendor)
 
int x86_cpu_get_name (char *name)
 
int x86_cpu_get_attribute (CPU_attr_e attr, int *value)
 
int x86_cpu_get_attribute_at (CPU_attr_e attr, int loc, int *value)
 

Variables

static _sysdetect_cache_level_info_t clevel [PAPI_MAX_MEM_HIERARCHY_LEVELS]
 
static int cpuid_has_leaf4
 
static int cpuid_has_leaf11
 

Function Documentation

◆ amd_get_cache_info()

int amd_get_cache_info ( CPU_attr_e  attr,
int  level,
int value 
)
static

Definition at line 381 of file x86_cpu_utils.c.

382{
383 static _sysdetect_cache_level_info_t *clevel_ptr;
384
385 if (clevel_ptr) {
386 return cpu_get_cache_info(attr, level, clevel_ptr, value);
387 }
388
389 cpuid_reg_t reg;
390
391 /* L1 Caches */
392 cpuid(&reg, 0x80000005);
393
394 unsigned char byt[16];
395 memcpy(byt , &reg.eax, 4);
396 memcpy(byt + 4 , &reg.ebx, 4);
397 memcpy(byt + 8 , &reg.ecx, 4);
398 memcpy(byt + 12, &reg.edx, 4);
399
400 clevel_ptr = clevel;
401 clevel_ptr[0].cache[0].type = PAPI_MH_TYPE_DATA;
402 clevel_ptr[0].cache[0].size = byt[11] << 10;
403 clevel_ptr[0].cache[0].line_size = byt[8];
404 clevel_ptr[0].cache[0].num_lines = clevel_ptr[0].cache[0].size / clevel_ptr[0].cache[0].line_size;
405 clevel_ptr[0].cache[0].associativity = byt[10];
406
407 clevel_ptr[0].cache[1].type = PAPI_MH_TYPE_INST;
408 clevel_ptr[0].cache[1].size = byt[15] << 10;
409 clevel_ptr[0].cache[1].line_size = byt[12];
410 clevel_ptr[0].cache[1].num_lines = clevel_ptr[0].cache[1].size / clevel_ptr[0].cache[1].line_size;
411 clevel_ptr[0].cache[1].associativity = byt[14];
412
413 clevel_ptr[0].num_caches = 2;
414
415 /* L2 and L3 caches */
416 cpuid(&reg, 0x80000006);
417
418 memcpy(byt , &reg.eax, 4);
419 memcpy(byt + 4 , &reg.ebx, 4);
420 memcpy(byt + 8 , &reg.ecx, 4);
421 memcpy(byt + 12, &reg.edx, 4);
422
423 static short int assoc[16] = {
424 0, 1, 2, -1, 4, -1, 8, -1, 16, -1, 32, 48, 64, 96, 128, SHRT_MAX
425 };
426
427 if (reg.ecx) {
428 clevel_ptr[1].cache[0].type = PAPI_MH_TYPE_UNIFIED;
429 clevel_ptr[1].cache[0].size = (int)((reg.ecx & 0xffff0000) >> 6);
430 clevel_ptr[1].cache[0].line_size = byt[8];
431 clevel_ptr[1].cache[0].num_lines = clevel_ptr[1].cache[0].size / clevel_ptr[1].cache[0].line_size;
432 clevel_ptr[1].cache[0].associativity = assoc[(byt[9] & 0xf0) >> 4];
433 clevel_ptr[1].num_caches = 1;
434 }
435
436 if (reg.edx) {
437 clevel_ptr[2].cache[0].type = PAPI_MH_TYPE_UNIFIED;
438 clevel_ptr[2].cache[0].size = (int)((reg.edx & 0xfffc0000) << 1);
439 clevel_ptr[2].cache[0].line_size = byt[12];
440 clevel_ptr[2].cache[0].num_lines = clevel_ptr[1].cache[0].size / clevel_ptr[1].cache[0].line_size;
441 clevel_ptr[2].cache[0].associativity = assoc[(byt[13] & 0xf0) >> 4];
442 clevel_ptr[2].num_caches = 1;
443 }
444
445 return cpu_get_cache_info(attr, level, clevel_ptr, value);
446}
int cpu_get_cache_info(CPU_attr_e attr, int level, _sysdetect_cache_level_info_t *clevel_ptr, int *value)
Definition: cpu_utils.c:94
#define PAPI_MH_TYPE_DATA
Definition: papi.h:720
#define PAPI_MH_TYPE_INST
Definition: papi.h:719
#define PAPI_MH_TYPE_UNIFIED
Definition: papi.h:723
int
Definition: sde_internal.h:89
PAPI_mh_cache_info_t cache[PAPI_MH_MAX_LEVELS]
Definition: sysdetect.h:57
unsigned int ecx
Definition: x86_cpu_utils.c:27
unsigned int edx
Definition: x86_cpu_utils.c:28
unsigned int ebx
Definition: x86_cpu_utils.c:26
unsigned int eax
Definition: x86_cpu_utils.c:25
static void cpuid(cpuid_reg_t *reg, const unsigned int func)
static _sysdetect_cache_level_info_t clevel[PAPI_MAX_MEM_HIERARCHY_LEVELS]
Definition: x86_cpu_utils.c:31
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bit_width()

unsigned int bit_width ( unsigned int  x)
static

Definition at line 736 of file x86_cpu_utils.c.

737{
738 int count = 0;
739 double y = (double) x;
740
741 while ((y /= 2) > 1) {
742 ++count;
743 }
744
745 return (y < 1) ? count + 1 : count;
746}
static long count
volatile double y
volatile double x
Here is the caller graph for this function:

◆ cpuid()

void cpuid ( cpuid_reg_t reg,
const unsigned int  func 
)
static

Definition at line 757 of file x86_cpu_utils.c.

758{
759 cpuid2(reg, func, 0);
760}
static void cpuid2(cpuid_reg_t *reg, const unsigned int func, const unsigned int subfunc)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpuid2()

void cpuid2 ( cpuid_reg_t reg,
const unsigned int  func,
const unsigned int  subfunc 
)
static

Definition at line 749 of file x86_cpu_utils.c.

750{
751 __asm__ ("cpuid;"
752 : "=a" (reg->eax), "=b" (reg->ebx), "=c" (reg->ecx), "=d" (reg->edx)
753 : "a" (func), "c" (subfunc));
754}
Here is the caller graph for this function:

◆ cpuid_get_apic_id()

unsigned int cpuid_get_apic_id ( void  )
static

Definition at line 724 of file x86_cpu_utils.c.

725{
726 if (cpuid_has_leaf11) {
727 return cpuid_get_x2apic_id();
728 }
729
730 cpuid_reg_t reg;
731 cpuid(&reg, 1);
732 return (reg.ebx >> 24) & 0x000000ff;
733}
static unsigned int cpuid_get_x2apic_id(void)
static int cpuid_has_leaf11
Definition: x86_cpu_utils.c:62
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpuid_get_attribute()

int cpuid_get_attribute ( CPU_attr_e  attr,
int value 
)
static

Definition at line 151 of file x86_cpu_utils.c.

152{
153 int status = CPU_SUCCESS;
154
155 switch(attr) {
160 status = cpuid_get_topology_info(attr, value);
161 break;
165 status = cpuid_get_versioning_info(attr, value);
166 break;
169 break;
170 default:
171 status = os_cpu_get_attribute(attr, value);
172 }
173
174 return status;
175}
#define CPU_SUCCESS
Definition: cpu_utils.h:4
@ CPU_ATTR__CPUID_MODEL
Definition: cpu_utils.h:14
@ CPU_ATTR__CACHE_MAX_NUM_LEVELS
Definition: cpu_utils.h:17
@ CPU_ATTR__NUM_THREADS
Definition: cpu_utils.h:11
@ CPU_ATTR__CPUID_FAMILY
Definition: cpu_utils.h:13
@ CPU_ATTR__NUM_NODES
Definition: cpu_utils.h:9
@ CPU_ATTR__CPUID_STEPPING
Definition: cpu_utils.h:15
@ CPU_ATTR__NUM_CORES
Definition: cpu_utils.h:10
@ CPU_ATTR__NUM_SOCKETS
Definition: cpu_utils.h:8
#define PAPI_MAX_MEM_HIERARCHY_LEVELS
Definition: f90papi.h:103
int os_cpu_get_attribute(CPU_attr_e attr, int *value)
Definition: os_cpu_utils.c:30
static int cpuid_get_topology_info(CPU_attr_e attr, int *value)
static int cpuid_get_versioning_info(CPU_attr_e attr, int *value)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpuid_get_attribute_at()

int cpuid_get_attribute_at ( CPU_attr_e  attr,
int  loc,
int value 
)
static

Definition at line 178 of file x86_cpu_utils.c.

179{
180 int status = CPU_SUCCESS;
181
182 switch(attr) {
198 status = cpuid_get_cache_info(attr, loc, value);
199 break;
202 status = os_cpu_get_attribute_at(attr, loc, value);
203 break;
204 default:
205 status = CPU_ERROR;
206 }
207
208 return status;
209}
#define CPU_ERROR
Definition: cpu_utils.h:5
@ CPU_ATTR__CACHE_INST_TOT_SIZE
Definition: cpu_utils.h:21
@ CPU_ATTR__HWTHREAD_NUMA_AFFINITY
Definition: cpu_utils.h:34
@ CPU_ATTR__CACHE_UNIF_TOT_SIZE
Definition: cpu_utils.h:29
@ CPU_ATTR__CACHE_DATA_ASSOCIATIVITY
Definition: cpu_utils.h:28
@ CPU_ATTR__CACHE_INST_LINE_SIZE
Definition: cpu_utils.h:22
@ CPU_ATTR__NUMA_MEM_SIZE
Definition: cpu_utils.h:36
@ CPU_ATTR__CACHE_UNIF_LINE_SIZE
Definition: cpu_utils.h:30
@ CPU_ATTR__CACHE_DATA_NUM_LINES
Definition: cpu_utils.h:27
@ CPU_ATTR__CACHE_UNIF_ASSOCIATIVITY
Definition: cpu_utils.h:32
@ CPU_ATTR__CACHE_INST_PRESENT
Definition: cpu_utils.h:18
@ CPU_ATTR__CACHE_DATA_PRESENT
Definition: cpu_utils.h:19
@ CPU_ATTR__CACHE_DATA_LINE_SIZE
Definition: cpu_utils.h:26
@ CPU_ATTR__CACHE_INST_ASSOCIATIVITY
Definition: cpu_utils.h:24
@ CPU_ATTR__CACHE_INST_NUM_LINES
Definition: cpu_utils.h:23
@ CPU_ATTR__CACHE_UNIF_NUM_LINES
Definition: cpu_utils.h:31
@ CPU_ATTR__CACHE_DATA_TOT_SIZE
Definition: cpu_utils.h:25
@ CPU_ATTR__CACHE_UNIF_PRESENT
Definition: cpu_utils.h:20
int os_cpu_get_attribute_at(CPU_attr_e attr, int loc, int *value)
Definition: os_cpu_utils.c:42
static int cpuid_get_cache_info(CPU_attr_e attr, int level, int *value)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpuid_get_cache_info()

int cpuid_get_cache_info ( CPU_attr_e  attr,
int  level,
int value 
)
static

Definition at line 295 of file x86_cpu_utils.c.

296{
297 int status = CPU_SUCCESS;
298 char vendor[13] = { 0 };
299
300 cpuid_get_vendor(vendor);
301
302 if (!strcmp(vendor, "GenuineIntel")) {
303 status = intel_get_cache_info(attr, level, value);
304 } else if (!strcmp(vendor, "AuthenticAMD")) {
305 status = amd_get_cache_info(attr, level, value);
306 } else {
307 status = CPU_ERROR;
308 }
309
310 return status;
311}
static int intel_get_cache_info(CPU_attr_e attr, int level, int *value)
static int amd_get_cache_info(CPU_attr_e attr, int level, int *value)
static int cpuid_get_vendor(char *vendor)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpuid_get_leaf11_mask()

int cpuid_get_leaf11_mask ( apic_subid_mask_t mask)
static

Definition at line 627 of file x86_cpu_utils.c.

628{
629 int status = CPU_SUCCESS;
630 int core_reported = 0;
631 int thread_reported = 0;
632 int sub_leaf = 0, level_type, level_shift;
633 unsigned int core_plus_smt_mask = 0;
634 unsigned int core_plus_smt_width = 0;
635
636 do {
637 cpuid_reg_t reg;
638 cpuid2(&reg, 11, sub_leaf);
639 if (reg.ebx == 0)
640 break;
641
642 level_type = (reg.ecx >> 8) & 0x000000ff;
643 level_shift = reg.eax & 0x0000001f;
644
645 /*
646 * x2APIC ID layout (32 bits)
647 * +---------+----------+---------+
648 * | pkg | core | smt |
649 * +---------+----------+---------+
650 * <--------->
651 * level type = 1
652 * level shift = smt width
653 * <-------------------->
654 * level type = 2
655 * level shift = core + smt width
656 *
657 */
658 switch (level_type) {
659 case 1: /* level type is SMT, so the mask width is level shift */
660 mask->smt_mask = ~(0xFFFFFFFF << level_shift);
661 mask->smt_width = level_shift;
662 thread_reported = 1;
663 break;
664 case 2: /* level type is core, so the core + smt mask width is level shift */
665 core_plus_smt_mask = ~(0xFFFFFFFF << level_shift);
666 core_plus_smt_width = level_shift;
667 mask->pkg_mask = 0xFFFFFFFF ^ core_plus_smt_mask;
668 mask->pkg_width = 8; /* use reasonably high value */
669 core_reported = 1;
670 break;
671 default:
672 break;
673 }
674 ++sub_leaf;
675 } while(1);
676
677 if (thread_reported && core_reported) {
678 mask->core_mask = core_plus_smt_mask ^ mask->smt_mask;
679 mask->core_width = core_plus_smt_width - mask->smt_width;
680 } else if (!core_reported && thread_reported) {
681 mask->core_mask = 0;
682 mask->core_width = 0;
683 mask->pkg_mask = 0xFFFFFFFF ^ mask->smt_mask;
684 mask->pkg_width = 8; /* use reasonably high value */
685 } else {
686 status = CPU_ERROR;
687 }
688
689 return status;
690}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpuid_get_leaf4_mask()

int cpuid_get_leaf4_mask ( apic_subid_mask_t mask)
static

Definition at line 693 of file x86_cpu_utils.c.

694{
695 cpuid_reg_t reg;
696 cpuid(&reg, 1);
697 unsigned int core_plus_smt_max_cnt = (reg.ebx >> 16) & 0x000000ff;
698
699 cpuid(&reg, 4);
700 unsigned int core_max_cnt = ((reg.eax >> 26) & 0x0000003f) + 1;
701
702 unsigned int core_width = bit_width(core_max_cnt);
703 unsigned int smt_width = bit_width(core_plus_smt_max_cnt) - core_width;
704
705 mask->smt_mask = ~(0xFFFFFFFF << smt_width);
706 mask->smt_width = smt_width;
707 mask->core_mask = ~(0xFFFFFFFF << bit_width(core_plus_smt_max_cnt)) ^ mask->smt_mask;
708 mask->core_width = core_width;
709 mask->pkg_mask = 0xFFFFFFFF << bit_width(core_plus_smt_max_cnt);
710 mask->pkg_width = 8; /* use reasonably high value */
711
712 return CPU_SUCCESS;
713}
static unsigned int bit_width(unsigned int x)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpuid_get_mask()

int cpuid_get_mask ( apic_subid_mask_t mask)
static

Definition at line 617 of file x86_cpu_utils.c.

618{
619 if (cpuid_has_leaf11) {
620 return cpuid_get_leaf11_mask(mask);
621 }
622
623 return cpuid_get_leaf4_mask(mask);
624}
static int cpuid_get_leaf4_mask(apic_subid_mask_t *mask)
static int cpuid_get_leaf11_mask(apic_subid_mask_t *mask)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpuid_get_name()

int cpuid_get_name ( char *  name)
static

Definition at line 118 of file x86_cpu_utils.c.

119{
120 cpuid_reg_t reg;
121 cpuid(&reg, 0x80000000);
122 if (reg.eax < 0x80000004) {
123 /* Feature not implemented. Fallback! */
124 return os_cpu_get_name(name);
125 }
126
127 cpuid(&reg, 0x80000002);
128 memcpy(name , &reg.eax, 4);
129 memcpy(name + 4 , &reg.ebx, 4);
130 memcpy(name + 8 , &reg.ecx, 4);
131 memcpy(name + 12, &reg.edx, 4);
132
133 cpuid(&reg, 0x80000003);
134 memcpy(name + 16, &reg.eax, 4);
135 memcpy(name + 20, &reg.ebx, 4);
136 memcpy(name + 24, &reg.ecx, 4);
137 memcpy(name + 28, &reg.edx, 4);
138
139 cpuid(&reg, 0x80000004);
140 memcpy(name + 32, &reg.eax, 4);
141 memcpy(name + 36, &reg.ebx, 4);
142 memcpy(name + 40, &reg.ecx, 4);
143 memcpy(name + 44, &reg.edx, 4);
144
145 name[48] = '\0';
146
147 return CPU_SUCCESS;
148}
int os_cpu_get_name(char *name)
Definition: os_cpu_utils.c:18
const char * name
Definition: rocs.c:225
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpuid_get_topology_info()

int cpuid_get_topology_info ( CPU_attr_e  attr,
int value 
)
static

Definition at line 212 of file x86_cpu_utils.c.

213{
214 int status = CPU_SUCCESS;
215 static int sockets, nodes, cores, threads;
216
217 if (attr == CPU_ATTR__NUM_SOCKETS && sockets) {
218 *value = sockets;
219 return status;
220 } else if (attr == CPU_ATTR__NUM_THREADS && threads) {
221 *value = threads;
222 return status;
223 } else if (attr == CPU_ATTR__NUM_CORES && cores) {
224 *value = cores;
225 return status;
226 } else if (attr == CPU_ATTR__NUM_NODES && nodes) {
227 *value = nodes;
228 return status;
229 }
230
231 /* Query for cpuid supported topology enumeration capabilities:
232 * - cpuid in the first generation of Intel Xeon and Intel Pentium 4
233 * supporting hyper-threading (2002) provides information that allows
234 * to decompose the 8-bit wide APIC IDs into a two-level topology
235 * enumeration;
236 * - with the introduction of dual-core Intel 64 processors in 2005,
237 * system topology enumeration using cpuid evolved into a three-level
238 * algorithm (to account for physical cores) on the 8-bit wide APIC ID;
239 * - modern Intel 64 platforms with support for large number of logical
240 * processors use an extended 32-bit wide x2APIC ID. This is known as
241 * cpuid leaf11 interface. Legacy cpuid interface with limited 256
242 * APIC IDs, is referred to as leaf4. */
244 return os_cpu_get_attribute(attr, value);
245 }
246
247 /* Allocate SUBIDs' space for each logical processor */
248 int os_proc_count = os_cpu_get_num_supported();
249 apic_subid_t *subids = papi_malloc(os_proc_count * sizeof(*subids));
250 if (!subids)
251 return CPU_ERROR;
252
253 /* Get masks for later SUBIDs extraction */
254 apic_subid_mask_t mask = { 0 };
255 if (cpuid_get_mask(&mask))
256 goto fn_fail;
257
258 /* For each logical processor get the unique APIC/x2APIC ID and use
259 * use previously retrieved masks to extract package, core and smt
260 * SUBIDs. */
261 int num_mappings = cpuid_parse_ids(os_proc_count, &mask, subids);
262 if (num_mappings == -1)
263 goto fn_fail;
264
265 /* Enumerate all cpu resources once and store them for later */
266 status = enum_cpu_resources(num_mappings, &mask, subids, &sockets,
267 &cores, &threads);
268 if (status != CPU_SUCCESS)
269 goto fn_fail;
270
271 if (attr == CPU_ATTR__NUM_SOCKETS && sockets) {
272 *value = sockets;
273 } else if (attr == CPU_ATTR__NUM_THREADS && threads) {
274 *value = threads;
275 } else if (attr == CPU_ATTR__NUM_CORES && cores) {
276 *value = cores;
277 } else if (attr == CPU_ATTR__NUM_NODES) {
278 /* We can't read the number of numa nodes using cpuid */
279 status = os_cpu_get_attribute(attr, &nodes);
280 *value = nodes;
281 }
282
283 /* Parse subids and get package, core and smt counts */
284 papi_free(subids);
285
286 fn_exit:
287 return status;
288 fn_fail:
289 papi_free(subids);
290 status = CPU_ERROR;
291 goto fn_exit;
292}
int os_cpu_get_num_supported(void)
Definition: os_cpu_utils.c:66
#define papi_free(a)
Definition: papi_memory.h:35
#define papi_malloc(a)
Definition: papi_memory.h:34
static int cpuid_parse_ids(int os_proc_count, apic_subid_mask_t *mask, apic_subid_t *subid)
static int cpuid_supports_leaves_4_11(void)
static int enum_cpu_resources(int num_mappings, apic_subid_mask_t *mask, apic_subid_t *subids, int *sockets, int *cores, int *threads)
static int cpuid_get_mask(apic_subid_mask_t *mask)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpuid_get_vendor()

int cpuid_get_vendor ( char *  vendor)
static

Definition at line 106 of file x86_cpu_utils.c.

107{
108 cpuid_reg_t reg;
109 cpuid(&reg, 0); /* Highest function parameter and manufacturer ID */
110 memcpy(vendor , &reg.ebx, 4);
111 memcpy(vendor + 4, &reg.edx, 4);
112 memcpy(vendor + 8, &reg.ecx, 4);
113 vendor[12] = '\0';
114 return CPU_SUCCESS;
115}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpuid_get_versioning_info()

int cpuid_get_versioning_info ( CPU_attr_e  attr,
int value 
)
static

Definition at line 532 of file x86_cpu_utils.c.

533{
534 static int family, model, stepping;
535
536 if (attr == CPU_ATTR__CPUID_FAMILY && family) {
537 *value = family;
538 return CPU_SUCCESS;
539 } else if (attr == CPU_ATTR__CPUID_MODEL && model) {
540 *value = model;
541 return CPU_SUCCESS;
542 } else if (attr == CPU_ATTR__CPUID_STEPPING && stepping) {
543 *value = stepping;
544 return CPU_SUCCESS;
545 }
546
547 cpuid_reg_t reg;
548 cpuid(&reg, 1);
549
550 /* Query versioning info once and store results for later */
551 family = (reg.eax >> 8) & 0x0000000f;
552 model = (family == 6 || family == 15) ?
553 ((reg.eax >> 4) & 0x0000000f) + ((reg.eax >> 12) & 0x000000f0) :
554 ((reg.eax >> 4) & 0x0000000f);
555 stepping = reg.eax & 0x0000000f;
556
557 char vendor[13];
558 cpuid_get_vendor(vendor);
559 if (!strcmp(vendor, "AuthenticAMD") && family == 15) {
560 /* Adjust family for AMD processors */
561 family += (reg.eax >> 20) & 0x000000ff;
562 }
563
564 if (attr == CPU_ATTR__CPUID_FAMILY) {
565 *value = family;
566 } else if (attr == CPU_ATTR__CPUID_MODEL) {
567 *value = model;
568 } else {
569 *value = stepping;
570 }
571
572 return CPU_SUCCESS;
573}
int model
Definition: pfmlib_amd64.c:86
int family
Definition: pfmlib_amd64.c:85
int stepping
Definition: pfmlib_amd64.c:87
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpuid_get_x2apic_id()

unsigned int cpuid_get_x2apic_id ( void  )
static

Definition at line 716 of file x86_cpu_utils.c.

717{
718 cpuid_reg_t reg;
719 cpuid(&reg, 11);
720 return reg.edx;
721}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpuid_parse_id_foreach_thread()

int cpuid_parse_id_foreach_thread ( unsigned int  num_mappings,
apic_subid_mask_t mask,
apic_subid_t subid 
)
static

Definition at line 576 of file x86_cpu_utils.c.

579{
580 unsigned int apic_id = cpuid_get_apic_id();
581 subid[num_mappings].pkg = ((apic_id & mask->pkg_mask ) >> (mask->smt_width + mask->core_width));
582 subid[num_mappings].core = ((apic_id & mask->core_mask) >> (mask->smt_width));
583 subid[num_mappings].smt = ((apic_id & mask->smt_mask ));
584 return CPU_SUCCESS;
585}
static unsigned int cpuid_get_apic_id(void)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpuid_parse_ids()

int cpuid_parse_ids ( int  os_proc_count,
apic_subid_mask_t mask,
apic_subid_t subid 
)
static

Definition at line 588 of file x86_cpu_utils.c.

589{
590 int i, ret = 0;
591 int num_mappings = 0;
592
593 /* save cpu affinity */
595
596 for (i = 0; i < os_proc_count; ++i) {
597 /* check if we are allowed to run on this logical processor */
598 if (os_cpu_set_affinity(i)) {
599 ret = -1;
600 break;
601 }
602
603 /* now query id for the logical processor */
604 cpuid_parse_id_foreach_thread(num_mappings, mask, subid);
605
606 /* increment parsed ids */
607 ret = ++num_mappings;
608 }
609
610 /* restore cpu affinity */
612
613 return ret;
614}
int i
int os_cpu_set_affinity(int cpu)
Definition: os_cpu_utils.c:54
int os_cpu_load_affinity(void)
Definition: os_cpu_utils.c:90
int os_cpu_store_affinity(void)
Definition: os_cpu_utils.c:78
static int cpuid_parse_id_foreach_thread(unsigned int num_mappings, apic_subid_mask_t *mask, apic_subid_t *subid)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpuid_supports_leaves_4_11()

int cpuid_supports_leaves_4_11 ( void  )
static

Definition at line 449 of file x86_cpu_utils.c.

450{
451 char vendor[13];
452 cpuid_get_vendor(vendor);
453
454 cpuid_reg_t reg;
455 cpuid(&reg, 0);
456
457 /* If leaf4 not supported or vendor is not Intel, fallback */
458 int fallback = (reg.eax < 4 || strcmp(vendor, "GenuineIntel"));
459 if (!fallback) {
460 cpuid_has_leaf4 = 1;
461 cpuid(&reg, 11);
462 if (reg.ebx != 0)
464 }
465
466 return !fallback;
467}
static int cpuid_has_leaf4
Definition: x86_cpu_utils.c:61
Here is the call graph for this function:
Here is the caller graph for this function:

◆ enum_cpu_resources()

int enum_cpu_resources ( int  num_mappings,
apic_subid_mask_t mask,
apic_subid_t subids,
int sockets,
int cores,
int threads 
)
static

Definition at line 470 of file x86_cpu_utils.c.

473{
474 int status = CPU_SUCCESS;
475 int max_num_pkgs = (1 << mask->pkg_width);
476 int max_num_cores = (1 << mask->core_width);
477 int max_num_threads = (1 << mask->smt_width);
478
479 int *pkg_arr = papi_calloc(max_num_pkgs, sizeof(int));
480 if (!pkg_arr)
481 goto fn_fail_pkg;
482
483 int *core_arr = papi_calloc(max_num_cores, sizeof(int));
484 if (!core_arr)
485 goto fn_fail_core;
486
487 int *smt_arr = papi_calloc(max_num_threads, sizeof(int));
488 if (!smt_arr)
489 goto fn_fail_thread;
490
491 int i;
492 for (i = 0; i < num_mappings; ++i) {
493 pkg_arr[subids[i].pkg] =
494 core_arr[subids[i].core] =
495 smt_arr[subids[i].smt] = 1;
496 }
497
498 i = 0, *sockets = 0;
499 while (i < max_num_pkgs) {
500 if (pkg_arr[i++] != 0)
501 (*sockets)++;
502 }
503
504 i = 0, *cores = 0;
505 while (i < max_num_cores) {
506 if (core_arr[i++] != 0)
507 (*cores)++;
508 }
509
510 i = 0, *threads = 0;
511 while (i < max_num_threads) {
512 if (smt_arr[i++] != 0)
513 (*threads)++;
514 }
515
516 papi_free(pkg_arr);
517 papi_free(core_arr);
518 papi_free(smt_arr);
519
520 fn_exit:
521 return status;
522 fn_fail_thread:
523 papi_free(core_arr);
524 fn_fail_core:
525 papi_free(pkg_arr);
526 fn_fail_pkg:
527 status = CPU_ERROR;
528 goto fn_exit;
529}
#define papi_calloc(a, b)
Definition: papi_memory.h:37
Here is the caller graph for this function:

◆ intel_get_cache_info()

int intel_get_cache_info ( CPU_attr_e  attr,
int  level,
int value 
)
static

Definition at line 314 of file x86_cpu_utils.c.

315{
316 static _sysdetect_cache_level_info_t *clevel_ptr;
317
318 if (clevel_ptr) {
319 return cpu_get_cache_info(attr, level, clevel_ptr, value);
320 }
321
323 return os_cpu_get_attribute_at(attr, level, value);
324 }
325
326 clevel_ptr = clevel;
327
328 cpuid_reg_t reg;
329 int subleaf = 0;
330 while(1) {
331 /*
332 * We query cache info only for the logical processor we are running on
333 * and rely on the fact that the rest are all identical
334 */
335 cpuid2(&reg, 4, subleaf);
336
337 /*
338 * Decoded as per table 3-12 in Intel's Software Developer's Manual
339 * Volume 2A
340 */
341 int type = reg.eax & 0x1f;
342 if (type == 0)
343 break;
344
345 switch(type) {
346 case 1:
348 break;
349 case 2:
351 break;
352 case 3:
354 break;
355 default:
357 }
358
359 int level = (reg.eax >> 5) & 0x3;
360 int fully_assoc = (reg.eax >> 9) & 0x1;
361 int line_size = (reg.ebx & 0xfff) + 1;
362 int partitions = ((reg.ebx >> 12) & 0x3ff) + 1;
363 int ways = ((reg.ebx >> 22) & 0x3ff) + 1;
364 int sets = (reg.ecx + 1);
365
366 int *num_caches = &clevel[level-1].num_caches;
367 clevel_ptr[level-1].cache[*num_caches].type = type;
368 clevel_ptr[level-1].cache[*num_caches].size = (ways * partitions * sets * line_size);
369 clevel_ptr[level-1].cache[*num_caches].line_size = line_size;
370 clevel_ptr[level-1].cache[*num_caches].num_lines = (ways * partitions * sets);
371 clevel_ptr[level-1].cache[*num_caches].associativity = (fully_assoc) ? SHRT_MAX : ways;
372 ++(*num_caches);
373
374 ++subleaf;
375 }
376
377 return cpu_get_cache_info(attr, level, clevel_ptr, value);
378}
uint16_t type
#define PAPI_MH_TYPE_UNKNOWN
Definition: papi.h:728
Here is the call graph for this function:
Here is the caller graph for this function:

◆ x86_cpu_finalize()

int x86_cpu_finalize ( void  )

Definition at line 76 of file x86_cpu_utils.c.

77{
78 return CPU_SUCCESS;
79}

◆ x86_cpu_get_attribute()

int x86_cpu_get_attribute ( CPU_attr_e  attr,
int value 
)

Definition at line 94 of file x86_cpu_utils.c.

95{
96 return cpuid_get_attribute(attr, value);
97}
static int cpuid_get_attribute(CPU_attr_e attr, int *value)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ x86_cpu_get_attribute_at()

int x86_cpu_get_attribute_at ( CPU_attr_e  attr,
int  loc,
int value 
)

Definition at line 100 of file x86_cpu_utils.c.

101{
102 return cpuid_get_attribute_at(attr, loc, value);
103}
static int cpuid_get_attribute_at(CPU_attr_e attr, int loc, int *value)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ x86_cpu_get_name()

int x86_cpu_get_name ( char *  name)

Definition at line 88 of file x86_cpu_utils.c.

89{
90 return cpuid_get_name(name);
91}
static int cpuid_get_name(char *name)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ x86_cpu_get_vendor()

int x86_cpu_get_vendor ( char *  vendor)

Definition at line 82 of file x86_cpu_utils.c.

83{
84 return cpuid_get_vendor(vendor);
85}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ x86_cpu_init()

int x86_cpu_init ( void  )

Definition at line 65 of file x86_cpu_utils.c.

66{
67 /*
68 * In the future we might need to dynamically
69 * allocate and free objects; init/finalize
70 * functions are a good place for doing that.
71 */
72 return CPU_SUCCESS;
73}

Variable Documentation

◆ clevel

◆ cpuid_has_leaf11

int cpuid_has_leaf11
static

Definition at line 62 of file x86_cpu_utils.c.

◆ cpuid_has_leaf4

int cpuid_has_leaf4
static

Definition at line 61 of file x86_cpu_utils.c.