op_cpu_type.c revision cc2ee177dbb3befca43e36cfc56778b006c3d050
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
18struct cpu_descr {
19	char const * pretty;
20	char const * name;
21	op_cpu cpu;
22	unsigned int nr_counters;
23};
24
25static struct cpu_descr const cpu_descrs[MAX_CPU_TYPE] = {
26	{ "Pentium Pro", "i386/ppro", CPU_PPRO, 2 },
27	{ "PII", "i386/pii", CPU_PII, 2 },
28	{ "PIII", "i386/piii", CPU_PIII, 2 },
29	{ "Athlon", "i386/athlon", CPU_ATHLON, 4 },
30	{ "CPU with timer interrupt", "timer", CPU_TIMER_INT, 1 },
31	{ "CPU with RTC device", "rtc", CPU_RTC, 1 },
32	{ "P4 / Xeon", "i386/p4", CPU_P4, 8 },
33	{ "IA64", "ia64/ia64", CPU_IA64, 4 },
34	{ "Itanium", "ia64/itanium", CPU_IA64_1, 4 },
35	{ "Itanium 2", "ia64/itanium2", CPU_IA64_2, 4 },
36	{ "AMD64 processors", "x86-64/hammer", CPU_HAMMER, 4 },
37	{ "P4 / Xeon with 2 hyper-threads", "i386/p4-ht", CPU_P4_HT2, 4 },
38	{ "Alpha EV4", "alpha/ev4", CPU_AXP_EV4, 2 },
39	{ "Alpha EV5", "alpha/ev5", CPU_AXP_EV5, 3 },
40	{ "Alpha PCA56", "alpha/pca56", CPU_AXP_PCA56, 3 },
41	{ "Alpha EV6", "alpha/ev6", CPU_AXP_EV6, 2 },
42	{ "Alpha EV67", "alpha/ev67", CPU_AXP_EV67, 20 },
43	{ "Pentium M (P6 core)", "i386/p6_mobile", CPU_P6_MOBILE, 2 },
44	{ "ARM/XScale PMU1", "arm/xscale1", CPU_ARM_XSCALE1, 3 },
45	{ "ARM/XScale PMU2", "arm/xscale2", CPU_ARM_XSCALE2, 5 },
46	{ "ppc64 POWER4", "ppc64/power4", CPU_PPC64_POWER4, 8 },
47	{ "ppc64 POWER5", "ppc64/power5", CPU_PPC64_POWER5, 6 },
48	{ "ppc64 970", "ppc64/970", CPU_PPC64_970, 8 },
49	{ "MIPS 24K", "mips/24K", CPU_MIPS_24K, 2},
50	{ "MIPS R10000", "mips/r10000", CPU_MIPS_R10000, 2 },
51	{ "MIPS R12000", "mips/r12000", CPU_MIPS_R12000, 4 },
52	{ "QED RM7000", "mips/rm7000", CPU_MIPS_RM7000, 1 },
53	{ "PMC-Sierra RM9000", "mips/rm9000", CPU_MIPS_RM9000, 2 },
54	{ "Sibyte SB1", "mips/sb1", CPU_MIPS_SB1, 4 },
55	{ "NEC VR5432", "mips/vr5432", CPU_MIPS_VR5432, 2 },
56	{ "NEC VR5500", "mips/vr5500", CPU_MIPS_VR5500, 2 },
57	{ "e500", "ppc/e500", CPU_PPC_E500, 4 },
58};
59
60static size_t const nr_cpu_descrs = sizeof(cpu_descrs) / sizeof(struct cpu_descr);
61
62op_cpu op_get_cpu_type(void)
63{
64	int cpu_type = CPU_NO_GOOD;
65	char str[100];
66	FILE * fp;
67
68	fp = fopen("/proc/sys/dev/oprofile/cpu_type", "r");
69	if (!fp) {
70		/* Try 2.6's oprofilefs one instead. */
71		fp = fopen("/dev/oprofile/cpu_type", "r");
72		if (!fp) {
73			fprintf(stderr, "Unable to open cpu_type file for reading\n");
74			fprintf(stderr, "Make sure you have done opcontrol --init\n");
75			return cpu_type;
76		}
77	}
78
79	if (!fgets(str, 99, fp)) {
80		fprintf(stderr, "Could not read cpu type.\n");
81		return CPU_NO_GOOD;
82	}
83
84	cpu_type = op_get_cpu_number(str);
85
86	fclose(fp);
87
88	return cpu_type;
89}
90
91
92op_cpu op_get_cpu_number(char const * cpu_string)
93{
94	int cpu_type = CPU_NO_GOOD;
95	size_t i;
96
97	for (i = 0; i < nr_cpu_descrs; ++i) {
98		if (!strcmp(cpu_descrs[i].name, cpu_string)) {
99			cpu_type = cpu_descrs[i].cpu;
100			break;
101		}
102	}
103
104	/* Attempt to convert into a number */
105	if (cpu_type == CPU_NO_GOOD)
106		sscanf(cpu_string, "%d\n", &cpu_type);
107
108	if (cpu_type <= CPU_NO_GOOD || cpu_type >= MAX_CPU_TYPE)
109		cpu_type = CPU_NO_GOOD;
110
111	return cpu_type;
112}
113
114
115char const * op_get_cpu_type_str(op_cpu cpu_type)
116{
117	if (cpu_type <= CPU_NO_GOOD || cpu_type >= MAX_CPU_TYPE)
118		return "invalid cpu type";
119
120	return cpu_descrs[cpu_type].pretty;
121}
122
123
124char const * op_get_cpu_name(op_cpu cpu_type)
125{
126	if (cpu_type <= CPU_NO_GOOD || cpu_type >= MAX_CPU_TYPE)
127		return "invalid cpu type";
128
129	return cpu_descrs[cpu_type].name;
130}
131
132
133int op_get_nr_counters(op_cpu cpu_type)
134{
135	if (cpu_type <= CPU_NO_GOOD || cpu_type >= MAX_CPU_TYPE)
136		return 0;
137
138	return cpu_descrs[cpu_type].nr_counters;
139}
140