static int op_powerpc_setup(void) { int err; op_per_cpu_rc = 0; /* Grab the hardware */ err = reserve_pmc_hardware(op_handle_interrupt); if (err) return err; /* Pre-compute the values to stuff in the hardware registers. */ op_per_cpu_rc = model->reg_setup(ctr, &sys, model->num_counters); if (op_per_cpu_rc) goto out; /* Configure the registers on all cpus. If an error occurs on one * of the cpus, op_per_cpu_rc will be set to the error */ on_each_cpu(op_powerpc_cpu_setup, NULL, 1); out: if (op_per_cpu_rc) { /* error on setup release the performance counter hardware */ release_pmc_hardware(); } return op_per_cpu_rc; }
static int op_powerpc_setup(void) { int err; op_per_cpu_rc = 0; err = reserve_pmc_hardware(op_handle_interrupt); if (err) return err; op_per_cpu_rc = model->reg_setup(ctr, &sys, model->num_counters); if (op_per_cpu_rc) goto out; on_each_cpu(op_powerpc_cpu_setup, NULL, 1); out: if (op_per_cpu_rc) { release_pmc_hardware(); } return op_per_cpu_rc; }
/* * proc handler for /proc/sys/tile/userspace_perf_counters */ int userspace_perf_counters_handler(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { int ret, changed; unsigned int old_userspace_perf_counters; /* Read /proc/sys/tile/userspace_perf_counters */ if (!write) { ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); return ret; } /* Write /proc/sys/tile/userspace_perf_counters */ old_userspace_perf_counters = userspace_perf_counters; ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); changed = userspace_perf_counters != old_userspace_perf_counters; /* * Do something only if the value of userspace_perf_counters * is changed. */ if (ret == 0 && changed) { if (userspace_perf_counters == 1) { if (reserve_pmc_hardware(userspace_perf_handler)) { pr_warning("PMC hardware busy (reserved " "by perf_event or oprofile)\n"); userspace_perf_counters = old_userspace_perf_counters; return -EBUSY; } } else release_pmc_hardware(); /* Set MPL_PERF_COUNT_SET_X on each tile. */ on_each_cpu(set_perf_count_sprs, NULL, 1); } return ret; }
int perfctr_reserve_pmc_hardware(void) { return reserve_pmc_hardware(do_perfctr_interrupt); }
static int __init setup_watchpoint(char *str) { char *p; unsigned long va, width; int mode; va = simple_strtoul(str, &p, 0); if (p == str) { pr_err("Unknown 'watch=' numeric value: %s\n", str); return -EINVAL; } str = p; if (*str == '/') { ++str; width = simple_strtoul(str, &p, 0); if (p == str) { pr_err("Unknown 'watch=' width qualifier: %s\n", str); return -EINVAL; } if (__builtin_popcount(width) != 1) { pr_err("'watch=' width value not power of two: %ld\n", width); return -EINVAL; } str = p; } else { width = 1; } if (*str == ',') { mode = string_to_mode(++str); if (mode == -1) { pr_err("Unknown 'watch=' qualifier '%s'\n", str); return -EINVAL; } } else { mode = string_to_mode("default"); } /* FIXME: we only need to reserve PERF_COUNT_0. */ if (reserve_pmc_hardware(handle_watch_interrupt)) return -EINVAL; pr_notice("Watching VAs %#lx..%#lx,%s\n", va, va + width - 1, mode_to_string(mode)); __insn_mtspr(SPR_WATCH_VAL, va); #ifdef __tilegx__ /* Watch only the VA bits, not the high bits. */ __insn_mtspr(SPR_WATCH_MASK, (-1ULL << 42) | (width - 1)); /* * We assume SPR_DIAG_MUX_CTL is set for Mbox output in the hv. * Select "special" for perf counter zero, using "watch SPR" output. */ __insn_mtspr(SPR_PERF_COUNT_CTL, (7 << 6) | 0); #else /* Watch requested VA bits. */ __insn_mtspr(SPR_WATCH_MASK, width - 1); /* Choose watching the appropriate type of access. */ __insn_mtspr(SPR_WATCH_CTL, mode); /* Select DIAG_SPCL_EVENT_WATCH for performance counter 0. */ __insn_mtspr(SPR_PERF_COUNT_CTL, 106); #endif __insn_mtspr(SPR_PERF_COUNT_0, -1); unmask_pmc_interrupts(); return 0; }