Merge tag 'pm+acpi-4.6-rc1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[cascardo/linux.git] / tools / power / x86 / turbostat / turbostat.c
index 2e47c2b..20a257a 100644 (file)
@@ -75,6 +75,7 @@ unsigned int extra_msr_offset64;
 unsigned int extra_delta_offset32;
 unsigned int extra_delta_offset64;
 unsigned int aperf_mperf_multiplier = 1;
+int do_irq = 1;
 int do_smi;
 double bclk;
 double base_hz;
@@ -89,6 +90,10 @@ char *output_buffer, *outp;
 unsigned int do_rapl;
 unsigned int do_dts;
 unsigned int do_ptm;
+unsigned int do_gfx_rc6_ms;
+unsigned long long  gfx_cur_rc6_ms;
+unsigned int do_gfx_mhz;
+unsigned int gfx_cur_mhz;
 unsigned int tcc_activation_temp;
 unsigned int tcc_activation_temp_override;
 double rapl_power_units, rapl_time_units;
@@ -154,6 +159,7 @@ struct thread_data {
        unsigned long long extra_delta64;
        unsigned long long extra_msr32;
        unsigned long long extra_delta32;
+       unsigned int irq_count;
        unsigned int smi_count;
        unsigned int cpu_id;
        unsigned int flags;
@@ -181,6 +187,8 @@ struct pkg_data {
        unsigned long long pkg_any_core_c0;
        unsigned long long pkg_any_gfxe_c0;
        unsigned long long pkg_both_core_gfxe_c0;
+       unsigned long long gfx_rc6_ms;
+       unsigned int gfx_mhz;
        unsigned int package_id;
        unsigned int energy_pkg;        /* MSR_PKG_ENERGY_STATUS */
        unsigned int energy_dram;       /* MSR_DRAM_ENERGY_STATUS */
@@ -221,6 +229,9 @@ struct topo_params {
 
 struct timeval tv_even, tv_odd, tv_delta;
 
+int *irq_column_2_cpu; /* /proc/interrupts column numbers */
+int *irqs_per_cpu;             /* indexed by cpu_num */
+
 void setup_all_buffers(void);
 
 int cpu_is_not_present(int cpu)
@@ -306,8 +317,8 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
 /*
  * Example Format w/ field column widths:
  *
- *  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
- * 123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678
+ *  Package    Core     CPU Avg_MHz Bzy_MHz TSC_MHz     IRQ   SMI   Busy% CPU_%c1 CPU_%c3 CPU_%c6 CPU_%c7 CoreTmp  PkgTmp  GFXMHz Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt
+ * 12345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678
  */
 
 void print_header(void)
@@ -338,6 +349,8 @@ void print_header(void)
        if (!debug)
                goto done;
 
+       if (do_irq)
+               outp += sprintf(outp, "     IRQ");
        if (do_smi)
                outp += sprintf(outp, "     SMI");
 
@@ -355,6 +368,12 @@ void print_header(void)
        if (do_ptm)
                outp += sprintf(outp, "  PkgTmp");
 
+       if (do_gfx_rc6_ms)
+               outp += sprintf(outp, " GFX%%rc6");
+
+       if (do_gfx_mhz)
+               outp += sprintf(outp, "  GFXMHz");
+
        if (do_skl_residency) {
                outp += sprintf(outp, " Totl%%C0");
                outp += sprintf(outp, "  Any%%C0");
@@ -429,6 +448,8 @@ int dump_counters(struct thread_data *t, struct core_data *c,
                        extra_msr_offset32, t->extra_msr32);
                outp += sprintf(outp, "msr0x%x: %016llX\n",
                        extra_msr_offset64, t->extra_msr64);
+               if (do_irq)
+                       outp += sprintf(outp, "IRQ: %08X\n", t->irq_count);
                if (do_smi)
                        outp += sprintf(outp, "SMI: %08X\n", t->smi_count);
        }
@@ -562,6 +583,10 @@ int format_counters(struct thread_data *t, struct core_data *c,
        if (!debug)
                goto done;
 
+       /* IRQ */
+       if (do_irq)
+               outp += sprintf(outp, "%8d", t->irq_count);
+
        /* SMI */
        if (do_smi)
                outp += sprintf(outp, "%8d", t->smi_count);
@@ -595,6 +620,14 @@ int format_counters(struct thread_data *t, struct core_data *c,
        if (do_ptm)
                outp += sprintf(outp, "%8d", p->pkg_temp_c);
 
+       /* GFXrc6 */
+       if (do_gfx_rc6_ms)
+               outp += sprintf(outp, "%8.2f", 100.0 * p->gfx_rc6_ms / 1000.0 / interval_float);
+
+       /* GFXMHz */
+       if (do_gfx_mhz)
+               outp += sprintf(outp, "%8d", p->gfx_mhz);
+
        /* Totl%C0, Any%C0 GFX%C0 CPUGFX% */
        if (do_skl_residency) {
                outp += sprintf(outp, "%8.2f", 100.0 * p->pkg_wtd_core_c0/t->tsc);
@@ -733,6 +766,9 @@ delta_package(struct pkg_data *new, struct pkg_data *old)
        old->pc10 = new->pc10 - old->pc10;
        old->pkg_temp_c = new->pkg_temp_c;
 
+       old->gfx_rc6_ms = new->gfx_rc6_ms - old->gfx_rc6_ms;
+       old->gfx_mhz = new->gfx_mhz;
+
        DELTA_WRAP32(new->energy_pkg, old->energy_pkg);
        DELTA_WRAP32(new->energy_cores, old->energy_cores);
        DELTA_WRAP32(new->energy_gfx, old->energy_gfx);
@@ -827,6 +863,9 @@ delta_thread(struct thread_data *new, struct thread_data *old,
        old->extra_msr32 = new->extra_msr32;
        old->extra_msr64 = new->extra_msr64;
 
+       if (do_irq)
+               old->irq_count = new->irq_count - old->irq_count;
+
        if (do_smi)
                old->smi_count = new->smi_count - old->smi_count;
 }
@@ -856,10 +895,12 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
        t->mperf = 0;
        t->c1 = 0;
 
-       t->smi_count = 0;
        t->extra_delta32 = 0;
        t->extra_delta64 = 0;
 
+       t->irq_count = 0;
+       t->smi_count = 0;
+
        /* tells format_counters to dump all fields from this set */
        t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE;
 
@@ -891,6 +932,9 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
        p->rapl_pkg_perf_status = 0;
        p->rapl_dram_perf_status = 0;
        p->pkg_temp_c = 0;
+
+       p->gfx_rc6_ms = 0;
+       p->gfx_mhz = 0;
 }
 int sum_counters(struct thread_data *t, struct core_data *c,
        struct pkg_data *p)
@@ -903,6 +947,9 @@ int sum_counters(struct thread_data *t, struct core_data *c,
        average.threads.extra_delta32 += t->extra_delta32;
        average.threads.extra_delta64 += t->extra_delta64;
 
+       average.threads.irq_count += t->irq_count;
+       average.threads.smi_count += t->smi_count;
+
        /* sum per-core values only for 1st thread in core */
        if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
                return 0;
@@ -940,6 +987,9 @@ int sum_counters(struct thread_data *t, struct core_data *c,
        average.packages.energy_cores += p->energy_cores;
        average.packages.energy_gfx += p->energy_gfx;
 
+       average.packages.gfx_rc6_ms = p->gfx_rc6_ms;
+       average.packages.gfx_mhz = p->gfx_mhz;
+
        average.packages.pkg_temp_c = MAX(average.packages.pkg_temp_c, p->pkg_temp_c);
 
        average.packages.rapl_pkg_perf_status += p->rapl_pkg_perf_status;
@@ -1000,7 +1050,6 @@ static unsigned long long rdtsc(void)
        return low | ((unsigned long long)high) << 32;
 }
 
-
 /*
  * get_counters(...)
  * migrate to cpu
@@ -1010,23 +1059,74 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
 {
        int cpu = t->cpu_id;
        unsigned long long msr;
+       int aperf_mperf_retry_count = 0;
 
        if (cpu_migrate(cpu)) {
                fprintf(outf, "Could not migrate to CPU %d\n", cpu);
                return -1;
        }
 
+retry:
        t->tsc = rdtsc();       /* we are running on local CPU of interest */
 
        if (has_aperf) {
+               unsigned long long tsc_before, tsc_between, tsc_after, aperf_time, mperf_time;
+
+               /*
+                * The TSC, APERF and MPERF must be read together for
+                * APERF/MPERF and MPERF/TSC to give accurate results.
+                *
+                * Unfortunately, APERF and MPERF are read by
+                * individual system call, so delays may occur
+                * between them.  If the time to read them
+                * varies by a large amount, we re-read them.
+                */
+
+               /*
+                * This initial dummy APERF read has been seen to
+                * reduce jitter in the subsequent reads.
+                */
+
+               if (get_msr(cpu, MSR_IA32_APERF, &t->aperf))
+                       return -3;
+
+               t->tsc = rdtsc();       /* re-read close to APERF */
+
+               tsc_before = t->tsc;
+
                if (get_msr(cpu, MSR_IA32_APERF, &t->aperf))
                        return -3;
+
+               tsc_between = rdtsc();
+
                if (get_msr(cpu, MSR_IA32_MPERF, &t->mperf))
                        return -4;
+
+               tsc_after = rdtsc();
+
+               aperf_time = tsc_between - tsc_before;
+               mperf_time = tsc_after - tsc_between;
+
+               /*
+                * If the system call latency to read APERF and MPERF
+                * differ by more than 2x, then try again.
+                */
+               if ((aperf_time > (2 * mperf_time)) || (mperf_time > (2 * aperf_time))) {
+                       aperf_mperf_retry_count++;
+                       if (aperf_mperf_retry_count < 5)
+                               goto retry;
+                       else
+                               warnx("cpu%d jitter %lld %lld",
+                                       cpu, aperf_time, mperf_time);
+               }
+               aperf_mperf_retry_count = 0;
+
                t->aperf = t->aperf * aperf_mperf_multiplier;
                t->mperf = t->mperf * aperf_mperf_multiplier;
        }
 
+       if (do_irq)
+               t->irq_count = irqs_per_cpu[cpu];
        if (do_smi) {
                if (get_msr(cpu, MSR_SMI_COUNT, &msr))
                        return -5;
@@ -1154,6 +1254,13 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
                        return -17;
                p->pkg_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F);
        }
+
+       if (do_gfx_rc6_ms)
+               p->gfx_rc6_ms = gfx_cur_rc6_ms;
+
+       if (do_gfx_mhz)
+               p->gfx_mhz = gfx_cur_mhz;
+
        return 0;
 }
 
@@ -1425,7 +1532,7 @@ dump_nhm_cst_cfg(void)
                (msr & NHM_C3_AUTO_DEMOTE) ? "demote-C3, " : "",
                (msr & NHM_C1_AUTO_DEMOTE) ? "demote-C1, " : "",
                (msr & (1 << 15)) ? "" : "UN",
-               (unsigned int)msr & 7,
+               (unsigned int)msr & 0xF,
                pkg_cstate_limit_strings[pkg_cstate_limit]);
        return;
 }
@@ -1437,25 +1544,25 @@ dump_config_tdp(void)
 
        get_msr(base_cpu, MSR_CONFIG_TDP_NOMINAL, &msr);
        fprintf(outf, "cpu%d: MSR_CONFIG_TDP_NOMINAL: 0x%08llx", base_cpu, msr);
-       fprintf(outf, " (base_ratio=%d)\n", (unsigned int)msr & 0xEF);
+       fprintf(outf, " (base_ratio=%d)\n", (unsigned int)msr & 0xFF);
 
        get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_1, &msr);
        fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_1: 0x%08llx (", base_cpu, msr);
        if (msr) {
-               fprintf(outf, "PKG_MIN_PWR_LVL1=%d ", (unsigned int)(msr >> 48) & 0xEFFF);
-               fprintf(outf, "PKG_MAX_PWR_LVL1=%d ", (unsigned int)(msr >> 32) & 0xEFFF);
-               fprintf(outf, "LVL1_RATIO=%d ", (unsigned int)(msr >> 16) & 0xEF);
-               fprintf(outf, "PKG_TDP_LVL1=%d", (unsigned int)(msr) & 0xEFFF);
+               fprintf(outf, "PKG_MIN_PWR_LVL1=%d ", (unsigned int)(msr >> 48) & 0x7FFF);
+               fprintf(outf, "PKG_MAX_PWR_LVL1=%d ", (unsigned int)(msr >> 32) & 0x7FFF);
+               fprintf(outf, "LVL1_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF);
+               fprintf(outf, "PKG_TDP_LVL1=%d", (unsigned int)(msr) & 0x7FFF);
        }
        fprintf(outf, ")\n");
 
        get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_2, &msr);
        fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_2: 0x%08llx (", base_cpu, msr);
        if (msr) {
-               fprintf(outf, "PKG_MIN_PWR_LVL2=%d ", (unsigned int)(msr >> 48) & 0xEFFF);
-               fprintf(outf, "PKG_MAX_PWR_LVL2=%d ", (unsigned int)(msr >> 32) & 0xEFFF);
-               fprintf(outf, "LVL2_RATIO=%d ", (unsigned int)(msr >> 16) & 0xEF);
-               fprintf(outf, "PKG_TDP_LVL2=%d", (unsigned int)(msr) & 0xEFFF);
+               fprintf(outf, "PKG_MIN_PWR_LVL2=%d ", (unsigned int)(msr >> 48) & 0x7FFF);
+               fprintf(outf, "PKG_MAX_PWR_LVL2=%d ", (unsigned int)(msr >> 32) & 0x7FFF);
+               fprintf(outf, "LVL2_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF);
+               fprintf(outf, "PKG_TDP_LVL2=%d", (unsigned int)(msr) & 0x7FFF);
        }
        fprintf(outf, ")\n");
 
@@ -1468,7 +1575,7 @@ dump_config_tdp(void)
 
        get_msr(base_cpu, MSR_TURBO_ACTIVATION_RATIO, &msr);
        fprintf(outf, "cpu%d: MSR_TURBO_ACTIVATION_RATIO: 0x%08llx (", base_cpu, msr);
-       fprintf(outf, "MAX_NON_TURBO_RATIO=%d", (unsigned int)(msr) & 0x7F);
+       fprintf(outf, "MAX_NON_TURBO_RATIO=%d", (unsigned int)(msr) & 0xFF);
        fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1);
        fprintf(outf, ")\n");
 }
@@ -1515,6 +1622,9 @@ void free_all_buffers(void)
        outp = NULL;
 
        free_fd_percpu();
+
+       free(irq_column_2_cpu);
+       free(irqs_per_cpu);
 }
 
 /*
@@ -1737,6 +1847,136 @@ int mark_cpu_present(int cpu)
        return 0;
 }
 
+/*
+ * snapshot_proc_interrupts()
+ *
+ * read and record summary of /proc/interrupts
+ *
+ * return 1 if config change requires a restart, else return 0
+ */
+int snapshot_proc_interrupts(void)
+{
+       static FILE *fp;
+       int column, retval;
+
+       if (fp == NULL)
+               fp = fopen_or_die("/proc/interrupts", "r");
+       else
+               rewind(fp);
+
+       /* read 1st line of /proc/interrupts to get cpu* name for each column */
+       for (column = 0; column < topo.num_cpus; ++column) {
+               int cpu_number;
+
+               retval = fscanf(fp, " CPU%d", &cpu_number);
+               if (retval != 1)
+                       break;
+
+               if (cpu_number > topo.max_cpu_num) {
+                       warn("/proc/interrupts: cpu%d: > %d", cpu_number, topo.max_cpu_num);
+                       return 1;
+               }
+
+               irq_column_2_cpu[column] = cpu_number;
+               irqs_per_cpu[cpu_number] = 0;
+       }
+
+       /* read /proc/interrupt count lines and sum up irqs per cpu */
+       while (1) {
+               int column;
+               char buf[64];
+
+               retval = fscanf(fp, " %s:", buf);       /* flush irq# "N:" */
+               if (retval != 1)
+                       break;
+
+               /* read the count per cpu */
+               for (column = 0; column < topo.num_cpus; ++column) {
+
+                       int cpu_number, irq_count;
+
+                       retval = fscanf(fp, " %d", &irq_count);
+                       if (retval != 1)
+                               break;
+
+                       cpu_number = irq_column_2_cpu[column];
+                       irqs_per_cpu[cpu_number] += irq_count;
+
+               }
+
+               while (getc(fp) != '\n')
+                       ;       /* flush interrupt description */
+
+       }
+       return 0;
+}
+/*
+ * snapshot_gfx_rc6_ms()
+ *
+ * record snapshot of
+ * /sys/class/drm/card0/power/rc6_residency_ms
+ *
+ * return 1 if config change requires a restart, else return 0
+ */
+int snapshot_gfx_rc6_ms(void)
+{
+       FILE *fp;
+       int retval;
+
+       fp = fopen_or_die("/sys/class/drm/card0/power/rc6_residency_ms", "r");
+
+       retval = fscanf(fp, "%lld", &gfx_cur_rc6_ms);
+       if (retval != 1)
+               err(1, "GFX rc6");
+
+       fclose(fp);
+
+       return 0;
+}
+/*
+ * snapshot_gfx_mhz()
+ *
+ * record snapshot of
+ * /sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz
+ *
+ * return 1 if config change requires a restart, else return 0
+ */
+int snapshot_gfx_mhz(void)
+{
+       static FILE *fp;
+       int retval;
+
+       if (fp == NULL)
+               fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", "r");
+       else
+               rewind(fp);
+
+       retval = fscanf(fp, "%d", &gfx_cur_mhz);
+       if (retval != 1)
+               err(1, "GFX MHz");
+
+       return 0;
+}
+
+/*
+ * snapshot /proc and /sys files
+ *
+ * return 1 if configuration restart needed, else return 0
+ */
+int snapshot_proc_sysfs_files(void)
+{
+       if (snapshot_proc_interrupts())
+               return 1;
+
+       if (do_gfx_rc6_ms)
+               snapshot_gfx_rc6_ms();
+
+       if (do_gfx_mhz)
+               snapshot_gfx_mhz();
+
+       return 0;
+}
+
 void turbostat_loop()
 {
        int retval;
@@ -1745,6 +1985,7 @@ void turbostat_loop()
 restart:
        restarted++;
 
+       snapshot_proc_sysfs_files();
        retval = for_all_cpus(get_counters, EVEN_COUNTERS);
        if (retval < -1) {
                exit(retval);
@@ -1764,6 +2005,8 @@ restart:
                        goto restart;
                }
                nanosleep(&interval_ts, NULL);
+               if (snapshot_proc_sysfs_files())
+                       goto restart;
                retval = for_all_cpus(get_counters, ODD_COUNTERS);
                if (retval < -1) {
                        exit(retval);
@@ -1778,6 +2021,8 @@ restart:
                format_all_counters(EVEN_COUNTERS);
                flush_output_stdout();
                nanosleep(&interval_ts, NULL);
+               if (snapshot_proc_sysfs_files())
+                       goto restart;
                retval = for_all_cpus(get_counters, EVEN_COUNTERS);
                if (retval < -1) {
                        exit(retval);
@@ -2012,7 +2257,7 @@ int has_config_tdp(unsigned int family, unsigned int model)
 }
 
 static void
-dump_cstate_pstate_config_info(int family, int model)
+dump_cstate_pstate_config_info(unsigned int family, unsigned int model)
 {
        if (!do_nhm_platform_info)
                return;
@@ -2275,7 +2520,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
 #define        RAPL_POWER_GRANULARITY  0x7FFF  /* 15 bit power granularity */
 #define        RAPL_TIME_GRANULARITY   0x3F /* 6 bit time granularity */
 
-double get_tdp(int model)
+double get_tdp(unsigned int model)
 {
        unsigned long long msr;
 
@@ -2389,7 +2634,7 @@ void rapl_probe(unsigned int family, unsigned int model)
        return;
 }
 
-void perf_limit_reasons_probe(int family, int model)
+void perf_limit_reasons_probe(unsigned int family, unsigned int model)
 {
        if (!genuine_intel)
                return;
@@ -2807,6 +3052,17 @@ guess:
        return 0;
 }
 
+void decode_feature_control_msr(void)
+{
+       unsigned long long msr;
+
+       if (!get_msr(base_cpu, MSR_IA32_FEATURE_CONTROL, &msr))
+               fprintf(outf, "cpu%d: MSR_IA32_FEATURE_CONTROL: 0x%08llx (%sLocked %s)\n",
+                       base_cpu, msr,
+                       msr & FEATURE_CONTROL_LOCKED ? "" : "UN-",
+                       msr & (1 << 18) ? "SGX" : "");
+}
+
 void decode_misc_enable_msr(void)
 {
        unsigned long long msr;
@@ -2847,7 +3103,7 @@ void process_cpuid()
 
        eax = ebx = ecx = edx = 0;
 
-       __get_cpuid(0, &max_level, &ebx, &ecx, &edx);
+       __cpuid(0, max_level, ebx, ecx, edx);
 
        if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
                genuine_intel = 1;
@@ -2856,7 +3112,7 @@ void process_cpuid()
                fprintf(outf, "CPUID(0): %.4s%.4s%.4s ",
                        (char *)&ebx, (char *)&edx, (char *)&ecx);
 
-       __get_cpuid(1, &fms, &ebx, &ecx, &edx);
+       __cpuid(1, fms, ebx, ecx, edx);
        family = (fms >> 8) & 0xf;
        model = (fms >> 4) & 0xf;
        stepping = fms & 0xf;
@@ -2866,9 +3122,10 @@ void process_cpuid()
        if (debug) {
                fprintf(outf, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
                        max_level, family, model, stepping, family, model, stepping);
-               fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s\n",
+               fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s\n",
                        ecx & (1 << 0) ? "SSE3" : "-",
                        ecx & (1 << 3) ? "MONITOR" : "-",
+                       ecx & (1 << 6) ? "SMX" : "-",
                        ecx & (1 << 7) ? "EIST" : "-",
                        ecx & (1 << 8) ? "TM2" : "-",
                        edx & (1 << 4) ? "TSC" : "-",
@@ -2886,7 +3143,7 @@ void process_cpuid()
         * This check is valid for both Intel and AMD.
         */
        ebx = ecx = edx = 0;
-       __get_cpuid(0x80000000, &max_extended_level, &ebx, &ecx, &edx);
+       __cpuid(0x80000000, max_extended_level, ebx, ecx, edx);
 
        if (max_extended_level >= 0x80000007) {
 
@@ -2894,7 +3151,7 @@ void process_cpuid()
                 * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8
                 * this check is valid for both Intel and AMD
                 */
-               __get_cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
+               __cpuid(0x80000007, eax, ebx, ecx, edx);
                has_invariant_tsc = edx & (1 << 8);
        }
 
@@ -2903,7 +3160,7 @@ void process_cpuid()
         * this check is valid for both Intel and AMD
         */
 
-       __get_cpuid(0x6, &eax, &ebx, &ecx, &edx);
+       __cpuid(0x6, eax, ebx, ecx, edx);
        has_aperf = ecx & (1 << 0);
        do_dts = eax & (1 << 0);
        do_ptm = eax & (1 << 6);
@@ -2930,6 +3187,20 @@ void process_cpuid()
        if (debug)
                decode_misc_enable_msr();
 
+       if (max_level >= 0x7) {
+               int has_sgx;
+
+               ecx = 0;
+
+               __cpuid_count(0x7, 0, eax, ebx, ecx, edx);
+
+               has_sgx = ebx & (1 << 2);
+               fprintf(outf, "CPUID(7): %sSGX\n", has_sgx ? "" : "No-");
+
+               if (has_sgx)
+                       decode_feature_control_msr();
+       }
+
        if (max_level >= 0x15) {
                unsigned int eax_crystal;
                unsigned int ebx_tsc;
@@ -2938,7 +3209,7 @@ void process_cpuid()
                 * CPUID 15H TSC/Crystal ratio, possibly Crystal Hz
                 */
                eax_crystal = ebx_tsc = crystal_hz = edx = 0;
-               __get_cpuid(0x15, &eax_crystal, &ebx_tsc, &crystal_hz, &edx);
+               __cpuid(0x15, eax_crystal, ebx_tsc, crystal_hz, edx);
 
                if (ebx_tsc != 0) {
 
@@ -2972,7 +3243,7 @@ void process_cpuid()
                 */
                base_mhz = max_mhz = bus_mhz = edx = 0;
 
-               __get_cpuid(0x16, &base_mhz, &max_mhz, &bus_mhz, &edx);
+               __cpuid(0x16, base_mhz, max_mhz, bus_mhz, edx);
                if (debug)
                        fprintf(outf, "CPUID(0x16): base_mhz: %d max_mhz: %d bus_mhz: %d\n",
                                base_mhz, max_mhz, bus_mhz);
@@ -3004,6 +3275,10 @@ void process_cpuid()
        if (has_skl_msrs(family, model))
                calculate_tsc_tweak();
 
+       do_gfx_rc6_ms = !access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK);
+
+       do_gfx_mhz = !access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK);
+
        return;
 }
 
@@ -3233,9 +3508,20 @@ void allocate_fd_percpu(void)
        if (fd_percpu == NULL)
                err(-1, "calloc fd_percpu");
 }
+void allocate_irq_buffers(void)
+{
+       irq_column_2_cpu = calloc(topo.num_cpus, sizeof(int));
+       if (irq_column_2_cpu == NULL)
+               err(-1, "calloc %d", topo.num_cpus);
+
+       irqs_per_cpu = calloc(topo.max_cpu_num, sizeof(int));
+       if (irqs_per_cpu == NULL)
+               err(-1, "calloc %d", topo.max_cpu_num);
+}
 void setup_all_buffers(void)
 {
        topology_probe();
+       allocate_irq_buffers();
        allocate_fd_percpu();
        allocate_counters(&thread_even, &core_even, &package_even);
        allocate_counters(&thread_odd, &core_odd, &package_odd);
@@ -3343,7 +3629,7 @@ int get_and_dump_counters(void)
 }
 
 void print_version() {
-       fprintf(outf, "turbostat version 4.10 10 Dec, 2015"
+       fprintf(outf, "turbostat version 4.11 27 Feb 2016"
                " - Len Brown <lenb@kernel.org>\n");
 }