diff options
Diffstat (limited to 'tools/perf/builtin-stat.c')
-rw-r--r-- | tools/perf/builtin-stat.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index ad9324d1daf9..48ac53b199fc 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -86,6 +86,7 @@ | |||
86 | #define DEFAULT_SEPARATOR " " | 86 | #define DEFAULT_SEPARATOR " " |
87 | #define CNTR_NOT_SUPPORTED "<not supported>" | 87 | #define CNTR_NOT_SUPPORTED "<not supported>" |
88 | #define CNTR_NOT_COUNTED "<not counted>" | 88 | #define CNTR_NOT_COUNTED "<not counted>" |
89 | #define FREEZE_ON_SMI_PATH "devices/cpu/freeze_on_smi" | ||
89 | 90 | ||
90 | static void print_counters(struct timespec *ts, int argc, const char **argv); | 91 | static void print_counters(struct timespec *ts, int argc, const char **argv); |
91 | 92 | ||
@@ -122,6 +123,14 @@ static const char * topdown_attrs[] = { | |||
122 | NULL, | 123 | NULL, |
123 | }; | 124 | }; |
124 | 125 | ||
126 | static const char *smi_cost_attrs = { | ||
127 | "{" | ||
128 | "msr/aperf/," | ||
129 | "msr/smi/," | ||
130 | "cycles" | ||
131 | "}" | ||
132 | }; | ||
133 | |||
125 | static struct perf_evlist *evsel_list; | 134 | static struct perf_evlist *evsel_list; |
126 | 135 | ||
127 | static struct target target = { | 136 | static struct target target = { |
@@ -137,6 +146,8 @@ static bool null_run = false; | |||
137 | static int detailed_run = 0; | 146 | static int detailed_run = 0; |
138 | static bool transaction_run; | 147 | static bool transaction_run; |
139 | static bool topdown_run = false; | 148 | static bool topdown_run = false; |
149 | static bool smi_cost = false; | ||
150 | static bool smi_reset = false; | ||
140 | static bool big_num = true; | 151 | static bool big_num = true; |
141 | static int big_num_opt = -1; | 152 | static int big_num_opt = -1; |
142 | static const char *csv_sep = NULL; | 153 | static const char *csv_sep = NULL; |
@@ -625,14 +636,14 @@ try_again: | |||
625 | } | 636 | } |
626 | 637 | ||
627 | if (perf_evlist__apply_filters(evsel_list, &counter)) { | 638 | if (perf_evlist__apply_filters(evsel_list, &counter)) { |
628 | error("failed to set filter \"%s\" on event %s with %d (%s)\n", | 639 | pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n", |
629 | counter->filter, perf_evsel__name(counter), errno, | 640 | counter->filter, perf_evsel__name(counter), errno, |
630 | str_error_r(errno, msg, sizeof(msg))); | 641 | str_error_r(errno, msg, sizeof(msg))); |
631 | return -1; | 642 | return -1; |
632 | } | 643 | } |
633 | 644 | ||
634 | if (perf_evlist__apply_drv_configs(evsel_list, &counter, &err_term)) { | 645 | if (perf_evlist__apply_drv_configs(evsel_list, &counter, &err_term)) { |
635 | error("failed to set config \"%s\" on event %s with %d (%s)\n", | 646 | pr_err("failed to set config \"%s\" on event %s with %d (%s)\n", |
636 | err_term->val.drv_cfg, perf_evsel__name(counter), errno, | 647 | err_term->val.drv_cfg, perf_evsel__name(counter), errno, |
637 | str_error_r(errno, msg, sizeof(msg))); | 648 | str_error_r(errno, msg, sizeof(msg))); |
638 | return -1; | 649 | return -1; |
@@ -1782,6 +1793,8 @@ static const struct option stat_options[] = { | |||
1782 | "Only print computed metrics. No raw values", enable_metric_only), | 1793 | "Only print computed metrics. No raw values", enable_metric_only), |
1783 | OPT_BOOLEAN(0, "topdown", &topdown_run, | 1794 | OPT_BOOLEAN(0, "topdown", &topdown_run, |
1784 | "measure topdown level 1 statistics"), | 1795 | "measure topdown level 1 statistics"), |
1796 | OPT_BOOLEAN(0, "smi-cost", &smi_cost, | ||
1797 | "measure SMI cost"), | ||
1785 | OPT_END() | 1798 | OPT_END() |
1786 | }; | 1799 | }; |
1787 | 1800 | ||
@@ -2160,6 +2173,39 @@ static int add_default_attributes(void) | |||
2160 | return 0; | 2173 | return 0; |
2161 | } | 2174 | } |
2162 | 2175 | ||
2176 | if (smi_cost) { | ||
2177 | int smi; | ||
2178 | |||
2179 | if (sysfs__read_int(FREEZE_ON_SMI_PATH, &smi) < 0) { | ||
2180 | fprintf(stderr, "freeze_on_smi is not supported.\n"); | ||
2181 | return -1; | ||
2182 | } | ||
2183 | |||
2184 | if (!smi) { | ||
2185 | if (sysfs__write_int(FREEZE_ON_SMI_PATH, 1) < 0) { | ||
2186 | fprintf(stderr, "Failed to set freeze_on_smi.\n"); | ||
2187 | return -1; | ||
2188 | } | ||
2189 | smi_reset = true; | ||
2190 | } | ||
2191 | |||
2192 | if (pmu_have_event("msr", "aperf") && | ||
2193 | pmu_have_event("msr", "smi")) { | ||
2194 | if (!force_metric_only) | ||
2195 | metric_only = true; | ||
2196 | err = parse_events(evsel_list, smi_cost_attrs, NULL); | ||
2197 | } else { | ||
2198 | fprintf(stderr, "To measure SMI cost, it needs " | ||
2199 | "msr/aperf/, msr/smi/ and cpu/cycles/ support\n"); | ||
2200 | return -1; | ||
2201 | } | ||
2202 | if (err) { | ||
2203 | fprintf(stderr, "Cannot set up SMI cost events\n"); | ||
2204 | return -1; | ||
2205 | } | ||
2206 | return 0; | ||
2207 | } | ||
2208 | |||
2163 | if (topdown_run) { | 2209 | if (topdown_run) { |
2164 | char *str = NULL; | 2210 | char *str = NULL; |
2165 | bool warn = false; | 2211 | bool warn = false; |
@@ -2742,6 +2788,9 @@ int cmd_stat(int argc, const char **argv) | |||
2742 | perf_stat__exit_aggr_mode(); | 2788 | perf_stat__exit_aggr_mode(); |
2743 | perf_evlist__free_stats(evsel_list); | 2789 | perf_evlist__free_stats(evsel_list); |
2744 | out: | 2790 | out: |
2791 | if (smi_cost && smi_reset) | ||
2792 | sysfs__write_int(FREEZE_ON_SMI_PATH, 0); | ||
2793 | |||
2745 | perf_evlist__delete(evsel_list); | 2794 | perf_evlist__delete(evsel_list); |
2746 | return status; | 2795 | return status; |
2747 | } | 2796 | } |