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 @@  #define DEFAULT_SEPARATOR	" "  #define CNTR_NOT_SUPPORTED	"<not supported>"  #define CNTR_NOT_COUNTED	"<not counted>" +#define FREEZE_ON_SMI_PATH	"devices/cpu/freeze_on_smi"  static void print_counters(struct timespec *ts, int argc, const char **argv); @@ -122,6 +123,14 @@ static const char * topdown_attrs[] = {  	NULL,  }; +static const char *smi_cost_attrs = { +	"{" +	"msr/aperf/," +	"msr/smi/," +	"cycles" +	"}" +}; +  static struct perf_evlist	*evsel_list;  static struct target target = { @@ -137,6 +146,8 @@ static bool			null_run			=  false;  static int			detailed_run			=  0;  static bool			transaction_run;  static bool			topdown_run			= false; +static bool			smi_cost			= false; +static bool			smi_reset			= false;  static bool			big_num				=  true;  static int			big_num_opt			=  -1;  static const char		*csv_sep			= NULL; @@ -625,14 +636,14 @@ try_again:  	}  	if (perf_evlist__apply_filters(evsel_list, &counter)) { -		error("failed to set filter \"%s\" on event %s with %d (%s)\n", +		pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",  			counter->filter, perf_evsel__name(counter), errno,  			str_error_r(errno, msg, sizeof(msg)));  		return -1;  	}  	if (perf_evlist__apply_drv_configs(evsel_list, &counter, &err_term)) { -		error("failed to set config \"%s\" on event %s with %d (%s)\n", +		pr_err("failed to set config \"%s\" on event %s with %d (%s)\n",  		      err_term->val.drv_cfg, perf_evsel__name(counter), errno,  		      str_error_r(errno, msg, sizeof(msg)));  		return -1; @@ -1782,6 +1793,8 @@ static const struct option stat_options[] = {  			"Only print computed metrics. No raw values", enable_metric_only),  	OPT_BOOLEAN(0, "topdown", &topdown_run,  			"measure topdown level 1 statistics"), +	OPT_BOOLEAN(0, "smi-cost", &smi_cost, +			"measure SMI cost"),  	OPT_END()  }; @@ -2160,6 +2173,39 @@ static int add_default_attributes(void)  		return 0;  	} +	if (smi_cost) { +		int smi; + +		if (sysfs__read_int(FREEZE_ON_SMI_PATH, &smi) < 0) { +			fprintf(stderr, "freeze_on_smi is not supported.\n"); +			return -1; +		} + +		if (!smi) { +			if (sysfs__write_int(FREEZE_ON_SMI_PATH, 1) < 0) { +				fprintf(stderr, "Failed to set freeze_on_smi.\n"); +				return -1; +			} +			smi_reset = true; +		} + +		if (pmu_have_event("msr", "aperf") && +		    pmu_have_event("msr", "smi")) { +			if (!force_metric_only) +				metric_only = true; +			err = parse_events(evsel_list, smi_cost_attrs, NULL); +		} else { +			fprintf(stderr, "To measure SMI cost, it needs " +				"msr/aperf/, msr/smi/ and cpu/cycles/ support\n"); +			return -1; +		} +		if (err) { +			fprintf(stderr, "Cannot set up SMI cost events\n"); +			return -1; +		} +		return 0; +	} +  	if (topdown_run) {  		char *str = NULL;  		bool warn = false; @@ -2742,6 +2788,9 @@ int cmd_stat(int argc, const char **argv)  	perf_stat__exit_aggr_mode();  	perf_evlist__free_stats(evsel_list);  out: +	if (smi_cost && smi_reset) +		sysfs__write_int(FREEZE_ON_SMI_PATH, 0); +  	perf_evlist__delete(evsel_list);  	return status;  } |