Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

* 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
perf: Fix the software context switch counter
perf, x86: Fixup Kconfig deps
x86, perf, nmi: Disable perf if counters are not accessible
perf: Fix inherit vs. context rotation bug

+57 -19
+1 -1
arch/x86/Kconfig
··· 21 21 select HAVE_UNSTABLE_SCHED_CLOCK 22 22 select HAVE_IDE 23 23 select HAVE_OPROFILE 24 - select HAVE_PERF_EVENTS if (!M386 && !M486) 24 + select HAVE_PERF_EVENTS 25 25 select HAVE_IRQ_WORK 26 26 select HAVE_IOREMAP_PROT 27 27 select HAVE_KPROBES
+20
arch/x86/kernel/cpu/perf_event.c
··· 381 381 382 382 #endif 383 383 384 + static bool check_hw_exists(void) 385 + { 386 + u64 val, val_new = 0; 387 + int ret = 0; 388 + 389 + val = 0xabcdUL; 390 + ret |= checking_wrmsrl(x86_pmu.perfctr, val); 391 + ret |= rdmsrl_safe(x86_pmu.perfctr, &val_new); 392 + if (ret || val != val_new) 393 + return false; 394 + 395 + return true; 396 + } 397 + 384 398 static void reserve_ds_buffers(void); 385 399 static void release_ds_buffers(void); 386 400 ··· 1385 1371 } 1386 1372 1387 1373 pmu_check_apic(); 1374 + 1375 + /* sanity check that the hardware exists or is emulated */ 1376 + if (!check_hw_exists()) { 1377 + pr_cont("Broken PMU hardware detected, software events only.\n"); 1378 + return; 1379 + } 1388 1380 1389 1381 pr_cont("%s PMU driver.\n", x86_pmu.name); 1390 1382
+16 -14
include/linux/perf_event.h
··· 850 850 int nr_active; 851 851 int is_active; 852 852 int nr_stat; 853 + int rotate_disable; 853 854 atomic_t refcount; 854 855 struct task_struct *task; 855 856 ··· 909 908 extern const char *perf_pmu_name(void); 910 909 extern void __perf_event_task_sched_in(struct task_struct *task); 911 910 extern void __perf_event_task_sched_out(struct task_struct *task, struct task_struct *next); 912 - 913 - extern atomic_t perf_task_events; 914 - 915 - static inline void perf_event_task_sched_in(struct task_struct *task) 916 - { 917 - COND_STMT(&perf_task_events, __perf_event_task_sched_in(task)); 918 - } 919 - 920 - static inline 921 - void perf_event_task_sched_out(struct task_struct *task, struct task_struct *next) 922 - { 923 - COND_STMT(&perf_task_events, __perf_event_task_sched_out(task, next)); 924 - } 925 - 926 911 extern int perf_event_init_task(struct task_struct *child); 927 912 extern void perf_event_exit_task(struct task_struct *child); 928 913 extern void perf_event_free_task(struct task_struct *task); ··· 1015 1028 regs = &hot_regs; 1016 1029 } 1017 1030 __perf_sw_event(event_id, nr, nmi, regs, addr); 1031 + } 1032 + 1033 + extern atomic_t perf_task_events; 1034 + 1035 + static inline void perf_event_task_sched_in(struct task_struct *task) 1036 + { 1037 + COND_STMT(&perf_task_events, __perf_event_task_sched_in(task)); 1038 + } 1039 + 1040 + static inline 1041 + void perf_event_task_sched_out(struct task_struct *task, struct task_struct *next) 1042 + { 1043 + perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0); 1044 + 1045 + COND_STMT(&perf_task_events, __perf_event_task_sched_out(task, next)); 1018 1046 } 1019 1047 1020 1048 extern void perf_event_mmap(struct vm_area_struct *vma);
+20 -4
kernel/perf_event.c
··· 1287 1287 { 1288 1288 int ctxn; 1289 1289 1290 - perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0); 1291 - 1292 1290 for_each_task_context_nr(ctxn) 1293 1291 perf_event_context_sched_out(task, ctxn, next); 1294 1292 } ··· 1620 1622 { 1621 1623 raw_spin_lock(&ctx->lock); 1622 1624 1623 - /* Rotate the first entry last of non-pinned groups */ 1624 - list_rotate_left(&ctx->flexible_groups); 1625 + /* 1626 + * Rotate the first entry last of non-pinned groups. Rotation might be 1627 + * disabled by the inheritance code. 1628 + */ 1629 + if (!ctx->rotate_disable) 1630 + list_rotate_left(&ctx->flexible_groups); 1625 1631 1626 1632 raw_spin_unlock(&ctx->lock); 1627 1633 } ··· 6164 6162 struct perf_event *event; 6165 6163 struct task_struct *parent = current; 6166 6164 int inherited_all = 1; 6165 + unsigned long flags; 6167 6166 int ret = 0; 6168 6167 6169 6168 child->perf_event_ctxp[ctxn] = NULL; ··· 6205 6202 break; 6206 6203 } 6207 6204 6205 + /* 6206 + * We can't hold ctx->lock when iterating the ->flexible_group list due 6207 + * to allocations, but we need to prevent rotation because 6208 + * rotate_ctx() will change the list from interrupt context. 6209 + */ 6210 + raw_spin_lock_irqsave(&parent_ctx->lock, flags); 6211 + parent_ctx->rotate_disable = 1; 6212 + raw_spin_unlock_irqrestore(&parent_ctx->lock, flags); 6213 + 6208 6214 list_for_each_entry(event, &parent_ctx->flexible_groups, group_entry) { 6209 6215 ret = inherit_task_group(event, parent, parent_ctx, 6210 6216 child, ctxn, &inherited_all); 6211 6217 if (ret) 6212 6218 break; 6213 6219 } 6220 + 6221 + raw_spin_lock_irqsave(&parent_ctx->lock, flags); 6222 + parent_ctx->rotate_disable = 0; 6223 + raw_spin_unlock_irqrestore(&parent_ctx->lock, flags); 6214 6224 6215 6225 child_ctx = child->perf_event_ctxp[ctxn]; 6216 6226