perf kvm: Add arch neutral function to choose event for perf kvm record
'perf kvm record' uses 'cycles'(if the user did not specify any event) as the default event to profile the guest. This will not provide any proper samples from the guest incase of powerpc architecture, since in powerpc the PMUs are controlled by the guest rather than the host. Patch adds a function to pick an arch specific event for 'perf kvm record', instead of selecting 'cycles' as a default event for all architectures. For powerpc this function checks for any user specified event, and if there isn't any it returns invalid instead of proceeding with 'cycles' event. Signed-off-by: Anju T Sudhakar <anju@linux.vnet.ibm.com> Reviewed-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Madhavan Srinivasan <maddy@linux.vnet.ibm.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: linuxppc-dev@lists.ozlabs.org Link: http://lore.kernel.org/lkml/20190718181749.30612-2-anju@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
8067b3da97
commit
124eb5f82b
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "book3s_hv_exits.h"
|
||||
#include "book3s_hcalls.h"
|
||||
#include <subcmd/parse-options.h>
|
||||
|
||||
#define NR_TPS 4
|
||||
|
||||
|
@ -172,3 +173,39 @@ int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid __maybe_unused)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Incase of powerpc architecture, pmu registers are programmable
|
||||
* by guest kernel. So monitoring guest via host may not provide
|
||||
* valid samples. It is better to fail the "perf kvm record"
|
||||
* with default "cycles" event to monitor guest in powerpc.
|
||||
*
|
||||
* Function to parse the arguments and return appropriate values.
|
||||
*/
|
||||
int kvm_add_default_arch_event(int *argc, const char **argv)
|
||||
{
|
||||
const char **tmp;
|
||||
bool event = false;
|
||||
int i, j = *argc;
|
||||
|
||||
const struct option event_options[] = {
|
||||
OPT_BOOLEAN('e', "event", &event, NULL),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
tmp = calloc(j + 1, sizeof(char *));
|
||||
if (!tmp)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < j; i++)
|
||||
tmp[i] = argv[i];
|
||||
|
||||
parse_options(j, tmp, event_options, NULL, PARSE_OPT_KEEP_UNKNOWN);
|
||||
if (!event) {
|
||||
free(tmp);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1514,11 +1514,21 @@ perf_stat:
|
|||
}
|
||||
#endif /* HAVE_KVM_STAT_SUPPORT */
|
||||
|
||||
int __weak kvm_add_default_arch_event(int *argc __maybe_unused,
|
||||
const char **argv __maybe_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cmd_record(const char *file_name, int argc, const char **argv)
|
||||
{
|
||||
int rec_argc, i = 0, j;
|
||||
int rec_argc, i = 0, j, ret;
|
||||
const char **rec_argv;
|
||||
|
||||
ret = kvm_add_default_arch_event(&argc, argv);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
rec_argc = argc + 2;
|
||||
rec_argv = calloc(rec_argc + 1, sizeof(char *));
|
||||
rec_argv[i++] = strdup("record");
|
||||
|
|
|
@ -148,4 +148,5 @@ extern const char *kvm_entry_trace;
|
|||
extern const char *kvm_exit_trace;
|
||||
#endif /* HAVE_KVM_STAT_SUPPORT */
|
||||
|
||||
extern int kvm_add_default_arch_event(int *argc, const char **argv);
|
||||
#endif /* __PERF_KVM_STAT_H */
|
||||
|
|
Loading…
Reference in New Issue