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

Changed files
+48 -19
arch
x86
events
include
linux
kernel
events
+7 -9
arch/x86/events/core.c
··· 2114 2114 load_mm_cr4(this_cpu_read(cpu_tlbstate.loaded_mm)); 2115 2115 } 2116 2116 2117 - static void x86_pmu_event_mapped(struct perf_event *event) 2117 + static void x86_pmu_event_mapped(struct perf_event *event, struct mm_struct *mm) 2118 2118 { 2119 2119 if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED)) 2120 2120 return; ··· 2129 2129 * For now, this can't happen because all callers hold mmap_sem 2130 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) 2135 - on_each_cpu_mask(mm_cpumask(current->mm), refresh_pce, NULL, 1); 2134 + if (atomic_inc_return(&mm->context.perf_rdpmc_allowed) == 1) 2135 + on_each_cpu_mask(mm_cpumask(mm), refresh_pce, NULL, 1); 2136 2136 } 2137 2137 2138 - static void x86_pmu_event_unmapped(struct perf_event *event) 2138 + static void x86_pmu_event_unmapped(struct perf_event *event, struct mm_struct *mm) 2139 2139 { 2140 - if (!current->mm) 2141 - return; 2142 2140 2143 2141 if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED)) 2144 2142 return; 2145 2143 2146 - if (atomic_dec_and_test(&current->mm->context.perf_rdpmc_allowed)) 2147 - on_each_cpu_mask(mm_cpumask(current->mm), refresh_pce, NULL, 1); 2144 + if (atomic_dec_and_test(&mm->context.perf_rdpmc_allowed)) 2145 + on_each_cpu_mask(mm_cpumask(mm), refresh_pce, NULL, 1); 2148 2146 } 2149 2147 2150 2148 static int x86_pmu_event_idx(struct perf_event *event)
+2 -2
include/linux/perf_event.h
··· 310 310 * Notification that the event was mapped or unmapped. Called 311 311 * in the context of the mapping task. 312 312 */ 313 - void (*event_mapped) (struct perf_event *event); /*optional*/ 314 - void (*event_unmapped) (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, struct mm_struct *mm); /* optional */ 315 315 316 316 /* 317 317 * Flags for ->add()/->del()/ ->start()/->stop(). There are
+39 -8
kernel/events/core.c
··· 2217 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 + */ 2238 + static 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 + 2220 2247 static void add_event_to_ctx(struct perf_event *event, 2221 2248 struct perf_event_context *ctx) 2222 2249 { ··· 2251 2224 2252 2225 list_add_event(event, ctx); 2253 2226 perf_group_attach(event); 2254 - event->tstamp_enabled = tstamp; 2255 - event->tstamp_running = tstamp; 2256 - event->tstamp_stopped = tstamp; 2227 + /* 2228 + * We can be called with event->state == STATE_OFF when we create with 2229 + * .disabled = 1. In that case the IOC_ENABLE will call this function. 2230 + */ 2231 + if (event->state == PERF_EVENT_STATE_INACTIVE) 2232 + __perf_event_enable_time(event, tstamp); 2257 2233 } 2258 2234 2259 2235 static void ctx_sched_out(struct perf_event_context *ctx, ··· 2501 2471 u64 tstamp = perf_event_time(event); 2502 2472 2503 2473 event->state = PERF_EVENT_STATE_INACTIVE; 2504 - event->tstamp_enabled = tstamp - event->total_time_enabled; 2474 + __perf_event_enable_time(event, tstamp); 2505 2475 list_for_each_entry(sub, &event->sibling_list, group_entry) { 2476 + /* XXX should not be > INACTIVE if event isn't */ 2506 2477 if (sub->state >= PERF_EVENT_STATE_INACTIVE) 2507 - sub->tstamp_enabled = tstamp - sub->total_time_enabled; 2478 + __perf_event_enable_time(sub, tstamp); 2508 2479 } 2509 2480 } 2510 2481 ··· 5121 5090 atomic_inc(&event->rb->aux_mmap_count); 5122 5091 5123 5092 if (event->pmu->event_mapped) 5124 - event->pmu->event_mapped(event); 5093 + event->pmu->event_mapped(event, vma->vm_mm); 5125 5094 } 5126 5095 5127 5096 static void perf_pmu_output_stop(struct perf_event *event); ··· 5144 5113 unsigned long size = perf_data_size(rb); 5145 5114 5146 5115 if (event->pmu->event_unmapped) 5147 - event->pmu->event_unmapped(event); 5116 + event->pmu->event_unmapped(event, vma->vm_mm); 5148 5117 5149 5118 /* 5150 5119 * rb->aux_mmap_count will always drop before rb->mmap_count and ··· 5442 5411 vma->vm_ops = &perf_mmap_vmops; 5443 5412 5444 5413 if (event->pmu->event_mapped) 5445 - event->pmu->event_mapped(event); 5414 + event->pmu->event_mapped(event, vma->vm_mm); 5446 5415 5447 5416 return ret; 5448 5417 }