Commit 6313e3c2 authored by Linus Torvalds's avatar Linus Torvalds

Merge branches 'x86-fixes-for-linus', 'perf-fixes-for-linus' and...

Merge branches 'x86-fixes-for-linus', 'perf-fixes-for-linus' and 'sched-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  x86/pvclock: Zero last_value on resume

* 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  perf record: Fix eternal wait for stillborn child
  perf header: Don't assume there's no attr info if no sample ids is provided
  perf symbols: Figure out start address of kernel map from kallsyms
  perf symbols: Fix kallsyms kernel/module map splitting

* 'sched-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  nohz: Fix printk_needs_cpu() return value on offline cpus
  printk: Fix wake_up_klogd() vs cpu hotplug
...@@ -11,6 +11,7 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src); ...@@ -11,6 +11,7 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src);
void pvclock_read_wallclock(struct pvclock_wall_clock *wall, void pvclock_read_wallclock(struct pvclock_wall_clock *wall,
struct pvclock_vcpu_time_info *vcpu, struct pvclock_vcpu_time_info *vcpu,
struct timespec *ts); struct timespec *ts);
void pvclock_resume(void);
/* /*
* Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction, * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
......
...@@ -83,6 +83,11 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src) ...@@ -83,6 +83,11 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src)
static atomic64_t last_value = ATOMIC64_INIT(0); static atomic64_t last_value = ATOMIC64_INIT(0);
void pvclock_resume(void)
{
atomic64_set(&last_value, 0);
}
cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src) cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src)
{ {
struct pvclock_shadow_time shadow; struct pvclock_shadow_time shadow;
......
...@@ -426,6 +426,8 @@ void xen_timer_resume(void) ...@@ -426,6 +426,8 @@ void xen_timer_resume(void)
{ {
int cpu; int cpu;
pvclock_resume();
if (xen_clockevent != &xen_vcpuop_clockevent) if (xen_clockevent != &xen_vcpuop_clockevent)
return; return;
......
...@@ -1082,13 +1082,15 @@ void printk_tick(void) ...@@ -1082,13 +1082,15 @@ void printk_tick(void)
int printk_needs_cpu(int cpu) int printk_needs_cpu(int cpu)
{ {
if (unlikely(cpu_is_offline(cpu)))
printk_tick();
return per_cpu(printk_pending, cpu); return per_cpu(printk_pending, cpu);
} }
void wake_up_klogd(void) void wake_up_klogd(void)
{ {
if (waitqueue_active(&log_wait)) if (waitqueue_active(&log_wait))
__raw_get_cpu_var(printk_pending) = 1; this_cpu_write(printk_pending, 1);
} }
/** /**
......
...@@ -197,7 +197,7 @@ static void sig_atexit(void) ...@@ -197,7 +197,7 @@ static void sig_atexit(void)
if (child_pid > 0) if (child_pid > 0)
kill(child_pid, SIGTERM); kill(child_pid, SIGTERM);
if (signr == -1) if (signr == -1 || signr == SIGUSR1)
return; return;
signal(signr, SIG_DFL); signal(signr, SIG_DFL);
...@@ -515,6 +515,7 @@ static int __cmd_record(int argc, const char **argv) ...@@ -515,6 +515,7 @@ static int __cmd_record(int argc, const char **argv)
atexit(sig_atexit); atexit(sig_atexit);
signal(SIGCHLD, sig_handler); signal(SIGCHLD, sig_handler);
signal(SIGINT, sig_handler); signal(SIGINT, sig_handler);
signal(SIGUSR1, sig_handler);
if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
perror("failed to create pipes"); perror("failed to create pipes");
...@@ -606,6 +607,7 @@ static int __cmd_record(int argc, const char **argv) ...@@ -606,6 +607,7 @@ static int __cmd_record(int argc, const char **argv)
execvp(argv[0], (char **)argv); execvp(argv[0], (char **)argv);
perror(argv[0]); perror(argv[0]);
kill(getppid(), SIGUSR1);
exit(-1); exit(-1);
} }
...@@ -762,7 +764,7 @@ static int __cmd_record(int argc, const char **argv) ...@@ -762,7 +764,7 @@ static int __cmd_record(int argc, const char **argv)
} }
} }
if (quiet) if (quiet || signr == SIGUSR1)
return 0; return 0;
fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
......
...@@ -946,11 +946,16 @@ perf_header__find_attr(u64 id, struct perf_header *header) ...@@ -946,11 +946,16 @@ perf_header__find_attr(u64 id, struct perf_header *header)
/* /*
* We set id to -1 if the data file doesn't contain sample * We set id to -1 if the data file doesn't contain sample
* ids. Check for this and avoid walking through the entire * ids. This can happen when the data file contains one type
* list of ids which may be large. * of event and in that case, the header can still store the
* event attribute information. Check for this and avoid
* walking through the entire list of ids which may be large.
*/ */
if (id == -1ULL) if (id == -1ULL) {
if (header->attrs > 0)
return &header->attr[0]->attr;
return NULL; return NULL;
}
for (i = 0; i < header->attrs; i++) { for (i = 0; i < header->attrs; i++) {
struct perf_header_attr *attr = header->attr[i]; struct perf_header_attr *attr = header->attr[i];
......
...@@ -532,7 +532,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, ...@@ -532,7 +532,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
struct machine *machine = kmaps->machine; struct machine *machine = kmaps->machine;
struct map *curr_map = map; struct map *curr_map = map;
struct symbol *pos; struct symbol *pos;
int count = 0; int count = 0, moved = 0;
struct rb_root *root = &self->symbols[map->type]; struct rb_root *root = &self->symbols[map->type];
struct rb_node *next = rb_first(root); struct rb_node *next = rb_first(root);
int kernel_range = 0; int kernel_range = 0;
...@@ -590,6 +590,11 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, ...@@ -590,6 +590,11 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
char dso_name[PATH_MAX]; char dso_name[PATH_MAX];
struct dso *dso; struct dso *dso;
if (count == 0) {
curr_map = map;
goto filter_symbol;
}
if (self->kernel == DSO_TYPE_GUEST_KERNEL) if (self->kernel == DSO_TYPE_GUEST_KERNEL)
snprintf(dso_name, sizeof(dso_name), snprintf(dso_name, sizeof(dso_name),
"[guest.kernel].%d", "[guest.kernel].%d",
...@@ -615,7 +620,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, ...@@ -615,7 +620,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
map_groups__insert(kmaps, curr_map); map_groups__insert(kmaps, curr_map);
++kernel_range; ++kernel_range;
} }
filter_symbol:
if (filter && filter(curr_map, pos)) { if (filter && filter(curr_map, pos)) {
discard_symbol: rb_erase(&pos->rb_node, root); discard_symbol: rb_erase(&pos->rb_node, root);
symbol__delete(pos); symbol__delete(pos);
...@@ -623,8 +628,9 @@ discard_symbol: rb_erase(&pos->rb_node, root); ...@@ -623,8 +628,9 @@ discard_symbol: rb_erase(&pos->rb_node, root);
if (curr_map != map) { if (curr_map != map) {
rb_erase(&pos->rb_node, root); rb_erase(&pos->rb_node, root);
symbols__insert(&curr_map->dso->symbols[curr_map->type], pos); symbols__insert(&curr_map->dso->symbols[curr_map->type], pos);
} ++moved;
count++; } else
++count;
} }
} }
...@@ -634,7 +640,7 @@ discard_symbol: rb_erase(&pos->rb_node, root); ...@@ -634,7 +640,7 @@ discard_symbol: rb_erase(&pos->rb_node, root);
dso__set_loaded(curr_map->dso, curr_map->type); dso__set_loaded(curr_map->dso, curr_map->type);
} }
return count; return count + moved;
} }
int dso__load_kallsyms(struct dso *self, const char *filename, int dso__load_kallsyms(struct dso *self, const char *filename,
...@@ -2125,14 +2131,55 @@ static struct dso *machine__create_kernel(struct machine *self) ...@@ -2125,14 +2131,55 @@ static struct dso *machine__create_kernel(struct machine *self)
return kernel; return kernel;
} }
struct process_args {
u64 start;
};
static int symbol__in_kernel(void *arg, const char *name,
char type __used, u64 start)
{
struct process_args *args = arg;
if (strchr(name, '['))
return 0;
args->start = start;
return 1;
}
/* Figure out the start address of kernel map from /proc/kallsyms */
static u64 machine__get_kernel_start_addr(struct machine *machine)
{
const char *filename;
char path[PATH_MAX];
struct process_args args;
if (machine__is_host(machine)) {
filename = "/proc/kallsyms";
} else {
if (machine__is_default_guest(machine))
filename = (char *)symbol_conf.default_guest_kallsyms;
else {
sprintf(path, "%s/proc/kallsyms", machine->root_dir);
filename = path;
}
}
if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0)
return 0;
return args.start;
}
int __machine__create_kernel_maps(struct machine *self, struct dso *kernel) int __machine__create_kernel_maps(struct machine *self, struct dso *kernel)
{ {
enum map_type type; enum map_type type;
u64 start = machine__get_kernel_start_addr(self);
for (type = 0; type < MAP__NR_TYPES; ++type) { for (type = 0; type < MAP__NR_TYPES; ++type) {
struct kmap *kmap; struct kmap *kmap;
self->vmlinux_maps[type] = map__new2(0, kernel, type); self->vmlinux_maps[type] = map__new2(start, kernel, type);
if (self->vmlinux_maps[type] == NULL) if (self->vmlinux_maps[type] == NULL)
return -1; return -1;
......
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