Skip to content

Commit

Permalink
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/…
Browse files Browse the repository at this point in the history
…linux/kernel/git/tip/tip

Pull perf fixes from Ingo Molnar:
 "This is larger than usual: the main reason are the ARM symbol lookup
  speedups that came in late and were hard to resist.

  There's also a kprobes fix and various tooling fixes, plus the minimal
  re-enablement of the mmap2 support interface"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (36 commits)
  x86/kprobes: Fix build errors and blacklist context_track_user
  perf tests: Add test for closing dso objects on EMFILE error
  perf tests: Add test for caching dso file descriptors
  perf tests: Allow reuse of test_file function
  perf tests: Spawn child for each test
  perf tools: Add dso__data_* interface descriptons
  perf tools: Allow to close dso fd in case of open failure
  perf tools: Add file size check and factor dso__data_read_offset
  perf tools: Cache dso data file descriptor
  perf tools: Add global count of opened dso objects
  perf tools: Add global list of opened dso objects
  perf tools: Add data_fd into dso object
  perf tools: Separate dso data related variables
  perf tools: Cache register accesses for unwind processing
  perf record: Fix to honor user freq/interval properly
  perf timechart: Reflow documentation
  perf probe: Improve error messages in --line option
  perf probe: Improve an error message of perf probe --vars mode
  perf probe: Show error code and description in verbose mode
  perf probe: Improve error message for unknown member of data structure
  ...
  • Loading branch information
Linus Torvalds committed Jun 21, 2014
2 parents 7b08d61 + cf23091 commit 401c58f
Show file tree
Hide file tree
Showing 41 changed files with 1,249 additions and 126 deletions.
7 changes: 4 additions & 3 deletions arch/x86/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code)
if (poke_int3_handler(regs))
return;

prev_state = exception_enter();
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
SIGTRAP) == NOTIFY_STOP)
Expand All @@ -351,9 +352,8 @@ dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code)

#ifdef CONFIG_KPROBES
if (kprobe_int3_handler(regs))
return;
goto exit;
#endif
prev_state = exception_enter();

if (notify_die(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
SIGTRAP) == NOTIFY_STOP)
Expand Down Expand Up @@ -433,6 +433,8 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code)
unsigned long dr6;
int si_code;

prev_state = exception_enter();

get_debugreg(dr6, 6);

/* Filter out all the reserved bits which are preset to 1 */
Expand Down Expand Up @@ -465,7 +467,6 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code)
if (kprobe_debug_handler(regs))
goto exit;
#endif
prev_state = exception_enter();

if (notify_die(DIE_DEBUG, "debug", regs, (long)&dr6, error_code,
SIGTRAP) == NOTIFY_STOP)
Expand Down
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
3 changes: 3 additions & 0 deletions kernel/context_tracking.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/sched.h>
#include <linux/hardirq.h>
#include <linux/export.h>
#include <linux/kprobes.h>

#define CREATE_TRACE_POINTS
#include <trace/events/context_tracking.h>
Expand Down Expand Up @@ -104,6 +105,7 @@ void context_tracking_user_enter(void)
}
local_irq_restore(flags);
}
NOKPROBE_SYMBOL(context_tracking_user_enter);

#ifdef CONFIG_PREEMPT
/**
Expand Down Expand Up @@ -181,6 +183,7 @@ void context_tracking_user_exit(void)
}
local_irq_restore(flags);
}
NOKPROBE_SYMBOL(context_tracking_user_exit);

/**
* __context_tracking_task_switch - context switch the syscall callbacks
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
Loading

0 comments on commit 401c58f

Please sign in to comment.