Skip to content

Commit

Permalink
Merge branch 'perf/core' into perf/urgent, to pick up the latest fixes
Browse files Browse the repository at this point in the history
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
Ingo Molnar committed Jun 14, 2014
2 parents 4cdf77a + 4ba9619 commit cf23091
Show file tree
Hide file tree
Showing 39 changed files with 1,242 additions and 123 deletions.
1 change: 1 addition & 0 deletions include/uapi/linux/perf_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,7 @@ enum perf_event_type {
* u32 min;
* u64 ino;
* u64 ino_generation;
* u32 prot, flags;
* char filename[];
* struct sample_id sample_id;
* };
Expand Down
37 changes: 33 additions & 4 deletions kernel/events/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <linux/mm_types.h>
#include <linux/cgroup.h>
#include <linux/module.h>
#include <linux/mman.h>

#include "internal.h"

Expand Down Expand Up @@ -5128,6 +5129,7 @@ struct perf_mmap_event {
int maj, min;
u64 ino;
u64 ino_generation;
u32 prot, flags;

struct {
struct perf_event_header header;
Expand Down Expand Up @@ -5169,6 +5171,8 @@ static void perf_event_mmap_output(struct perf_event *event,
mmap_event->event_id.header.size += sizeof(mmap_event->min);
mmap_event->event_id.header.size += sizeof(mmap_event->ino);
mmap_event->event_id.header.size += sizeof(mmap_event->ino_generation);
mmap_event->event_id.header.size += sizeof(mmap_event->prot);
mmap_event->event_id.header.size += sizeof(mmap_event->flags);
}

perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);
Expand All @@ -5187,6 +5191,8 @@ static void perf_event_mmap_output(struct perf_event *event,
perf_output_put(&handle, mmap_event->min);
perf_output_put(&handle, mmap_event->ino);
perf_output_put(&handle, mmap_event->ino_generation);
perf_output_put(&handle, mmap_event->prot);
perf_output_put(&handle, mmap_event->flags);
}

__output_copy(&handle, mmap_event->file_name,
Expand All @@ -5205,6 +5211,7 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
struct file *file = vma->vm_file;
int maj = 0, min = 0;
u64 ino = 0, gen = 0;
u32 prot = 0, flags = 0;
unsigned int size;
char tmp[16];
char *buf = NULL;
Expand Down Expand Up @@ -5235,6 +5242,28 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
gen = inode->i_generation;
maj = MAJOR(dev);
min = MINOR(dev);

if (vma->vm_flags & VM_READ)
prot |= PROT_READ;
if (vma->vm_flags & VM_WRITE)
prot |= PROT_WRITE;
if (vma->vm_flags & VM_EXEC)
prot |= PROT_EXEC;

if (vma->vm_flags & VM_MAYSHARE)
flags = MAP_SHARED;
else
flags = MAP_PRIVATE;

if (vma->vm_flags & VM_DENYWRITE)
flags |= MAP_DENYWRITE;
if (vma->vm_flags & VM_MAYEXEC)
flags |= MAP_EXECUTABLE;
if (vma->vm_flags & VM_LOCKED)
flags |= MAP_LOCKED;
if (vma->vm_flags & VM_HUGETLB)
flags |= MAP_HUGETLB;

goto got_name;
} else {
name = (char *)arch_vma_name(vma);
Expand Down Expand Up @@ -5275,6 +5304,8 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
mmap_event->min = min;
mmap_event->ino = ino;
mmap_event->ino_generation = gen;
mmap_event->prot = prot;
mmap_event->flags = flags;

if (!(vma->vm_flags & VM_EXEC))
mmap_event->event_id.header.misc |= PERF_RECORD_MISC_MMAP_DATA;
Expand Down Expand Up @@ -5315,6 +5346,8 @@ void perf_event_mmap(struct vm_area_struct *vma)
/* .min (attr_mmap2 only) */
/* .ino (attr_mmap2 only) */
/* .ino_generation (attr_mmap2 only) */
/* .prot (attr_mmap2 only) */
/* .flags (attr_mmap2 only) */
};

perf_event_mmap_event(&mmap_event);
Expand Down Expand Up @@ -6897,10 +6930,6 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr,
if (ret)
return -EFAULT;

/* disabled for now */
if (attr->mmap2)
return -EINVAL;

if (attr->__reserved_1)
return -EINVAL;

Expand Down
113 changes: 113 additions & 0 deletions tools/lib/traceevent/event-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,9 @@ static void free_arg(struct print_arg *arg)
case PRINT_BSTRING:
free(arg->string.string);
break;
case PRINT_BITMASK:
free(arg->bitmask.bitmask);
break;
case PRINT_DYNAMIC_ARRAY:
free(arg->dynarray.index);
break;
Expand Down Expand Up @@ -2268,6 +2271,7 @@ static int arg_num_eval(struct print_arg *arg, long long *val)
case PRINT_FIELD ... PRINT_SYMBOL:
case PRINT_STRING:
case PRINT_BSTRING:
case PRINT_BITMASK:
default:
do_warning("invalid eval type %d", arg->type);
ret = 0;
Expand Down Expand Up @@ -2296,6 +2300,7 @@ static char *arg_eval (struct print_arg *arg)
case PRINT_FIELD ... PRINT_SYMBOL:
case PRINT_STRING:
case PRINT_BSTRING:
case PRINT_BITMASK:
default:
do_warning("invalid eval type %d", arg->type);
break;
Expand Down Expand Up @@ -2683,6 +2688,35 @@ process_str(struct event_format *event __maybe_unused, struct print_arg *arg,
return EVENT_ERROR;
}

static enum event_type
process_bitmask(struct event_format *event __maybe_unused, struct print_arg *arg,
char **tok)
{
enum event_type type;
char *token;

if (read_expect_type(EVENT_ITEM, &token) < 0)
goto out_free;

arg->type = PRINT_BITMASK;
arg->bitmask.bitmask = token;
arg->bitmask.offset = -1;

if (read_expected(EVENT_DELIM, ")") < 0)
goto out_err;

type = read_token(&token);
*tok = token;

return type;

out_free:
free_token(token);
out_err:
*tok = NULL;
return EVENT_ERROR;
}

static struct pevent_function_handler *
find_func_handler(struct pevent *pevent, char *func_name)
{
Expand Down Expand Up @@ -2797,6 +2831,10 @@ process_function(struct event_format *event, struct print_arg *arg,
free_token(token);
return process_str(event, arg, tok);
}
if (strcmp(token, "__get_bitmask") == 0) {
free_token(token);
return process_bitmask(event, arg, tok);
}
if (strcmp(token, "__get_dynamic_array") == 0) {
free_token(token);
return process_dynamic_array(event, arg, tok);
Expand Down Expand Up @@ -3324,6 +3362,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
return eval_type(val, arg, 0);
case PRINT_STRING:
case PRINT_BSTRING:
case PRINT_BITMASK:
return 0;
case PRINT_FUNC: {
struct trace_seq s;
Expand Down Expand Up @@ -3556,6 +3595,60 @@ static void print_str_to_seq(struct trace_seq *s, const char *format,
trace_seq_printf(s, format, str);
}

static void print_bitmask_to_seq(struct pevent *pevent,
struct trace_seq *s, const char *format,
int len_arg, const void *data, int size)
{
int nr_bits = size * 8;
int str_size = (nr_bits + 3) / 4;
int len = 0;
char buf[3];
char *str;
int index;
int i;

/*
* The kernel likes to put in commas every 32 bits, we
* can do the same.
*/
str_size += (nr_bits - 1) / 32;

str = malloc(str_size + 1);
if (!str) {
do_warning("%s: not enough memory!", __func__);
return;
}
str[str_size] = 0;

/* Start out with -2 for the two chars per byte */
for (i = str_size - 2; i >= 0; i -= 2) {
/*
* data points to a bit mask of size bytes.
* In the kernel, this is an array of long words, thus
* endianess is very important.
*/
if (pevent->file_bigendian)
index = size - (len + 1);
else
index = len;

snprintf(buf, 3, "%02x", *((unsigned char *)data + index));
memcpy(str + i, buf, 2);
len++;
if (!(len & 3) && i > 0) {
i--;
str[i] = ',';
}
}

if (len_arg >= 0)
trace_seq_printf(s, format, len_arg, str);
else
trace_seq_printf(s, format, str);

free(str);
}

static void print_str_arg(struct trace_seq *s, void *data, int size,
struct event_format *event, const char *format,
int len_arg, struct print_arg *arg)
Expand Down Expand Up @@ -3691,6 +3784,23 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
case PRINT_BSTRING:
print_str_to_seq(s, format, len_arg, arg->string.string);
break;
case PRINT_BITMASK: {
int bitmask_offset;
int bitmask_size;

if (arg->bitmask.offset == -1) {
struct format_field *f;

f = pevent_find_any_field(event, arg->bitmask.bitmask);
arg->bitmask.offset = f->offset;
}
bitmask_offset = data2host4(pevent, data + arg->bitmask.offset);
bitmask_size = bitmask_offset >> 16;
bitmask_offset &= 0xffff;
print_bitmask_to_seq(pevent, s, format, len_arg,
data + bitmask_offset, bitmask_size);
break;
}
case PRINT_OP:
/*
* The only op for string should be ? :
Expand Down Expand Up @@ -4822,6 +4932,9 @@ static void print_args(struct print_arg *args)
case PRINT_BSTRING:
printf("__get_str(%s)", args->string.string);
break;
case PRINT_BITMASK:
printf("__get_bitmask(%s)", args->bitmask.bitmask);
break;
case PRINT_TYPE:
printf("(%s)", args->typecast.type);
print_args(args->typecast.item);
Expand Down
25 changes: 22 additions & 3 deletions tools/lib/traceevent/event-parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ typedef int (*pevent_event_handler_func)(struct trace_seq *s,
typedef int (*pevent_plugin_load_func)(struct pevent *pevent);
typedef int (*pevent_plugin_unload_func)(struct pevent *pevent);

struct plugin_option {
struct plugin_option *next;
struct pevent_plugin_option {
struct pevent_plugin_option *next;
void *handle;
char *file;
char *name;
Expand All @@ -135,7 +135,7 @@ struct plugin_option {
* PEVENT_PLUGIN_OPTIONS: (optional)
* Plugin options that can be set before loading
*
* struct plugin_option PEVENT_PLUGIN_OPTIONS[] = {
* struct pevent_plugin_option PEVENT_PLUGIN_OPTIONS[] = {
* {
* .name = "option-name",
* .plugin_alias = "overide-file-name", (optional)
Expand Down Expand Up @@ -208,6 +208,11 @@ struct print_arg_string {
int offset;
};

struct print_arg_bitmask {
char *bitmask;
int offset;
};

struct print_arg_field {
char *name;
struct format_field *field;
Expand Down Expand Up @@ -274,6 +279,7 @@ enum print_arg_type {
PRINT_DYNAMIC_ARRAY,
PRINT_OP,
PRINT_FUNC,
PRINT_BITMASK,
};

struct print_arg {
Expand All @@ -288,6 +294,7 @@ struct print_arg {
struct print_arg_hex hex;
struct print_arg_func func;
struct print_arg_string string;
struct print_arg_bitmask bitmask;
struct print_arg_op op;
struct print_arg_dynarray dynarray;
};
Expand Down Expand Up @@ -354,6 +361,8 @@ enum pevent_func_arg_type {

enum pevent_flag {
PEVENT_NSEC_OUTPUT = 1, /* output in NSECS */
PEVENT_DISABLE_SYS_PLUGINS = 1 << 1,
PEVENT_DISABLE_PLUGINS = 1 << 2,
};

#define PEVENT_ERRORS \
Expand Down Expand Up @@ -410,9 +419,19 @@ enum pevent_errno {

struct plugin_list;

#define INVALID_PLUGIN_LIST_OPTION ((char **)((unsigned long)-1))

struct plugin_list *traceevent_load_plugins(struct pevent *pevent);
void traceevent_unload_plugins(struct plugin_list *plugin_list,
struct pevent *pevent);
char **traceevent_plugin_list_options(void);
void traceevent_plugin_free_options_list(char **list);
int traceevent_plugin_add_options(const char *name,
struct pevent_plugin_option *options);
void traceevent_plugin_remove_options(struct pevent_plugin_option *options);
void traceevent_print_plugins(struct trace_seq *s,
const char *prefix, const char *suffix,
const struct plugin_list *list);

struct cmdline;
struct cmdline_list;
Expand Down
Loading

0 comments on commit cf23091

Please sign in to comment.