perf tools: allow user to specify hardware breakpoint bp_len

Currently bp_len is given a default value of 4. Allow user to override it:

  $ perf stat -e mem:0x1000/8
                            ^
                            bp_len

If no value is given, it will default to 4 as it did before.

Signed-off-by: Jacob Shin <jacob.w.shin@gmail.com>
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: xiakaixu <xiakaixu@huawei.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
This commit is contained in:
Jacob Shin 2014-05-29 17:26:51 +02:00 committed by Frederic Weisbecker
parent d6d55f0b9d
commit 3741eb9f8c
5 changed files with 42 additions and 15 deletions

View file

@ -33,12 +33,15 @@ OPTIONS
- a raw PMU event (eventsel+umask) in the form of rNNN where NNN is a - a raw PMU event (eventsel+umask) in the form of rNNN where NNN is a
hexadecimal event descriptor. hexadecimal event descriptor.
- a hardware breakpoint event in the form of '\mem:addr[:access]' - a hardware breakpoint event in the form of '\mem:addr[/len][:access]'
where addr is the address in memory you want to break in. where addr is the address in memory you want to break in.
Access is the memory access type (read, write, execute) it can Access is the memory access type (read, write, execute) it can
be passed as follows: '\mem:addr[:[r][w][x]]'. be passed as follows: '\mem:addr[:[r][w][x]]'. len is the range,
number of bytes from specified addr, which the breakpoint will cover.
If you want to profile read-write accesses in 0x1000, just set If you want to profile read-write accesses in 0x1000, just set
'mem:0x1000:rw'. 'mem:0x1000:rw'.
If you want to profile write accesses in [0x1000~1008), just set
'mem:0x1000/8:w'.
--filter=<filter>:: --filter=<filter>::
Event filter. Event filter.

View file

@ -526,7 +526,7 @@ do { \
} }
int parse_events_add_breakpoint(struct list_head *list, int *idx, int parse_events_add_breakpoint(struct list_head *list, int *idx,
void *ptr, char *type) void *ptr, char *type, u64 len)
{ {
struct perf_event_attr attr; struct perf_event_attr attr;
@ -536,14 +536,15 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
if (parse_breakpoint_type(type, &attr)) if (parse_breakpoint_type(type, &attr))
return -EINVAL; return -EINVAL;
/* /* Provide some defaults if len is not specified */
* We should find a nice way to override the access length if (!len) {
* Provide some defaults for now
*/
if (attr.bp_type == HW_BREAKPOINT_X) if (attr.bp_type == HW_BREAKPOINT_X)
attr.bp_len = sizeof(long); len = sizeof(long);
else else
attr.bp_len = HW_BREAKPOINT_LEN_4; len = HW_BREAKPOINT_LEN_4;
}
attr.bp_len = len;
attr.type = PERF_TYPE_BREAKPOINT; attr.type = PERF_TYPE_BREAKPOINT;
attr.sample_period = 1; attr.sample_period = 1;
@ -1364,7 +1365,7 @@ void print_events(const char *event_glob, bool name_only)
printf("\n"); printf("\n");
printf(" %-50s [%s]\n", printf(" %-50s [%s]\n",
"mem:<addr>[:access]", "mem:<addr>[/len][:access]",
event_type_descriptors[PERF_TYPE_BREAKPOINT]); event_type_descriptors[PERF_TYPE_BREAKPOINT]);
printf("\n"); printf("\n");
} }

View file

@ -104,7 +104,7 @@ int parse_events_add_numeric(struct list_head *list, int *idx,
int parse_events_add_cache(struct list_head *list, int *idx, int parse_events_add_cache(struct list_head *list, int *idx,
char *type, char *op_result1, char *op_result2); char *type, char *op_result1, char *op_result2);
int parse_events_add_breakpoint(struct list_head *list, int *idx, int parse_events_add_breakpoint(struct list_head *list, int *idx,
void *ptr, char *type); void *ptr, char *type, u64 len);
int parse_events_add_pmu(struct list_head *list, int *idx, int parse_events_add_pmu(struct list_head *list, int *idx,
char *pmu , struct list_head *head_config); char *pmu , struct list_head *head_config);
enum perf_pmu_event_symbol_type enum perf_pmu_event_symbol_type

View file

@ -159,6 +159,7 @@ branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE
<mem>{ <mem>{
{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); } {modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
: { return ':'; } : { return ':'; }
"/" { return '/'; }
{num_dec} { return value(yyscanner, 10); } {num_dec} { return value(yyscanner, 10); }
{num_hex} { return value(yyscanner, 16); } {num_hex} { return value(yyscanner, 16); }
/* /*

View file

@ -326,6 +326,28 @@ PE_NAME_CACHE_TYPE
} }
event_legacy_mem: event_legacy_mem:
PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc
{
struct parse_events_evlist *data = _data;
struct list_head *list;
ALLOC_LIST(list);
ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
(void *) $2, $6, $4));
$$ = list;
}
|
PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc
{
struct parse_events_evlist *data = _data;
struct list_head *list;
ALLOC_LIST(list);
ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
(void *) $2, NULL, $4));
$$ = list;
}
|
PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
{ {
struct parse_events_evlist *data = _data; struct parse_events_evlist *data = _data;
@ -333,7 +355,7 @@ PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
ALLOC_LIST(list); ALLOC_LIST(list);
ABORT_ON(parse_events_add_breakpoint(list, &data->idx, ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
(void *) $2, $4)); (void *) $2, $4, 0));
$$ = list; $$ = list;
} }
| |
@ -344,7 +366,7 @@ PE_PREFIX_MEM PE_VALUE sep_dc
ALLOC_LIST(list); ALLOC_LIST(list);
ABORT_ON(parse_events_add_breakpoint(list, &data->idx, ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
(void *) $2, NULL)); (void *) $2, NULL, 0));
$$ = list; $$ = list;
} }