The Android Open Source Project | 10e23ee | 2009-03-03 19:30:30 -0800 | [diff] [blame] | 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" |
Ben Cheng | 5a4eb4e | 2009-09-14 16:00:41 -0700 | [diff] [blame] | 17 | #include "op_hw_specific.h" |
The Android Open Source Project | 10e23ee | 2009-03-03 19:30:30 -0800 | [diff] [blame] | 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}, |
Ben Cheng | 5bbbe46 | 2010-09-02 21:48:01 -0700 | [diff] [blame] | 54 | { "MIPS 34K", "mips/34K", CPU_MIPS_34K, 2}, |
The Android Open Source Project | 10e23ee | 2009-03-03 19:30:30 -0800 | [diff] [blame] | 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 }, |
Ben Cheng | 5bbbe46 | 2010-09-02 21:48:01 -0700 | [diff] [blame] | 73 | { "ARM 11MPCore", "arm/mpcore", CPU_ARM_MPCORE, 2 }, |
The Android Open Source Project | 10e23ee | 2009-03-03 19:30:30 -0800 | [diff] [blame] | 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 }, |
Ben Cheng | 5bbbe46 | 2010-09-02 21:48:01 -0700 | [diff] [blame] | 78 | { "ARM Cortex-A8", "arm/armv7", CPU_ARM_V7, 5 }, |
Ben Cheng | 5a4eb4e | 2009-09-14 16:00:41 -0700 | [diff] [blame] | 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 }, |
Ben Cheng | 5bbbe46 | 2010-09-02 21:48:01 -0700 | [diff] [blame] | 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}, |
Jeff Brown | 7a33c86 | 2011-02-02 14:00:44 -0800 | [diff] [blame] | 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 }, |
The Android Open Source Project | 10e23ee | 2009-03-03 19:30:30 -0800 | [diff] [blame] | 94 | }; |
| 95 | |
| 96 | static size_t const nr_cpu_descrs = sizeof(cpu_descrs) / sizeof(struct cpu_descr); |
| 97 | |
Jeff Brown | 7a33c86 | 2011-02-02 14:00:44 -0800 | [diff] [blame] | 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 | |
The Android Open Source Project | 10e23ee | 2009-03-03 19:30:30 -0800 | [diff] [blame] | 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 | |
Jeff Brown | 7a33c86 | 2011-02-02 14:00:44 -0800 | [diff] [blame] | 149 | if (op_cpu_variations(cpu_type)) |
| 150 | cpu_type = op_cpu_specific_type(cpu_type); |
| 151 | |
The Android Open Source Project | 10e23ee | 2009-03-03 19:30:30 -0800 | [diff] [blame] | 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 | { |
Ben Cheng | 5a4eb4e | 2009-09-14 16:00:41 -0700 | [diff] [blame] | 201 | int cnt; |
| 202 | |
The Android Open Source Project | 10e23ee | 2009-03-03 19:30:30 -0800 | [diff] [blame] | 203 | if (cpu_type <= CPU_NO_GOOD || cpu_type >= MAX_CPU_TYPE) |
| 204 | return 0; |
| 205 | |
Ben Cheng | 5a4eb4e | 2009-09-14 16:00:41 -0700 | [diff] [blame] | 206 | cnt = arch_num_counters(cpu_type); |
| 207 | if (cnt >= 0) |
| 208 | return cnt; |
| 209 | |
The Android Open Source Project | 10e23ee | 2009-03-03 19:30:30 -0800 | [diff] [blame] | 210 | return cpu_descrs[cpu_type].nr_counters; |
| 211 | } |