turbostat.c 26 KB

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