turbostat.c 26 KB

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