aboutsummaryrefslogtreecommitdiffstats
path: root/tools/power
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2016-02-26 23:48:05 -0500
committerLen Brown <len.brown@intel.com>2016-03-13 03:55:40 -0400
commit562a2d377bb9882c49debc9e1be7127a1717e242 (patch)
tree78d5fe76290e7e46ae6e824d48bf412946204e9a /tools/power
parent36229897ba966bb0dc9e060222ff17b198252367 (diff)
tools/power turbostat: show IRQs per CPU
The new IRQ column shows how many interrupts have occurred on each CPU during the measurement inteval. This information comes from the difference between /proc/interrupts shapshots made before and after the measurement interval. The first row, the system summary, shows the sum of the IRQS for all CPUs during that interval. Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'tools/power')
-rw-r--r--tools/power/x86/turbostat/turbostat.c126
1 files changed, 122 insertions, 4 deletions
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 2e47c2bc3e27..c6793268d81f 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -75,6 +75,7 @@ unsigned int extra_msr_offset64;
75unsigned int extra_delta_offset32; 75unsigned int extra_delta_offset32;
76unsigned int extra_delta_offset64; 76unsigned int extra_delta_offset64;
77unsigned int aperf_mperf_multiplier = 1; 77unsigned int aperf_mperf_multiplier = 1;
78int do_irq = 1;
78int do_smi; 79int do_smi;
79double bclk; 80double bclk;
80double base_hz; 81double base_hz;
@@ -154,6 +155,7 @@ struct thread_data {
154 unsigned long long extra_delta64; 155 unsigned long long extra_delta64;
155 unsigned long long extra_msr32; 156 unsigned long long extra_msr32;
156 unsigned long long extra_delta32; 157 unsigned long long extra_delta32;
158 unsigned int irq_count;
157 unsigned int smi_count; 159 unsigned int smi_count;
158 unsigned int cpu_id; 160 unsigned int cpu_id;
159 unsigned int flags; 161 unsigned int flags;
@@ -221,6 +223,9 @@ struct topo_params {
221 223
222struct timeval tv_even, tv_odd, tv_delta; 224struct timeval tv_even, tv_odd, tv_delta;
223 225
226int *irq_column_2_cpu; /* /proc/interrupts column numbers */
227int *irqs_per_cpu; /* indexed by cpu_num */
228
224void setup_all_buffers(void); 229void setup_all_buffers(void);
225 230
226int cpu_is_not_present(int cpu) 231int cpu_is_not_present(int cpu)
@@ -306,8 +311,8 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
306/* 311/*
307 * Example Format w/ field column widths: 312 * Example Format w/ field column widths:
308 * 313 *
309 * Package Core CPU Avg_MHz Bzy_MHz TSC_MHz SMI Busy% CPU_%c1 CPU_%c3 CPU_%c6 CPU_%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt 314 * Package Core CPU Avg_MHz Bzy_MHz TSC_MHz IRQ SMI Busy% CPU_%c1 CPU_%c3 CPU_%c6 CPU_%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt
310 * 123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678 315 * 12345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678
311 */ 316 */
312 317
313void print_header(void) 318void print_header(void)
@@ -338,6 +343,8 @@ void print_header(void)
338 if (!debug) 343 if (!debug)
339 goto done; 344 goto done;
340 345
346 if (do_irq)
347 outp += sprintf(outp, " IRQ");
341 if (do_smi) 348 if (do_smi)
342 outp += sprintf(outp, " SMI"); 349 outp += sprintf(outp, " SMI");
343 350
@@ -429,6 +436,8 @@ int dump_counters(struct thread_data *t, struct core_data *c,
429 extra_msr_offset32, t->extra_msr32); 436 extra_msr_offset32, t->extra_msr32);
430 outp += sprintf(outp, "msr0x%x: %016llX\n", 437 outp += sprintf(outp, "msr0x%x: %016llX\n",
431 extra_msr_offset64, t->extra_msr64); 438 extra_msr_offset64, t->extra_msr64);
439 if (do_irq)
440 outp += sprintf(outp, "IRQ: %08X\n", t->irq_count);
432 if (do_smi) 441 if (do_smi)
433 outp += sprintf(outp, "SMI: %08X\n", t->smi_count); 442 outp += sprintf(outp, "SMI: %08X\n", t->smi_count);
434 } 443 }
@@ -562,6 +571,10 @@ int format_counters(struct thread_data *t, struct core_data *c,
562 if (!debug) 571 if (!debug)
563 goto done; 572 goto done;
564 573
574 /* IRQ */
575 if (do_irq)
576 outp += sprintf(outp, "%8d", t->irq_count);
577
565 /* SMI */ 578 /* SMI */
566 if (do_smi) 579 if (do_smi)
567 outp += sprintf(outp, "%8d", t->smi_count); 580 outp += sprintf(outp, "%8d", t->smi_count);
@@ -827,6 +840,9 @@ delta_thread(struct thread_data *new, struct thread_data *old,
827 old->extra_msr32 = new->extra_msr32; 840 old->extra_msr32 = new->extra_msr32;
828 old->extra_msr64 = new->extra_msr64; 841 old->extra_msr64 = new->extra_msr64;
829 842
843 if (do_irq)
844 old->irq_count = new->irq_count - old->irq_count;
845
830 if (do_smi) 846 if (do_smi)
831 old->smi_count = new->smi_count - old->smi_count; 847 old->smi_count = new->smi_count - old->smi_count;
832} 848}
@@ -856,10 +872,12 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
856 t->mperf = 0; 872 t->mperf = 0;
857 t->c1 = 0; 873 t->c1 = 0;
858 874
859 t->smi_count = 0;
860 t->extra_delta32 = 0; 875 t->extra_delta32 = 0;
861 t->extra_delta64 = 0; 876 t->extra_delta64 = 0;
862 877
878 t->irq_count = 0;
879 t->smi_count = 0;
880
863 /* tells format_counters to dump all fields from this set */ 881 /* tells format_counters to dump all fields from this set */
864 t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE; 882 t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE;
865 883
@@ -903,6 +921,9 @@ int sum_counters(struct thread_data *t, struct core_data *c,
903 average.threads.extra_delta32 += t->extra_delta32; 921 average.threads.extra_delta32 += t->extra_delta32;
904 average.threads.extra_delta64 += t->extra_delta64; 922 average.threads.extra_delta64 += t->extra_delta64;
905 923
924 average.threads.irq_count += t->irq_count;
925 average.threads.smi_count += t->smi_count;
926
906 /* sum per-core values only for 1st thread in core */ 927 /* sum per-core values only for 1st thread in core */
907 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 928 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
908 return 0; 929 return 0;
@@ -1000,7 +1021,6 @@ static unsigned long long rdtsc(void)
1000 return low | ((unsigned long long)high) << 32; 1021 return low | ((unsigned long long)high) << 32;
1001} 1022}
1002 1023
1003
1004/* 1024/*
1005 * get_counters(...) 1025 * get_counters(...)
1006 * migrate to cpu 1026 * migrate to cpu
@@ -1027,6 +1047,8 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
1027 t->mperf = t->mperf * aperf_mperf_multiplier; 1047 t->mperf = t->mperf * aperf_mperf_multiplier;
1028 } 1048 }
1029 1049
1050 if (do_irq)
1051 t->irq_count = irqs_per_cpu[cpu];
1030 if (do_smi) { 1052 if (do_smi) {
1031 if (get_msr(cpu, MSR_SMI_COUNT, &msr)) 1053 if (get_msr(cpu, MSR_SMI_COUNT, &msr))
1032 return -5; 1054 return -5;
@@ -1515,6 +1537,9 @@ void free_all_buffers(void)
1515 outp = NULL; 1537 outp = NULL;
1516 1538
1517 free_fd_percpu(); 1539 free_fd_percpu();
1540
1541 free(irq_column_2_cpu);
1542 free(irqs_per_cpu);
1518} 1543}
1519 1544
1520/* 1545/*
@@ -1737,6 +1762,83 @@ int mark_cpu_present(int cpu)
1737 return 0; 1762 return 0;
1738} 1763}
1739 1764
1765/*
1766 * snapshot_proc_interrupts()
1767 *
1768 * read and record summary of /proc/interrupts
1769 *
1770 * return 1 if config change requires a restart, else return 0
1771 */
1772int snapshot_proc_interrupts(void)
1773{
1774 static FILE *fp;
1775 int column, retval;
1776
1777 if (fp == NULL)
1778 fp = fopen_or_die("/proc/interrupts", "r");
1779 else
1780 rewind(fp);
1781
1782 /* read 1st line of /proc/interrupts to get cpu* name for each column */
1783 for (column = 0; column < topo.num_cpus; ++column) {
1784 int cpu_number;
1785
1786 retval = fscanf(fp, " CPU%d", &cpu_number);
1787 if (retval != 1)
1788 break;
1789
1790 if (cpu_number > topo.max_cpu_num) {
1791 warn("/proc/interrupts: cpu%d: > %d", cpu_number, topo.max_cpu_num);
1792 return 1;
1793 }
1794
1795 irq_column_2_cpu[column] = cpu_number;
1796 irqs_per_cpu[cpu_number] = 0;
1797 }
1798
1799 /* read /proc/interrupt count lines and sum up irqs per cpu */
1800 while (1) {
1801 int column;
1802 char buf[64];
1803
1804 retval = fscanf(fp, " %s:", buf); /* flush irq# "N:" */
1805 if (retval != 1)
1806 break;
1807
1808 /* read the count per cpu */
1809 for (column = 0; column < topo.num_cpus; ++column) {
1810
1811 int cpu_number, irq_count;
1812
1813 retval = fscanf(fp, " %d", &irq_count);
1814 if (retval != 1)
1815 break;
1816
1817 cpu_number = irq_column_2_cpu[column];
1818 irqs_per_cpu[cpu_number] += irq_count;
1819
1820 }
1821
1822 while (getc(fp) != '\n')
1823 ; /* flush interrupt description */
1824
1825 }
1826 return 0;
1827}
1828
1829/*
1830 * snapshot /proc and /sys files
1831 *
1832 * return 1 if configuration restart needed, else return 0
1833 */
1834int snapshot_proc_sysfs_files(void)
1835{
1836 if (snapshot_proc_interrupts())
1837 return 1;
1838
1839 return 0;
1840}
1841
1740void turbostat_loop() 1842void turbostat_loop()
1741{ 1843{
1742 int retval; 1844 int retval;
@@ -1745,6 +1847,7 @@ void turbostat_loop()
1745restart: 1847restart:
1746 restarted++; 1848 restarted++;
1747 1849
1850 snapshot_proc_sysfs_files();
1748 retval = for_all_cpus(get_counters, EVEN_COUNTERS); 1851 retval = for_all_cpus(get_counters, EVEN_COUNTERS);
1749 if (retval < -1) { 1852 if (retval < -1) {
1750 exit(retval); 1853 exit(retval);
@@ -1764,6 +1867,8 @@ restart:
1764 goto restart; 1867 goto restart;
1765 } 1868 }
1766 nanosleep(&interval_ts, NULL); 1869 nanosleep(&interval_ts, NULL);
1870 if (snapshot_proc_sysfs_files())
1871 goto restart;
1767 retval = for_all_cpus(get_counters, ODD_COUNTERS); 1872 retval = for_all_cpus(get_counters, ODD_COUNTERS);
1768 if (retval < -1) { 1873 if (retval < -1) {
1769 exit(retval); 1874 exit(retval);
@@ -1778,6 +1883,8 @@ restart:
1778 format_all_counters(EVEN_COUNTERS); 1883 format_all_counters(EVEN_COUNTERS);
1779 flush_output_stdout(); 1884 flush_output_stdout();
1780 nanosleep(&interval_ts, NULL); 1885 nanosleep(&interval_ts, NULL);
1886 if (snapshot_proc_sysfs_files())
1887 goto restart;
1781 retval = for_all_cpus(get_counters, EVEN_COUNTERS); 1888 retval = for_all_cpus(get_counters, EVEN_COUNTERS);
1782 if (retval < -1) { 1889 if (retval < -1) {
1783 exit(retval); 1890 exit(retval);
@@ -3233,9 +3340,20 @@ void allocate_fd_percpu(void)
3233 if (fd_percpu == NULL) 3340 if (fd_percpu == NULL)
3234 err(-1, "calloc fd_percpu"); 3341 err(-1, "calloc fd_percpu");
3235} 3342}
3343void allocate_irq_buffers(void)
3344{
3345 irq_column_2_cpu = calloc(topo.num_cpus, sizeof(int));
3346 if (irq_column_2_cpu == NULL)
3347 err(-1, "calloc %d", topo.num_cpus);
3348
3349 irqs_per_cpu = calloc(topo.max_cpu_num, sizeof(int));
3350 if (irqs_per_cpu == NULL)
3351 err(-1, "calloc %d", topo.max_cpu_num);
3352}
3236void setup_all_buffers(void) 3353void setup_all_buffers(void)
3237{ 3354{
3238 topology_probe(); 3355 topology_probe();
3356 allocate_irq_buffers();
3239 allocate_fd_percpu(); 3357 allocate_fd_percpu();
3240 allocate_counters(&thread_even, &core_even, &package_even); 3358 allocate_counters(&thread_even, &core_even, &package_even);
3241 allocate_counters(&thread_odd, &core_odd, &package_odd); 3359 allocate_counters(&thread_odd, &core_odd, &package_odd);