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