18cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/**
28cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @file op_pmu.c
38cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Setup and handling of IA64 Performance Monitoring Unit (PMU)
48cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
58cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Copyright 2002 OProfile authors
68cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Read the file COPYING
78cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
88cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Bob Montgomery
98cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Will Cohen
108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author John Levon
118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Philippe Elie
128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "oprofile.h"
168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_util.h"
178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <asm/perfmon.h>
188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_ia64_model.h"
198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* number of counters physically present */
218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic uint op_nr_counters = 4;
228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* performance counters are in pairs: pmcN and pmdN.  The pmc register acts
248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * as the event selection; the pmd register is the counter. */
258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define perf_reg(c)	((c)+4)
268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define IA64_1_PMD_MASK_VAL	((1UL << 32) - 1)
288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define IA64_2_PMD_MASK_VAL	((1UL << 47) - 1)
298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* The appropriate value is selected in pmu_init() */
318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddunsigned long pmd_mask = IA64_2_PMD_MASK_VAL;
328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define pmd_overflowed(r, c) ((r) & (1 << perf_reg(c)))
348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define set_pmd_neg(v, c) do { \
358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ia64_set_pmd(perf_reg(c), -(ulong)(v) & pmd_mask); \
368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ia64_srlz_d(); } while (0)
378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define set_pmd(v, c) do { \
388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ia64_set_pmd(perf_reg(c), (v) & pmd_mask); \
398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ia64_srlz_d(); } while (0)
408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define set_pmc(v, c) do { ia64_set_pmc(perf_reg(c), (v)); ia64_srlz_d(); } while (0)
418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define get_pmd(c) ia64_get_pmd(perf_reg(c))
428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define get_pmc(c) ia64_get_pmc(perf_reg(c))
438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* ---------------- IRQ handler ------------------ */
458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* The args match the args for pfm_overflow_handler in perfmon.c.
478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * The task_struct is currently filled in with the perfmon "owner" of
488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * the PMU.  This might change.  I'm not sure it makes sense in perfmon
498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * either with system-wide profiling.
508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * pmc0 is a bit mask for overflowed counters (bits 4-7)
518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * This routine should return 0 to resume interrupts.
528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddinline static void
548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddop_do_pmu_interrupt(u64 pmc0, struct pt_regs * regs)
558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	uint cpu = op_cpu_id();
578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int ctr;
588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (ctr = 0 ; ctr < op_nr_counters ; ++ctr) {
608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (pmd_overflowed(pmc0, ctr)) {
618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			op_do_profile(cpu, regs->cr_iip, 1, ctr);
628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			set_pmd_neg(oprof_data[cpu].ctr_count[ctr], ctr);
638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return;
668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void
708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddop_raw_pmu_interrupt(int irq, void * arg, struct pt_regs * regs)
718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	u64 pmc0;
738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	pmc0 = ia64_get_pmc(0);
758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if ((pmc0 & ~0x1UL) != 0UL) {
778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		op_do_pmu_interrupt(pmc0, regs);
788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		ia64_set_pmc(0, 0);
798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		ia64_srlz_d();
808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define MY_OPROFILE_VECTOR (IA64_PERFMON_VECTOR - 2)
858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void
878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddop_set_pmv(void * dummy)
888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ia64_set_pmv(MY_OPROFILE_VECTOR);
908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ia64_srlz_d();
918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void
958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddop_restore_pmv(void* dummy)
968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ia64_set_pmv(IA64_PERFMON_VECTOR);
988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ia64_srlz_d();
998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic int
1038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddinstall_handler(void)
1048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int err = 0;
1068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* Try it legally - confusion about vec vs irq */
1088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	err = request_irq(MY_OPROFILE_VECTOR, op_raw_pmu_interrupt,
1098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			SA_INTERRUPT | SA_PERCPU_IRQ, "oprofile", NULL);
1108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (err) {
1128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printk(KERN_ALERT "oprofile_IA64: request_irq fails, "
1138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				"returns %d\n", err);
1148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return err;
1158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if ((smp_call_function(op_set_pmv, NULL, 0, 1))) {
1188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printk(KERN_ALERT "oprofile_IA64: unexpected failure "
1198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				"of smp_call_function(op_set_pmv)\n");
1208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	op_set_pmv(NULL);
1238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return err;
1258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic int
1298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddrestore_handler(void)
1308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int err = 0;
1328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if ((smp_call_function(op_restore_pmv, NULL, 0, 1))) {
1348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printk(KERN_ALERT "oprofile_IA64: unexpected failure "
1358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				"of smp_call_function(op_restore_pmv)\n");
1368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	op_restore_pmv(NULL);
1398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	free_irq(MY_OPROFILE_VECTOR, NULL);
1418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return err;
1428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* ---------------- PMU setup ------------------ */
1468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* This is kind of artificial.  The proc interface might really want to
1488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * accept register values directly.  There are other features not exposed
1498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * by this limited interface.  Of course that might require all sorts of
1508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * validity checking??? */
1518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void
1528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddpmc_fill_in(ulong * val, u8 kernel, u8 user, u8 event, u8 um)
1538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* enable interrupt generation */
1558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	*val |= (1 << 5);
1568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* setup as a privileged monitor */
1588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	*val |= (1 << 6);
1598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* McKinley requires pmc4 to have bit 23 set (enable PMU).
1618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * It is supposedly ignored in other pmc registers.
1628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * Try assuming it's ignored in Itanium, too, and just
1638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * set it for everyone.
1648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
1658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	*val |= (1 << 23);
1678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* enable/disable chosen OS and USR counting */
1698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	(user)   ? (*val |= (1 << 3))
1708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 : (*val &= ~(1 << 3));
1718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	(kernel) ? (*val |= (1 << 0))
1738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 : (*val &= ~(1 << 0));
1748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* what are we counting ? */
1768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	*val &= ~(0xff << 8);
1778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	*val |= ((event & 0xff) << 8);
1788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	*val &= ~(0xf << 16);
1798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	*val |= ((um & 0xf) << 16);
1808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void
1848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddpmu_setup(void * dummy)
1858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ulong pmc_val;
1878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int ii;
1888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* setup each counter */
1908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (ii = 0 ; ii < op_nr_counters ; ++ii) {
1918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (sysctl.ctr[ii].enabled) {
1928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			pmc_val = 0;
1938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			set_pmd_neg(sysctl.ctr[ii].count, ii);
1958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			pmc_fill_in(&pmc_val, sysctl.ctr[ii].kernel,
1968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				sysctl.ctr[ii].user, sysctl.ctr[ii].event,
1978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				sysctl.ctr[ii].unit_mask);
1988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			set_pmc(pmc_val, ii);
2008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
2018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
2028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
2038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid
2068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodddisable_psr(void * dummy)
2078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
2088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct pt_regs * regs;
2098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* disable profiling for my saved state */
2108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	regs = (struct pt_regs *)((unsigned long) current + IA64_STK_OFFSET);
2118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	regs--;
2128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ia64_psr(regs)->pp = 0;
2138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* shouldn't need to */
2148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ia64_psr(regs)->up = 0;
2158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* disable profiling for my current state */
2178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	__asm__ __volatile__ ("rsm psr.pp;;"::: "memory");
2188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#if defined(CONFIG_PERFMON) && defined(CONFIG_SMP)
2208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#if V_AT_LEAST(2, 4, 21)
2218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	local_cpu_data->pfm_syst_info |=  PFM_CPUINFO_SYST_WIDE;
2228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	local_cpu_data->pfm_syst_info &= ~PFM_CPUINFO_DCR_PP;
2238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* FIXME: what todo with the 3rd flags PFM_CPUINFO_EXCL_IDLE 0x4 */
2248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#else
2258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* disable profiling for everyone else */
2268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	local_cpu_data->pfm_syst_wide = 1;
2278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	local_cpu_data->pfm_dcr_pp = 0;
2288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif
2298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif
2308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ia64_set_pmc(0, 0);
2318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ia64_srlz_d();
2328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
2338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic int
2368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddpmu_setup_all(void)
2378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
2388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* This would be a great place to reserve all cpus with
2408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * some sort of call to perfmonctl (something like the
2418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * CREATE_CONTEXT command).  The current interface to
2428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * perfmonctl wants to be called from a different task id
2438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * for each CPU to be set up (and doesn't allow calls from
2448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * modules.
2458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
2468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* disable profiling with the psr.pp bit */
2488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if ((smp_call_function(disable_psr, NULL, 0, 1)))
2498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return -EFAULT;
2508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	disable_psr(NULL);
2528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* now I've reserved the PMUs and they should be quiet */
2548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if ((smp_call_function(pmu_setup, NULL, 0, 1)))
2568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return -EFAULT;
2578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	pmu_setup(NULL);
2598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return 0;
2608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
2618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#ifndef CONFIG_SMP
2648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* from linux/arch/ia64/kernel/perfmon.c */
2658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/*
2668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Originaly Written by Ganesh Venkitachalam, IBM Corp.
2678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Copyright (C) 1999 Ganesh Venkitachalam <venkitac@us.ibm.com>
2688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
2698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Modifications by Stephane Eranian, Hewlett-Packard Co.
2708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Modifications by David Mosberger-Tang, Hewlett-Packard Co.
2718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
2728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Copyright (C) 1999-2002  Hewlett Packard Co
2738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *               Stephane Eranian <eranian@hpl.hp.com>
2748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *               David Mosberger-Tang <davidm@hpl.hp.com>
2758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
2768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/*
2788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * On UP kernels, we do not need to constantly set the psr.pp bit
2798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * when a task is scheduled. The psr.pp bit can only be changed in
2808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * the kernel because of a user request. Given we are on a UP non preeemptive
2818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * kernel we know that no other task is running, so we cna simply update their
2828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * psr.pp from their saved state. There is this no impact on the context switch
2838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * code compared to the SMP case.
2848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
2858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void
2868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddop_tasklist_toggle_pp(unsigned int val)
2878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
2888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct task_struct * p;
2898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct pt_regs * regs;
2908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	read_lock(&tasklist_lock);
2928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for_each_task(p) {
2948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		regs = (struct pt_regs *)((unsigned long) p + IA64_STK_OFFSET);
2958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/*
2978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 * position on pt_regs saved on stack on 1st entry into the kernel
2988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 */
2998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		regs--;
3008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/*
3028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 * update psr.pp
3038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 */
3048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		ia64_psr(regs)->pp = val;
3058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
3068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	read_unlock(&tasklist_lock);
3078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
3088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif
3098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void
3128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddpmu_start(void * info)
3138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
3148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct pt_regs * regs;
3158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (info && (*((uint *)info) != op_cpu_id()))
3178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return;
3188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* printk(KERN_ALERT "oprofile_IA64: pmu_start on cpu %d\n",
3208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	  	op_cpu_id()); */
3218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* The default control register pp value is copied into psr.pp
3228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * on an interrupt.  This allows interrupt service routines to
3238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * be monitored.
3248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
3258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ia64_set_dcr(ia64_get_dcr() | IA64_DCR_PP);
3268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#ifdef CONFIG_PERFMON
3288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#ifdef CONFIG_SMP
3298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#if V_AT_LEAST(2, 4, 21)
3308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	local_cpu_data->pfm_syst_info |= PFM_CPUINFO_SYST_WIDE;
3318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	local_cpu_data->pfm_syst_info |= PFM_CPUINFO_DCR_PP;
3328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* FIXME: what todo with the 3rd flags PFM_CPUINFO_EXCL_IDLE 0x4 */
3338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#else
3348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	local_cpu_data->pfm_syst_wide = 1;
3358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	local_cpu_data->pfm_dcr_pp = 1;
3368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif
3378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#else
3388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	op_tasklist_toggle_pp(1);
3398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif
3408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif
3418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* set it in my saved state */
3428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	regs = (struct pt_regs *)((unsigned long) current + IA64_STK_OFFSET);
3438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	regs--;
3448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ia64_psr(regs)->pp = 1;
3458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* set it in my current state */
3478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	__asm__ __volatile__ ("ssm psr.pp;;"::: "memory");
3488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ia64_srlz_d();
3498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
3508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void
3538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddpmu_stop(void * info)
3548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
3558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct pt_regs * regs;
3568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (info && (*((uint *)info) != op_cpu_id()))
3588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return;
3598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* stop in my current state */
3618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	__asm__ __volatile__ ("rsm psr.pp;;"::: "memory");
3628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* disable the dcr pp */
3648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ia64_set_dcr(ia64_get_dcr() & ~IA64_DCR_PP);
3658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#ifdef CONFIG_PERFMON
3678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#ifdef CONFIG_SMP
3688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#if V_AT_LEAST(2, 4, 21)
3698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	local_cpu_data->pfm_syst_info &= ~PFM_CPUINFO_SYST_WIDE;
3708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	local_cpu_data->pfm_syst_info &= ~PFM_CPUINFO_DCR_PP;
3718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* FIXME: what todo with the 3rd flags PFM_CPUINFO_EXCL_IDLE 0x4 */
3728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#else
3738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	local_cpu_data->pfm_syst_wide = 0;
3748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	local_cpu_data->pfm_dcr_pp = 0;
3758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif
3768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#else
3778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	pfm_tasklist_toggle_pp(0);
3788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif
3798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif
3808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* disable in my saved state */
3828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	regs = (struct pt_regs *)((unsigned long) current + IA64_STK_OFFSET);
3838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	regs--;
3848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ia64_psr(regs)->pp = 0;
3858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
3868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void
3898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddpmu_select_start(uint cpu)
3908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
3918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (cpu == op_cpu_id())
3928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		pmu_start(NULL);
3938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	else
3948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		smp_call_function(pmu_start, &cpu, 0, 1);
3958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
3968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void
3998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddpmu_select_stop(uint cpu)
4008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
4018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (cpu == op_cpu_id())
4028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		pmu_stop(NULL);
4038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	else
4048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		smp_call_function(pmu_stop, &cpu, 0, 1);
4058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
4068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void
4098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddpmu_start_all(void)
4108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
4118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int cpu, i;
4128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (cpu=0; cpu < smp_num_cpus; cpu++) {
4148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		struct _oprof_data * data = &oprof_data[cpu];
4158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		for (i = 0 ; i < op_nr_counters ; ++i) {
4178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			if (sysctl.ctr[i].enabled) {
4188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				data->ctr_count[i] = sysctl.ctr[i].count;
4198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			} else {
4208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				data->ctr_count[i] = 0;
4218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			}
4228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
4238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!install_handler()) {
4268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		smp_call_function(pmu_start, NULL, 0, 1);
4278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		pmu_start(NULL);
4288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* FIXME need some way to fail here */;
4308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
4318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void
4348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddpmu_stop_all(void)
4358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
4368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	smp_call_function(pmu_stop, NULL, 0, 1);
4378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	pmu_stop(NULL);
4388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	restore_handler();
4398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
4408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic int
4438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddpmu_check_params(void)
4448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
4458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int i;
4468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int enabled = 0;
4478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (i = 0; i < op_nr_counters ; i++) {
4498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!sysctl.ctr[i].enabled)
4508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			continue;
4518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		enabled = 1;
4538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!sysctl.ctr[i].user && !sysctl.ctr[i].kernel) {
4558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			printk(KERN_ERR "oprofile: neither kernel nor user "
4568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			       "set for counter %d\n", i);
4578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return -EINVAL;
4588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
4598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (check_range(sysctl.ctr[i].count, 1, OP_MAX_PERF_COUNT,
4618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			"ctr count value %d not in range (%d %ld)\n"))
4628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return -EINVAL;
4638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!enabled) {
4668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printk(KERN_ERR "oprofile: no counters have been enabled.\n");
4678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return -EINVAL;
4688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return 0;
4718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
4728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic struct op_msrs cpu_msrs[NR_CPUS];
4758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void free_msr_group(struct op_msr_group * group)
4788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
4798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (group->addrs)
4808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		kfree(group->addrs);
4818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (group->saved)
4828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		kfree(group->saved);
4838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	group->addrs = NULL;
4848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	group->saved = NULL;
4858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
4868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void pmu_save_registers(void * dummy)
4898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
4908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	uint i;
4918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	uint const cpu = op_cpu_id();
4928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct op_msr_group * counters = &cpu_msrs[cpu].counters;
4938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct op_msr_group * controls = &cpu_msrs[cpu].controls;
4948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	counters->addrs = NULL;
4968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	counters->saved = NULL;
4978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	controls->addrs = NULL;
4988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	controls->saved = NULL;
4998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	counters->saved = kmalloc(
5018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		op_nr_counters * sizeof(struct op_saved_msr), GFP_KERNEL);
5028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!counters->saved)
5038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto fault;
5048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	controls->saved = kmalloc(
5068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		op_nr_counters * sizeof(struct op_saved_msr), GFP_KERNEL);
5078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!controls->saved)
5088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto fault;
5098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (i = 0; i < op_nr_counters; ++i) {
5118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		controls->saved[i].low = get_pmc(i);
5128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		counters->saved[i].low = get_pmd(i);
5138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return;
5158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddfault:
5178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	free_msr_group(counters);
5188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	free_msr_group(controls);
5198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
5208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void pmu_restore_registers(void * dummy)
5238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
5248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	uint i;
5258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	uint const cpu = op_cpu_id();
5268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct op_msr_group * counters = &cpu_msrs[cpu].counters;
5278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct op_msr_group * controls = &cpu_msrs[cpu].controls;
5288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (i = 0; i < op_nr_counters; ++i) {
5308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		set_pmc(controls->saved[i].low, i);
5318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		set_pmd(counters->saved[i].low, i);
5328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	free_msr_group(counters);
5358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	free_msr_group(controls);
5368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
5378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic int
5418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddpmu_init(void)
5428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
5438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int err = 0;
5448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* figure out processor type configure number of bits in pmd
5468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	   and number of counters */
5478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	switch (get_cpu_type()) {
5488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	case CPU_IA64_1:
5498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		pmd_mask = IA64_1_PMD_MASK_VAL; break;
5508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	case CPU_IA64_2:
5518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	case CPU_IA64:
5528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		pmd_mask = IA64_2_PMD_MASK_VAL; break;
5538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	default:
5548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		err = -EIO; break;
5558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	op_nr_counters = 4;
5588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if ((err = smp_call_function(pmu_save_registers, NULL, 0, 1)))
5608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto out;
5618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	pmu_save_registers(NULL);
5638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddout:
5658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return err;
5668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
5678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void
5708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddpmu_deinit(void)
5718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
5728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	smp_call_function(pmu_restore_registers, NULL, 0, 1);
5738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	pmu_restore_registers(NULL);
5748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
5758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic char * names[] = { "0", "1", "2", "3", };
5788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic int
5818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddpmu_add_sysctls(ctl_table * next)
5828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
5838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ctl_table * start = next;
5848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ctl_table * tab;
5858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int i, j;
5868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (i=0; i < op_nr_counters; i++) {
5888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		next->ctl_name = 1;
5898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		next->procname = names[i];
5908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		next->mode = 0700;
5918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!(tab = kmalloc(sizeof(ctl_table)*7, GFP_KERNEL)))
5938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			goto cleanup;
5948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		next->child = tab;
5968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		memset(tab, 0, sizeof(ctl_table)*7);
5988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		tab[0] = ((ctl_table) { 1, "enabled", &sysctl_parms.ctr[i].enabled, sizeof(int), 0600, NULL, lproc_dointvec, NULL, });
5998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		tab[1] = ((ctl_table) { 1, "event", &sysctl_parms.ctr[i].event, sizeof(int), 0600, NULL, lproc_dointvec, NULL,  });
6008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		tab[2] = ((ctl_table) { 1, "count", &sysctl_parms.ctr[i].count, sizeof(int), 0600, NULL, lproc_dointvec, NULL, });
6018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		tab[3] = ((ctl_table) { 1, "unit_mask", &sysctl_parms.ctr[i].unit_mask, sizeof(int), 0600, NULL, lproc_dointvec, NULL, });
6028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		tab[4] = ((ctl_table) { 1, "kernel", &sysctl_parms.ctr[i].kernel, sizeof(int), 0600, NULL, lproc_dointvec, NULL, });
6038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		tab[5] = ((ctl_table) { 1, "user", &sysctl_parms.ctr[i].user, sizeof(int), 0600, NULL, lproc_dointvec, NULL, });
6048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		next++;
6058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
6068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return 0;
6088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddcleanup:
6108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	next = start;
6118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (j = 0; j < i; j++) {
6128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		kfree(next->child);
6138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		next++;
6148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
6158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return -EFAULT;
6168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
6178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void pmu_remove_sysctls(ctl_table * next)
6208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
6218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int ii;
6228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (ii=0; ii < op_nr_counters; ii++) {
6248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		kfree(next->child);
6258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		next++;
6268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
6278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
6288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct op_int_operations op_nmi_ops = {
6318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	init: pmu_init,
6328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	deinit: pmu_deinit,
6338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	add_sysctls: pmu_add_sysctls,
6348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	remove_sysctls: pmu_remove_sysctls,
6358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	check_params: pmu_check_params,
6368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	setup: pmu_setup_all,
6378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	start: pmu_start_all,
6388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	stop: pmu_stop_all,
6398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	start_cpu: pmu_select_start,
6408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	stop_cpu: pmu_select_stop,
6418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd};
6428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct op_int_operations const * op_int_interface()
6458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
6468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return &op_nmi_ops;
6478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
6488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* Need this dummy so module/oprofile.c links */
6508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct op_int_operations op_rtc_ops = {
6518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	init: NULL,
6528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	deinit: NULL,
6538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	add_sysctls: NULL,
6548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	remove_sysctls: NULL,
6558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	check_params: NULL,
6568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	setup: NULL,
6578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	start: NULL,
6588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	stop: NULL,
6598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	start_cpu: NULL,
6608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	stop_cpu: NULL,
6618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd};
662