Home | History | Annotate | Download | only in libop
      1 /**
      2  * @file op_cpu_type.c
      3  * CPU type determination
      4  *
      5  * @remark Copyright 2002 OProfile authors
      6  * @remark Read the file COPYING
      7  *
      8  * @author John Levon
      9  * @author Philippe Elie
     10  */
     11 
     12 #include <stdio.h>
     13 #include <stdlib.h>
     14 #include <string.h>
     15 
     16 #include "op_cpu_type.h"
     17 #include "op_hw_specific.h"
     18 
     19 struct cpu_descr {
     20 	char const * pretty;
     21 	char const * name;
     22 	op_cpu cpu;
     23 	unsigned int nr_counters;
     24 };
     25 
     26 static struct cpu_descr const cpu_descrs[MAX_CPU_TYPE] = {
     27 	{ "Pentium Pro", "i386/ppro", CPU_PPRO, 2 },
     28 	{ "PII", "i386/pii", CPU_PII, 2 },
     29 	{ "PIII", "i386/piii", CPU_PIII, 2 },
     30 	{ "Athlon", "i386/athlon", CPU_ATHLON, 4 },
     31 	{ "CPU with timer interrupt", "timer", CPU_TIMER_INT, 1 },
     32 	{ "CPU with RTC device", "rtc", CPU_RTC, 1 },
     33 	{ "P4 / Xeon", "i386/p4", CPU_P4, 8 },
     34 	{ "IA64", "ia64/ia64", CPU_IA64, 4 },
     35 	{ "Itanium", "ia64/itanium", CPU_IA64_1, 4 },
     36 	{ "Itanium 2", "ia64/itanium2", CPU_IA64_2, 4 },
     37 	{ "AMD64 processors", "x86-64/hammer", CPU_HAMMER, 4 },
     38 	{ "P4 / Xeon with 2 hyper-threads", "i386/p4-ht", CPU_P4_HT2, 4 },
     39 	{ "Alpha EV4", "alpha/ev4", CPU_AXP_EV4, 2 },
     40 	{ "Alpha EV5", "alpha/ev5", CPU_AXP_EV5, 3 },
     41 	{ "Alpha PCA56", "alpha/pca56", CPU_AXP_PCA56, 3 },
     42 	{ "Alpha EV6", "alpha/ev6", CPU_AXP_EV6, 2 },
     43 	{ "Alpha EV67", "alpha/ev67", CPU_AXP_EV67, 20 },
     44 	{ "Pentium M (P6 core)", "i386/p6_mobile", CPU_P6_MOBILE, 2 },
     45 	{ "ARM/XScale PMU1", "arm/xscale1", CPU_ARM_XSCALE1, 3 },
     46 	{ "ARM/XScale PMU2", "arm/xscale2", CPU_ARM_XSCALE2, 5 },
     47 	{ "ppc64 POWER4", "ppc64/power4", CPU_PPC64_POWER4, 8 },
     48 	{ "ppc64 POWER5", "ppc64/power5", CPU_PPC64_POWER5, 6 },
     49 	{ "ppc64 POWER5+", "ppc64/power5+", CPU_PPC64_POWER5p, 6 },
     50 	{ "ppc64 970", "ppc64/970", CPU_PPC64_970, 8 },
     51 	{ "MIPS 20K", "mips/20K", CPU_MIPS_20K, 1},
     52 	{ "MIPS 24K", "mips/24K", CPU_MIPS_24K, 2},
     53 	{ "MIPS 25K", "mips/25K", CPU_MIPS_25K, 2},
     54 	{ "MIPS 34K", "mips/34K", CPU_MIPS_34K, 2},
     55 	{ "MIPS 5K", "mips/5K", CPU_MIPS_5K, 2},
     56 	{ "MIPS R10000", "mips/r10000", CPU_MIPS_R10000, 2 },
     57 	{ "MIPS R12000", "mips/r12000", CPU_MIPS_R12000, 4 },
     58 	{ "QED RM7000", "mips/rm7000", CPU_MIPS_RM7000, 1 },
     59 	{ "PMC-Sierra RM9000", "mips/rm9000", CPU_MIPS_RM9000, 2 },
     60 	{ "Sibyte SB1", "mips/sb1", CPU_MIPS_SB1, 4 },
     61 	{ "NEC VR5432", "mips/vr5432", CPU_MIPS_VR5432, 2 },
     62 	{ "NEC VR5500", "mips/vr5500", CPU_MIPS_VR5500, 2 },
     63 	{ "e500", "ppc/e500", CPU_PPC_E500, 4 },
     64 	{ "e500v2", "ppc/e500v2", CPU_PPC_E500_2, 4 },
     65 	{ "Core Solo / Duo", "i386/core", CPU_CORE, 2 },
     66 	{ "PowerPC G4", "ppc/7450",  CPU_PPC_7450, 6 },
     67 	{ "Core 2", "i386/core_2", CPU_CORE_2, 2 },
     68 	{ "ppc64 POWER6", "ppc64/power6", CPU_PPC64_POWER6, 4 },
     69 	{ "ppc64 970MP", "ppc64/970MP", CPU_PPC64_970MP, 8 },
     70 	{ "ppc64 Cell Broadband Engine", "ppc64/cell-be", CPU_PPC64_CELL, 8 },
     71 	{ "AMD64 family10", "x86-64/family10", CPU_FAMILY10, 4 },
     72 	{ "ppc64 PA6T", "ppc64/pa6t", CPU_PPC64_PA6T, 6 },
     73 	{ "ARM 11MPCore", "arm/mpcore", CPU_ARM_MPCORE, 2 },
     74 	{ "ARM V6 PMU", "arm/armv6", CPU_ARM_V6, 3 },
     75 	{ "ppc64 POWER5++", "ppc64/power5++", CPU_PPC64_POWER5pp, 6 },
     76 	{ "e300", "ppc/e300", CPU_PPC_E300, 4 },
     77 	{ "AVR32", "avr32", CPU_AVR32, 3 },
     78 	{ "ARM Cortex-A8", "arm/armv7", CPU_ARM_V7, 5 },
     79  	{ "Intel Architectural Perfmon", "i386/arch_perfmon", CPU_ARCH_PERFMON, 0},
     80 	{ "AMD64 family11h", "x86-64/family11h", CPU_FAMILY11H, 4 },
     81 	{ "ppc64 POWER7", "ppc64/power7", CPU_PPC64_POWER7, 6 },
     82 	{ "ppc64 compat version 1", "ppc64/ibm-compat-v1", CPU_PPC64_IBM_COMPAT_V1, 4 },
     83    	{ "Intel Core/i7", "i386/core_i7", CPU_CORE_I7, 4 },
     84    	{ "Intel Atom", "i386/atom", CPU_ATOM, 2 },
     85 	{ "Loongson2", "mips/loongson2", CPU_MIPS_LOONGSON2, 2 },
     86 	{ "Intel Nehalem microarchitecture", "i386/nehalem", CPU_NEHALEM, 4 },
     87 	{ "ARM Cortex-A9", "arm/armv7-ca9", CPU_ARM_V7_CA9, 7 },
     88 	{ "MIPS 74K", "mips/74K", CPU_MIPS_74K, 4},
     89 	{ "MIPS 1004K", "mips/1004K", CPU_MIPS_1004K, 2},
     90 	{ "AMD64 family12h", "x86-64/family12h", CPU_FAMILY12H, 4 },
     91 	{ "AMD64 family14h", "x86-64/family14h", CPU_FAMILY14H, 4 },
     92 	{ "AMD64 family15h", "x86-64/family15h", CPU_FAMILY15H, 6 },
     93 	{ "Intel Westmere microarchitecture", "i386/westmere", CPU_WESTMERE, 4 },
     94 };
     95 
     96 static size_t const nr_cpu_descrs = sizeof(cpu_descrs) / sizeof(struct cpu_descr);
     97 
     98 int op_cpu_variations(op_cpu cpu_type)
     99 {
    100 	switch (cpu_type) {
    101 	case  CPU_ARCH_PERFMON:
    102 		return 1;
    103 	default:
    104 		return 0;
    105 	}
    106 }
    107 
    108 
    109 op_cpu op_cpu_base_type(op_cpu cpu_type)
    110 {
    111 	/* All the processors that support CPU_ARCH_PERFMON */
    112 	switch (cpu_type) {
    113 	case CPU_CORE_2:
    114 	case CPU_CORE_I7:
    115 	case CPU_ATOM:
    116 	case CPU_NEHALEM:
    117 	case CPU_WESTMERE:
    118 		return CPU_ARCH_PERFMON;
    119 	default:
    120 		/* assume processor in a class by itself */
    121 		return cpu_type;
    122 	}
    123 }
    124 
    125 op_cpu op_get_cpu_type(void)
    126 {
    127 	int cpu_type = CPU_NO_GOOD;
    128 	char str[100];
    129 	FILE * fp;
    130 
    131 	fp = fopen("/proc/sys/dev/oprofile/cpu_type", "r");
    132 	if (!fp) {
    133 		/* Try 2.6's oprofilefs one instead. */
    134 		fp = fopen("/dev/oprofile/cpu_type", "r");
    135 		if (!fp) {
    136 			fprintf(stderr, "Unable to open cpu_type file for reading\n");
    137 			fprintf(stderr, "Make sure you have done opcontrol --init\n");
    138 			return cpu_type;
    139 		}
    140 	}
    141 
    142 	if (!fgets(str, 99, fp)) {
    143 		fprintf(stderr, "Could not read cpu type.\n");
    144 		return CPU_NO_GOOD;
    145 	}
    146 
    147 	cpu_type = op_get_cpu_number(str);
    148 
    149 	if (op_cpu_variations(cpu_type))
    150 		cpu_type = op_cpu_specific_type(cpu_type);
    151 
    152 	fclose(fp);
    153 
    154 	return cpu_type;
    155 }
    156 
    157 
    158 op_cpu op_get_cpu_number(char const * cpu_string)
    159 {
    160 	int cpu_type = CPU_NO_GOOD;
    161 	size_t i;
    162 
    163 	for (i = 0; i < nr_cpu_descrs; ++i) {
    164 		if (!strcmp(cpu_descrs[i].name, cpu_string)) {
    165 			cpu_type = cpu_descrs[i].cpu;
    166 			break;
    167 		}
    168 	}
    169 
    170 	/* Attempt to convert into a number */
    171 	if (cpu_type == CPU_NO_GOOD)
    172 		sscanf(cpu_string, "%d\n", &cpu_type);
    173 
    174 	if (cpu_type <= CPU_NO_GOOD || cpu_type >= MAX_CPU_TYPE)
    175 		cpu_type = CPU_NO_GOOD;
    176 
    177 	return cpu_type;
    178 }
    179 
    180 
    181 char const * op_get_cpu_type_str(op_cpu cpu_type)
    182 {
    183 	if (cpu_type <= CPU_NO_GOOD || cpu_type >= MAX_CPU_TYPE)
    184 		return "invalid cpu type";
    185 
    186 	return cpu_descrs[cpu_type].pretty;
    187 }
    188 
    189 
    190 char const * op_get_cpu_name(op_cpu cpu_type)
    191 {
    192 	if (cpu_type <= CPU_NO_GOOD || cpu_type >= MAX_CPU_TYPE)
    193 		return "invalid cpu type";
    194 
    195 	return cpu_descrs[cpu_type].name;
    196 }
    197 
    198 
    199 int op_get_nr_counters(op_cpu cpu_type)
    200 {
    201 	int cnt;
    202 
    203 	if (cpu_type <= CPU_NO_GOOD || cpu_type >= MAX_CPU_TYPE)
    204 		return 0;
    205 
    206 	cnt = arch_num_counters(cpu_type);
    207 	if (cnt >= 0)
    208 		return cnt;
    209 
    210 	return cpu_descrs[cpu_type].nr_counters;
    211 }
    212