blob: 946e9ab48edbc6ddac367d215c798f27002d2e96 [file] [log] [blame]
Len Brown103a8fe2010-10-22 23:53:03 -04001/*
2 * turbostat -- show CPU frequency and C-state residency
3 * on modern Intel turbo-capable processors.
4 *
Len Browne23da032012-02-06 18:37:16 -05005 * Copyright (c) 2012 Intel Corporation.
Len Brown103a8fe2010-10-22 23:53:03 -04006 * Len Brown <len.brown@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
Len Brown88c32812012-03-29 21:44:40 -040022#define _GNU_SOURCE
Len Brown103a8fe2010-10-22 23:53:03 -040023#include <stdio.h>
24#include <unistd.h>
25#include <sys/types.h>
26#include <sys/wait.h>
27#include <sys/stat.h>
28#include <sys/resource.h>
29#include <fcntl.h>
30#include <signal.h>
31#include <sys/time.h>
32#include <stdlib.h>
33#include <dirent.h>
34#include <string.h>
35#include <ctype.h>
Len Brown88c32812012-03-29 21:44:40 -040036#include <sched.h>
Len Brown103a8fe2010-10-22 23:53:03 -040037
Len Brown103a8fe2010-10-22 23:53:03 -040038#define MSR_NEHALEM_PLATFORM_INFO 0xCE
39#define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1AD
Len Brown6574a5d2012-09-21 00:01:31 -040040#define MSR_IVT_TURBO_RATIO_LIMIT 0x1AE
Len Brown103a8fe2010-10-22 23:53:03 -040041#define MSR_APERF 0xE8
42#define MSR_MPERF 0xE7
43#define MSR_PKG_C2_RESIDENCY 0x60D /* SNB only */
44#define MSR_PKG_C3_RESIDENCY 0x3F8
45#define MSR_PKG_C6_RESIDENCY 0x3F9
46#define MSR_PKG_C7_RESIDENCY 0x3FA /* SNB only */
47#define MSR_CORE_C3_RESIDENCY 0x3FC
48#define MSR_CORE_C6_RESIDENCY 0x3FD
49#define MSR_CORE_C7_RESIDENCY 0x3FE /* SNB only */
50
51char *proc_stat = "/proc/stat";
52unsigned int interval_sec = 5; /* set with -i interval_sec */
53unsigned int verbose; /* set with -v */
Len Browne23da032012-02-06 18:37:16 -050054unsigned int summary_only; /* set with -s */
Len Brown103a8fe2010-10-22 23:53:03 -040055unsigned int skip_c0;
56unsigned int skip_c1;
57unsigned int do_nhm_cstates;
58unsigned int do_snb_cstates;
59unsigned int has_aperf;
60unsigned int units = 1000000000; /* Ghz etc */
61unsigned int genuine_intel;
62unsigned int has_invariant_tsc;
63unsigned int do_nehalem_platform_info;
64unsigned int do_nehalem_turbo_ratio_limit;
Len Brown6574a5d2012-09-21 00:01:31 -040065unsigned int do_ivt_turbo_ratio_limit;
Len Brown2f32edf2012-09-21 23:45:46 -040066unsigned int extra_msr_offset32;
67unsigned int extra_msr_offset64;
Len Brown103a8fe2010-10-22 23:53:03 -040068double bclk;
69unsigned int show_pkg;
70unsigned int show_core;
71unsigned int show_cpu;
Len Brownc98d5d92012-06-04 00:56:40 -040072unsigned int show_pkg_only;
73unsigned int show_core_only;
74char *output_buffer, *outp;
Len Brown103a8fe2010-10-22 23:53:03 -040075
76int aperf_mperf_unstable;
77int backwards_count;
78char *progname;
Len Brown103a8fe2010-10-22 23:53:03 -040079
Len Brownc98d5d92012-06-04 00:56:40 -040080cpu_set_t *cpu_present_set, *cpu_affinity_set;
81size_t cpu_present_setsize, cpu_affinity_setsize;
Len Brown103a8fe2010-10-22 23:53:03 -040082
Len Brownc98d5d92012-06-04 00:56:40 -040083struct thread_data {
84 unsigned long long tsc;
85 unsigned long long aperf;
86 unsigned long long mperf;
87 unsigned long long c1; /* derived */
Len Brown2f32edf2012-09-21 23:45:46 -040088 unsigned long long extra_msr64;
89 unsigned int extra_msr32;
Len Brownc98d5d92012-06-04 00:56:40 -040090 unsigned int cpu_id;
91 unsigned int flags;
92#define CPU_IS_FIRST_THREAD_IN_CORE 0x2
93#define CPU_IS_FIRST_CORE_IN_PACKAGE 0x4
94} *thread_even, *thread_odd;
Len Brown103a8fe2010-10-22 23:53:03 -040095
Len Brownc98d5d92012-06-04 00:56:40 -040096struct core_data {
97 unsigned long long c3;
98 unsigned long long c6;
99 unsigned long long c7;
100 unsigned int core_id;
101} *core_even, *core_odd;
Len Brown103a8fe2010-10-22 23:53:03 -0400102
Len Brownc98d5d92012-06-04 00:56:40 -0400103struct pkg_data {
104 unsigned long long pc2;
105 unsigned long long pc3;
106 unsigned long long pc6;
107 unsigned long long pc7;
108 unsigned int package_id;
109} *package_even, *package_odd;
110
111#define ODD_COUNTERS thread_odd, core_odd, package_odd
112#define EVEN_COUNTERS thread_even, core_even, package_even
113
114#define GET_THREAD(thread_base, thread_no, core_no, pkg_no) \
115 (thread_base + (pkg_no) * topo.num_cores_per_pkg * \
116 topo.num_threads_per_core + \
117 (core_no) * topo.num_threads_per_core + (thread_no))
118#define GET_CORE(core_base, core_no, pkg_no) \
119 (core_base + (pkg_no) * topo.num_cores_per_pkg + (core_no))
120#define GET_PKG(pkg_base, pkg_no) (pkg_base + pkg_no)
121
122struct system_summary {
123 struct thread_data threads;
124 struct core_data cores;
125 struct pkg_data packages;
126} sum, average;
127
128
129struct topo_params {
130 int num_packages;
131 int num_cpus;
132 int num_cores;
133 int max_cpu_num;
134 int num_cores_per_pkg;
135 int num_threads_per_core;
136} topo;
137
138struct timeval tv_even, tv_odd, tv_delta;
139
140void setup_all_buffers(void);
141
142int cpu_is_not_present(int cpu)
Len Brownd15cf7c2012-06-03 23:24:00 -0400143{
Len Brownc98d5d92012-06-04 00:56:40 -0400144 return !CPU_ISSET_S(cpu, cpu_present_setsize, cpu_present_set);
Len Brownd15cf7c2012-06-03 23:24:00 -0400145}
Len Brown88c32812012-03-29 21:44:40 -0400146/*
Len Brownc98d5d92012-06-04 00:56:40 -0400147 * run func(thread, core, package) in topology order
148 * skip non-present cpus
Len Brown88c32812012-03-29 21:44:40 -0400149 */
Len Brownd15cf7c2012-06-03 23:24:00 -0400150
Len Brownc98d5d92012-06-04 00:56:40 -0400151int for_all_cpus(int (func)(struct thread_data *, struct core_data *, struct pkg_data *),
152 struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base)
Len Brown88c32812012-03-29 21:44:40 -0400153{
Len Brownc98d5d92012-06-04 00:56:40 -0400154 int retval, pkg_no, core_no, thread_no;
155
156 for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) {
157 for (core_no = 0; core_no < topo.num_cores_per_pkg; ++core_no) {
158 for (thread_no = 0; thread_no <
159 topo.num_threads_per_core; ++thread_no) {
160 struct thread_data *t;
161 struct core_data *c;
162 struct pkg_data *p;
163
164 t = GET_THREAD(thread_base, thread_no, core_no, pkg_no);
165
166 if (cpu_is_not_present(t->cpu_id))
167 continue;
168
169 c = GET_CORE(core_base, core_no, pkg_no);
170 p = GET_PKG(pkg_base, pkg_no);
171
172 retval = func(t, c, p);
173 if (retval)
174 return retval;
175 }
176 }
177 }
178 return 0;
Len Brown88c32812012-03-29 21:44:40 -0400179}
180
181int cpu_migrate(int cpu)
182{
Len Brownc98d5d92012-06-04 00:56:40 -0400183 CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set);
184 CPU_SET_S(cpu, cpu_affinity_setsize, cpu_affinity_set);
185 if (sched_setaffinity(0, cpu_affinity_setsize, cpu_affinity_set) == -1)
Len Brown88c32812012-03-29 21:44:40 -0400186 return -1;
187 else
188 return 0;
189}
190
Len Brown15aaa342012-03-29 22:19:58 -0400191int get_msr(int cpu, off_t offset, unsigned long long *msr)
Len Brown103a8fe2010-10-22 23:53:03 -0400192{
193 ssize_t retval;
Len Brown103a8fe2010-10-22 23:53:03 -0400194 char pathname[32];
195 int fd;
196
197 sprintf(pathname, "/dev/cpu/%d/msr", cpu);
198 fd = open(pathname, O_RDONLY);
Len Brown15aaa342012-03-29 22:19:58 -0400199 if (fd < 0)
200 return -1;
Len Brown103a8fe2010-10-22 23:53:03 -0400201
Len Brown15aaa342012-03-29 22:19:58 -0400202 retval = pread(fd, msr, sizeof *msr, offset);
Len Brown103a8fe2010-10-22 23:53:03 -0400203 close(fd);
Len Brown15aaa342012-03-29 22:19:58 -0400204
205 if (retval != sizeof *msr)
206 return -1;
207
208 return 0;
Len Brown103a8fe2010-10-22 23:53:03 -0400209}
210
Len Brown2f32edf2012-09-21 23:45:46 -0400211/*
212 * Truncate the 8 bytes we read from /dev/cpu/.../msr
213 * to the 4 bytes requested
214 */
215
216int get_msr32(int cpu, off_t offset, unsigned int *msr)
217{
218 int retval;
219
220 unsigned long long msr64;
221
222 retval = get_msr(cpu, offset, &msr64);
223 *msr = (unsigned int) msr64;
224
225 return retval;
226}
227
228
Len Browna829eb42011-02-10 23:36:34 -0500229void print_header(void)
Len Brown103a8fe2010-10-22 23:53:03 -0400230{
231 if (show_pkg)
Len Brownc98d5d92012-06-04 00:56:40 -0400232 outp += sprintf(outp, "pk");
Len Browne23da032012-02-06 18:37:16 -0500233 if (show_pkg)
Len Brownc98d5d92012-06-04 00:56:40 -0400234 outp += sprintf(outp, " ");
Len Brown103a8fe2010-10-22 23:53:03 -0400235 if (show_core)
Len Brownc98d5d92012-06-04 00:56:40 -0400236 outp += sprintf(outp, "cor");
Len Brown103a8fe2010-10-22 23:53:03 -0400237 if (show_cpu)
Len Brownc98d5d92012-06-04 00:56:40 -0400238 outp += sprintf(outp, " CPU");
Len Browne23da032012-02-06 18:37:16 -0500239 if (show_pkg || show_core || show_cpu)
Len Brownc98d5d92012-06-04 00:56:40 -0400240 outp += sprintf(outp, " ");
Len Brown103a8fe2010-10-22 23:53:03 -0400241 if (do_nhm_cstates)
Len Brownc98d5d92012-06-04 00:56:40 -0400242 outp += sprintf(outp, " %%c0");
Len Brown103a8fe2010-10-22 23:53:03 -0400243 if (has_aperf)
Len Brownc98d5d92012-06-04 00:56:40 -0400244 outp += sprintf(outp, " GHz");
245 outp += sprintf(outp, " TSC");
Len Brown2f32edf2012-09-21 23:45:46 -0400246 if (extra_msr_offset32)
247 outp += sprintf(outp, " MSR 0x%04X", extra_msr_offset32);
248 if (extra_msr_offset64)
249 outp += sprintf(outp, " MSR 0x%04X", extra_msr_offset64);
Len Brown103a8fe2010-10-22 23:53:03 -0400250 if (do_nhm_cstates)
Len Brownc98d5d92012-06-04 00:56:40 -0400251 outp += sprintf(outp, " %%c1");
Len Brown103a8fe2010-10-22 23:53:03 -0400252 if (do_nhm_cstates)
Len Brownc98d5d92012-06-04 00:56:40 -0400253 outp += sprintf(outp, " %%c3");
Len Brown103a8fe2010-10-22 23:53:03 -0400254 if (do_nhm_cstates)
Len Brownc98d5d92012-06-04 00:56:40 -0400255 outp += sprintf(outp, " %%c6");
Len Brown103a8fe2010-10-22 23:53:03 -0400256 if (do_snb_cstates)
Len Brownc98d5d92012-06-04 00:56:40 -0400257 outp += sprintf(outp, " %%c7");
Len Brown103a8fe2010-10-22 23:53:03 -0400258 if (do_snb_cstates)
Len Brownc98d5d92012-06-04 00:56:40 -0400259 outp += sprintf(outp, " %%pc2");
Len Brown103a8fe2010-10-22 23:53:03 -0400260 if (do_nhm_cstates)
Len Brownc98d5d92012-06-04 00:56:40 -0400261 outp += sprintf(outp, " %%pc3");
Len Brown103a8fe2010-10-22 23:53:03 -0400262 if (do_nhm_cstates)
Len Brownc98d5d92012-06-04 00:56:40 -0400263 outp += sprintf(outp, " %%pc6");
Len Brown103a8fe2010-10-22 23:53:03 -0400264 if (do_snb_cstates)
Len Brownc98d5d92012-06-04 00:56:40 -0400265 outp += sprintf(outp, " %%pc7");
Len Brown103a8fe2010-10-22 23:53:03 -0400266
Len Brownc98d5d92012-06-04 00:56:40 -0400267 outp += sprintf(outp, "\n");
Len Brown103a8fe2010-10-22 23:53:03 -0400268}
269
Len Brownc98d5d92012-06-04 00:56:40 -0400270int dump_counters(struct thread_data *t, struct core_data *c,
271 struct pkg_data *p)
Len Brown103a8fe2010-10-22 23:53:03 -0400272{
Len Brownc98d5d92012-06-04 00:56:40 -0400273 fprintf(stderr, "t %p, c %p, p %p\n", t, c, p);
Len Brown103a8fe2010-10-22 23:53:03 -0400274
Len Brownc98d5d92012-06-04 00:56:40 -0400275 if (t) {
276 fprintf(stderr, "CPU: %d flags 0x%x\n", t->cpu_id, t->flags);
277 fprintf(stderr, "TSC: %016llX\n", t->tsc);
278 fprintf(stderr, "aperf: %016llX\n", t->aperf);
279 fprintf(stderr, "mperf: %016llX\n", t->mperf);
280 fprintf(stderr, "c1: %016llX\n", t->c1);
Len Brown2f32edf2012-09-21 23:45:46 -0400281 fprintf(stderr, "msr0x%x: %08X\n",
282 extra_msr_offset32, t->extra_msr32);
Len Brownc98d5d92012-06-04 00:56:40 -0400283 fprintf(stderr, "msr0x%x: %016llX\n",
Len Brown2f32edf2012-09-21 23:45:46 -0400284 extra_msr_offset64, t->extra_msr64);
Len Brownc98d5d92012-06-04 00:56:40 -0400285 }
Len Brown103a8fe2010-10-22 23:53:03 -0400286
Len Brownc98d5d92012-06-04 00:56:40 -0400287 if (c) {
288 fprintf(stderr, "core: %d\n", c->core_id);
289 fprintf(stderr, "c3: %016llX\n", c->c3);
290 fprintf(stderr, "c6: %016llX\n", c->c6);
291 fprintf(stderr, "c7: %016llX\n", c->c7);
292 }
293
294 if (p) {
295 fprintf(stderr, "package: %d\n", p->package_id);
296 fprintf(stderr, "pc2: %016llX\n", p->pc2);
297 fprintf(stderr, "pc3: %016llX\n", p->pc3);
298 fprintf(stderr, "pc6: %016llX\n", p->pc6);
299 fprintf(stderr, "pc7: %016llX\n", p->pc7);
300 }
301 return 0;
Len Brown103a8fe2010-10-22 23:53:03 -0400302}
303
Len Browne23da032012-02-06 18:37:16 -0500304/*
305 * column formatting convention & formats
306 * package: "pk" 2 columns %2d
307 * core: "cor" 3 columns %3d
308 * CPU: "CPU" 3 columns %3d
309 * GHz: "GHz" 3 columns %3.2
310 * TSC: "TSC" 3 columns %3.2
311 * percentage " %pc3" %6.2
312 */
Len Brownc98d5d92012-06-04 00:56:40 -0400313int format_counters(struct thread_data *t, struct core_data *c,
314 struct pkg_data *p)
Len Brown103a8fe2010-10-22 23:53:03 -0400315{
316 double interval_float;
317
Len Brownc98d5d92012-06-04 00:56:40 -0400318 /* if showing only 1st thread in core and this isn't one, bail out */
319 if (show_core_only && !(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
320 return 0;
321
322 /* if showing only 1st thread in pkg and this isn't one, bail out */
323 if (show_pkg_only && !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
324 return 0;
325
Len Brown103a8fe2010-10-22 23:53:03 -0400326 interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0;
327
Len Brownc98d5d92012-06-04 00:56:40 -0400328 /* topo columns, print blanks on 1st (average) line */
329 if (t == &average.threads) {
Len Brown103a8fe2010-10-22 23:53:03 -0400330 if (show_pkg)
Len Brownc98d5d92012-06-04 00:56:40 -0400331 outp += sprintf(outp, " ");
Len Browne23da032012-02-06 18:37:16 -0500332 if (show_pkg && show_core)
Len Brownc98d5d92012-06-04 00:56:40 -0400333 outp += sprintf(outp, " ");
Len Brown103a8fe2010-10-22 23:53:03 -0400334 if (show_core)
Len Brownc98d5d92012-06-04 00:56:40 -0400335 outp += sprintf(outp, " ");
Len Brown103a8fe2010-10-22 23:53:03 -0400336 if (show_cpu)
Len Brownc98d5d92012-06-04 00:56:40 -0400337 outp += sprintf(outp, " " " ");
Len Brown103a8fe2010-10-22 23:53:03 -0400338 } else {
Len Brownc98d5d92012-06-04 00:56:40 -0400339 if (show_pkg) {
340 if (p)
341 outp += sprintf(outp, "%2d", p->package_id);
342 else
343 outp += sprintf(outp, " ");
344 }
Len Browne23da032012-02-06 18:37:16 -0500345 if (show_pkg && show_core)
Len Brownc98d5d92012-06-04 00:56:40 -0400346 outp += sprintf(outp, " ");
347 if (show_core) {
348 if (c)
349 outp += sprintf(outp, "%3d", c->core_id);
350 else
351 outp += sprintf(outp, " ");
352 }
Len Brown103a8fe2010-10-22 23:53:03 -0400353 if (show_cpu)
Len Brownc98d5d92012-06-04 00:56:40 -0400354 outp += sprintf(outp, " %3d", t->cpu_id);
Len Brown103a8fe2010-10-22 23:53:03 -0400355 }
356
357 /* %c0 */
358 if (do_nhm_cstates) {
Len Browne23da032012-02-06 18:37:16 -0500359 if (show_pkg || show_core || show_cpu)
Len Brownc98d5d92012-06-04 00:56:40 -0400360 outp += sprintf(outp, " ");
Len Brown103a8fe2010-10-22 23:53:03 -0400361 if (!skip_c0)
Len Brownc98d5d92012-06-04 00:56:40 -0400362 outp += sprintf(outp, "%6.2f", 100.0 * t->mperf/t->tsc);
Len Brown103a8fe2010-10-22 23:53:03 -0400363 else
Len Brownc98d5d92012-06-04 00:56:40 -0400364 outp += sprintf(outp, " ****");
Len Brown103a8fe2010-10-22 23:53:03 -0400365 }
366
367 /* GHz */
368 if (has_aperf) {
369 if (!aperf_mperf_unstable) {
Len Brownc98d5d92012-06-04 00:56:40 -0400370 outp += sprintf(outp, " %3.2f",
371 1.0 * t->tsc / units * t->aperf /
372 t->mperf / interval_float);
Len Brown103a8fe2010-10-22 23:53:03 -0400373 } else {
Len Brownc98d5d92012-06-04 00:56:40 -0400374 if (t->aperf > t->tsc || t->mperf > t->tsc) {
375 outp += sprintf(outp, " ***");
Len Brown103a8fe2010-10-22 23:53:03 -0400376 } else {
Len Brownc98d5d92012-06-04 00:56:40 -0400377 outp += sprintf(outp, "%3.1f*",
378 1.0 * t->tsc /
379 units * t->aperf /
380 t->mperf / interval_float);
Len Brown103a8fe2010-10-22 23:53:03 -0400381 }
382 }
383 }
384
385 /* TSC */
Len Brownc98d5d92012-06-04 00:56:40 -0400386 outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float);
Len Brown103a8fe2010-10-22 23:53:03 -0400387
Len Brown2f32edf2012-09-21 23:45:46 -0400388 /* msr */
389 if (extra_msr_offset32)
390 outp += sprintf(outp, " 0x%08x", t->extra_msr32);
391
Len Brown130ff302012-09-21 22:56:06 -0400392 /* MSR */
Len Brown2f32edf2012-09-21 23:45:46 -0400393 if (extra_msr_offset64)
394 outp += sprintf(outp, " 0x%016llx", t->extra_msr64);
Len Brown130ff302012-09-21 22:56:06 -0400395
Len Brown103a8fe2010-10-22 23:53:03 -0400396 if (do_nhm_cstates) {
397 if (!skip_c1)
Len Brownc98d5d92012-06-04 00:56:40 -0400398 outp += sprintf(outp, " %6.2f", 100.0 * t->c1/t->tsc);
Len Brown103a8fe2010-10-22 23:53:03 -0400399 else
Len Brownc98d5d92012-06-04 00:56:40 -0400400 outp += sprintf(outp, " ****");
Len Brown103a8fe2010-10-22 23:53:03 -0400401 }
Len Brownc98d5d92012-06-04 00:56:40 -0400402
403 /* print per-core data only for 1st thread in core */
404 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
405 goto done;
406
Len Brown103a8fe2010-10-22 23:53:03 -0400407 if (do_nhm_cstates)
Len Brownc98d5d92012-06-04 00:56:40 -0400408 outp += sprintf(outp, " %6.2f", 100.0 * c->c3/t->tsc);
Len Brown103a8fe2010-10-22 23:53:03 -0400409 if (do_nhm_cstates)
Len Brownc98d5d92012-06-04 00:56:40 -0400410 outp += sprintf(outp, " %6.2f", 100.0 * c->c6/t->tsc);
Len Brown103a8fe2010-10-22 23:53:03 -0400411 if (do_snb_cstates)
Len Brownc98d5d92012-06-04 00:56:40 -0400412 outp += sprintf(outp, " %6.2f", 100.0 * c->c7/t->tsc);
413
414 /* print per-package data only for 1st core in package */
415 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
416 goto done;
417
Len Brown103a8fe2010-10-22 23:53:03 -0400418 if (do_snb_cstates)
Len Brownc98d5d92012-06-04 00:56:40 -0400419 outp += sprintf(outp, " %6.2f", 100.0 * p->pc2/t->tsc);
Len Brown103a8fe2010-10-22 23:53:03 -0400420 if (do_nhm_cstates)
Len Brownc98d5d92012-06-04 00:56:40 -0400421 outp += sprintf(outp, " %6.2f", 100.0 * p->pc3/t->tsc);
Len Brown103a8fe2010-10-22 23:53:03 -0400422 if (do_nhm_cstates)
Len Brownc98d5d92012-06-04 00:56:40 -0400423 outp += sprintf(outp, " %6.2f", 100.0 * p->pc6/t->tsc);
Len Brown103a8fe2010-10-22 23:53:03 -0400424 if (do_snb_cstates)
Len Brownc98d5d92012-06-04 00:56:40 -0400425 outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc);
426done:
Len Brownc98d5d92012-06-04 00:56:40 -0400427 outp += sprintf(outp, "\n");
428
429 return 0;
Len Brown103a8fe2010-10-22 23:53:03 -0400430}
431
Len Brownc98d5d92012-06-04 00:56:40 -0400432void flush_stdout()
Len Brown103a8fe2010-10-22 23:53:03 -0400433{
Len Brownc98d5d92012-06-04 00:56:40 -0400434 fputs(output_buffer, stdout);
435 outp = output_buffer;
436}
437void flush_stderr()
438{
439 fputs(output_buffer, stderr);
440 outp = output_buffer;
441}
442void format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
443{
Len Browne23da032012-02-06 18:37:16 -0500444 static int printed;
Len Brown103a8fe2010-10-22 23:53:03 -0400445
Len Browne23da032012-02-06 18:37:16 -0500446 if (!printed || !summary_only)
447 print_header();
Len Brown103a8fe2010-10-22 23:53:03 -0400448
Len Brownc98d5d92012-06-04 00:56:40 -0400449 if (topo.num_cpus > 1)
450 format_counters(&average.threads, &average.cores,
451 &average.packages);
Len Brown103a8fe2010-10-22 23:53:03 -0400452
Len Browne23da032012-02-06 18:37:16 -0500453 printed = 1;
454
455 if (summary_only)
456 return;
457
Len Brownc98d5d92012-06-04 00:56:40 -0400458 for_all_cpus(format_counters, t, c, p);
Len Brown103a8fe2010-10-22 23:53:03 -0400459}
460
Len Brownc98d5d92012-06-04 00:56:40 -0400461void
462delta_package(struct pkg_data *new, struct pkg_data *old)
Len Brown103a8fe2010-10-22 23:53:03 -0400463{
Len Brownc98d5d92012-06-04 00:56:40 -0400464 old->pc2 = new->pc2 - old->pc2;
465 old->pc3 = new->pc3 - old->pc3;
466 old->pc6 = new->pc6 - old->pc6;
467 old->pc7 = new->pc7 - old->pc7;
468}
Len Brown103a8fe2010-10-22 23:53:03 -0400469
Len Brownc98d5d92012-06-04 00:56:40 -0400470void
471delta_core(struct core_data *new, struct core_data *old)
472{
473 old->c3 = new->c3 - old->c3;
474 old->c6 = new->c6 - old->c6;
475 old->c7 = new->c7 - old->c7;
476}
Len Brown103a8fe2010-10-22 23:53:03 -0400477
Len Brownc3ae3312012-06-13 21:31:46 -0400478/*
479 * old = new - old
480 */
Len Brownc98d5d92012-06-04 00:56:40 -0400481void
482delta_thread(struct thread_data *new, struct thread_data *old,
483 struct core_data *core_delta)
484{
485 old->tsc = new->tsc - old->tsc;
Len Brown103a8fe2010-10-22 23:53:03 -0400486
Len Brownc98d5d92012-06-04 00:56:40 -0400487 /* check for TSC < 1 Mcycles over interval */
488 if (old->tsc < (1000 * 1000)) {
489 fprintf(stderr, "Insanely slow TSC rate, TSC stops in idle?\n");
490 fprintf(stderr, "You can disable all c-states by booting with \"idle=poll\"\n");
491 fprintf(stderr, "or just the deep ones with \"processor.max_cstate=1\"\n");
492 exit(-3);
493 }
Len Brown103a8fe2010-10-22 23:53:03 -0400494
Len Brownc98d5d92012-06-04 00:56:40 -0400495 old->c1 = new->c1 - old->c1;
Len Brown103a8fe2010-10-22 23:53:03 -0400496
Len Brownc98d5d92012-06-04 00:56:40 -0400497 if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) {
498 old->aperf = new->aperf - old->aperf;
499 old->mperf = new->mperf - old->mperf;
500 } else {
Len Brown103a8fe2010-10-22 23:53:03 -0400501
Len Brownc98d5d92012-06-04 00:56:40 -0400502 if (!aperf_mperf_unstable) {
503 fprintf(stderr, "%s: APERF or MPERF went backwards *\n", progname);
504 fprintf(stderr, "* Frequency results do not cover entire interval *\n");
505 fprintf(stderr, "* fix this by running Linux-2.6.30 or later *\n");
506
507 aperf_mperf_unstable = 1;
508 }
Len Brown103a8fe2010-10-22 23:53:03 -0400509 /*
Len Brownc98d5d92012-06-04 00:56:40 -0400510 * mperf delta is likely a huge "positive" number
511 * can not use it for calculating c0 time
Len Brown103a8fe2010-10-22 23:53:03 -0400512 */
Len Brownc98d5d92012-06-04 00:56:40 -0400513 skip_c0 = 1;
514 skip_c1 = 1;
515 }
Len Brown103a8fe2010-10-22 23:53:03 -0400516
Len Brown103a8fe2010-10-22 23:53:03 -0400517
Len Brownc98d5d92012-06-04 00:56:40 -0400518 /*
Len Brownc3ae3312012-06-13 21:31:46 -0400519 * As counter collection is not atomic,
520 * it is possible for mperf's non-halted cycles + idle states
Len Brownc98d5d92012-06-04 00:56:40 -0400521 * to exceed TSC's all cycles: show c1 = 0% in that case.
522 */
Len Brownc3ae3312012-06-13 21:31:46 -0400523 if ((old->mperf + core_delta->c3 + core_delta->c6 + core_delta->c7) > old->tsc)
Len Brownc98d5d92012-06-04 00:56:40 -0400524 old->c1 = 0;
525 else {
526 /* normal case, derive c1 */
527 old->c1 = old->tsc - old->mperf - core_delta->c3
528 - core_delta->c6 - core_delta->c7;
529 }
Len Brownc3ae3312012-06-13 21:31:46 -0400530
Len Brownc98d5d92012-06-04 00:56:40 -0400531 if (old->mperf == 0) {
Len Brownc3ae3312012-06-13 21:31:46 -0400532 if (verbose > 1) fprintf(stderr, "cpu%d MPERF 0!\n", old->cpu_id);
Len Brownc98d5d92012-06-04 00:56:40 -0400533 old->mperf = 1; /* divide by 0 protection */
534 }
535
536 /*
Len Brown2f32edf2012-09-21 23:45:46 -0400537 * Extra MSR is a snapshot, simply copy latest w/o subtracting
Len Brownc98d5d92012-06-04 00:56:40 -0400538 */
Len Brown2f32edf2012-09-21 23:45:46 -0400539 old->extra_msr32 = new->extra_msr32;
540 old->extra_msr64 = new->extra_msr64;
Len Brownc98d5d92012-06-04 00:56:40 -0400541}
542
543int delta_cpu(struct thread_data *t, struct core_data *c,
544 struct pkg_data *p, struct thread_data *t2,
545 struct core_data *c2, struct pkg_data *p2)
546{
547 /* calculate core delta only for 1st thread in core */
548 if (t->flags & CPU_IS_FIRST_THREAD_IN_CORE)
549 delta_core(c, c2);
550
551 /* always calculate thread delta */
552 delta_thread(t, t2, c2); /* c2 is core delta */
553
554 /* calculate package delta only for 1st core in package */
555 if (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)
556 delta_package(p, p2);
557
558 return 0;
559}
560
561void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
562{
563 t->tsc = 0;
564 t->aperf = 0;
565 t->mperf = 0;
566 t->c1 = 0;
567
568 /* tells format_counters to dump all fields from this set */
569 t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE;
570
571 c->c3 = 0;
572 c->c6 = 0;
573 c->c7 = 0;
574
575 p->pc2 = 0;
576 p->pc3 = 0;
577 p->pc6 = 0;
578 p->pc7 = 0;
579}
580int sum_counters(struct thread_data *t, struct core_data *c,
581 struct pkg_data *p)
582{
583 average.threads.tsc += t->tsc;
584 average.threads.aperf += t->aperf;
585 average.threads.mperf += t->mperf;
586 average.threads.c1 += t->c1;
587
588 /* sum per-core values only for 1st thread in core */
589 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
590 return 0;
591
592 average.cores.c3 += c->c3;
593 average.cores.c6 += c->c6;
594 average.cores.c7 += c->c7;
595
596 /* sum per-pkg values only for 1st core in pkg */
597 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
598 return 0;
599
600 average.packages.pc2 += p->pc2;
601 average.packages.pc3 += p->pc3;
602 average.packages.pc6 += p->pc6;
603 average.packages.pc7 += p->pc7;
604
605 return 0;
606}
607/*
608 * sum the counters for all cpus in the system
609 * compute the weighted average
610 */
611void compute_average(struct thread_data *t, struct core_data *c,
612 struct pkg_data *p)
613{
614 clear_counters(&average.threads, &average.cores, &average.packages);
615
616 for_all_cpus(sum_counters, t, c, p);
617
618 average.threads.tsc /= topo.num_cpus;
619 average.threads.aperf /= topo.num_cpus;
620 average.threads.mperf /= topo.num_cpus;
621 average.threads.c1 /= topo.num_cpus;
622
623 average.cores.c3 /= topo.num_cores;
624 average.cores.c6 /= topo.num_cores;
625 average.cores.c7 /= topo.num_cores;
626
627 average.packages.pc2 /= topo.num_packages;
628 average.packages.pc3 /= topo.num_packages;
629 average.packages.pc6 /= topo.num_packages;
630 average.packages.pc7 /= topo.num_packages;
631}
632
633static unsigned long long rdtsc(void)
634{
635 unsigned int low, high;
636
637 asm volatile("rdtsc" : "=a" (low), "=d" (high));
638
639 return low | ((unsigned long long)high) << 32;
640}
641
642
643/*
644 * get_counters(...)
645 * migrate to cpu
646 * acquire and record local counters for that cpu
647 */
648int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
649{
650 int cpu = t->cpu_id;
651
652 if (cpu_migrate(cpu))
653 return -1;
654
655 t->tsc = rdtsc(); /* we are running on local CPU of interest */
656
657 if (has_aperf) {
658 if (get_msr(cpu, MSR_APERF, &t->aperf))
659 return -3;
660 if (get_msr(cpu, MSR_MPERF, &t->mperf))
661 return -4;
662 }
663
Len Brown2f32edf2012-09-21 23:45:46 -0400664 if (extra_msr_offset32)
665 if (get_msr32(cpu, extra_msr_offset32, &t->extra_msr32))
666 return -5;
667
668 if (extra_msr_offset64)
669 if (get_msr(cpu, extra_msr_offset64, &t->extra_msr64))
Len Brownc98d5d92012-06-04 00:56:40 -0400670 return -5;
671
672 /* collect core counters only for 1st thread in core */
673 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
674 return 0;
675
676 if (do_nhm_cstates) {
677 if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3))
678 return -6;
679 if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6))
680 return -7;
681 }
682
683 if (do_snb_cstates)
684 if (get_msr(cpu, MSR_CORE_C7_RESIDENCY, &c->c7))
685 return -8;
686
687 /* collect package counters only for 1st core in package */
688 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
689 return 0;
690
691 if (do_nhm_cstates) {
692 if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3))
693 return -9;
694 if (get_msr(cpu, MSR_PKG_C6_RESIDENCY, &p->pc6))
695 return -10;
696 }
697 if (do_snb_cstates) {
698 if (get_msr(cpu, MSR_PKG_C2_RESIDENCY, &p->pc2))
699 return -11;
700 if (get_msr(cpu, MSR_PKG_C7_RESIDENCY, &p->pc7))
701 return -12;
Len Brown103a8fe2010-10-22 23:53:03 -0400702 }
703 return 0;
704}
705
Len Brownc98d5d92012-06-04 00:56:40 -0400706void print_verbose_header(void)
Len Brown103a8fe2010-10-22 23:53:03 -0400707{
708 unsigned long long msr;
709 unsigned int ratio;
710
711 if (!do_nehalem_platform_info)
712 return;
713
Len Brown15aaa342012-03-29 22:19:58 -0400714 get_msr(0, MSR_NEHALEM_PLATFORM_INFO, &msr);
Len Brown103a8fe2010-10-22 23:53:03 -0400715
Len Brown6574a5d2012-09-21 00:01:31 -0400716 if (verbose > 1)
717 fprintf(stderr, "MSR_NEHALEM_PLATFORM_INFO: 0x%llx\n", msr);
718
Len Brown103a8fe2010-10-22 23:53:03 -0400719 ratio = (msr >> 40) & 0xFF;
720 fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n",
721 ratio, bclk, ratio * bclk);
722
723 ratio = (msr >> 8) & 0xFF;
724 fprintf(stderr, "%d * %.0f = %.0f MHz TSC frequency\n",
725 ratio, bclk, ratio * bclk);
726
Len Brown6574a5d2012-09-21 00:01:31 -0400727 if (!do_ivt_turbo_ratio_limit)
728 goto print_nhm_turbo_ratio_limits;
729
730 get_msr(0, MSR_IVT_TURBO_RATIO_LIMIT, &msr);
731
Len Brown103a8fe2010-10-22 23:53:03 -0400732 if (verbose > 1)
Len Brown6574a5d2012-09-21 00:01:31 -0400733 fprintf(stderr, "MSR_IVT_TURBO_RATIO_LIMIT: 0x%llx\n", msr);
734
735 ratio = (msr >> 56) & 0xFF;
736 if (ratio)
737 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 16 active cores\n",
738 ratio, bclk, ratio * bclk);
739
740 ratio = (msr >> 48) & 0xFF;
741 if (ratio)
742 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 15 active cores\n",
743 ratio, bclk, ratio * bclk);
744
745 ratio = (msr >> 40) & 0xFF;
746 if (ratio)
747 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 14 active cores\n",
748 ratio, bclk, ratio * bclk);
749
750 ratio = (msr >> 32) & 0xFF;
751 if (ratio)
752 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 13 active cores\n",
753 ratio, bclk, ratio * bclk);
754
755 ratio = (msr >> 24) & 0xFF;
756 if (ratio)
757 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 12 active cores\n",
758 ratio, bclk, ratio * bclk);
759
760 ratio = (msr >> 16) & 0xFF;
761 if (ratio)
762 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 11 active cores\n",
763 ratio, bclk, ratio * bclk);
764
765 ratio = (msr >> 8) & 0xFF;
766 if (ratio)
767 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 10 active cores\n",
768 ratio, bclk, ratio * bclk);
769
770 ratio = (msr >> 0) & 0xFF;
771 if (ratio)
772 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 9 active cores\n",
773 ratio, bclk, ratio * bclk);
774
775print_nhm_turbo_ratio_limits:
Len Brown103a8fe2010-10-22 23:53:03 -0400776
777 if (!do_nehalem_turbo_ratio_limit)
778 return;
779
Len Brown15aaa342012-03-29 22:19:58 -0400780 get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT, &msr);
Len Brown103a8fe2010-10-22 23:53:03 -0400781
Len Brown6574a5d2012-09-21 00:01:31 -0400782 if (verbose > 1)
783 fprintf(stderr, "MSR_NEHALEM_TURBO_RATIO_LIMIT: 0x%llx\n", msr);
784
785 ratio = (msr >> 56) & 0xFF;
786 if (ratio)
787 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 8 active cores\n",
788 ratio, bclk, ratio * bclk);
789
790 ratio = (msr >> 48) & 0xFF;
791 if (ratio)
792 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 7 active cores\n",
793 ratio, bclk, ratio * bclk);
794
795 ratio = (msr >> 40) & 0xFF;
796 if (ratio)
797 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 6 active cores\n",
798 ratio, bclk, ratio * bclk);
799
800 ratio = (msr >> 32) & 0xFF;
801 if (ratio)
802 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 5 active cores\n",
803 ratio, bclk, ratio * bclk);
804
Len Brown103a8fe2010-10-22 23:53:03 -0400805 ratio = (msr >> 24) & 0xFF;
806 if (ratio)
807 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 4 active cores\n",
808 ratio, bclk, ratio * bclk);
809
810 ratio = (msr >> 16) & 0xFF;
811 if (ratio)
812 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 3 active cores\n",
813 ratio, bclk, ratio * bclk);
814
815 ratio = (msr >> 8) & 0xFF;
816 if (ratio)
817 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 2 active cores\n",
818 ratio, bclk, ratio * bclk);
819
820 ratio = (msr >> 0) & 0xFF;
821 if (ratio)
822 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n",
823 ratio, bclk, ratio * bclk);
Len Brown103a8fe2010-10-22 23:53:03 -0400824}
825
Len Brownc98d5d92012-06-04 00:56:40 -0400826void free_all_buffers(void)
Len Brown103a8fe2010-10-22 23:53:03 -0400827{
Len Brownc98d5d92012-06-04 00:56:40 -0400828 CPU_FREE(cpu_present_set);
829 cpu_present_set = NULL;
830 cpu_present_set = 0;
Len Brown103a8fe2010-10-22 23:53:03 -0400831
Len Brownc98d5d92012-06-04 00:56:40 -0400832 CPU_FREE(cpu_affinity_set);
833 cpu_affinity_set = NULL;
834 cpu_affinity_setsize = 0;
Len Brown103a8fe2010-10-22 23:53:03 -0400835
Len Brownc98d5d92012-06-04 00:56:40 -0400836 free(thread_even);
837 free(core_even);
838 free(package_even);
839
840 thread_even = NULL;
841 core_even = NULL;
842 package_even = NULL;
843
844 free(thread_odd);
845 free(core_odd);
846 free(package_odd);
847
848 thread_odd = NULL;
849 core_odd = NULL;
850 package_odd = NULL;
851
852 free(output_buffer);
853 output_buffer = NULL;
854 outp = NULL;
Len Brown103a8fe2010-10-22 23:53:03 -0400855}
856
Len Brownc98d5d92012-06-04 00:56:40 -0400857/*
858 * cpu_is_first_sibling_in_core(cpu)
859 * return 1 if given CPU is 1st HT sibling in the core
860 */
861int cpu_is_first_sibling_in_core(int cpu)
Len Brown103a8fe2010-10-22 23:53:03 -0400862{
Len Brownc98d5d92012-06-04 00:56:40 -0400863 char path[64];
864 FILE *filep;
865 int first_cpu;
Len Brown103a8fe2010-10-22 23:53:03 -0400866
Len Brownc98d5d92012-06-04 00:56:40 -0400867 sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", cpu);
868 filep = fopen(path, "r");
869 if (filep == NULL) {
870 perror(path);
871 exit(1);
872 }
873 fscanf(filep, "%d", &first_cpu);
874 fclose(filep);
875 return (cpu == first_cpu);
Len Brown103a8fe2010-10-22 23:53:03 -0400876}
877
Len Brownc98d5d92012-06-04 00:56:40 -0400878/*
879 * cpu_is_first_core_in_package(cpu)
880 * return 1 if given CPU is 1st core in package
881 */
882int cpu_is_first_core_in_package(int cpu)
Len Brown103a8fe2010-10-22 23:53:03 -0400883{
Len Brownc98d5d92012-06-04 00:56:40 -0400884 char path[64];
885 FILE *filep;
886 int first_cpu;
Len Brown103a8fe2010-10-22 23:53:03 -0400887
Len Brownc98d5d92012-06-04 00:56:40 -0400888 sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/core_siblings_list", cpu);
889 filep = fopen(path, "r");
890 if (filep == NULL) {
891 perror(path);
Len Brown103a8fe2010-10-22 23:53:03 -0400892 exit(1);
893 }
Len Brownc98d5d92012-06-04 00:56:40 -0400894 fscanf(filep, "%d", &first_cpu);
895 fclose(filep);
896 return (cpu == first_cpu);
Len Brown103a8fe2010-10-22 23:53:03 -0400897}
898
899int get_physical_package_id(int cpu)
900{
Len Brownc98d5d92012-06-04 00:56:40 -0400901 char path[80];
Len Brown103a8fe2010-10-22 23:53:03 -0400902 FILE *filep;
903 int pkg;
904
905 sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu);
906 filep = fopen(path, "r");
907 if (filep == NULL) {
908 perror(path);
909 exit(1);
910 }
911 fscanf(filep, "%d", &pkg);
912 fclose(filep);
913 return pkg;
914}
915
916int get_core_id(int cpu)
917{
Len Brownc98d5d92012-06-04 00:56:40 -0400918 char path[80];
Len Brown103a8fe2010-10-22 23:53:03 -0400919 FILE *filep;
920 int core;
921
922 sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/core_id", cpu);
923 filep = fopen(path, "r");
924 if (filep == NULL) {
925 perror(path);
926 exit(1);
927 }
928 fscanf(filep, "%d", &core);
929 fclose(filep);
930 return core;
931}
932
Len Brownc98d5d92012-06-04 00:56:40 -0400933int get_num_ht_siblings(int cpu)
934{
935 char path[80];
936 FILE *filep;
937 int sib1, sib2;
938 int matches;
939 char character;
940
941 sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", cpu);
942 filep = fopen(path, "r");
943 if (filep == NULL) {
944 perror(path);
945 exit(1);
946 }
947 /*
948 * file format:
949 * if a pair of number with a character between: 2 siblings (eg. 1-2, or 1,4)
950 * otherwinse 1 sibling (self).
951 */
952 matches = fscanf(filep, "%d%c%d\n", &sib1, &character, &sib2);
953
954 fclose(filep);
955
956 if (matches == 3)
957 return 2;
958 else
959 return 1;
960}
961
Len Brown103a8fe2010-10-22 23:53:03 -0400962/*
Len Brownc98d5d92012-06-04 00:56:40 -0400963 * run func(thread, core, package) in topology order
964 * skip non-present cpus
Len Brown103a8fe2010-10-22 23:53:03 -0400965 */
966
Len Brownc98d5d92012-06-04 00:56:40 -0400967int for_all_cpus_2(int (func)(struct thread_data *, struct core_data *,
968 struct pkg_data *, struct thread_data *, struct core_data *,
969 struct pkg_data *), struct thread_data *thread_base,
970 struct core_data *core_base, struct pkg_data *pkg_base,
971 struct thread_data *thread_base2, struct core_data *core_base2,
972 struct pkg_data *pkg_base2)
973{
974 int retval, pkg_no, core_no, thread_no;
975
976 for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) {
977 for (core_no = 0; core_no < topo.num_cores_per_pkg; ++core_no) {
978 for (thread_no = 0; thread_no <
979 topo.num_threads_per_core; ++thread_no) {
980 struct thread_data *t, *t2;
981 struct core_data *c, *c2;
982 struct pkg_data *p, *p2;
983
984 t = GET_THREAD(thread_base, thread_no, core_no, pkg_no);
985
986 if (cpu_is_not_present(t->cpu_id))
987 continue;
988
989 t2 = GET_THREAD(thread_base2, thread_no, core_no, pkg_no);
990
991 c = GET_CORE(core_base, core_no, pkg_no);
992 c2 = GET_CORE(core_base2, core_no, pkg_no);
993
994 p = GET_PKG(pkg_base, pkg_no);
995 p2 = GET_PKG(pkg_base2, pkg_no);
996
997 retval = func(t, c, p, t2, c2, p2);
998 if (retval)
999 return retval;
1000 }
1001 }
1002 }
1003 return 0;
1004}
1005
1006/*
1007 * run func(cpu) on every cpu in /proc/stat
1008 * return max_cpu number
1009 */
1010int for_all_proc_cpus(int (func)(int))
Len Brown103a8fe2010-10-22 23:53:03 -04001011{
1012 FILE *fp;
Len Brownc98d5d92012-06-04 00:56:40 -04001013 int cpu_num;
Len Brown103a8fe2010-10-22 23:53:03 -04001014 int retval;
1015
1016 fp = fopen(proc_stat, "r");
1017 if (fp == NULL) {
1018 perror(proc_stat);
1019 exit(1);
1020 }
1021
1022 retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
1023 if (retval != 0) {
1024 perror("/proc/stat format");
1025 exit(1);
1026 }
1027
Len Brownc98d5d92012-06-04 00:56:40 -04001028 while (1) {
1029 retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num);
Len Brown103a8fe2010-10-22 23:53:03 -04001030 if (retval != 1)
1031 break;
1032
Len Brownc98d5d92012-06-04 00:56:40 -04001033 retval = func(cpu_num);
1034 if (retval) {
1035 fclose(fp);
1036 return(retval);
1037 }
Len Brown103a8fe2010-10-22 23:53:03 -04001038 }
1039 fclose(fp);
Len Brownc98d5d92012-06-04 00:56:40 -04001040 return 0;
Len Brown103a8fe2010-10-22 23:53:03 -04001041}
1042
1043void re_initialize(void)
1044{
Len Brownc98d5d92012-06-04 00:56:40 -04001045 free_all_buffers();
1046 setup_all_buffers();
1047 printf("turbostat: re-initialized with num_cpus %d\n", topo.num_cpus);
Len Brown103a8fe2010-10-22 23:53:03 -04001048}
1049
Len Brownc98d5d92012-06-04 00:56:40 -04001050
Len Brown103a8fe2010-10-22 23:53:03 -04001051/*
Len Brownc98d5d92012-06-04 00:56:40 -04001052 * count_cpus()
1053 * remember the last one seen, it will be the max
Len Brown103a8fe2010-10-22 23:53:03 -04001054 */
Len Brownc98d5d92012-06-04 00:56:40 -04001055int count_cpus(int cpu)
Len Brown103a8fe2010-10-22 23:53:03 -04001056{
Len Brownc98d5d92012-06-04 00:56:40 -04001057 if (topo.max_cpu_num < cpu)
1058 topo.max_cpu_num = cpu;
Len Brown103a8fe2010-10-22 23:53:03 -04001059
Len Brownc98d5d92012-06-04 00:56:40 -04001060 topo.num_cpus += 1;
1061 return 0;
1062}
1063int mark_cpu_present(int cpu)
1064{
1065 CPU_SET_S(cpu, cpu_present_setsize, cpu_present_set);
Len Brown15aaa342012-03-29 22:19:58 -04001066 return 0;
Len Brown103a8fe2010-10-22 23:53:03 -04001067}
1068
1069void turbostat_loop()
1070{
Len Brownc98d5d92012-06-04 00:56:40 -04001071 int retval;
1072
Len Brown103a8fe2010-10-22 23:53:03 -04001073restart:
Len Brownc98d5d92012-06-04 00:56:40 -04001074 retval = for_all_cpus(get_counters, EVEN_COUNTERS);
1075 if (retval) {
1076 re_initialize();
1077 goto restart;
1078 }
Len Brown103a8fe2010-10-22 23:53:03 -04001079 gettimeofday(&tv_even, (struct timezone *)NULL);
1080
1081 while (1) {
Len Brownc98d5d92012-06-04 00:56:40 -04001082 if (for_all_proc_cpus(cpu_is_not_present)) {
Len Brown103a8fe2010-10-22 23:53:03 -04001083 re_initialize();
1084 goto restart;
1085 }
1086 sleep(interval_sec);
Len Brownc98d5d92012-06-04 00:56:40 -04001087 retval = for_all_cpus(get_counters, ODD_COUNTERS);
1088 if (retval) {
Len Brown15aaa342012-03-29 22:19:58 -04001089 re_initialize();
1090 goto restart;
1091 }
Len Brown103a8fe2010-10-22 23:53:03 -04001092 gettimeofday(&tv_odd, (struct timezone *)NULL);
Len Brown103a8fe2010-10-22 23:53:03 -04001093 timersub(&tv_odd, &tv_even, &tv_delta);
Len Brownc98d5d92012-06-04 00:56:40 -04001094 for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS);
1095 compute_average(EVEN_COUNTERS);
1096 format_all_counters(EVEN_COUNTERS);
1097 flush_stdout();
Len Brown15aaa342012-03-29 22:19:58 -04001098 sleep(interval_sec);
Len Brownc98d5d92012-06-04 00:56:40 -04001099 retval = for_all_cpus(get_counters, EVEN_COUNTERS);
1100 if (retval) {
Len Brown103a8fe2010-10-22 23:53:03 -04001101 re_initialize();
1102 goto restart;
1103 }
Len Brown103a8fe2010-10-22 23:53:03 -04001104 gettimeofday(&tv_even, (struct timezone *)NULL);
Len Brown103a8fe2010-10-22 23:53:03 -04001105 timersub(&tv_even, &tv_odd, &tv_delta);
Len Brownc98d5d92012-06-04 00:56:40 -04001106 for_all_cpus_2(delta_cpu, EVEN_COUNTERS, ODD_COUNTERS);
1107 compute_average(ODD_COUNTERS);
1108 format_all_counters(ODD_COUNTERS);
1109 flush_stdout();
Len Brown103a8fe2010-10-22 23:53:03 -04001110 }
1111}
1112
1113void check_dev_msr()
1114{
1115 struct stat sb;
1116
1117 if (stat("/dev/cpu/0/msr", &sb)) {
1118 fprintf(stderr, "no /dev/cpu/0/msr\n");
1119 fprintf(stderr, "Try \"# modprobe msr\"\n");
1120 exit(-5);
1121 }
1122}
1123
1124void check_super_user()
1125{
1126 if (getuid() != 0) {
1127 fprintf(stderr, "must be root\n");
1128 exit(-6);
1129 }
1130}
1131
1132int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
1133{
1134 if (!genuine_intel)
1135 return 0;
1136
1137 if (family != 6)
1138 return 0;
1139
1140 switch (model) {
1141 case 0x1A: /* Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP */
1142 case 0x1E: /* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */
1143 case 0x1F: /* Core i7 and i5 Processor - Nehalem */
1144 case 0x25: /* Westmere Client - Clarkdale, Arrandale */
1145 case 0x2C: /* Westmere EP - Gulftown */
1146 case 0x2A: /* SNB */
1147 case 0x2D: /* SNB Xeon */
Len Brown553575f2011-11-18 03:32:01 -05001148 case 0x3A: /* IVB */
Len Brown13006512012-09-26 18:11:31 -04001149 case 0x3E: /* IVB Xeon */
Len Brown103a8fe2010-10-22 23:53:03 -04001150 return 1;
1151 case 0x2E: /* Nehalem-EX Xeon - Beckton */
1152 case 0x2F: /* Westmere-EX Xeon - Eagleton */
1153 default:
1154 return 0;
1155 }
1156}
Len Brown6574a5d2012-09-21 00:01:31 -04001157int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model)
1158{
1159 if (!genuine_intel)
1160 return 0;
1161
1162 if (family != 6)
1163 return 0;
1164
1165 switch (model) {
1166 case 0x3E: /* IVB Xeon */
1167 return 1;
1168 default:
1169 return 0;
1170 }
1171}
1172
Len Brown103a8fe2010-10-22 23:53:03 -04001173
1174int is_snb(unsigned int family, unsigned int model)
1175{
1176 if (!genuine_intel)
1177 return 0;
1178
1179 switch (model) {
1180 case 0x2A:
1181 case 0x2D:
Len Brown650a37f2012-06-03 23:34:44 -04001182 case 0x3A: /* IVB */
Len Brown13006512012-09-26 18:11:31 -04001183 case 0x3E: /* IVB Xeon */
Len Brown103a8fe2010-10-22 23:53:03 -04001184 return 1;
1185 }
1186 return 0;
1187}
1188
1189double discover_bclk(unsigned int family, unsigned int model)
1190{
1191 if (is_snb(family, model))
1192 return 100.00;
1193 else
1194 return 133.33;
1195}
1196
1197void check_cpuid()
1198{
1199 unsigned int eax, ebx, ecx, edx, max_level;
1200 unsigned int fms, family, model, stepping;
1201
1202 eax = ebx = ecx = edx = 0;
1203
1204 asm("cpuid" : "=a" (max_level), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0));
1205
1206 if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
1207 genuine_intel = 1;
1208
1209 if (verbose)
1210 fprintf(stderr, "%.4s%.4s%.4s ",
1211 (char *)&ebx, (char *)&edx, (char *)&ecx);
1212
1213 asm("cpuid" : "=a" (fms), "=c" (ecx), "=d" (edx) : "a" (1) : "ebx");
1214 family = (fms >> 8) & 0xf;
1215 model = (fms >> 4) & 0xf;
1216 stepping = fms & 0xf;
1217 if (family == 6 || family == 0xf)
1218 model += ((fms >> 16) & 0xf) << 4;
1219
1220 if (verbose)
1221 fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
1222 max_level, family, model, stepping, family, model, stepping);
1223
1224 if (!(edx & (1 << 5))) {
1225 fprintf(stderr, "CPUID: no MSR\n");
1226 exit(1);
1227 }
1228
1229 /*
1230 * check max extended function levels of CPUID.
1231 * This is needed to check for invariant TSC.
1232 * This check is valid for both Intel and AMD.
1233 */
1234 ebx = ecx = edx = 0;
1235 asm("cpuid" : "=a" (max_level), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x80000000));
1236
1237 if (max_level < 0x80000007) {
1238 fprintf(stderr, "CPUID: no invariant TSC (max_level 0x%x)\n", max_level);
1239 exit(1);
1240 }
1241
1242 /*
1243 * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8
1244 * this check is valid for both Intel and AMD
1245 */
1246 asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x80000007));
Thomas Renninger8209e052011-01-21 15:11:19 +01001247 has_invariant_tsc = edx & (1 << 8);
Len Brown103a8fe2010-10-22 23:53:03 -04001248
1249 if (!has_invariant_tsc) {
1250 fprintf(stderr, "No invariant TSC\n");
1251 exit(1);
1252 }
1253
1254 /*
1255 * APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit0
1256 * this check is valid for both Intel and AMD
1257 */
1258
1259 asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x6));
Thomas Renninger8209e052011-01-21 15:11:19 +01001260 has_aperf = ecx & (1 << 0);
Len Brown103a8fe2010-10-22 23:53:03 -04001261 if (!has_aperf) {
1262 fprintf(stderr, "No APERF MSR\n");
1263 exit(1);
1264 }
1265
1266 do_nehalem_platform_info = genuine_intel && has_invariant_tsc;
1267 do_nhm_cstates = genuine_intel; /* all Intel w/ non-stop TSC have NHM counters */
1268 do_snb_cstates = is_snb(family, model);
1269 bclk = discover_bclk(family, model);
1270
1271 do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model);
Len Brown6574a5d2012-09-21 00:01:31 -04001272 do_ivt_turbo_ratio_limit = has_ivt_turbo_ratio_limit(family, model);
Len Brown103a8fe2010-10-22 23:53:03 -04001273}
1274
1275
1276void usage()
1277{
Len Brown2f32edf2012-09-21 23:45:46 -04001278 fprintf(stderr, "%s: [-v] [-m msr#] [-M MSR#] [-i interval_sec | command ...]\n",
Len Brown103a8fe2010-10-22 23:53:03 -04001279 progname);
1280 exit(1);
1281}
1282
1283
1284/*
1285 * in /dev/cpu/ return success for names that are numbers
1286 * ie. filter out ".", "..", "microcode".
1287 */
1288int dir_filter(const struct dirent *dirp)
1289{
1290 if (isdigit(dirp->d_name[0]))
1291 return 1;
1292 else
1293 return 0;
1294}
1295
1296int open_dev_cpu_msr(int dummy1)
1297{
1298 return 0;
1299}
1300
Len Brownc98d5d92012-06-04 00:56:40 -04001301void topology_probe()
1302{
1303 int i;
1304 int max_core_id = 0;
1305 int max_package_id = 0;
1306 int max_siblings = 0;
1307 struct cpu_topology {
1308 int core_id;
1309 int physical_package_id;
1310 } *cpus;
1311
1312 /* Initialize num_cpus, max_cpu_num */
1313 topo.num_cpus = 0;
1314 topo.max_cpu_num = 0;
1315 for_all_proc_cpus(count_cpus);
1316 if (!summary_only && topo.num_cpus > 1)
1317 show_cpu = 1;
1318
1319 if (verbose > 1)
1320 fprintf(stderr, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num);
1321
1322 cpus = calloc(1, (topo.max_cpu_num + 1) * sizeof(struct cpu_topology));
1323 if (cpus == NULL) {
1324 perror("calloc cpus");
1325 exit(1);
1326 }
1327
1328 /*
1329 * Allocate and initialize cpu_present_set
1330 */
1331 cpu_present_set = CPU_ALLOC((topo.max_cpu_num + 1));
1332 if (cpu_present_set == NULL) {
1333 perror("CPU_ALLOC");
1334 exit(3);
1335 }
1336 cpu_present_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));
1337 CPU_ZERO_S(cpu_present_setsize, cpu_present_set);
1338 for_all_proc_cpus(mark_cpu_present);
1339
1340 /*
1341 * Allocate and initialize cpu_affinity_set
1342 */
1343 cpu_affinity_set = CPU_ALLOC((topo.max_cpu_num + 1));
1344 if (cpu_affinity_set == NULL) {
1345 perror("CPU_ALLOC");
1346 exit(3);
1347 }
1348 cpu_affinity_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));
1349 CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set);
1350
1351
1352 /*
1353 * For online cpus
1354 * find max_core_id, max_package_id
1355 */
1356 for (i = 0; i <= topo.max_cpu_num; ++i) {
1357 int siblings;
1358
1359 if (cpu_is_not_present(i)) {
1360 if (verbose > 1)
1361 fprintf(stderr, "cpu%d NOT PRESENT\n", i);
1362 continue;
1363 }
1364 cpus[i].core_id = get_core_id(i);
1365 if (cpus[i].core_id > max_core_id)
1366 max_core_id = cpus[i].core_id;
1367
1368 cpus[i].physical_package_id = get_physical_package_id(i);
1369 if (cpus[i].physical_package_id > max_package_id)
1370 max_package_id = cpus[i].physical_package_id;
1371
1372 siblings = get_num_ht_siblings(i);
1373 if (siblings > max_siblings)
1374 max_siblings = siblings;
1375 if (verbose > 1)
1376 fprintf(stderr, "cpu %d pkg %d core %d\n",
1377 i, cpus[i].physical_package_id, cpus[i].core_id);
1378 }
1379 topo.num_cores_per_pkg = max_core_id + 1;
1380 if (verbose > 1)
1381 fprintf(stderr, "max_core_id %d, sizing for %d cores per package\n",
1382 max_core_id, topo.num_cores_per_pkg);
1383 if (!summary_only && topo.num_cores_per_pkg > 1)
1384 show_core = 1;
1385
1386 topo.num_packages = max_package_id + 1;
1387 if (verbose > 1)
1388 fprintf(stderr, "max_package_id %d, sizing for %d packages\n",
1389 max_package_id, topo.num_packages);
1390 if (!summary_only && topo.num_packages > 1)
1391 show_pkg = 1;
1392
1393 topo.num_threads_per_core = max_siblings;
1394 if (verbose > 1)
1395 fprintf(stderr, "max_siblings %d\n", max_siblings);
1396
1397 free(cpus);
1398}
1399
1400void
1401allocate_counters(struct thread_data **t, struct core_data **c, struct pkg_data **p)
1402{
1403 int i;
1404
1405 *t = calloc(topo.num_threads_per_core * topo.num_cores_per_pkg *
1406 topo.num_packages, sizeof(struct thread_data));
1407 if (*t == NULL)
1408 goto error;
1409
1410 for (i = 0; i < topo.num_threads_per_core *
1411 topo.num_cores_per_pkg * topo.num_packages; i++)
1412 (*t)[i].cpu_id = -1;
1413
1414 *c = calloc(topo.num_cores_per_pkg * topo.num_packages,
1415 sizeof(struct core_data));
1416 if (*c == NULL)
1417 goto error;
1418
1419 for (i = 0; i < topo.num_cores_per_pkg * topo.num_packages; i++)
1420 (*c)[i].core_id = -1;
1421
1422 *p = calloc(topo.num_packages, sizeof(struct pkg_data));
1423 if (*p == NULL)
1424 goto error;
1425
1426 for (i = 0; i < topo.num_packages; i++)
1427 (*p)[i].package_id = i;
1428
1429 return;
1430error:
1431 perror("calloc counters");
1432 exit(1);
1433}
1434/*
1435 * init_counter()
1436 *
1437 * set cpu_id, core_num, pkg_num
1438 * set FIRST_THREAD_IN_CORE and FIRST_CORE_IN_PACKAGE
1439 *
1440 * increment topo.num_cores when 1st core in pkg seen
1441 */
1442void init_counter(struct thread_data *thread_base, struct core_data *core_base,
1443 struct pkg_data *pkg_base, int thread_num, int core_num,
1444 int pkg_num, int cpu_id)
1445{
1446 struct thread_data *t;
1447 struct core_data *c;
1448 struct pkg_data *p;
1449
1450 t = GET_THREAD(thread_base, thread_num, core_num, pkg_num);
1451 c = GET_CORE(core_base, core_num, pkg_num);
1452 p = GET_PKG(pkg_base, pkg_num);
1453
1454 t->cpu_id = cpu_id;
1455 if (thread_num == 0) {
1456 t->flags |= CPU_IS_FIRST_THREAD_IN_CORE;
1457 if (cpu_is_first_core_in_package(cpu_id))
1458 t->flags |= CPU_IS_FIRST_CORE_IN_PACKAGE;
1459 }
1460
1461 c->core_id = core_num;
1462 p->package_id = pkg_num;
1463}
1464
1465
1466int initialize_counters(int cpu_id)
1467{
1468 int my_thread_id, my_core_id, my_package_id;
1469
1470 my_package_id = get_physical_package_id(cpu_id);
1471 my_core_id = get_core_id(cpu_id);
1472
1473 if (cpu_is_first_sibling_in_core(cpu_id)) {
1474 my_thread_id = 0;
1475 topo.num_cores++;
1476 } else {
1477 my_thread_id = 1;
1478 }
1479
1480 init_counter(EVEN_COUNTERS, my_thread_id, my_core_id, my_package_id, cpu_id);
1481 init_counter(ODD_COUNTERS, my_thread_id, my_core_id, my_package_id, cpu_id);
1482 return 0;
1483}
1484
1485void allocate_output_buffer()
1486{
1487 output_buffer = calloc(1, (1 + topo.num_cpus) * 128);
1488 outp = output_buffer;
1489 if (outp == NULL) {
1490 perror("calloc");
1491 exit(-1);
1492 }
1493}
1494
1495void setup_all_buffers(void)
1496{
1497 topology_probe();
1498 allocate_counters(&thread_even, &core_even, &package_even);
1499 allocate_counters(&thread_odd, &core_odd, &package_odd);
1500 allocate_output_buffer();
1501 for_all_proc_cpus(initialize_counters);
1502}
Len Brown103a8fe2010-10-22 23:53:03 -04001503void turbostat_init()
1504{
1505 check_cpuid();
1506
1507 check_dev_msr();
1508 check_super_user();
1509
Len Brownc98d5d92012-06-04 00:56:40 -04001510 setup_all_buffers();
Len Brown103a8fe2010-10-22 23:53:03 -04001511
1512 if (verbose)
Len Brownc98d5d92012-06-04 00:56:40 -04001513 print_verbose_header();
Len Brown103a8fe2010-10-22 23:53:03 -04001514}
1515
1516int fork_it(char **argv)
1517{
Len Brown103a8fe2010-10-22 23:53:03 -04001518 pid_t child_pid;
Len Brownd15cf7c2012-06-03 23:24:00 -04001519
Len Brownc98d5d92012-06-04 00:56:40 -04001520 for_all_cpus(get_counters, EVEN_COUNTERS);
1521 /* clear affinity side-effect of get_counters() */
1522 sched_setaffinity(0, cpu_present_setsize, cpu_present_set);
Len Brown103a8fe2010-10-22 23:53:03 -04001523 gettimeofday(&tv_even, (struct timezone *)NULL);
1524
1525 child_pid = fork();
1526 if (!child_pid) {
1527 /* child */
1528 execvp(argv[0], argv);
1529 } else {
1530 int status;
1531
1532 /* parent */
1533 if (child_pid == -1) {
1534 perror("fork");
1535 exit(1);
1536 }
1537
1538 signal(SIGINT, SIG_IGN);
1539 signal(SIGQUIT, SIG_IGN);
1540 if (waitpid(child_pid, &status, 0) == -1) {
1541 perror("wait");
1542 exit(1);
1543 }
1544 }
Len Brownc98d5d92012-06-04 00:56:40 -04001545 /*
1546 * n.b. fork_it() does not check for errors from for_all_cpus()
1547 * because re-starting is problematic when forking
1548 */
1549 for_all_cpus(get_counters, ODD_COUNTERS);
Len Brown103a8fe2010-10-22 23:53:03 -04001550 gettimeofday(&tv_odd, (struct timezone *)NULL);
Len Brown103a8fe2010-10-22 23:53:03 -04001551 timersub(&tv_odd, &tv_even, &tv_delta);
Len Brownc98d5d92012-06-04 00:56:40 -04001552 for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS);
1553 compute_average(EVEN_COUNTERS);
1554 format_all_counters(EVEN_COUNTERS);
1555 flush_stderr();
Len Brown103a8fe2010-10-22 23:53:03 -04001556
Justin P. Mattock6eab04a2011-04-08 19:49:08 -07001557 fprintf(stderr, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0);
Len Brown103a8fe2010-10-22 23:53:03 -04001558
1559 return 0;
1560}
1561
1562void cmdline(int argc, char **argv)
1563{
1564 int opt;
1565
1566 progname = argv[0];
1567
Len Brown2f32edf2012-09-21 23:45:46 -04001568 while ((opt = getopt(argc, argv, "+cpsvi:m:M:")) != -1) {
Len Brown103a8fe2010-10-22 23:53:03 -04001569 switch (opt) {
Len Brownc98d5d92012-06-04 00:56:40 -04001570 case 'c':
1571 show_core_only++;
1572 break;
1573 case 'p':
1574 show_pkg_only++;
1575 break;
Len Browne23da032012-02-06 18:37:16 -05001576 case 's':
1577 summary_only++;
1578 break;
Len Brown103a8fe2010-10-22 23:53:03 -04001579 case 'v':
1580 verbose++;
1581 break;
1582 case 'i':
1583 interval_sec = atoi(optarg);
1584 break;
Len Brown2f32edf2012-09-21 23:45:46 -04001585 case 'm':
1586 sscanf(optarg, "%x", &extra_msr_offset32);
Len Brown103a8fe2010-10-22 23:53:03 -04001587 if (verbose > 1)
Len Brown2f32edf2012-09-21 23:45:46 -04001588 fprintf(stderr, "msr 0x%X\n", extra_msr_offset32);
1589 break;
1590 case 'M':
1591 sscanf(optarg, "%x", &extra_msr_offset64);
1592 if (verbose > 1)
1593 fprintf(stderr, "MSR 0x%X\n", extra_msr_offset64);
Len Brown103a8fe2010-10-22 23:53:03 -04001594 break;
1595 default:
1596 usage();
1597 }
1598 }
1599}
1600
1601int main(int argc, char **argv)
1602{
1603 cmdline(argc, argv);
1604
1605 if (verbose > 1)
Len Brownc98d5d92012-06-04 00:56:40 -04001606 fprintf(stderr, "turbostat v2.0 May 16, 2012"
Len Brown103a8fe2010-10-22 23:53:03 -04001607 " - Len Brown <lenb@kernel.org>\n");
Len Brown103a8fe2010-10-22 23:53:03 -04001608
1609 turbostat_init();
1610
1611 /*
1612 * if any params left, it must be a command to fork
1613 */
1614 if (argc - optind)
1615 return fork_it(argv + optind);
1616 else
1617 turbostat_loop();
1618
1619 return 0;
1620}