diff options
-rw-r--r-- | arch/x86/include/uapi/asm/msr-index.h | 3 | ||||
-rw-r--r-- | drivers/idle/intel_idle.c | 21 | ||||
-rw-r--r-- | include/linux/cpuidle.h | 2 | ||||
-rw-r--r-- | tools/power/x86/turbostat/turbostat.c | 54 |
4 files changed, 78 insertions, 2 deletions
diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h index b3a4866661c5..2af848dfa754 100644 --- a/arch/x86/include/uapi/asm/msr-index.h +++ b/arch/x86/include/uapi/asm/msr-index.h | |||
@@ -120,6 +120,9 @@ | |||
120 | #define MSR_CORE_C6_RESIDENCY 0x000003fd | 120 | #define MSR_CORE_C6_RESIDENCY 0x000003fd |
121 | #define MSR_CORE_C7_RESIDENCY 0x000003fe | 121 | #define MSR_CORE_C7_RESIDENCY 0x000003fe |
122 | #define MSR_PKG_C2_RESIDENCY 0x0000060d | 122 | #define MSR_PKG_C2_RESIDENCY 0x0000060d |
123 | #define MSR_PKG_C8_RESIDENCY 0x00000630 | ||
124 | #define MSR_PKG_C9_RESIDENCY 0x00000631 | ||
125 | #define MSR_PKG_C10_RESIDENCY 0x00000632 | ||
123 | 126 | ||
124 | /* Run Time Average Power Limiting (RAPL) Interface */ | 127 | /* Run Time Average Power Limiting (RAPL) Interface */ |
125 | 128 | ||
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 0e8fab1913df..fa6964d8681a 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -273,6 +273,27 @@ static struct cpuidle_state hsw_cstates[CPUIDLE_STATE_MAX] = { | |||
273 | .target_residency = 500, | 273 | .target_residency = 500, |
274 | .enter = &intel_idle }, | 274 | .enter = &intel_idle }, |
275 | { | 275 | { |
276 | .name = "C8-HSW", | ||
277 | .desc = "MWAIT 0x40", | ||
278 | .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
279 | .exit_latency = 300, | ||
280 | .target_residency = 900, | ||
281 | .enter = &intel_idle }, | ||
282 | { | ||
283 | .name = "C9-HSW", | ||
284 | .desc = "MWAIT 0x50", | ||
285 | .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
286 | .exit_latency = 600, | ||
287 | .target_residency = 1800, | ||
288 | .enter = &intel_idle }, | ||
289 | { | ||
290 | .name = "C10-HSW", | ||
291 | .desc = "MWAIT 0x60", | ||
292 | .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
293 | .exit_latency = 2600, | ||
294 | .target_residency = 7700, | ||
295 | .enter = &intel_idle }, | ||
296 | { | ||
276 | .enter = NULL } | 297 | .enter = NULL } |
277 | }; | 298 | }; |
278 | 299 | ||
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 3c86faa59798..8f0406230a0a 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/completion.h> | 17 | #include <linux/completion.h> |
18 | #include <linux/hrtimer.h> | 18 | #include <linux/hrtimer.h> |
19 | 19 | ||
20 | #define CPUIDLE_STATE_MAX 8 | 20 | #define CPUIDLE_STATE_MAX 10 |
21 | #define CPUIDLE_NAME_LEN 16 | 21 | #define CPUIDLE_NAME_LEN 16 |
22 | #define CPUIDLE_DESC_LEN 32 | 22 | #define CPUIDLE_DESC_LEN 32 |
23 | 23 | ||
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 321e066a0753..9e9d34871195 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c | |||
@@ -46,6 +46,7 @@ unsigned int skip_c0; | |||
46 | unsigned int skip_c1; | 46 | unsigned int skip_c1; |
47 | unsigned int do_nhm_cstates; | 47 | unsigned int do_nhm_cstates; |
48 | unsigned int do_snb_cstates; | 48 | unsigned int do_snb_cstates; |
49 | unsigned int do_c8_c9_c10; | ||
49 | unsigned int has_aperf; | 50 | unsigned int has_aperf; |
50 | unsigned int has_epb; | 51 | unsigned int has_epb; |
51 | unsigned int units = 1000000000; /* Ghz etc */ | 52 | unsigned int units = 1000000000; /* Ghz etc */ |
@@ -120,6 +121,9 @@ struct pkg_data { | |||
120 | unsigned long long pc3; | 121 | unsigned long long pc3; |
121 | unsigned long long pc6; | 122 | unsigned long long pc6; |
122 | unsigned long long pc7; | 123 | unsigned long long pc7; |
124 | unsigned long long pc8; | ||
125 | unsigned long long pc9; | ||
126 | unsigned long long pc10; | ||
123 | unsigned int package_id; | 127 | unsigned int package_id; |
124 | unsigned int energy_pkg; /* MSR_PKG_ENERGY_STATUS */ | 128 | unsigned int energy_pkg; /* MSR_PKG_ENERGY_STATUS */ |
125 | unsigned int energy_dram; /* MSR_DRAM_ENERGY_STATUS */ | 129 | unsigned int energy_dram; /* MSR_DRAM_ENERGY_STATUS */ |
@@ -282,6 +286,11 @@ void print_header(void) | |||
282 | outp += sprintf(outp, " %%pc6"); | 286 | outp += sprintf(outp, " %%pc6"); |
283 | if (do_snb_cstates) | 287 | if (do_snb_cstates) |
284 | outp += sprintf(outp, " %%pc7"); | 288 | outp += sprintf(outp, " %%pc7"); |
289 | if (do_c8_c9_c10) { | ||
290 | outp += sprintf(outp, " %%pc8"); | ||
291 | outp += sprintf(outp, " %%pc9"); | ||
292 | outp += sprintf(outp, " %%pc10"); | ||
293 | } | ||
285 | 294 | ||
286 | if (do_rapl & RAPL_PKG) | 295 | if (do_rapl & RAPL_PKG) |
287 | outp += sprintf(outp, " Pkg_W"); | 296 | outp += sprintf(outp, " Pkg_W"); |
@@ -336,6 +345,9 @@ int dump_counters(struct thread_data *t, struct core_data *c, | |||
336 | fprintf(stderr, "pc3: %016llX\n", p->pc3); | 345 | fprintf(stderr, "pc3: %016llX\n", p->pc3); |
337 | fprintf(stderr, "pc6: %016llX\n", p->pc6); | 346 | fprintf(stderr, "pc6: %016llX\n", p->pc6); |
338 | fprintf(stderr, "pc7: %016llX\n", p->pc7); | 347 | fprintf(stderr, "pc7: %016llX\n", p->pc7); |
348 | fprintf(stderr, "pc8: %016llX\n", p->pc8); | ||
349 | fprintf(stderr, "pc9: %016llX\n", p->pc9); | ||
350 | fprintf(stderr, "pc10: %016llX\n", p->pc10); | ||
339 | fprintf(stderr, "Joules PKG: %0X\n", p->energy_pkg); | 351 | fprintf(stderr, "Joules PKG: %0X\n", p->energy_pkg); |
340 | fprintf(stderr, "Joules COR: %0X\n", p->energy_cores); | 352 | fprintf(stderr, "Joules COR: %0X\n", p->energy_cores); |
341 | fprintf(stderr, "Joules GFX: %0X\n", p->energy_gfx); | 353 | fprintf(stderr, "Joules GFX: %0X\n", p->energy_gfx); |
@@ -493,6 +505,11 @@ int format_counters(struct thread_data *t, struct core_data *c, | |||
493 | outp += sprintf(outp, " %6.2f", 100.0 * p->pc6/t->tsc); | 505 | outp += sprintf(outp, " %6.2f", 100.0 * p->pc6/t->tsc); |
494 | if (do_snb_cstates) | 506 | if (do_snb_cstates) |
495 | outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc); | 507 | outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc); |
508 | if (do_c8_c9_c10) { | ||
509 | outp += sprintf(outp, " %6.2f", 100.0 * p->pc8/t->tsc); | ||
510 | outp += sprintf(outp, " %6.2f", 100.0 * p->pc9/t->tsc); | ||
511 | outp += sprintf(outp, " %6.2f", 100.0 * p->pc10/t->tsc); | ||
512 | } | ||
496 | 513 | ||
497 | /* | 514 | /* |
498 | * If measurement interval exceeds minimum RAPL Joule Counter range, | 515 | * If measurement interval exceeds minimum RAPL Joule Counter range, |
@@ -569,6 +586,9 @@ delta_package(struct pkg_data *new, struct pkg_data *old) | |||
569 | old->pc3 = new->pc3 - old->pc3; | 586 | old->pc3 = new->pc3 - old->pc3; |
570 | old->pc6 = new->pc6 - old->pc6; | 587 | old->pc6 = new->pc6 - old->pc6; |
571 | old->pc7 = new->pc7 - old->pc7; | 588 | old->pc7 = new->pc7 - old->pc7; |
589 | old->pc8 = new->pc8 - old->pc8; | ||
590 | old->pc9 = new->pc9 - old->pc9; | ||
591 | old->pc10 = new->pc10 - old->pc10; | ||
572 | old->pkg_temp_c = new->pkg_temp_c; | 592 | old->pkg_temp_c = new->pkg_temp_c; |
573 | 593 | ||
574 | DELTA_WRAP32(new->energy_pkg, old->energy_pkg); | 594 | DELTA_WRAP32(new->energy_pkg, old->energy_pkg); |
@@ -702,6 +722,9 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data | |||
702 | p->pc3 = 0; | 722 | p->pc3 = 0; |
703 | p->pc6 = 0; | 723 | p->pc6 = 0; |
704 | p->pc7 = 0; | 724 | p->pc7 = 0; |
725 | p->pc8 = 0; | ||
726 | p->pc9 = 0; | ||
727 | p->pc10 = 0; | ||
705 | 728 | ||
706 | p->energy_pkg = 0; | 729 | p->energy_pkg = 0; |
707 | p->energy_dram = 0; | 730 | p->energy_dram = 0; |
@@ -740,6 +763,9 @@ int sum_counters(struct thread_data *t, struct core_data *c, | |||
740 | average.packages.pc3 += p->pc3; | 763 | average.packages.pc3 += p->pc3; |
741 | average.packages.pc6 += p->pc6; | 764 | average.packages.pc6 += p->pc6; |
742 | average.packages.pc7 += p->pc7; | 765 | average.packages.pc7 += p->pc7; |
766 | average.packages.pc8 += p->pc8; | ||
767 | average.packages.pc9 += p->pc9; | ||
768 | average.packages.pc10 += p->pc10; | ||
743 | 769 | ||
744 | average.packages.energy_pkg += p->energy_pkg; | 770 | average.packages.energy_pkg += p->energy_pkg; |
745 | average.packages.energy_dram += p->energy_dram; | 771 | average.packages.energy_dram += p->energy_dram; |
@@ -781,6 +807,10 @@ void compute_average(struct thread_data *t, struct core_data *c, | |||
781 | average.packages.pc3 /= topo.num_packages; | 807 | average.packages.pc3 /= topo.num_packages; |
782 | average.packages.pc6 /= topo.num_packages; | 808 | average.packages.pc6 /= topo.num_packages; |
783 | average.packages.pc7 /= topo.num_packages; | 809 | average.packages.pc7 /= topo.num_packages; |
810 | |||
811 | average.packages.pc8 /= topo.num_packages; | ||
812 | average.packages.pc9 /= topo.num_packages; | ||
813 | average.packages.pc10 /= topo.num_packages; | ||
784 | } | 814 | } |
785 | 815 | ||
786 | static unsigned long long rdtsc(void) | 816 | static unsigned long long rdtsc(void) |
@@ -880,6 +910,14 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) | |||
880 | if (get_msr(cpu, MSR_PKG_C7_RESIDENCY, &p->pc7)) | 910 | if (get_msr(cpu, MSR_PKG_C7_RESIDENCY, &p->pc7)) |
881 | return -12; | 911 | return -12; |
882 | } | 912 | } |
913 | if (do_c8_c9_c10) { | ||
914 | if (get_msr(cpu, MSR_PKG_C8_RESIDENCY, &p->pc8)) | ||
915 | return -13; | ||
916 | if (get_msr(cpu, MSR_PKG_C9_RESIDENCY, &p->pc9)) | ||
917 | return -13; | ||
918 | if (get_msr(cpu, MSR_PKG_C10_RESIDENCY, &p->pc10)) | ||
919 | return -13; | ||
920 | } | ||
883 | if (do_rapl & RAPL_PKG) { | 921 | if (do_rapl & RAPL_PKG) { |
884 | if (get_msr(cpu, MSR_PKG_ENERGY_STATUS, &msr)) | 922 | if (get_msr(cpu, MSR_PKG_ENERGY_STATUS, &msr)) |
885 | return -13; | 923 | return -13; |
@@ -1762,6 +1800,19 @@ int is_snb(unsigned int family, unsigned int model) | |||
1762 | return 0; | 1800 | return 0; |
1763 | } | 1801 | } |
1764 | 1802 | ||
1803 | int has_c8_c9_c10(unsigned int family, unsigned int model) | ||
1804 | { | ||
1805 | if (!genuine_intel) | ||
1806 | return 0; | ||
1807 | |||
1808 | switch (model) { | ||
1809 | case 0x45: | ||
1810 | return 1; | ||
1811 | } | ||
1812 | return 0; | ||
1813 | } | ||
1814 | |||
1815 | |||
1765 | double discover_bclk(unsigned int family, unsigned int model) | 1816 | double discover_bclk(unsigned int family, unsigned int model) |
1766 | { | 1817 | { |
1767 | if (is_snb(family, model)) | 1818 | if (is_snb(family, model)) |
@@ -1918,6 +1969,7 @@ void check_cpuid() | |||
1918 | do_nhm_cstates = genuine_intel; /* all Intel w/ non-stop TSC have NHM counters */ | 1969 | do_nhm_cstates = genuine_intel; /* all Intel w/ non-stop TSC have NHM counters */ |
1919 | do_smi = do_nhm_cstates; | 1970 | do_smi = do_nhm_cstates; |
1920 | do_snb_cstates = is_snb(family, model); | 1971 | do_snb_cstates = is_snb(family, model); |
1972 | do_c8_c9_c10 = has_c8_c9_c10(family, model); | ||
1921 | bclk = discover_bclk(family, model); | 1973 | bclk = discover_bclk(family, model); |
1922 | 1974 | ||
1923 | do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model); | 1975 | do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model); |
@@ -2279,7 +2331,7 @@ int main(int argc, char **argv) | |||
2279 | cmdline(argc, argv); | 2331 | cmdline(argc, argv); |
2280 | 2332 | ||
2281 | if (verbose) | 2333 | if (verbose) |
2282 | fprintf(stderr, "turbostat v3.3 March 15, 2013" | 2334 | fprintf(stderr, "turbostat v3.4 April 17, 2013" |
2283 | " - Len Brown <lenb@kernel.org>\n"); | 2335 | " - Len Brown <lenb@kernel.org>\n"); |
2284 | 2336 | ||
2285 | turbostat_init(); | 2337 | turbostat_init(); |