turbostat.c 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135
  1. /*
  2. * turbostat -- show CPU frequency and C-state residency
  3. * on modern Intel turbo-capable processors.
  4. *
  5. * Copyright (c) 2012 Intel Corporation.
  6. * 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. #define _GNU_SOURCE
  22. #include <stdio.h>
  23. #include <unistd.h>
  24. #include <sys/types.h>
  25. #include <sys/wait.h>
  26. #include <sys/stat.h>
  27. #include <sys/resource.h>
  28. #include <fcntl.h>
  29. #include <signal.h>
  30. #include <sys/time.h>
  31. #include <stdlib.h>
  32. #include <dirent.h>
  33. #include <string.h>
  34. #include <ctype.h>
  35. #include <sched.h>
  36. #define MSR_TSC 0x10
  37. #define MSR_NEHALEM_PLATFORM_INFO 0xCE
  38. #define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1AD
  39. #define MSR_APERF 0xE8
  40. #define MSR_MPERF 0xE7
  41. #define MSR_PKG_C2_RESIDENCY 0x60D /* SNB only */
  42. #define MSR_PKG_C3_RESIDENCY 0x3F8
  43. #define MSR_PKG_C6_RESIDENCY 0x3F9
  44. #define MSR_PKG_C7_RESIDENCY 0x3FA /* SNB only */
  45. #define MSR_CORE_C3_RESIDENCY 0x3FC
  46. #define MSR_CORE_C6_RESIDENCY 0x3FD
  47. #define MSR_CORE_C7_RESIDENCY 0x3FE /* SNB only */
  48. char *proc_stat = "/proc/stat";
  49. unsigned int interval_sec = 5; /* set with -i interval_sec */
  50. unsigned int verbose; /* set with -v */
  51. unsigned int summary_only; /* set with -s */
  52. unsigned int skip_c0;
  53. unsigned int skip_c1;
  54. unsigned int do_nhm_cstates;
  55. unsigned int do_snb_cstates;
  56. unsigned int has_aperf;
  57. unsigned int units = 1000000000; /* Ghz etc */
  58. unsigned int genuine_intel;
  59. unsigned int has_invariant_tsc;
  60. unsigned int do_nehalem_platform_info;
  61. unsigned int do_nehalem_turbo_ratio_limit;
  62. unsigned int extra_msr_offset;
  63. double bclk;
  64. unsigned int show_pkg;
  65. unsigned int show_core;
  66. unsigned int show_cpu;
  67. int aperf_mperf_unstable;
  68. int backwards_count;
  69. char *progname;
  70. int num_cpus;
  71. cpu_set_t *cpu_mask;
  72. size_t cpu_mask_size;
  73. struct counters {
  74. unsigned long long tsc; /* per thread */
  75. unsigned long long aperf; /* per thread */
  76. unsigned long long mperf; /* per thread */
  77. unsigned long long c1; /* per thread (calculated) */
  78. unsigned long long c3; /* per core */
  79. unsigned long long c6; /* per core */
  80. unsigned long long c7; /* per core */
  81. unsigned long long pc2; /* per package */
  82. unsigned long long pc3; /* per package */
  83. unsigned long long pc6; /* per package */
  84. unsigned long long pc7; /* per package */
  85. unsigned long long extra_msr; /* per thread */
  86. int pkg;
  87. int core;
  88. int cpu;
  89. struct counters *next;
  90. };
  91. struct counters *cnt_even;
  92. struct counters *cnt_odd;
  93. struct counters *cnt_delta;
  94. struct counters *cnt_average;
  95. struct timeval tv_even;
  96. struct timeval tv_odd;
  97. struct timeval tv_delta;
  98. /*
  99. * cpu_mask_init(ncpus)
  100. *
  101. * allocate and clear cpu_mask
  102. * set cpu_mask_size
  103. */
  104. void cpu_mask_init(int ncpus)
  105. {
  106. cpu_mask = CPU_ALLOC(ncpus);
  107. if (cpu_mask == NULL) {
  108. perror("CPU_ALLOC");
  109. exit(3);
  110. }
  111. cpu_mask_size = CPU_ALLOC_SIZE(ncpus);
  112. CPU_ZERO_S(cpu_mask_size, cpu_mask);
  113. }
  114. void cpu_mask_uninit()
  115. {
  116. CPU_FREE(cpu_mask);
  117. cpu_mask = NULL;
  118. cpu_mask_size = 0;
  119. }
  120. int cpu_migrate(int cpu)
  121. {
  122. CPU_ZERO_S(cpu_mask_size, cpu_mask);
  123. CPU_SET_S(cpu, cpu_mask_size, cpu_mask);
  124. if (sched_setaffinity(0, cpu_mask_size, cpu_mask) == -1)
  125. return -1;
  126. else
  127. return 0;
  128. }
  129. int get_msr(int cpu, off_t offset, unsigned long long *msr)
  130. {
  131. ssize_t retval;
  132. char pathname[32];
  133. int fd;
  134. sprintf(pathname, "/dev/cpu/%d/msr", cpu);
  135. fd = open(pathname, O_RDONLY);
  136. if (fd < 0)
  137. return -1;
  138. retval = pread(fd, msr, sizeof *msr, offset);
  139. close(fd);
  140. if (retval != sizeof *msr)
  141. return -1;
  142. return 0;
  143. }
  144. void print_header(void)
  145. {
  146. if (show_pkg)
  147. fprintf(stderr, "pk");
  148. if (show_pkg)
  149. fprintf(stderr, " ");
  150. if (show_core)
  151. fprintf(stderr, "cor");
  152. if (show_cpu)
  153. fprintf(stderr, " CPU");
  154. if (show_pkg || show_core || show_cpu)
  155. fprintf(stderr, " ");
  156. if (do_nhm_cstates)
  157. fprintf(stderr, " %%c0");
  158. if (has_aperf)
  159. fprintf(stderr, " GHz");
  160. fprintf(stderr, " TSC");
  161. if (do_nhm_cstates)
  162. fprintf(stderr, " %%c1");
  163. if (do_nhm_cstates)
  164. fprintf(stderr, " %%c3");
  165. if (do_nhm_cstates)
  166. fprintf(stderr, " %%c6");
  167. if (do_snb_cstates)
  168. fprintf(stderr, " %%c7");
  169. if (do_snb_cstates)
  170. fprintf(stderr, " %%pc2");
  171. if (do_nhm_cstates)
  172. fprintf(stderr, " %%pc3");
  173. if (do_nhm_cstates)
  174. fprintf(stderr, " %%pc6");
  175. if (do_snb_cstates)
  176. fprintf(stderr, " %%pc7");
  177. if (extra_msr_offset)
  178. fprintf(stderr, " MSR 0x%x ", extra_msr_offset);
  179. putc('\n', stderr);
  180. }
  181. void dump_cnt(struct counters *cnt)
  182. {
  183. if (!cnt)
  184. return;
  185. if (cnt->pkg) fprintf(stderr, "package: %d ", cnt->pkg);
  186. if (cnt->core) fprintf(stderr, "core:: %d ", cnt->core);
  187. if (cnt->cpu) fprintf(stderr, "CPU: %d ", cnt->cpu);
  188. if (cnt->tsc) fprintf(stderr, "TSC: %016llX\n", cnt->tsc);
  189. if (cnt->c3) fprintf(stderr, "c3: %016llX\n", cnt->c3);
  190. if (cnt->c6) fprintf(stderr, "c6: %016llX\n", cnt->c6);
  191. if (cnt->c7) fprintf(stderr, "c7: %016llX\n", cnt->c7);
  192. if (cnt->aperf) fprintf(stderr, "aperf: %016llX\n", cnt->aperf);
  193. if (cnt->pc2) fprintf(stderr, "pc2: %016llX\n", cnt->pc2);
  194. if (cnt->pc3) fprintf(stderr, "pc3: %016llX\n", cnt->pc3);
  195. if (cnt->pc6) fprintf(stderr, "pc6: %016llX\n", cnt->pc6);
  196. if (cnt->pc7) fprintf(stderr, "pc7: %016llX\n", cnt->pc7);
  197. if (cnt->extra_msr) fprintf(stderr, "msr0x%x: %016llX\n", extra_msr_offset, cnt->extra_msr);
  198. }
  199. void dump_list(struct counters *cnt)
  200. {
  201. printf("dump_list 0x%p\n", cnt);
  202. for (; cnt; cnt = cnt->next)
  203. dump_cnt(cnt);
  204. }
  205. /*
  206. * column formatting convention & formats
  207. * package: "pk" 2 columns %2d
  208. * core: "cor" 3 columns %3d
  209. * CPU: "CPU" 3 columns %3d
  210. * GHz: "GHz" 3 columns %3.2
  211. * TSC: "TSC" 3 columns %3.2
  212. * percentage " %pc3" %6.2
  213. */
  214. void print_cnt(struct counters *p)
  215. {
  216. double interval_float;
  217. interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0;
  218. /* topology columns, print blanks on 1st (average) line */
  219. if (p == cnt_average) {
  220. if (show_pkg)
  221. fprintf(stderr, " ");
  222. if (show_pkg && show_core)
  223. fprintf(stderr, " ");
  224. if (show_core)
  225. fprintf(stderr, " ");
  226. if (show_cpu)
  227. fprintf(stderr, " " " ");
  228. } else {
  229. if (show_pkg)
  230. fprintf(stderr, "%2d", p->pkg);
  231. if (show_pkg && show_core)
  232. fprintf(stderr, " ");
  233. if (show_core)
  234. fprintf(stderr, "%3d", p->core);
  235. if (show_cpu)
  236. fprintf(stderr, " %3d", p->cpu);
  237. }
  238. /* %c0 */
  239. if (do_nhm_cstates) {
  240. if (show_pkg || show_core || show_cpu)
  241. fprintf(stderr, " ");
  242. if (!skip_c0)
  243. fprintf(stderr, "%6.2f", 100.0 * p->mperf/p->tsc);
  244. else
  245. fprintf(stderr, " ****");
  246. }
  247. /* GHz */
  248. if (has_aperf) {
  249. if (!aperf_mperf_unstable) {
  250. fprintf(stderr, " %3.2f",
  251. 1.0 * p->tsc / units * p->aperf /
  252. p->mperf / interval_float);
  253. } else {
  254. if (p->aperf > p->tsc || p->mperf > p->tsc) {
  255. fprintf(stderr, " ***");
  256. } else {
  257. fprintf(stderr, "%3.1f*",
  258. 1.0 * p->tsc /
  259. units * p->aperf /
  260. p->mperf / interval_float);
  261. }
  262. }
  263. }
  264. /* TSC */
  265. fprintf(stderr, "%5.2f", 1.0 * p->tsc/units/interval_float);
  266. if (do_nhm_cstates) {
  267. if (!skip_c1)
  268. fprintf(stderr, " %6.2f", 100.0 * p->c1/p->tsc);
  269. else
  270. fprintf(stderr, " ****");
  271. }
  272. if (do_nhm_cstates)
  273. fprintf(stderr, " %6.2f", 100.0 * p->c3/p->tsc);
  274. if (do_nhm_cstates)
  275. fprintf(stderr, " %6.2f", 100.0 * p->c6/p->tsc);
  276. if (do_snb_cstates)
  277. fprintf(stderr, " %6.2f", 100.0 * p->c7/p->tsc);
  278. if (do_snb_cstates)
  279. fprintf(stderr, " %6.2f", 100.0 * p->pc2/p->tsc);
  280. if (do_nhm_cstates)
  281. fprintf(stderr, " %6.2f", 100.0 * p->pc3/p->tsc);
  282. if (do_nhm_cstates)
  283. fprintf(stderr, " %6.2f", 100.0 * p->pc6/p->tsc);
  284. if (do_snb_cstates)
  285. fprintf(stderr, " %6.2f", 100.0 * p->pc7/p->tsc);
  286. if (extra_msr_offset)
  287. fprintf(stderr, " 0x%016llx", p->extra_msr);
  288. putc('\n', stderr);
  289. }
  290. void print_counters(struct counters *counters)
  291. {
  292. struct counters *cnt;
  293. static int printed;
  294. if (!printed || !summary_only)
  295. print_header();
  296. if (num_cpus > 1)
  297. print_cnt(cnt_average);
  298. printed = 1;
  299. if (summary_only)
  300. return;
  301. for (cnt = counters; cnt != NULL; cnt = cnt->next)
  302. print_cnt(cnt);
  303. }
  304. #define SUBTRACT_COUNTER(after, before, delta) (delta = (after - before), (before > after))
  305. int compute_delta(struct counters *after,
  306. struct counters *before, struct counters *delta)
  307. {
  308. int errors = 0;
  309. int perf_err = 0;
  310. skip_c0 = skip_c1 = 0;
  311. for ( ; after && before && delta;
  312. after = after->next, before = before->next, delta = delta->next) {
  313. if (before->cpu != after->cpu) {
  314. printf("cpu configuration changed: %d != %d\n",
  315. before->cpu, after->cpu);
  316. return -1;
  317. }
  318. if (SUBTRACT_COUNTER(after->tsc, before->tsc, delta->tsc)) {
  319. fprintf(stderr, "cpu%d TSC went backwards %llX to %llX\n",
  320. before->cpu, before->tsc, after->tsc);
  321. errors++;
  322. }
  323. /* check for TSC < 1 Mcycles over interval */
  324. if (delta->tsc < (1000 * 1000)) {
  325. fprintf(stderr, "Insanely slow TSC rate,"
  326. " TSC stops in idle?\n");
  327. fprintf(stderr, "You can disable all c-states"
  328. " by booting with \"idle=poll\"\n");
  329. fprintf(stderr, "or just the deep ones with"
  330. " \"processor.max_cstate=1\"\n");
  331. exit(-3);
  332. }
  333. if (SUBTRACT_COUNTER(after->c3, before->c3, delta->c3)) {
  334. fprintf(stderr, "cpu%d c3 counter went backwards %llX to %llX\n",
  335. before->cpu, before->c3, after->c3);
  336. errors++;
  337. }
  338. if (SUBTRACT_COUNTER(after->c6, before->c6, delta->c6)) {
  339. fprintf(stderr, "cpu%d c6 counter went backwards %llX to %llX\n",
  340. before->cpu, before->c6, after->c6);
  341. errors++;
  342. }
  343. if (SUBTRACT_COUNTER(after->c7, before->c7, delta->c7)) {
  344. fprintf(stderr, "cpu%d c7 counter went backwards %llX to %llX\n",
  345. before->cpu, before->c7, after->c7);
  346. errors++;
  347. }
  348. if (SUBTRACT_COUNTER(after->pc2, before->pc2, delta->pc2)) {
  349. fprintf(stderr, "cpu%d pc2 counter went backwards %llX to %llX\n",
  350. before->cpu, before->pc2, after->pc2);
  351. errors++;
  352. }
  353. if (SUBTRACT_COUNTER(after->pc3, before->pc3, delta->pc3)) {
  354. fprintf(stderr, "cpu%d pc3 counter went backwards %llX to %llX\n",
  355. before->cpu, before->pc3, after->pc3);
  356. errors++;
  357. }
  358. if (SUBTRACT_COUNTER(after->pc6, before->pc6, delta->pc6)) {
  359. fprintf(stderr, "cpu%d pc6 counter went backwards %llX to %llX\n",
  360. before->cpu, before->pc6, after->pc6);
  361. errors++;
  362. }
  363. if (SUBTRACT_COUNTER(after->pc7, before->pc7, delta->pc7)) {
  364. fprintf(stderr, "cpu%d pc7 counter went backwards %llX to %llX\n",
  365. before->cpu, before->pc7, after->pc7);
  366. errors++;
  367. }
  368. perf_err = SUBTRACT_COUNTER(after->aperf, before->aperf, delta->aperf);
  369. if (perf_err) {
  370. fprintf(stderr, "cpu%d aperf counter went backwards %llX to %llX\n",
  371. before->cpu, before->aperf, after->aperf);
  372. }
  373. perf_err |= SUBTRACT_COUNTER(after->mperf, before->mperf, delta->mperf);
  374. if (perf_err) {
  375. fprintf(stderr, "cpu%d mperf counter went backwards %llX to %llX\n",
  376. before->cpu, before->mperf, after->mperf);
  377. }
  378. if (perf_err) {
  379. if (!aperf_mperf_unstable) {
  380. fprintf(stderr, "%s: APERF or MPERF went backwards *\n", progname);
  381. fprintf(stderr, "* Frequency results do not cover entire interval *\n");
  382. fprintf(stderr, "* fix this by running Linux-2.6.30 or later *\n");
  383. aperf_mperf_unstable = 1;
  384. }
  385. /*
  386. * mperf delta is likely a huge "positive" number
  387. * can not use it for calculating c0 time
  388. */
  389. skip_c0 = 1;
  390. skip_c1 = 1;
  391. }
  392. /*
  393. * As mperf and tsc collection are not atomic,
  394. * it is possible for mperf's non-halted cycles
  395. * to exceed TSC's all cycles: show c1 = 0% in that case.
  396. */
  397. if (delta->mperf > delta->tsc)
  398. delta->c1 = 0;
  399. else /* normal case, derive c1 */
  400. delta->c1 = delta->tsc - delta->mperf
  401. - delta->c3 - delta->c6 - delta->c7;
  402. if (delta->mperf == 0)
  403. delta->mperf = 1; /* divide by 0 protection */
  404. /*
  405. * for "extra msr", just copy the latest w/o subtracting
  406. */
  407. delta->extra_msr = after->extra_msr;
  408. if (errors) {
  409. fprintf(stderr, "ERROR cpu%d before:\n", before->cpu);
  410. dump_cnt(before);
  411. fprintf(stderr, "ERROR cpu%d after:\n", before->cpu);
  412. dump_cnt(after);
  413. errors = 0;
  414. }
  415. }
  416. return 0;
  417. }
  418. void compute_average(struct counters *delta, struct counters *avg)
  419. {
  420. struct counters *sum;
  421. sum = calloc(1, sizeof(struct counters));
  422. if (sum == NULL) {
  423. perror("calloc sum");
  424. exit(1);
  425. }
  426. for (; delta; delta = delta->next) {
  427. sum->tsc += delta->tsc;
  428. sum->c1 += delta->c1;
  429. sum->c3 += delta->c3;
  430. sum->c6 += delta->c6;
  431. sum->c7 += delta->c7;
  432. sum->aperf += delta->aperf;
  433. sum->mperf += delta->mperf;
  434. sum->pc2 += delta->pc2;
  435. sum->pc3 += delta->pc3;
  436. sum->pc6 += delta->pc6;
  437. sum->pc7 += delta->pc7;
  438. }
  439. avg->tsc = sum->tsc/num_cpus;
  440. avg->c1 = sum->c1/num_cpus;
  441. avg->c3 = sum->c3/num_cpus;
  442. avg->c6 = sum->c6/num_cpus;
  443. avg->c7 = sum->c7/num_cpus;
  444. avg->aperf = sum->aperf/num_cpus;
  445. avg->mperf = sum->mperf/num_cpus;
  446. avg->pc2 = sum->pc2/num_cpus;
  447. avg->pc3 = sum->pc3/num_cpus;
  448. avg->pc6 = sum->pc6/num_cpus;
  449. avg->pc7 = sum->pc7/num_cpus;
  450. free(sum);
  451. }
  452. int get_counters(struct counters *cnt)
  453. {
  454. for ( ; cnt; cnt = cnt->next) {
  455. if (cpu_migrate(cnt->cpu))
  456. return -1;
  457. if (get_msr(cnt->cpu, MSR_TSC, &cnt->tsc))
  458. return -1;
  459. if (has_aperf) {
  460. if (get_msr(cnt->cpu, MSR_APERF, &cnt->aperf))
  461. return -1;
  462. if (get_msr(cnt->cpu, MSR_MPERF, &cnt->mperf))
  463. return -1;
  464. }
  465. if (do_nhm_cstates) {
  466. if (get_msr(cnt->cpu, MSR_CORE_C3_RESIDENCY, &cnt->c3))
  467. return -1;
  468. if (get_msr(cnt->cpu, MSR_CORE_C6_RESIDENCY, &cnt->c6))
  469. return -1;
  470. }
  471. if (do_snb_cstates)
  472. if (get_msr(cnt->cpu, MSR_CORE_C7_RESIDENCY, &cnt->c7))
  473. return -1;
  474. if (do_nhm_cstates) {
  475. if (get_msr(cnt->cpu, MSR_PKG_C3_RESIDENCY, &cnt->pc3))
  476. return -1;
  477. if (get_msr(cnt->cpu, MSR_PKG_C6_RESIDENCY, &cnt->pc6))
  478. return -1;
  479. }
  480. if (do_snb_cstates) {
  481. if (get_msr(cnt->cpu, MSR_PKG_C2_RESIDENCY, &cnt->pc2))
  482. return -1;
  483. if (get_msr(cnt->cpu, MSR_PKG_C7_RESIDENCY, &cnt->pc7))
  484. return -1;
  485. }
  486. if (extra_msr_offset)
  487. if (get_msr(cnt->cpu, extra_msr_offset, &cnt->extra_msr))
  488. return -1;
  489. }
  490. return 0;
  491. }
  492. void print_nehalem_info(void)
  493. {
  494. unsigned long long msr;
  495. unsigned int ratio;
  496. if (!do_nehalem_platform_info)
  497. return;
  498. get_msr(0, MSR_NEHALEM_PLATFORM_INFO, &msr);
  499. ratio = (msr >> 40) & 0xFF;
  500. fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n",
  501. ratio, bclk, ratio * bclk);
  502. ratio = (msr >> 8) & 0xFF;
  503. fprintf(stderr, "%d * %.0f = %.0f MHz TSC frequency\n",
  504. ratio, bclk, ratio * bclk);
  505. if (verbose > 1)
  506. fprintf(stderr, "MSR_NEHALEM_PLATFORM_INFO: 0x%llx\n", msr);
  507. if (!do_nehalem_turbo_ratio_limit)
  508. return;
  509. get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT, &msr);
  510. ratio = (msr >> 24) & 0xFF;
  511. if (ratio)
  512. fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 4 active cores\n",
  513. ratio, bclk, ratio * bclk);
  514. ratio = (msr >> 16) & 0xFF;
  515. if (ratio)
  516. fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 3 active cores\n",
  517. ratio, bclk, ratio * bclk);
  518. ratio = (msr >> 8) & 0xFF;
  519. if (ratio)
  520. fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 2 active cores\n",
  521. ratio, bclk, ratio * bclk);
  522. ratio = (msr >> 0) & 0xFF;
  523. if (ratio)
  524. fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n",
  525. ratio, bclk, ratio * bclk);
  526. }
  527. void free_counter_list(struct counters *list)
  528. {
  529. struct counters *p;
  530. for (p = list; p; ) {
  531. struct counters *free_me;
  532. free_me = p;
  533. p = p->next;
  534. free(free_me);
  535. }
  536. }
  537. void free_all_counters(void)
  538. {
  539. free_counter_list(cnt_even);
  540. cnt_even = NULL;
  541. free_counter_list(cnt_odd);
  542. cnt_odd = NULL;
  543. free_counter_list(cnt_delta);
  544. cnt_delta = NULL;
  545. free_counter_list(cnt_average);
  546. cnt_average = NULL;
  547. }
  548. void insert_counters(struct counters **list,
  549. struct counters *new)
  550. {
  551. struct counters *prev;
  552. /*
  553. * list was empty
  554. */
  555. if (*list == NULL) {
  556. new->next = *list;
  557. *list = new;
  558. return;
  559. }
  560. if (!summary_only)
  561. show_cpu = 1; /* there is more than one CPU */
  562. /*
  563. * insert on front of list.
  564. * It is sorted by ascending package#, core#, cpu#
  565. */
  566. if (((*list)->pkg > new->pkg) ||
  567. (((*list)->pkg == new->pkg) && ((*list)->core > new->core)) ||
  568. (((*list)->pkg == new->pkg) && ((*list)->core == new->core) && ((*list)->cpu > new->cpu))) {
  569. new->next = *list;
  570. *list = new;
  571. return;
  572. }
  573. prev = *list;
  574. while (prev->next && (prev->next->pkg < new->pkg)) {
  575. prev = prev->next;
  576. if (!summary_only)
  577. show_pkg = 1; /* there is more than 1 package */
  578. }
  579. while (prev->next && (prev->next->pkg == new->pkg)
  580. && (prev->next->core < new->core)) {
  581. prev = prev->next;
  582. if (!summary_only)
  583. show_core = 1; /* there is more than 1 core */
  584. }
  585. while (prev->next && (prev->next->pkg == new->pkg)
  586. && (prev->next->core == new->core)
  587. && (prev->next->cpu < new->cpu)) {
  588. prev = prev->next;
  589. }
  590. /*
  591. * insert after "prev"
  592. */
  593. new->next = prev->next;
  594. prev->next = new;
  595. }
  596. void alloc_new_counters(int pkg, int core, int cpu)
  597. {
  598. struct counters *new;
  599. if (verbose > 1)
  600. printf("pkg%d core%d, cpu%d\n", pkg, core, cpu);
  601. new = (struct counters *)calloc(1, sizeof(struct counters));
  602. if (new == NULL) {
  603. perror("calloc");
  604. exit(1);
  605. }
  606. new->pkg = pkg;
  607. new->core = core;
  608. new->cpu = cpu;
  609. insert_counters(&cnt_odd, new);
  610. new = (struct counters *)calloc(1,
  611. sizeof(struct counters));
  612. if (new == NULL) {
  613. perror("calloc");
  614. exit(1);
  615. }
  616. new->pkg = pkg;
  617. new->core = core;
  618. new->cpu = cpu;
  619. insert_counters(&cnt_even, new);
  620. new = (struct counters *)calloc(1, sizeof(struct counters));
  621. if (new == NULL) {
  622. perror("calloc");
  623. exit(1);
  624. }
  625. new->pkg = pkg;
  626. new->core = core;
  627. new->cpu = cpu;
  628. insert_counters(&cnt_delta, new);
  629. new = (struct counters *)calloc(1, sizeof(struct counters));
  630. if (new == NULL) {
  631. perror("calloc");
  632. exit(1);
  633. }
  634. new->pkg = pkg;
  635. new->core = core;
  636. new->cpu = cpu;
  637. cnt_average = new;
  638. }
  639. int get_physical_package_id(int cpu)
  640. {
  641. char path[64];
  642. FILE *filep;
  643. int pkg;
  644. sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu);
  645. filep = fopen(path, "r");
  646. if (filep == NULL) {
  647. perror(path);
  648. exit(1);
  649. }
  650. fscanf(filep, "%d", &pkg);
  651. fclose(filep);
  652. return pkg;
  653. }
  654. int get_core_id(int cpu)
  655. {
  656. char path[64];
  657. FILE *filep;
  658. int core;
  659. sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/core_id", cpu);
  660. filep = fopen(path, "r");
  661. if (filep == NULL) {
  662. perror(path);
  663. exit(1);
  664. }
  665. fscanf(filep, "%d", &core);
  666. fclose(filep);
  667. return core;
  668. }
  669. /*
  670. * run func(pkg, core, cpu) on every cpu in /proc/stat
  671. */
  672. int for_all_cpus(void (func)(int, int, int))
  673. {
  674. FILE *fp;
  675. int cpu_count;
  676. int retval;
  677. fp = fopen(proc_stat, "r");
  678. if (fp == NULL) {
  679. perror(proc_stat);
  680. exit(1);
  681. }
  682. retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
  683. if (retval != 0) {
  684. perror("/proc/stat format");
  685. exit(1);
  686. }
  687. for (cpu_count = 0; ; cpu_count++) {
  688. int cpu;
  689. retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu);
  690. if (retval != 1)
  691. break;
  692. func(get_physical_package_id(cpu), get_core_id(cpu), cpu);
  693. }
  694. fclose(fp);
  695. return cpu_count;
  696. }
  697. void re_initialize(void)
  698. {
  699. free_all_counters();
  700. num_cpus = for_all_cpus(alloc_new_counters);
  701. cpu_mask_uninit();
  702. cpu_mask_init(num_cpus);
  703. printf("turbostat: re-initialized with num_cpus %d\n", num_cpus);
  704. }
  705. void dummy(int pkg, int core, int cpu) { return; }
  706. /*
  707. * check to see if a cpu came on-line
  708. */
  709. int verify_num_cpus(void)
  710. {
  711. int new_num_cpus;
  712. new_num_cpus = for_all_cpus(dummy);
  713. if (new_num_cpus != num_cpus) {
  714. if (verbose)
  715. printf("num_cpus was %d, is now %d\n",
  716. num_cpus, new_num_cpus);
  717. return -1;
  718. }
  719. return 0;
  720. }
  721. void turbostat_loop()
  722. {
  723. restart:
  724. get_counters(cnt_even);
  725. gettimeofday(&tv_even, (struct timezone *)NULL);
  726. while (1) {
  727. if (verify_num_cpus()) {
  728. re_initialize();
  729. goto restart;
  730. }
  731. sleep(interval_sec);
  732. if (get_counters(cnt_odd)) {
  733. re_initialize();
  734. goto restart;
  735. }
  736. gettimeofday(&tv_odd, (struct timezone *)NULL);
  737. compute_delta(cnt_odd, cnt_even, cnt_delta);
  738. timersub(&tv_odd, &tv_even, &tv_delta);
  739. compute_average(cnt_delta, cnt_average);
  740. print_counters(cnt_delta);
  741. sleep(interval_sec);
  742. if (get_counters(cnt_even)) {
  743. re_initialize();
  744. goto restart;
  745. }
  746. gettimeofday(&tv_even, (struct timezone *)NULL);
  747. compute_delta(cnt_even, cnt_odd, cnt_delta);
  748. timersub(&tv_even, &tv_odd, &tv_delta);
  749. compute_average(cnt_delta, cnt_average);
  750. print_counters(cnt_delta);
  751. }
  752. }
  753. void check_dev_msr()
  754. {
  755. struct stat sb;
  756. if (stat("/dev/cpu/0/msr", &sb)) {
  757. fprintf(stderr, "no /dev/cpu/0/msr\n");
  758. fprintf(stderr, "Try \"# modprobe msr\"\n");
  759. exit(-5);
  760. }
  761. }
  762. void check_super_user()
  763. {
  764. if (getuid() != 0) {
  765. fprintf(stderr, "must be root\n");
  766. exit(-6);
  767. }
  768. }
  769. int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
  770. {
  771. if (!genuine_intel)
  772. return 0;
  773. if (family != 6)
  774. return 0;
  775. switch (model) {
  776. case 0x1A: /* Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP */
  777. case 0x1E: /* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */
  778. case 0x1F: /* Core i7 and i5 Processor - Nehalem */
  779. case 0x25: /* Westmere Client - Clarkdale, Arrandale */
  780. case 0x2C: /* Westmere EP - Gulftown */
  781. case 0x2A: /* SNB */
  782. case 0x2D: /* SNB Xeon */
  783. case 0x3A: /* IVB */
  784. case 0x3D: /* IVB Xeon */
  785. return 1;
  786. case 0x2E: /* Nehalem-EX Xeon - Beckton */
  787. case 0x2F: /* Westmere-EX Xeon - Eagleton */
  788. default:
  789. return 0;
  790. }
  791. }
  792. int is_snb(unsigned int family, unsigned int model)
  793. {
  794. if (!genuine_intel)
  795. return 0;
  796. switch (model) {
  797. case 0x2A:
  798. case 0x2D:
  799. return 1;
  800. }
  801. return 0;
  802. }
  803. double discover_bclk(unsigned int family, unsigned int model)
  804. {
  805. if (is_snb(family, model))
  806. return 100.00;
  807. else
  808. return 133.33;
  809. }
  810. void check_cpuid()
  811. {
  812. unsigned int eax, ebx, ecx, edx, max_level;
  813. unsigned int fms, family, model, stepping;
  814. eax = ebx = ecx = edx = 0;
  815. asm("cpuid" : "=a" (max_level), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0));
  816. if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
  817. genuine_intel = 1;
  818. if (verbose)
  819. fprintf(stderr, "%.4s%.4s%.4s ",
  820. (char *)&ebx, (char *)&edx, (char *)&ecx);
  821. asm("cpuid" : "=a" (fms), "=c" (ecx), "=d" (edx) : "a" (1) : "ebx");
  822. family = (fms >> 8) & 0xf;
  823. model = (fms >> 4) & 0xf;
  824. stepping = fms & 0xf;
  825. if (family == 6 || family == 0xf)
  826. model += ((fms >> 16) & 0xf) << 4;
  827. if (verbose)
  828. fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
  829. max_level, family, model, stepping, family, model, stepping);
  830. if (!(edx & (1 << 5))) {
  831. fprintf(stderr, "CPUID: no MSR\n");
  832. exit(1);
  833. }
  834. /*
  835. * check max extended function levels of CPUID.
  836. * This is needed to check for invariant TSC.
  837. * This check is valid for both Intel and AMD.
  838. */
  839. ebx = ecx = edx = 0;
  840. asm("cpuid" : "=a" (max_level), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x80000000));
  841. if (max_level < 0x80000007) {
  842. fprintf(stderr, "CPUID: no invariant TSC (max_level 0x%x)\n", max_level);
  843. exit(1);
  844. }
  845. /*
  846. * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8
  847. * this check is valid for both Intel and AMD
  848. */
  849. asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x80000007));
  850. has_invariant_tsc = edx & (1 << 8);
  851. if (!has_invariant_tsc) {
  852. fprintf(stderr, "No invariant TSC\n");
  853. exit(1);
  854. }
  855. /*
  856. * APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit0
  857. * this check is valid for both Intel and AMD
  858. */
  859. asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x6));
  860. has_aperf = ecx & (1 << 0);
  861. if (!has_aperf) {
  862. fprintf(stderr, "No APERF MSR\n");
  863. exit(1);
  864. }
  865. do_nehalem_platform_info = genuine_intel && has_invariant_tsc;
  866. do_nhm_cstates = genuine_intel; /* all Intel w/ non-stop TSC have NHM counters */
  867. do_snb_cstates = is_snb(family, model);
  868. bclk = discover_bclk(family, model);
  869. do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model);
  870. }
  871. void usage()
  872. {
  873. fprintf(stderr, "%s: [-v] [-M MSR#] [-i interval_sec | command ...]\n",
  874. progname);
  875. exit(1);
  876. }
  877. /*
  878. * in /dev/cpu/ return success for names that are numbers
  879. * ie. filter out ".", "..", "microcode".
  880. */
  881. int dir_filter(const struct dirent *dirp)
  882. {
  883. if (isdigit(dirp->d_name[0]))
  884. return 1;
  885. else
  886. return 0;
  887. }
  888. int open_dev_cpu_msr(int dummy1)
  889. {
  890. return 0;
  891. }
  892. void turbostat_init()
  893. {
  894. check_cpuid();
  895. check_dev_msr();
  896. check_super_user();
  897. num_cpus = for_all_cpus(alloc_new_counters);
  898. cpu_mask_init(num_cpus);
  899. if (verbose)
  900. print_nehalem_info();
  901. }
  902. int fork_it(char **argv)
  903. {
  904. int retval;
  905. pid_t child_pid;
  906. get_counters(cnt_even);
  907. gettimeofday(&tv_even, (struct timezone *)NULL);
  908. child_pid = fork();
  909. if (!child_pid) {
  910. /* child */
  911. execvp(argv[0], argv);
  912. } else {
  913. int status;
  914. /* parent */
  915. if (child_pid == -1) {
  916. perror("fork");
  917. exit(1);
  918. }
  919. signal(SIGINT, SIG_IGN);
  920. signal(SIGQUIT, SIG_IGN);
  921. if (waitpid(child_pid, &status, 0) == -1) {
  922. perror("wait");
  923. exit(1);
  924. }
  925. }
  926. get_counters(cnt_odd);
  927. gettimeofday(&tv_odd, (struct timezone *)NULL);
  928. retval = compute_delta(cnt_odd, cnt_even, cnt_delta);
  929. timersub(&tv_odd, &tv_even, &tv_delta);
  930. compute_average(cnt_delta, cnt_average);
  931. if (!retval)
  932. print_counters(cnt_delta);
  933. fprintf(stderr, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0);
  934. return 0;
  935. }
  936. void cmdline(int argc, char **argv)
  937. {
  938. int opt;
  939. progname = argv[0];
  940. while ((opt = getopt(argc, argv, "+svi:M:")) != -1) {
  941. switch (opt) {
  942. case 's':
  943. summary_only++;
  944. break;
  945. case 'v':
  946. verbose++;
  947. break;
  948. case 'i':
  949. interval_sec = atoi(optarg);
  950. break;
  951. case 'M':
  952. sscanf(optarg, "%x", &extra_msr_offset);
  953. if (verbose > 1)
  954. fprintf(stderr, "MSR 0x%X\n", extra_msr_offset);
  955. break;
  956. default:
  957. usage();
  958. }
  959. }
  960. }
  961. int main(int argc, char **argv)
  962. {
  963. cmdline(argc, argv);
  964. if (verbose > 1)
  965. fprintf(stderr, "turbostat Dec 6, 2010"
  966. " - Len Brown <lenb@kernel.org>\n");
  967. if (verbose > 1)
  968. fprintf(stderr, "http://userweb.kernel.org/~lenb/acpi/utils/pmtools/turbostat/\n");
  969. turbostat_init();
  970. /*
  971. * if any params left, it must be a command to fork
  972. */
  973. if (argc - optind)
  974. return fork_it(argv + optind);
  975. else
  976. turbostat_loop();
  977. return 0;
  978. }