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:
Родитель
d6d55f0b9d
Коммит
3741eb9f8c
|
@ -33,12 +33,15 @@ OPTIONS
|
|||
- a raw PMU event (eventsel+umask) in the form of rNNN where NNN is a
|
||||
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.
|
||||
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
|
||||
'mem:0x1000:rw'.
|
||||
If you want to profile write accesses in [0x1000~1008), just set
|
||||
'mem:0x1000/8:w'.
|
||||
|
||||
--filter=<filter>::
|
||||
Event filter.
|
||||
|
|
|
@ -526,7 +526,7 @@ do { \
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -536,14 +536,15 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
|
|||
if (parse_breakpoint_type(type, &attr))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* We should find a nice way to override the access length
|
||||
* Provide some defaults for now
|
||||
*/
|
||||
if (attr.bp_type == HW_BREAKPOINT_X)
|
||||
attr.bp_len = sizeof(long);
|
||||
else
|
||||
attr.bp_len = HW_BREAKPOINT_LEN_4;
|
||||
/* Provide some defaults if len is not specified */
|
||||
if (!len) {
|
||||
if (attr.bp_type == HW_BREAKPOINT_X)
|
||||
len = sizeof(long);
|
||||
else
|
||||
len = HW_BREAKPOINT_LEN_4;
|
||||
}
|
||||
|
||||
attr.bp_len = len;
|
||||
|
||||
attr.type = PERF_TYPE_BREAKPOINT;
|
||||
attr.sample_period = 1;
|
||||
|
@ -1364,7 +1365,7 @@ void print_events(const char *event_glob, bool name_only)
|
|||
printf("\n");
|
||||
|
||||
printf(" %-50s [%s]\n",
|
||||
"mem:<addr>[:access]",
|
||||
"mem:<addr>[/len][:access]",
|
||||
event_type_descriptors[PERF_TYPE_BREAKPOINT]);
|
||||
printf("\n");
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
char *type, char *op_result1, char *op_result2);
|
||||
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,
|
||||
char *pmu , struct list_head *head_config);
|
||||
enum perf_pmu_event_symbol_type
|
||||
|
|
|
@ -159,6 +159,7 @@ branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE
|
|||
<mem>{
|
||||
{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
|
||||
: { return ':'; }
|
||||
"/" { return '/'; }
|
||||
{num_dec} { return value(yyscanner, 10); }
|
||||
{num_hex} { return value(yyscanner, 16); }
|
||||
/*
|
||||
|
|
|
@ -326,6 +326,28 @@ PE_NAME_CACHE_TYPE
|
|||
}
|
||||
|
||||
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
|
||||
{
|
||||
struct parse_events_evlist *data = _data;
|
||||
|
@ -333,7 +355,7 @@ PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
|
|||
|
||||
ALLOC_LIST(list);
|
||||
ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
|
||||
(void *) $2, $4));
|
||||
(void *) $2, $4, 0));
|
||||
$$ = list;
|
||||
}
|
||||
|
|
||||
|
@ -344,7 +366,7 @@ PE_PREFIX_MEM PE_VALUE sep_dc
|
|||
|
||||
ALLOC_LIST(list);
|
||||
ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
|
||||
(void *) $2, NULL));
|
||||
(void *) $2, NULL, 0));
|
||||
$$ = list;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче