0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/errno.h>
0012 #include <linux/bug.h>
0013 #include <linux/spinlock.h>
0014 #include <linux/export.h>
0015
0016 #include <asm/processor.h>
0017 #include <asm/cputable.h>
0018 #include <asm/pmc.h>
0019
0020 #ifndef MMCR0_PMAO
0021 #define MMCR0_PMAO 0
0022 #endif
0023
0024 static void dummy_perf(struct pt_regs *regs)
0025 {
0026 #if defined(CONFIG_FSL_EMB_PERFMON)
0027 mtpmr(PMRN_PMGC0, mfpmr(PMRN_PMGC0) & ~PMGC0_PMIE);
0028 #elif defined(CONFIG_PPC64) || defined(CONFIG_PPC_BOOK3S_32)
0029 if (cur_cpu_spec->pmc_type == PPC_PMC_IBM)
0030 mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) & ~(MMCR0_PMXE|MMCR0_PMAO));
0031 #else
0032 mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) & ~MMCR0_PMXE);
0033 #endif
0034 }
0035
0036
0037 static DEFINE_RAW_SPINLOCK(pmc_owner_lock);
0038 static void *pmc_owner_caller;
0039 perf_irq_t perf_irq = dummy_perf;
0040
0041 int reserve_pmc_hardware(perf_irq_t new_perf_irq)
0042 {
0043 int err = 0;
0044
0045 raw_spin_lock(&pmc_owner_lock);
0046
0047 if (pmc_owner_caller) {
0048 printk(KERN_WARNING "reserve_pmc_hardware: "
0049 "PMC hardware busy (reserved by caller %p)\n",
0050 pmc_owner_caller);
0051 err = -EBUSY;
0052 goto out;
0053 }
0054
0055 pmc_owner_caller = __builtin_return_address(0);
0056 perf_irq = new_perf_irq ? new_perf_irq : dummy_perf;
0057
0058 out:
0059 raw_spin_unlock(&pmc_owner_lock);
0060 return err;
0061 }
0062 EXPORT_SYMBOL_GPL(reserve_pmc_hardware);
0063
0064 void release_pmc_hardware(void)
0065 {
0066 raw_spin_lock(&pmc_owner_lock);
0067
0068 WARN_ON(! pmc_owner_caller);
0069
0070 pmc_owner_caller = NULL;
0071 perf_irq = dummy_perf;
0072
0073 raw_spin_unlock(&pmc_owner_lock);
0074 }
0075 EXPORT_SYMBOL_GPL(release_pmc_hardware);
0076
0077 #ifdef CONFIG_PPC64
0078 void power4_enable_pmcs(void)
0079 {
0080 unsigned long hid0;
0081
0082 hid0 = mfspr(SPRN_HID0);
0083 hid0 |= 1UL << (63 - 20);
0084
0085
0086 asm volatile(
0087 "sync\n"
0088 "mtspr %1, %0\n"
0089 "mfspr %0, %1\n"
0090 "mfspr %0, %1\n"
0091 "mfspr %0, %1\n"
0092 "mfspr %0, %1\n"
0093 "mfspr %0, %1\n"
0094 "mfspr %0, %1\n"
0095 "isync" : "=&r" (hid0) : "i" (SPRN_HID0), "0" (hid0):
0096 "memory");
0097 }
0098 #endif