History

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf fixes from Thomas Gleixner: "Two fixes for the perf subsystem: - Fix an inconsistency of RDPMC mm struct tagging across exec() which causes RDPMC to fault. - Correct the timestamp mechanics across IOC_DISABLE/ENABLE which causes incorrect timestamps and total time calculations" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf/core: Fix time on IOC_ENABLE perf/x86: Fix RDPMC vs. mm_struct tracking

Linus Torvalds committed 9 years ago

Commit e46db8d2 parents 9dae41a 9b231d93 files · +48 −19Browse files

Unified · Split

3 files
  1. arch/x86/events/core.c +7 −9
  2. include/linux/perf_event.h +2 −2
  3. kernel/events/core.c +39 −8
arch/x86/events/core.c+7−9
@@ -2114,7 +2114,7 @@ static void refresh_pce(void *ignored) · 2113 unmodified lines
2114 load_mm_cr4(this_cpu_read(cpu_tlbstate.loaded_mm));2114 load_mm_cr4(this_cpu_read(cpu_tlbstate.loaded_mm));
2115}2115}
2116 2116
2117static void x86_pmu_event_mapped(struct perf_event *event)2117static void x86_pmu_event_mapped(struct perf_event *event, struct mm_struct *mm)
2118{2118{
2119 if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED))2119 if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED))
2120 return;2120 return;
@@ -2129,22 +2129,20 @@ static void x86_pmu_event_mapped(struct perf_event *event) · 8 unmodified lines
2129 * For now, this can't happen because all callers hold mmap_sem2129 * For now, this can't happen because all callers hold mmap_sem
2130 * for write. If this changes, we'll need a different solution.2130 * for write. If this changes, we'll need a different solution.
2131 */2131 */
2132 lockdep_assert_held_exclusive(&current->mm->mmap_sem);2132 lockdep_assert_held_exclusive(&mm->mmap_sem);
2133 2133
2134 if (atomic_inc_return(&current->mm->context.perf_rdpmc_allowed) == 1)2134 if (atomic_inc_return(&mm->context.perf_rdpmc_allowed) == 1)
2135 on_each_cpu_mask(mm_cpumask(current->mm), refresh_pce, NULL, 1);2135 on_each_cpu_mask(mm_cpumask(mm), refresh_pce, NULL, 1);
2136}2136}
2137 2137
2138static void x86_pmu_event_unmapped(struct perf_event *event)2138static void x86_pmu_event_unmapped(struct perf_event *event, struct mm_struct *mm)
2139{2139{
2140 if (!current->mm)
2141 return;
2142 2140
2143 if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED))2141 if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED))
2144 return;2142 return;
2145 2143
2146 if (atomic_dec_and_test(&current->mm->context.perf_rdpmc_allowed))2144 if (atomic_dec_and_test(&mm->context.perf_rdpmc_allowed))
2147 on_each_cpu_mask(mm_cpumask(current->mm), refresh_pce, NULL, 1);2145 on_each_cpu_mask(mm_cpumask(mm), refresh_pce, NULL, 1);
2148}2146}
2149 2147
2150static int x86_pmu_event_idx(struct perf_event *event)2148static int x86_pmu_event_idx(struct perf_event *event)
include/linux/perf_event.h+2−2
@@ -310,8 +310,8 @@ struct pmu { · 309 unmodified lines
310 * Notification that the event was mapped or unmapped. Called310 * Notification that the event was mapped or unmapped. Called
311 * in the context of the mapping task.311 * in the context of the mapping task.
312 */312 */
313 void (*event_mapped) (struct perf_event *event); /*optional*/313 void (*event_mapped) (struct perf_event *event, struct mm_struct *mm); /* optional */
314 void (*event_unmapped) (struct perf_event *event); /*optional*/314 void (*event_unmapped) (struct perf_event *event, struct mm_struct *mm); /* optional */
315 315
316 /*316 /*
317 * Flags for ->add()/->del()/ ->start()/->stop(). There are317 * Flags for ->add()/->del()/ ->start()/->stop(). There are
kernel/events/core.c+39−8
@@ -2217,6 +2217,33 @@ static int group_can_go_on(struct perf_event *event, · 2216 unmodified lines
2217 return can_add_hw;2217 return can_add_hw;
2218}2218}
2219 2219
2220/*
2221 * Complement to update_event_times(). This computes the tstamp_* values to
2222 * continue 'enabled' state from @now, and effectively discards the time
2223 * between the prior tstamp_stopped and now (as we were in the OFF state, or
2224 * just switched (context) time base).
2225 *
2226 * This further assumes '@event->state == INACTIVE' (we just came from OFF) and
2227 * cannot have been scheduled in yet. And going into INACTIVE state means
2228 * '@event->tstamp_stopped = @now'.
2229 *
2230 * Thus given the rules of update_event_times():
2231 *
2232 * total_time_enabled = tstamp_stopped - tstamp_enabled
2233 * total_time_running = tstamp_stopped - tstamp_running
2234 *
2235 * We can insert 'tstamp_stopped == now' and reverse them to compute new
2236 * tstamp_* values.
2237 */
2238static void __perf_event_enable_time(struct perf_event *event, u64 now)
2239{
2240 WARN_ON_ONCE(event->state != PERF_EVENT_STATE_INACTIVE);
2241
2242 event->tstamp_stopped = now;
2243 event->tstamp_enabled = now - event->total_time_enabled;
2244 event->tstamp_running = now - event->total_time_running;
2245}
2246
2220static void add_event_to_ctx(struct perf_event *event,2247static void add_event_to_ctx(struct perf_event *event,
2221 struct perf_event_context *ctx)2248 struct perf_event_context *ctx)
2222{2249{
@@ -2224,9 +2251,12 @@ static void add_event_to_ctx(struct perf_event *event, · 1 unmodified line
2224 2251
2225 list_add_event(event, ctx);2252 list_add_event(event, ctx);
2226 perf_group_attach(event);2253 perf_group_attach(event);
2227 event->tstamp_enabled = tstamp;2254 /*
2228 event->tstamp_running = tstamp;2255 * We can be called with event->state == STATE_OFF when we create with
2229 event->tstamp_stopped = tstamp;2256 * .disabled = 1. In that case the IOC_ENABLE will call this function.
2257 */
2258 if (event->state == PERF_EVENT_STATE_INACTIVE)
2259 __perf_event_enable_time(event, tstamp);
2230}2260}
2231 2261
2232static void ctx_sched_out(struct perf_event_context *ctx,2262static void ctx_sched_out(struct perf_event_context *ctx,
@@ -2471,10 +2501,11 @@ static void __perf_event_mark_enabled(struct perf_event *event) · 238 unmodified lines
2471 u64 tstamp = perf_event_time(event);2501 u64 tstamp = perf_event_time(event);
2472 2502
2473 event->state = PERF_EVENT_STATE_INACTIVE;2503 event->state = PERF_EVENT_STATE_INACTIVE;
2474 event->tstamp_enabled = tstamp - event->total_time_enabled;2504 __perf_event_enable_time(event, tstamp);
2475 list_for_each_entry(sub, &event->sibling_list, group_entry) {2505 list_for_each_entry(sub, &event->sibling_list, group_entry) {
2506 /* XXX should not be > INACTIVE if event isn't */
2476 if (sub->state >= PERF_EVENT_STATE_INACTIVE)2507 if (sub->state >= PERF_EVENT_STATE_INACTIVE)
2477 sub->tstamp_enabled = tstamp - sub->total_time_enabled;2508 __perf_event_enable_time(sub, tstamp);
2478 }2509 }
2479}2510}
2480 2511
@@ -5090,7 +5121,7 @@ static void perf_mmap_open(struct vm_area_struct *vma) · 2609 unmodified lines
5090 atomic_inc(&event->rb->aux_mmap_count);5121 atomic_inc(&event->rb->aux_mmap_count);
5091 5122
5092 if (event->pmu->event_mapped)5123 if (event->pmu->event_mapped)
5093 event->pmu->event_mapped(event);5124 event->pmu->event_mapped(event, vma->vm_mm);
5094}5125}
5095 5126
5096static void perf_pmu_output_stop(struct perf_event *event);5127static void perf_pmu_output_stop(struct perf_event *event);
@@ -5113,7 +5144,7 @@ static void perf_mmap_close(struct vm_area_struct *vma) · 16 unmodified lines
5113 unsigned long size = perf_data_size(rb);5144 unsigned long size = perf_data_size(rb);
5114 5145
5115 if (event->pmu->event_unmapped)5146 if (event->pmu->event_unmapped)
5116 event->pmu->event_unmapped(event);5147 event->pmu->event_unmapped(event, vma->vm_mm);
5117 5148
5118 /*5149 /*
5119 * rb->aux_mmap_count will always drop before rb->mmap_count and5150 * rb->aux_mmap_count will always drop before rb->mmap_count and
@@ -5411,7 +5442,7 @@ aux_unlock: · 291 unmodified lines
5411 vma->vm_ops = &perf_mmap_vmops;5442 vma->vm_ops = &perf_mmap_vmops;
5412 5443
5413 if (event->pmu->event_mapped)5444 if (event->pmu->event_mapped)
5414 event->pmu->event_mapped(event);5445 event->pmu->event_mapped(event, vma->vm_mm);
5415 5446
5416 return ret;5447 return ret;
5417}5448}