Commit 6640b6c2 authored by Jiri Olsa's avatar Jiri Olsa Committed by Arnaldo Carvalho de Melo

perf cpu_map: Add cpu_map user level event

Adding the cpu_map event to pass/store cpu maps as data in
a pipe/perf.data.

We store maps in 2 formats:
  - list of cpus
  - mask of cpus

The format that takes less space is selected transparently in the
following patch.

The interface is made generic, so we could add the cpumap event data
into another event in the following patches.
Signed-off-by: default avatarJiri Olsa <jolsa@kernel.org>
Tested-by: default avatarKan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-8-git-send-email-jolsa@kernel.org
[ cpu_map_data_cpus -> cpu_map_entries, cpu_map_data_mask -> cpu_map_mask ]
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent ec7fa596
...@@ -38,6 +38,7 @@ static const char *perf_event__names[] = { ...@@ -38,6 +38,7 @@ static const char *perf_event__names[] = {
[PERF_RECORD_AUXTRACE] = "AUXTRACE", [PERF_RECORD_AUXTRACE] = "AUXTRACE",
[PERF_RECORD_AUXTRACE_ERROR] = "AUXTRACE_ERROR", [PERF_RECORD_AUXTRACE_ERROR] = "AUXTRACE_ERROR",
[PERF_RECORD_THREAD_MAP] = "THREAD_MAP", [PERF_RECORD_THREAD_MAP] = "THREAD_MAP",
[PERF_RECORD_CPU_MAP] = "CPU_MAP",
}; };
const char *perf_event__name(unsigned int id) const char *perf_event__name(unsigned int id)
......
...@@ -227,6 +227,7 @@ enum perf_user_event_type { /* above any possible kernel type */ ...@@ -227,6 +227,7 @@ enum perf_user_event_type { /* above any possible kernel type */
PERF_RECORD_AUXTRACE = 71, PERF_RECORD_AUXTRACE = 71,
PERF_RECORD_AUXTRACE_ERROR = 72, PERF_RECORD_AUXTRACE_ERROR = 72,
PERF_RECORD_THREAD_MAP = 73, PERF_RECORD_THREAD_MAP = 73,
PERF_RECORD_CPU_MAP = 74,
PERF_RECORD_HEADER_MAX PERF_RECORD_HEADER_MAX
}; };
...@@ -271,6 +272,32 @@ struct events_stats { ...@@ -271,6 +272,32 @@ struct events_stats {
u32 nr_proc_map_timeout; u32 nr_proc_map_timeout;
}; };
enum {
PERF_CPU_MAP__CPUS = 0,
PERF_CPU_MAP__MASK = 1,
};
struct cpu_map_entries {
u16 nr;
u16 cpu[];
};
struct cpu_map_mask {
u16 nr;
u16 long_size;
unsigned long mask[];
};
struct cpu_map_data {
u16 type;
char data[];
};
struct cpu_map_event {
struct perf_event_header header;
struct cpu_map_data data;
};
struct attr_event { struct attr_event {
struct perf_event_header header; struct perf_event_header header;
struct perf_event_attr attr; struct perf_event_attr attr;
...@@ -391,6 +418,7 @@ union perf_event { ...@@ -391,6 +418,7 @@ union perf_event {
struct itrace_start_event itrace_start; struct itrace_start_event itrace_start;
struct context_switch_event context_switch; struct context_switch_event context_switch;
struct thread_map_event thread_map; struct thread_map_event thread_map;
struct cpu_map_event cpu_map;
}; };
void perf_event__print_totals(void); void perf_event__print_totals(void);
......
...@@ -306,6 +306,15 @@ int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused, ...@@ -306,6 +306,15 @@ int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
return 0; return 0;
} }
static
int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_session *session __maybe_unused)
{
dump_printf(": unhandled!\n");
return 0;
}
void perf_tool__fill_defaults(struct perf_tool *tool) void perf_tool__fill_defaults(struct perf_tool *tool)
{ {
if (tool->sample == NULL) if (tool->sample == NULL)
...@@ -358,6 +367,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) ...@@ -358,6 +367,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
tool->auxtrace_error = process_event_auxtrace_error_stub; tool->auxtrace_error = process_event_auxtrace_error_stub;
if (tool->thread_map == NULL) if (tool->thread_map == NULL)
tool->thread_map = process_event_thread_map_stub; tool->thread_map = process_event_thread_map_stub;
if (tool->cpu_map == NULL)
tool->cpu_map = process_event_cpu_map_stub;
} }
static void swap_sample_id_all(union perf_event *event, void *data) static void swap_sample_id_all(union perf_event *event, void *data)
...@@ -639,6 +650,42 @@ static void perf_event__thread_map_swap(union perf_event *event, ...@@ -639,6 +650,42 @@ static void perf_event__thread_map_swap(union perf_event *event,
event->thread_map.entries[i].pid = bswap_64(event->thread_map.entries[i].pid); event->thread_map.entries[i].pid = bswap_64(event->thread_map.entries[i].pid);
} }
static void perf_event__cpu_map_swap(union perf_event *event,
bool sample_id_all __maybe_unused)
{
struct cpu_map_data *data = &event->cpu_map.data;
struct cpu_map_entries *cpus;
struct cpu_map_mask *mask;
unsigned i;
data->type = bswap_64(data->type);
switch (data->type) {
case PERF_CPU_MAP__CPUS:
cpus = (struct cpu_map_entries *)data->data;
cpus->nr = bswap_16(cpus->nr);
for (i = 0; i < cpus->nr; i++)
cpus->cpu[i] = bswap_16(cpus->cpu[i]);
break;
case PERF_CPU_MAP__MASK:
mask = (struct cpu_map_mask *) data->data;
mask->nr = bswap_16(mask->nr);
mask->long_size = bswap_16(mask->long_size);
switch (mask->long_size) {
case 4: mem_bswap_32(&mask->mask, mask->nr); break;
case 8: mem_bswap_64(&mask->mask, mask->nr); break;
default:
pr_err("cpu_map swap: unsupported long size\n");
}
default:
break;
}
}
typedef void (*perf_event__swap_op)(union perf_event *event, typedef void (*perf_event__swap_op)(union perf_event *event,
bool sample_id_all); bool sample_id_all);
...@@ -667,6 +714,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { ...@@ -667,6 +714,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
[PERF_RECORD_AUXTRACE] = perf_event__auxtrace_swap, [PERF_RECORD_AUXTRACE] = perf_event__auxtrace_swap,
[PERF_RECORD_AUXTRACE_ERROR] = perf_event__auxtrace_error_swap, [PERF_RECORD_AUXTRACE_ERROR] = perf_event__auxtrace_error_swap,
[PERF_RECORD_THREAD_MAP] = perf_event__thread_map_swap, [PERF_RECORD_THREAD_MAP] = perf_event__thread_map_swap,
[PERF_RECORD_CPU_MAP] = perf_event__cpu_map_swap,
[PERF_RECORD_HEADER_MAX] = NULL, [PERF_RECORD_HEADER_MAX] = NULL,
}; };
...@@ -1205,6 +1253,8 @@ static s64 perf_session__process_user_event(struct perf_session *session, ...@@ -1205,6 +1253,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
return tool->auxtrace_error(tool, event, session); return tool->auxtrace_error(tool, event, session);
case PERF_RECORD_THREAD_MAP: case PERF_RECORD_THREAD_MAP:
return tool->thread_map(tool, event, session); return tool->thread_map(tool, event, session);
case PERF_RECORD_CPU_MAP:
return tool->cpu_map(tool, event, session);
default: default:
return -EINVAL; return -EINVAL;
} }
......
...@@ -56,7 +56,8 @@ struct perf_tool { ...@@ -56,7 +56,8 @@ struct perf_tool {
id_index, id_index,
auxtrace_info, auxtrace_info,
auxtrace_error, auxtrace_error,
thread_map; thread_map,
cpu_map;
event_op3 auxtrace; event_op3 auxtrace;
bool ordered_events; bool ordered_events;
bool ordering_requires_timestamps; bool ordering_requires_timestamps;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment