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

Merge branch 'urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/rric/oprofile into perf/urgent

+80 -45
+23 -1
arch/powerpc/oprofile/op_model_power4.c
··· 261 261 return is_kernel; 262 262 } 263 263 264 + static bool pmc_overflow(unsigned long val) 265 + { 266 + if ((int)val < 0) 267 + return true; 268 + 269 + /* 270 + * Events on POWER7 can roll back if a speculative event doesn't 271 + * eventually complete. Unfortunately in some rare cases they will 272 + * raise a performance monitor exception. We need to catch this to 273 + * ensure we reset the PMC. In all cases the PMC will be 256 or less 274 + * cycles from overflow. 275 + * 276 + * We only do this if the first pass fails to find any overflowing 277 + * PMCs because a user might set a period of less than 256 and we 278 + * don't want to mistakenly reset them. 279 + */ 280 + if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256)) 281 + return true; 282 + 283 + return false; 284 + } 285 + 264 286 static void power4_handle_interrupt(struct pt_regs *regs, 265 287 struct op_counter_config *ctr) 266 288 { ··· 303 281 304 282 for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) { 305 283 val = classic_ctr_read(i); 306 - if (val < 0) { 284 + if (pmc_overflow(val)) { 307 285 if (oprofile_running && ctr[i].enabled) { 308 286 oprofile_add_ext_sample(pc, regs, i, is_kernel); 309 287 classic_ctr_write(i, reset_value[i]);
+55 -42
arch/x86/oprofile/op_model_amd.c
··· 316 316 wrmsrl(MSR_AMD64_IBSOPCTL, 0); 317 317 } 318 318 319 - static inline int eilvt_is_available(int offset) 319 + static inline int get_eilvt(int offset) 320 320 { 321 - /* check if we may assign a vector */ 322 321 return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1); 322 + } 323 + 324 + static inline int put_eilvt(int offset) 325 + { 326 + return !setup_APIC_eilvt(offset, 0, 0, 1); 323 327 } 324 328 325 329 static inline int ibs_eilvt_valid(void) 326 330 { 327 331 int offset; 328 332 u64 val; 333 + int valid = 0; 334 + 335 + preempt_disable(); 329 336 330 337 rdmsrl(MSR_AMD64_IBSCTL, val); 331 338 offset = val & IBSCTL_LVT_OFFSET_MASK; ··· 340 333 if (!(val & IBSCTL_LVT_OFFSET_VALID)) { 341 334 pr_err(FW_BUG "cpu %d, invalid IBS interrupt offset %d (MSR%08X=0x%016llx)\n", 342 335 smp_processor_id(), offset, MSR_AMD64_IBSCTL, val); 343 - return 0; 336 + goto out; 344 337 } 345 338 346 - if (!eilvt_is_available(offset)) { 339 + if (!get_eilvt(offset)) { 347 340 pr_err(FW_BUG "cpu %d, IBS interrupt offset %d not available (MSR%08X=0x%016llx)\n", 348 341 smp_processor_id(), offset, MSR_AMD64_IBSCTL, val); 349 - return 0; 342 + goto out; 350 343 } 351 344 352 - return 1; 345 + valid = 1; 346 + out: 347 + preempt_enable(); 348 + 349 + return valid; 353 350 } 354 351 355 352 static inline int get_ibs_offset(void) ··· 611 600 612 601 static int force_ibs_eilvt_setup(void) 613 602 { 614 - int i; 603 + int offset; 615 604 int ret; 616 605 617 - /* find the next free available EILVT entry */ 618 - for (i = 1; i < 4; i++) { 619 - if (!eilvt_is_available(i)) 620 - continue; 621 - ret = setup_ibs_ctl(i); 622 - if (ret) 623 - return ret; 624 - pr_err(FW_BUG "using offset %d for IBS interrupts\n", i); 625 - return 0; 606 + /* 607 + * find the next free available EILVT entry, skip offset 0, 608 + * pin search to this cpu 609 + */ 610 + preempt_disable(); 611 + for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) { 612 + if (get_eilvt(offset)) 613 + break; 614 + } 615 + preempt_enable(); 616 + 617 + if (offset == APIC_EILVT_NR_MAX) { 618 + printk(KERN_DEBUG "No EILVT entry available\n"); 619 + return -EBUSY; 626 620 } 627 621 628 - printk(KERN_DEBUG "No EILVT entry available\n"); 629 - 630 - return -EBUSY; 631 - } 632 - 633 - static int __init_ibs_nmi(void) 634 - { 635 - int ret; 636 - 637 - if (ibs_eilvt_valid()) 638 - return 0; 639 - 640 - ret = force_ibs_eilvt_setup(); 622 + ret = setup_ibs_ctl(offset); 641 623 if (ret) 642 - return ret; 624 + goto out; 643 625 644 - if (!ibs_eilvt_valid()) 645 - return -EFAULT; 626 + if (!ibs_eilvt_valid()) { 627 + ret = -EFAULT; 628 + goto out; 629 + } 646 630 631 + pr_err(FW_BUG "using offset %d for IBS interrupts\n", offset); 647 632 pr_err(FW_BUG "workaround enabled for IBS LVT offset\n"); 648 633 649 634 return 0; 635 + out: 636 + preempt_disable(); 637 + put_eilvt(offset); 638 + preempt_enable(); 639 + return ret; 650 640 } 651 641 652 642 /* 653 643 * check and reserve APIC extended interrupt LVT offset for IBS if 654 644 * available 655 - * 656 - * init_ibs() preforms implicitly cpu-local operations, so pin this 657 - * thread to its current CPU 658 645 */ 659 646 660 647 static void init_ibs(void) 661 648 { 662 - preempt_disable(); 663 - 664 649 ibs_caps = get_ibs_caps(); 650 + 665 651 if (!ibs_caps) 652 + return; 653 + 654 + if (ibs_eilvt_valid()) 666 655 goto out; 667 656 668 - if (__init_ibs_nmi() < 0) 669 - ibs_caps = 0; 670 - else 671 - printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps); 657 + if (!force_ibs_eilvt_setup()) 658 + goto out; 659 + 660 + /* Failed to setup ibs */ 661 + ibs_caps = 0; 662 + return; 672 663 673 664 out: 674 - preempt_enable(); 665 + printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps); 675 666 } 676 667 677 668 static int (*create_arch_files)(struct super_block *sb, struct dentry *root);
+1 -1
drivers/oprofile/event_buffer.h
··· 11 11 #define EVENT_BUFFER_H 12 12 13 13 #include <linux/types.h> 14 - #include <asm/mutex.h> 14 + #include <linux/mutex.h> 15 15 16 16 int alloc_event_buffer(void); 17 17
+1 -1
drivers/oprofile/oprof.c
··· 14 14 #include <linux/moduleparam.h> 15 15 #include <linux/workqueue.h> 16 16 #include <linux/time.h> 17 - #include <asm/mutex.h> 17 + #include <linux/mutex.h> 18 18 19 19 #include "oprof.h" 20 20 #include "event_buffer.h"