svn commit: r233319 - in head/sys: conf dev/hwpmc mips/atheros mips/include

Oleksandr Tymoshenko gonzo at FreeBSD.org
Thu Mar 22 18:01:23 UTC 2012


Author: gonzo
Date: Thu Mar 22 18:01:23 2012
New Revision: 233319
URL: http://svn.freebsd.org/changeset/base/233319

Log:
  Rework MIPS PMC code:
  
  - Replace MIPS24K-specific code with more generic framework that will
      make adding new CPU support easier
  - Add MIPS24K support for new framework
  - Limit backtrace depth to 1 for stability reasons and add option
      HWPMC_MIPS_BACKTRACE to override this limitation

Deleted:
  head/sys/dev/hwpmc/hwpmc_mips24k.h
Modified:
  head/sys/conf/files.mips
  head/sys/conf/options
  head/sys/dev/hwpmc/hwpmc_mips.c
  head/sys/dev/hwpmc/hwpmc_mips24k.c
  head/sys/mips/atheros/files.ar71xx
  head/sys/mips/include/pmc_mdep.h

Modified: head/sys/conf/files.mips
==============================================================================
--- head/sys/conf/files.mips	Thu Mar 22 17:47:52 2012	(r233318)
+++ head/sys/conf/files.mips	Thu Mar 22 18:01:23 2012	(r233319)
@@ -107,7 +107,6 @@ dev/siba/siba_pcib.c		optional	siba pci
 #mips/sentry5/siba_mips.c			optional siba # not yet
 
 dev/hwpmc/hwpmc_mips.c		optional hwpmc
-dev/hwpmc/hwpmc_mips24k.c	optional hwpmc
 
 dev/rt/if_rt.c			optional 	rt
 dev/nvram2env/nvram2env.c	optional	nvram2env

Modified: head/sys/conf/options
==============================================================================
--- head/sys/conf/options	Thu Mar 22 17:47:52 2012	(r233318)
+++ head/sys/conf/options	Thu Mar 22 18:01:23 2012	(r233319)
@@ -829,6 +829,7 @@ DCONS_FORCE_GDB		opt_dcons.h
 
 # HWPMC options
 HWPMC_HOOKS
+HWPMC_MIPS_BACKTRACE 	opt_hwpmc_hooks.h
 
 # XBOX options for FreeBSD/i386, but some files are MI
 XBOX			opt_xbox.h

Modified: head/sys/dev/hwpmc/hwpmc_mips.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_mips.c	Thu Mar 22 17:47:52 2012	(r233318)
+++ head/sys/dev/hwpmc/hwpmc_mips.c	Thu Mar 22 18:01:23 2012	(r233319)
@@ -28,8 +28,11 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_hwpmc_hooks.h"
+
 #include <sys/param.h>
 #include <sys/pmc.h>
+#include <sys/pmckern.h>
 #include <sys/systm.h>
 
 #include <machine/pmc_mdep.h>
@@ -37,6 +40,17 @@ __FBSDID("$FreeBSD$");
 #include <machine/mips_opcode.h>
 #include <machine/vmparam.h>
 
+int mips_npmcs;
+
+/*
+ * Per-processor information.
+ */
+struct mips_cpu {
+	struct pmc_hw	*pc_mipspmcs;
+};
+
+static struct mips_cpu **mips_pcpu;
+
 #if defined(__mips_n64)
 #	define	MIPS_IS_VALID_KERNELADDR(reg)	((((reg) & 3) == 0) && \
 					((vm_offset_t)(reg) >= MIPS_XKPHYS_START))
@@ -53,6 +67,413 @@ __FBSDID("$FreeBSD$");
 #define	MAX_PROLOGUE_SIZE 0x100
 
 static int
+mips_allocate_pmc(int cpu, int ri, struct pmc *pm,
+  const struct pmc_op_pmcallocate *a)
+{
+	enum pmc_event pe;
+	uint32_t caps, config, counter;
+	uint32_t event;
+	int i;
+
+	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+	    ("[mips,%d] illegal CPU value %d", __LINE__, cpu));
+	KASSERT(ri >= 0 && ri < mips_npmcs,
+	    ("[mips,%d] illegal row index %d", __LINE__, ri));
+
+	caps = a->pm_caps;
+	if (a->pm_class != mips_pmc_spec.ps_cpuclass)
+		return (EINVAL);
+	pe = a->pm_ev;
+	counter = MIPS_CTR_ALL;
+	event = 0;
+	for (i = 0; i < mips_event_codes_size; i++) {
+		if (mips_event_codes[i].pe_ev == pe) {
+			event = mips_event_codes[i].pe_code;
+			counter =  mips_event_codes[i].pe_counter;
+			break;
+		}
+	}
+
+	if (i == mips_event_codes_size)
+		return (EINVAL);
+
+	if ((counter != MIPS_CTR_ALL) && (counter != ri))
+		return (EINVAL);
+
+	config = mips_get_perfctl(cpu, ri, event, caps);
+
+	pm->pm_md.pm_mips_evsel = config;
+
+	PMCDBG(MDP,ALL,2,"mips-allocate ri=%d -> config=0x%x", ri, config);
+
+	return 0;
+}
+
+
+static int
+mips_read_pmc(int cpu, int ri, pmc_value_t *v)
+{
+	struct pmc *pm;
+	pmc_value_t tmp;
+
+	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+	    ("[mips,%d] illegal CPU value %d", __LINE__, cpu));
+	KASSERT(ri >= 0 && ri < mips_npmcs,
+	    ("[mips,%d] illegal row index %d", __LINE__, ri));
+
+	pm  = mips_pcpu[cpu]->pc_mipspmcs[ri].phw_pmc;
+	tmp = mips_pmcn_read(ri);
+	PMCDBG(MDP,REA,2,"mips-read id=%d -> %jd", ri, tmp);
+
+	if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+		*v = tmp - (1UL << (mips_pmc_spec.ps_counter_width - 1));
+	else
+		*v = tmp;
+
+	return 0;
+}
+
+static int
+mips_write_pmc(int cpu, int ri, pmc_value_t v)
+{
+	struct pmc *pm;
+
+	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+	    ("[mips,%d] illegal CPU value %d", __LINE__, cpu));
+	KASSERT(ri >= 0 && ri < mips_npmcs,
+	    ("[mips,%d] illegal row-index %d", __LINE__, ri));
+
+	pm  = mips_pcpu[cpu]->pc_mipspmcs[ri].phw_pmc;
+
+	if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+		v = (1UL << (mips_pmc_spec.ps_counter_width - 1)) - v;
+	
+	PMCDBG(MDP,WRI,1,"mips-write cpu=%d ri=%d v=%jx", cpu, ri, v);
+
+	mips_pmcn_write(ri, v);
+
+	return 0;
+}
+
+static int
+mips_config_pmc(int cpu, int ri, struct pmc *pm)
+{
+	struct pmc_hw *phw;
+
+	PMCDBG(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm);
+
+	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+	    ("[mips,%d] illegal CPU value %d", __LINE__, cpu));
+	KASSERT(ri >= 0 && ri < mips_npmcs,
+	    ("[mips,%d] illegal row-index %d", __LINE__, ri));
+
+	phw = &mips_pcpu[cpu]->pc_mipspmcs[ri];
+
+	KASSERT(pm == NULL || phw->phw_pmc == NULL,
+	    ("[mips,%d] pm=%p phw->pm=%p hwpmc not unconfigured",
+	    __LINE__, pm, phw->phw_pmc));
+
+	phw->phw_pmc = pm;
+
+	return 0;
+}
+
+static int
+mips_start_pmc(int cpu, int ri)
+{
+	uint32_t config;
+        struct pmc *pm;
+        struct pmc_hw *phw;
+
+	phw    = &mips_pcpu[cpu]->pc_mipspmcs[ri];
+	pm     = phw->phw_pmc;
+	config = pm->pm_md.pm_mips_evsel;
+
+	/* Enable the PMC. */
+	switch (ri) {
+	case 0:
+		mips_wr_perfcnt0(config);
+		break;
+	case 1:
+		mips_wr_perfcnt2(config);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int
+mips_stop_pmc(int cpu, int ri)
+{
+        struct pmc *pm;
+        struct pmc_hw *phw;
+
+	phw    = &mips_pcpu[cpu]->pc_mipspmcs[ri];
+	pm     = phw->phw_pmc;
+
+	/*
+	 * Disable the PMCs.
+	 *
+	 * Clearing the entire register turns the counter off as well
+	 * as removes the previously sampled event.
+	 */
+	switch (ri) {
+	case 0:
+		mips_wr_perfcnt0(0);
+		break;
+	case 1:
+		mips_wr_perfcnt2(0);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int
+mips_release_pmc(int cpu, int ri, struct pmc *pmc)
+{
+	struct pmc_hw *phw;
+
+	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+	    ("[mips,%d] illegal CPU value %d", __LINE__, cpu));
+	KASSERT(ri >= 0 && ri < mips_npmcs,
+	    ("[mips,%d] illegal row-index %d", __LINE__, ri));
+
+	phw = &mips_pcpu[cpu]->pc_mipspmcs[ri];
+	KASSERT(phw->phw_pmc == NULL,
+	    ("[mips,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc));
+
+	return 0;
+}
+
+static int
+mips_pmc_intr(int cpu, struct trapframe *tf)
+{
+	int error;
+	int retval, ri;
+	struct pmc *pm;
+	struct mips_cpu *pc;
+	uint32_t r0, r2;
+	pmc_value_t r;
+
+	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+	    ("[mips,%d] CPU %d out of range", __LINE__, cpu));
+
+	retval = 0;
+	pc = mips_pcpu[cpu];
+
+	/* Stop PMCs without clearing the counter */
+	r0 = mips_rd_perfcnt0();
+	mips_wr_perfcnt0(r0 & ~(0x1f));
+	r2 = mips_rd_perfcnt2();
+	mips_wr_perfcnt2(r2 & ~(0x1f));
+
+	for (ri = 0; ri < mips_npmcs; ri++) {
+		pm = mips_pcpu[cpu]->pc_mipspmcs[ri].phw_pmc;
+		if (pm == NULL)
+			continue;
+		if (! PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+			continue;
+
+		r = mips_pmcn_read(ri);
+
+		/* If bit 31 is set, the counter has overflowed */
+		if ((r & (1UL << (mips_pmc_spec.ps_counter_width - 1))) == 0)
+			continue;
+
+		retval = 1;
+		if (pm->pm_state != PMC_STATE_RUNNING)
+			continue;
+		error = pmc_process_interrupt(cpu, pm, tf,
+		    TRAPF_USERMODE(tf));
+		if (error) {
+			/* Clear/disable the relevant counter */
+			if (ri == 0)
+				r0 = 0;
+			else if (ri == 1)
+				r2 = 0;
+			mips_stop_pmc(cpu, ri);
+		}
+
+		/* Reload sampling count */
+		mips_write_pmc(cpu, ri, pm->pm_sc.pm_reloadcount);
+	}
+
+	/*
+	 * Re-enable the PMC counters where they left off.
+	 *
+	 * Any counter which overflowed will have its sample count
+	 * reloaded in the loop above.
+	 */
+	mips_wr_perfcnt0(r0);
+	mips_wr_perfcnt2(r2);
+
+	return retval;
+}
+
+static int
+mips_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc)
+{
+	int error;
+	struct pmc_hw *phw;
+	char mips_name[PMC_NAME_MAX];
+
+	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+	    ("[mips,%d], illegal CPU %d", __LINE__, cpu));
+	KASSERT(ri >= 0 && ri < mips_npmcs,
+	    ("[mips,%d] row-index %d out of range", __LINE__, ri));
+
+	phw = &mips_pcpu[cpu]->pc_mipspmcs[ri];
+	snprintf(mips_name, sizeof(mips_name), "MIPS-%d", ri);
+	if ((error = copystr(mips_name, pi->pm_name, PMC_NAME_MAX,
+	    NULL)) != 0)
+		return error;
+	pi->pm_class = mips_pmc_spec.ps_cpuclass;
+	if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) {
+		pi->pm_enabled = TRUE;
+		*ppmc          = phw->phw_pmc;
+	} else {
+		pi->pm_enabled = FALSE;
+		*ppmc	       = NULL;
+	}
+
+	return (0);
+}
+
+static int
+mips_get_config(int cpu, int ri, struct pmc **ppm)
+{
+	*ppm = mips_pcpu[cpu]->pc_mipspmcs[ri].phw_pmc;
+
+	return 0;
+}
+
+/*
+ * XXX don't know what we should do here.
+ */
+static int
+mips_pmc_switch_in(struct pmc_cpu *pc, struct pmc_process *pp)
+{
+	return 0;
+}
+
+static int
+mips_pmc_switch_out(struct pmc_cpu *pc, struct pmc_process *pp)
+{
+	return 0;
+}
+
+static int
+mips_pcpu_init(struct pmc_mdep *md, int cpu)
+{
+	int first_ri, i;
+	struct pmc_cpu *pc;
+	struct mips_cpu *pac;
+	struct pmc_hw  *phw;
+
+	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+	    ("[mips,%d] wrong cpu number %d", __LINE__, cpu));
+	PMCDBG(MDP,INI,1,"mips-init cpu=%d", cpu);
+
+	mips_pcpu[cpu] = pac = malloc(sizeof(struct mips_cpu), M_PMC,
+	    M_WAITOK|M_ZERO);
+	pac->pc_mipspmcs = malloc(sizeof(struct pmc_hw) * mips_npmcs,
+	    M_PMC, M_WAITOK|M_ZERO);
+	pc = pmc_pcpu[cpu];
+	first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_MIPS].pcd_ri;
+	KASSERT(pc != NULL, ("[mips,%d] NULL per-cpu pointer", __LINE__));
+
+	for (i = 0, phw = pac->pc_mipspmcs; i < mips_npmcs; i++, phw++) {
+		phw->phw_state    = PMC_PHW_FLAG_IS_ENABLED |
+		    PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i);
+		phw->phw_pmc      = NULL;
+		pc->pc_hwpmcs[i + first_ri] = phw;
+	}
+
+	/*
+	 * Clear the counter control register which has the effect
+	 * of disabling counting.
+	 */
+	for (i = 0; i < mips_npmcs; i++)
+		mips_pmcn_write(i, 0);
+
+	return 0;
+}
+
+static int
+mips_pcpu_fini(struct pmc_mdep *md, int cpu)
+{
+	return 0;
+}
+
+struct pmc_mdep *
+pmc_mips_initialize()
+{
+	struct pmc_mdep *pmc_mdep;
+	struct pmc_classdep *pcd;
+	
+	/*
+	 * TODO: Use More bit of PerfCntlX register to detect actual 
+	 * number of counters
+	 */
+	mips_npmcs = 2;
+	
+	PMCDBG(MDP,INI,1,"mips-init npmcs=%d", mips_npmcs);
+
+	/*
+	 * Allocate space for pointers to PMC HW descriptors and for
+	 * the MDEP structure used by MI code.
+	 */
+	mips_pcpu = malloc(sizeof(struct mips_cpu *) * pmc_cpu_max(), M_PMC,
+			   M_WAITOK|M_ZERO);
+
+	/* Just one class */
+	pmc_mdep = malloc(sizeof(struct pmc_mdep) + sizeof(struct pmc_classdep),
+			  M_PMC, M_WAITOK|M_ZERO);
+
+	pmc_mdep->pmd_cputype = mips_pmc_spec.ps_cputype;
+	pmc_mdep->pmd_nclass  = 1;
+
+	pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_MIPS];
+	pcd->pcd_caps  = mips_pmc_spec.ps_capabilities;
+	pcd->pcd_class = mips_pmc_spec.ps_cpuclass;
+	pcd->pcd_num   = mips_npmcs;
+	pcd->pcd_ri    = pmc_mdep->pmd_npmc;
+	pcd->pcd_width = mips_pmc_spec.ps_counter_width;
+
+	pcd->pcd_allocate_pmc   = mips_allocate_pmc;
+	pcd->pcd_config_pmc     = mips_config_pmc;
+	pcd->pcd_pcpu_fini      = mips_pcpu_fini;
+	pcd->pcd_pcpu_init      = mips_pcpu_init;
+	pcd->pcd_describe       = mips_describe;
+	pcd->pcd_get_config	= mips_get_config;
+	pcd->pcd_read_pmc       = mips_read_pmc;
+	pcd->pcd_release_pmc    = mips_release_pmc;
+	pcd->pcd_start_pmc      = mips_start_pmc;
+	pcd->pcd_stop_pmc       = mips_stop_pmc;
+ 	pcd->pcd_write_pmc      = mips_write_pmc;
+
+	pmc_mdep->pmd_intr       = mips_pmc_intr;
+	pmc_mdep->pmd_switch_in  = mips_pmc_switch_in;
+	pmc_mdep->pmd_switch_out = mips_pmc_switch_out;
+	
+	pmc_mdep->pmd_npmc   += mips_npmcs;
+
+	return (pmc_mdep);
+}
+
+void
+pmc_mips_finalize(struct pmc_mdep *md)
+{
+	(void) md;
+}
+
+#ifdef	HWPMC_MIPS_BACKTRACE
+
+static int
 pmc_next_frame(register_t *pc, register_t *sp)
 {
 	InstFmt i;
@@ -310,23 +731,18 @@ pmc_next_uframe(register_t *pc, register
 	return (0);
 }
 
+#endif /* HWPMC_MIPS_BACKTRACE */
+
 struct pmc_mdep *
 pmc_md_initialize()
 {
-  /*	if (cpu_class == CPU_CLASS_MIPS24K)*/
-		return pmc_mips24k_initialize();
-		/*	else
-			return NULL;*/
+	return pmc_mips_initialize();
 }
 
 void
 pmc_md_finalize(struct pmc_mdep *md)
 {
-  /*	if (cpu_class == CPU_CLASS_MIPS24K) */
-		pmc_mips24k_finalize(md);
-		/*	else
-		KASSERT(0, ("[mips,%d] Unknown CPU Class 0x%x", __LINE__,
-		cpu_class));*/
+	return pmc_mips_finalize(md);
 }
 
 int
@@ -340,17 +756,22 @@ pmc_save_kernel_callchain(uintptr_t *cc,
 	sp = tf->sp;
 	ra = tf->ra;
 
+	cc[frames++] = pc;
+
+#ifdef	HWPMC_MIPS_BACKTRACE
 	/*
 	 * Unwind, and unwind, and unwind
 	 */
 	while (1) {
-		cc[frames++] = pc;
 		if (frames >= nframes)
 			break;
 
 		if (pmc_next_frame(&pc, &sp) < 0)
 			break;
+
+		cc[frames++] = pc;
 	}
+#endif
 
 	return (frames);
 }
@@ -366,17 +787,23 @@ pmc_save_user_callchain(uintptr_t *cc, i
 	sp = tf->sp;
 	ra = tf->ra;
 
+	cc[frames++] = pc;
+
+#ifdef	HWPMC_MIPS_BACKTRACE
+
 	/*
 	 * Unwind, and unwind, and unwind
 	 */
 	while (1) {
-		cc[frames++] = pc;
 		if (frames >= nframes)
 			break;
 
 		if (pmc_next_uframe(&pc, &sp, &ra) < 0)
 			break;
+
+		cc[frames++] = pc;
 	}
+#endif
 
 	return (frames);
 }

Modified: head/sys/dev/hwpmc/hwpmc_mips24k.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_mips24k.c	Thu Mar 22 17:47:52 2012	(r233318)
+++ head/sys/dev/hwpmc/hwpmc_mips24k.c	Thu Mar 22 18:01:23 2012	(r233319)
@@ -37,147 +37,137 @@ __FBSDID("$FreeBSD$");
 #include <machine/cpufunc.h>
 #include <machine/pmc_mdep.h>
 
-/*
- * Support for MIPS CPUs
- *
- */
-static int mips24k_npmcs;
-
-struct mips24k_event_code_map {
-	enum pmc_event	pe_ev;       /* enum value */
-	uint8_t         pe_counter;  /* Which counter this can be counted in. */
-	uint8_t		pe_code;     /* numeric code */
-};
-
-/*
- * MIPS event codes are encoded with a select bit.  The
- * select bit is used when writing to CP0 so that we 
- * can select either counter 0/2 or 1/3.  The cycle
- * and instruction counters are special in that they
- * can be counted on either 0/2 or 1/3.
- */
-
-#define MIPS24K_ALL 255 /* Count events in any counter. */
-#define MIPS24K_CTR_0 0 /* Counter 0 Event */
-#define MIPS24K_CTR_1 1 /* Counter 1 Event */
-
-const struct mips24k_event_code_map mips24k_event_codes[] = {
-	{ PMC_EV_MIPS24K_CYCLE, MIPS24K_ALL, 0},
-	{ PMC_EV_MIPS24K_INSTR_EXECUTED, MIPS24K_ALL, 1},
-	{ PMC_EV_MIPS24K_BRANCH_COMPLETED, MIPS24K_CTR_0, 2},
-	{ PMC_EV_MIPS24K_BRANCH_MISPRED, MIPS24K_CTR_1, 2},
-	{ PMC_EV_MIPS24K_RETURN, MIPS24K_CTR_0, 3},
-	{ PMC_EV_MIPS24K_RETURN_MISPRED, MIPS24K_CTR_1, 3},
-	{ PMC_EV_MIPS24K_RETURN_NOT_31, MIPS24K_CTR_0, 4},
-	{ PMC_EV_MIPS24K_RETURN_NOTPRED, MIPS24K_CTR_1, 4},
-	{ PMC_EV_MIPS24K_ITLB_ACCESS, MIPS24K_CTR_0, 5},
-	{ PMC_EV_MIPS24K_ITLB_MISS, MIPS24K_CTR_1, 5},
-	{ PMC_EV_MIPS24K_DTLB_ACCESS, MIPS24K_CTR_0, 6},
-	{ PMC_EV_MIPS24K_DTLB_MISS, MIPS24K_CTR_1, 6},
-	{ PMC_EV_MIPS24K_JTLB_IACCESS, MIPS24K_CTR_0, 7},
-	{ PMC_EV_MIPS24K_JTLB_IMISS, MIPS24K_CTR_1, 7},
-	{ PMC_EV_MIPS24K_JTLB_DACCESS, MIPS24K_CTR_0, 8},
-	{ PMC_EV_MIPS24K_JTLB_DMISS, MIPS24K_CTR_1, 8},
-	{ PMC_EV_MIPS24K_IC_FETCH, MIPS24K_CTR_0, 9},
-	{ PMC_EV_MIPS24K_IC_MISS, MIPS24K_CTR_1, 9},
-	{ PMC_EV_MIPS24K_DC_LOADSTORE, MIPS24K_CTR_0, 10},
-	{ PMC_EV_MIPS24K_DC_WRITEBACK, MIPS24K_CTR_1, 10},
-	{ PMC_EV_MIPS24K_DC_MISS, MIPS24K_ALL, 11},  
+#define	MIPS24K_PMC_CAPS	(PMC_CAP_INTERRUPT | PMC_CAP_USER |     \
+				 PMC_CAP_SYSTEM | PMC_CAP_EDGE |	\
+				 PMC_CAP_THRESHOLD | PMC_CAP_READ |	\
+				 PMC_CAP_WRITE | PMC_CAP_INVERT |	\
+				 PMC_CAP_QUALIFIER)
+
+#define MIPS24K_PMC_INTERRUPT_ENABLE      0x10 /* Enable interrupts */
+#define MIPS24K_PMC_USER_ENABLE           0x08 /* Count in USER mode */
+#define MIPS24K_PMC_SUPER_ENABLE          0x04 /* Count in SUPERVISOR mode */
+#define MIPS24K_PMC_KERNEL_ENABLE         0x02 /* Count in KERNEL mode */
+#define MIPS24K_PMC_ENABLE (MIPS24K_PMC_USER_ENABLE |	   \
+			    MIPS24K_PMC_SUPER_ENABLE |	   \
+			    MIPS24K_PMC_KERNEL_ENABLE)
+
+#define MIPS24K_PMC_SELECT 5 /* Which bit position the event starts at. */
+
+const struct mips_event_code_map mips_event_codes[] = {
+	{ PMC_EV_MIPS24K_CYCLE, MIPS_CTR_ALL, 0},
+	{ PMC_EV_MIPS24K_INSTR_EXECUTED, MIPS_CTR_ALL, 1},
+	{ PMC_EV_MIPS24K_BRANCH_COMPLETED, MIPS_CTR_0, 2},
+	{ PMC_EV_MIPS24K_BRANCH_MISPRED, MIPS_CTR_1, 2},
+	{ PMC_EV_MIPS24K_RETURN, MIPS_CTR_0, 3},
+	{ PMC_EV_MIPS24K_RETURN_MISPRED, MIPS_CTR_1, 3},
+	{ PMC_EV_MIPS24K_RETURN_NOT_31, MIPS_CTR_0, 4},
+	{ PMC_EV_MIPS24K_RETURN_NOTPRED, MIPS_CTR_1, 4},
+	{ PMC_EV_MIPS24K_ITLB_ACCESS, MIPS_CTR_0, 5},
+	{ PMC_EV_MIPS24K_ITLB_MISS, MIPS_CTR_1, 5},
+	{ PMC_EV_MIPS24K_DTLB_ACCESS, MIPS_CTR_0, 6},
+	{ PMC_EV_MIPS24K_DTLB_MISS, MIPS_CTR_1, 6},
+	{ PMC_EV_MIPS24K_JTLB_IACCESS, MIPS_CTR_0, 7},
+	{ PMC_EV_MIPS24K_JTLB_IMISS, MIPS_CTR_1, 7},
+	{ PMC_EV_MIPS24K_JTLB_DACCESS, MIPS_CTR_0, 8},
+	{ PMC_EV_MIPS24K_JTLB_DMISS, MIPS_CTR_1, 8},
+	{ PMC_EV_MIPS24K_IC_FETCH, MIPS_CTR_0, 9},
+	{ PMC_EV_MIPS24K_IC_MISS, MIPS_CTR_1, 9},
+	{ PMC_EV_MIPS24K_DC_LOADSTORE, MIPS_CTR_0, 10},
+	{ PMC_EV_MIPS24K_DC_WRITEBACK, MIPS_CTR_1, 10},
+	{ PMC_EV_MIPS24K_DC_MISS, MIPS_CTR_ALL, 11},
 	/* 12 reserved */
-	{ PMC_EV_MIPS24K_STORE_MISS, MIPS24K_CTR_0, 13},
-	{ PMC_EV_MIPS24K_LOAD_MISS, MIPS24K_CTR_1, 13},
-	{ PMC_EV_MIPS24K_INTEGER_COMPLETED, MIPS24K_CTR_0, 14},
-	{ PMC_EV_MIPS24K_FP_COMPLETED, MIPS24K_CTR_1, 14},
-	{ PMC_EV_MIPS24K_LOAD_COMPLETED, MIPS24K_CTR_0, 15},
-	{ PMC_EV_MIPS24K_STORE_COMPLETED, MIPS24K_CTR_1, 15},
-	{ PMC_EV_MIPS24K_BARRIER_COMPLETED, MIPS24K_CTR_0, 16},
-	{ PMC_EV_MIPS24K_MIPS16_COMPLETED, MIPS24K_CTR_1, 16},
-	{ PMC_EV_MIPS24K_NOP_COMPLETED, MIPS24K_CTR_0, 17},
-	{ PMC_EV_MIPS24K_INTEGER_MULDIV_COMPLETED, MIPS24K_CTR_1, 17},
-	{ PMC_EV_MIPS24K_RF_STALL, MIPS24K_CTR_0, 18},
-	{ PMC_EV_MIPS24K_INSTR_REFETCH, MIPS24K_CTR_1, 18},
-	{ PMC_EV_MIPS24K_STORE_COND_COMPLETED, MIPS24K_CTR_0, 19},
-	{ PMC_EV_MIPS24K_STORE_COND_FAILED, MIPS24K_CTR_1, 19},
-	{ PMC_EV_MIPS24K_ICACHE_REQUESTS, MIPS24K_CTR_0, 20},
-	{ PMC_EV_MIPS24K_ICACHE_HIT, MIPS24K_CTR_1, 20},
-	{ PMC_EV_MIPS24K_L2_WRITEBACK, MIPS24K_CTR_0, 21},
-	{ PMC_EV_MIPS24K_L2_ACCESS, MIPS24K_CTR_1, 21},
-	{ PMC_EV_MIPS24K_L2_MISS, MIPS24K_CTR_0, 22},
-	{ PMC_EV_MIPS24K_L2_ERR_CORRECTED, MIPS24K_CTR_1, 22},
-	{ PMC_EV_MIPS24K_EXCEPTIONS, MIPS24K_CTR_0, 23},
+	{ PMC_EV_MIPS24K_STORE_MISS, MIPS_CTR_0, 13},
+	{ PMC_EV_MIPS24K_LOAD_MISS, MIPS_CTR_1, 13},
+	{ PMC_EV_MIPS24K_INTEGER_COMPLETED, MIPS_CTR_0, 14},
+	{ PMC_EV_MIPS24K_FP_COMPLETED, MIPS_CTR_1, 14},
+	{ PMC_EV_MIPS24K_LOAD_COMPLETED, MIPS_CTR_0, 15},
+	{ PMC_EV_MIPS24K_STORE_COMPLETED, MIPS_CTR_1, 15},
+	{ PMC_EV_MIPS24K_BARRIER_COMPLETED, MIPS_CTR_0, 16},
+	{ PMC_EV_MIPS24K_MIPS16_COMPLETED, MIPS_CTR_1, 16},
+	{ PMC_EV_MIPS24K_NOP_COMPLETED, MIPS_CTR_0, 17},
+	{ PMC_EV_MIPS24K_INTEGER_MULDIV_COMPLETED, MIPS_CTR_1, 17},
+	{ PMC_EV_MIPS24K_RF_STALL, MIPS_CTR_0, 18},
+	{ PMC_EV_MIPS24K_INSTR_REFETCH, MIPS_CTR_1, 18},
+	{ PMC_EV_MIPS24K_STORE_COND_COMPLETED, MIPS_CTR_0, 19},
+	{ PMC_EV_MIPS24K_STORE_COND_FAILED, MIPS_CTR_1, 19},
+	{ PMC_EV_MIPS24K_ICACHE_REQUESTS, MIPS_CTR_0, 20},
+	{ PMC_EV_MIPS24K_ICACHE_HIT, MIPS_CTR_1, 20},
+	{ PMC_EV_MIPS24K_L2_WRITEBACK, MIPS_CTR_0, 21},
+	{ PMC_EV_MIPS24K_L2_ACCESS, MIPS_CTR_1, 21},
+	{ PMC_EV_MIPS24K_L2_MISS, MIPS_CTR_0, 22},
+	{ PMC_EV_MIPS24K_L2_ERR_CORRECTED, MIPS_CTR_1, 22},
+	{ PMC_EV_MIPS24K_EXCEPTIONS, MIPS_CTR_0, 23},
 	/* Event 23 on COP0 1/3 is undefined */
-	{ PMC_EV_MIPS24K_RF_CYCLES_STALLED, MIPS24K_CTR_0, 24},
-	{ PMC_EV_MIPS24K_IFU_CYCLES_STALLED, MIPS24K_CTR_0, 25},
-	{ PMC_EV_MIPS24K_ALU_CYCLES_STALLED, MIPS24K_CTR_1, 25},
+	{ PMC_EV_MIPS24K_RF_CYCLES_STALLED, MIPS_CTR_0, 24},
+	{ PMC_EV_MIPS24K_IFU_CYCLES_STALLED, MIPS_CTR_0, 25},
+	{ PMC_EV_MIPS24K_ALU_CYCLES_STALLED, MIPS_CTR_1, 25},
 	/* Events 26 through 32 undefined or reserved to customers */
-	{ PMC_EV_MIPS24K_UNCACHED_LOAD, MIPS24K_CTR_0, 33},
-	{ PMC_EV_MIPS24K_UNCACHED_STORE, MIPS24K_CTR_1, 33},
-	{ PMC_EV_MIPS24K_CP2_REG_TO_REG_COMPLETED, MIPS24K_CTR_0, 35},
-	{ PMC_EV_MIPS24K_MFTC_COMPLETED, MIPS24K_CTR_1, 35},
+	{ PMC_EV_MIPS24K_UNCACHED_LOAD, MIPS_CTR_0, 33},
+	{ PMC_EV_MIPS24K_UNCACHED_STORE, MIPS_CTR_1, 33},
+	{ PMC_EV_MIPS24K_CP2_REG_TO_REG_COMPLETED, MIPS_CTR_0, 35},
+	{ PMC_EV_MIPS24K_MFTC_COMPLETED, MIPS_CTR_1, 35},
 	/* Event 36 reserved */
-	{ PMC_EV_MIPS24K_IC_BLOCKED_CYCLES, MIPS24K_CTR_0, 37},
-	{ PMC_EV_MIPS24K_DC_BLOCKED_CYCLES, MIPS24K_CTR_1, 37},
-	{ PMC_EV_MIPS24K_L2_IMISS_STALL_CYCLES, MIPS24K_CTR_0, 38},
-	{ PMC_EV_MIPS24K_L2_DMISS_STALL_CYCLES, MIPS24K_CTR_1, 38},
-	{ PMC_EV_MIPS24K_DMISS_CYCLES, MIPS24K_CTR_0, 39},
-	{ PMC_EV_MIPS24K_L2_MISS_CYCLES, MIPS24K_CTR_1, 39},
-	{ PMC_EV_MIPS24K_UNCACHED_BLOCK_CYCLES, MIPS24K_CTR_0, 40},
-	{ PMC_EV_MIPS24K_MDU_STALL_CYCLES, MIPS24K_CTR_0, 41},
-	{ PMC_EV_MIPS24K_FPU_STALL_CYCLES, MIPS24K_CTR_1, 41},
-	{ PMC_EV_MIPS24K_CP2_STALL_CYCLES, MIPS24K_CTR_0, 42},
-	{ PMC_EV_MIPS24K_COREXTEND_STALL_CYCLES, MIPS24K_CTR_1, 42},
-	{ PMC_EV_MIPS24K_ISPRAM_STALL_CYCLES, MIPS24K_CTR_0, 43},
-	{ PMC_EV_MIPS24K_DSPRAM_STALL_CYCLES, MIPS24K_CTR_1, 43},
-	{ PMC_EV_MIPS24K_CACHE_STALL_CYCLES, MIPS24K_CTR_0, 44},
+	{ PMC_EV_MIPS24K_IC_BLOCKED_CYCLES, MIPS_CTR_0, 37},
+	{ PMC_EV_MIPS24K_DC_BLOCKED_CYCLES, MIPS_CTR_1, 37},
+	{ PMC_EV_MIPS24K_L2_IMISS_STALL_CYCLES, MIPS_CTR_0, 38},
+	{ PMC_EV_MIPS24K_L2_DMISS_STALL_CYCLES, MIPS_CTR_1, 38},
+	{ PMC_EV_MIPS24K_DMISS_CYCLES, MIPS_CTR_0, 39},
+	{ PMC_EV_MIPS24K_L2_MISS_CYCLES, MIPS_CTR_1, 39},
+	{ PMC_EV_MIPS24K_UNCACHED_BLOCK_CYCLES, MIPS_CTR_0, 40},
+	{ PMC_EV_MIPS24K_MDU_STALL_CYCLES, MIPS_CTR_0, 41},
+	{ PMC_EV_MIPS24K_FPU_STALL_CYCLES, MIPS_CTR_1, 41},
+	{ PMC_EV_MIPS24K_CP2_STALL_CYCLES, MIPS_CTR_0, 42},
+	{ PMC_EV_MIPS24K_COREXTEND_STALL_CYCLES, MIPS_CTR_1, 42},
+	{ PMC_EV_MIPS24K_ISPRAM_STALL_CYCLES, MIPS_CTR_0, 43},
+	{ PMC_EV_MIPS24K_DSPRAM_STALL_CYCLES, MIPS_CTR_1, 43},
+	{ PMC_EV_MIPS24K_CACHE_STALL_CYCLES, MIPS_CTR_0, 44},
 	/* Event 44 undefined on 1/3 */
-	{ PMC_EV_MIPS24K_LOAD_TO_USE_STALLS, MIPS24K_CTR_0, 45},
-	{ PMC_EV_MIPS24K_BASE_MISPRED_STALLS, MIPS24K_CTR_1, 45},
-	{ PMC_EV_MIPS24K_CPO_READ_STALLS, MIPS24K_CTR_0, 46},
-	{ PMC_EV_MIPS24K_BRANCH_MISPRED_CYCLES, MIPS24K_CTR_1, 46},
+	{ PMC_EV_MIPS24K_LOAD_TO_USE_STALLS, MIPS_CTR_0, 45},
+	{ PMC_EV_MIPS24K_BASE_MISPRED_STALLS, MIPS_CTR_1, 45},
+	{ PMC_EV_MIPS24K_CPO_READ_STALLS, MIPS_CTR_0, 46},
+	{ PMC_EV_MIPS24K_BRANCH_MISPRED_CYCLES, MIPS_CTR_1, 46},
 	/* Event 47 reserved */
-	{ PMC_EV_MIPS24K_IFETCH_BUFFER_FULL, MIPS24K_CTR_0, 48},
-	{ PMC_EV_MIPS24K_FETCH_BUFFER_ALLOCATED, MIPS24K_CTR_1, 48},
-	{ PMC_EV_MIPS24K_EJTAG_ITRIGGER, MIPS24K_CTR_0, 49},
-	{ PMC_EV_MIPS24K_EJTAG_DTRIGGER, MIPS24K_CTR_1, 49},
-	{ PMC_EV_MIPS24K_FSB_LT_QUARTER, MIPS24K_CTR_0, 50},
-	{ PMC_EV_MIPS24K_FSB_QUARTER_TO_HALF, MIPS24K_CTR_1, 50},
-	{ PMC_EV_MIPS24K_FSB_GT_HALF, MIPS24K_CTR_0, 51},
-	{ PMC_EV_MIPS24K_FSB_FULL_PIPELINE_STALLS, MIPS24K_CTR_1, 51},
-	{ PMC_EV_MIPS24K_LDQ_LT_QUARTER, MIPS24K_CTR_0, 52},
-	{ PMC_EV_MIPS24K_LDQ_QUARTER_TO_HALF, MIPS24K_CTR_1, 52},
-	{ PMC_EV_MIPS24K_LDQ_GT_HALF, MIPS24K_CTR_0, 53},
-	{ PMC_EV_MIPS24K_LDQ_FULL_PIPELINE_STALLS, MIPS24K_CTR_1, 53},
-	{ PMC_EV_MIPS24K_WBB_LT_QUARTER, MIPS24K_CTR_0, 54},
-	{ PMC_EV_MIPS24K_WBB_QUARTER_TO_HALF, MIPS24K_CTR_1, 54},
-	{ PMC_EV_MIPS24K_WBB_GT_HALF, MIPS24K_CTR_0, 55},
-	{ PMC_EV_MIPS24K_WBB_FULL_PIPELINE_STALLS, MIPS24K_CTR_1, 55},
+	{ PMC_EV_MIPS24K_IFETCH_BUFFER_FULL, MIPS_CTR_0, 48},
+	{ PMC_EV_MIPS24K_FETCH_BUFFER_ALLOCATED, MIPS_CTR_1, 48},
+	{ PMC_EV_MIPS24K_EJTAG_ITRIGGER, MIPS_CTR_0, 49},
+	{ PMC_EV_MIPS24K_EJTAG_DTRIGGER, MIPS_CTR_1, 49},
+	{ PMC_EV_MIPS24K_FSB_LT_QUARTER, MIPS_CTR_0, 50},
+	{ PMC_EV_MIPS24K_FSB_QUARTER_TO_HALF, MIPS_CTR_1, 50},
+	{ PMC_EV_MIPS24K_FSB_GT_HALF, MIPS_CTR_0, 51},
+	{ PMC_EV_MIPS24K_FSB_FULL_PIPELINE_STALLS, MIPS_CTR_1, 51},
+	{ PMC_EV_MIPS24K_LDQ_LT_QUARTER, MIPS_CTR_0, 52},
+	{ PMC_EV_MIPS24K_LDQ_QUARTER_TO_HALF, MIPS_CTR_1, 52},
+	{ PMC_EV_MIPS24K_LDQ_GT_HALF, MIPS_CTR_0, 53},
+	{ PMC_EV_MIPS24K_LDQ_FULL_PIPELINE_STALLS, MIPS_CTR_1, 53},
+	{ PMC_EV_MIPS24K_WBB_LT_QUARTER, MIPS_CTR_0, 54},
+	{ PMC_EV_MIPS24K_WBB_QUARTER_TO_HALF, MIPS_CTR_1, 54},
+	{ PMC_EV_MIPS24K_WBB_GT_HALF, MIPS_CTR_0, 55},
+	{ PMC_EV_MIPS24K_WBB_FULL_PIPELINE_STALLS, MIPS_CTR_1, 55},
 	/* Events 56-63 reserved */
-	{ PMC_EV_MIPS24K_REQUEST_LATENCY, MIPS24K_CTR_0, 61},
-	{ PMC_EV_MIPS24K_REQUEST_COUNT, MIPS24K_CTR_1, 61}
+	{ PMC_EV_MIPS24K_REQUEST_LATENCY, MIPS_CTR_0, 61},
+	{ PMC_EV_MIPS24K_REQUEST_COUNT, MIPS_CTR_1, 61}
 
 };
 
-const int mips24k_event_codes_size =
-	sizeof(mips24k_event_codes) / sizeof(mips24k_event_codes[0]);
+const int mips_event_codes_size =
+	sizeof(mips_event_codes) / sizeof(mips_event_codes[0]);
 
-/*
- * Per-processor information.
- */
-struct mips24k_cpu {
-	struct pmc_hw   *pc_mipspmcs;
+struct mips_pmc_spec mips_pmc_spec = {
+	.ps_cpuclass = PMC_CLASS_MIPS24K,
+	.ps_cputype = PMC_CPU_MIPS_24K,
+	.ps_capabilities = MIPS24K_PMC_CAPS,
+	.ps_counter_width = 32
 };
 
-static struct mips24k_cpu **mips24k_pcpu;
-
 /*
  * Performance Count Register N
  */
-static uint32_t
-mips24k_pmcn_read(unsigned int pmc)
+uint64_t
+mips_pmcn_read(unsigned int pmc)
 {
 	uint32_t reg = 0;
 
-	KASSERT(pmc < mips24k_npmcs, ("[mips,%d] illegal PMC number %d", 
+	KASSERT(pmc < mips_npmcs, ("[mips24k,%d] illegal PMC number %d",
 				   __LINE__, pmc));
 
 	/* The counter value is the next value after the control register. */
@@ -194,13 +184,13 @@ mips24k_pmcn_read(unsigned int pmc)
 	return (reg);
 }
 
-static uint32_t
-mips24k_pmcn_write(unsigned int pmc, uint32_t reg)
+uint64_t
+mips_pmcn_write(unsigned int pmc, uint64_t reg)
 {
 
-	KASSERT(pmc < mips24k_npmcs, ("[mips,%d] illegal PMC number %d", 
+	KASSERT(pmc < mips_npmcs, ("[mips24k,%d] illegal PMC number %d",
 				   __LINE__, pmc));
-	
+
 	switch (pmc) {
 	case 0:
 		mips_wr_perfcnt1(reg);
@@ -214,40 +204,17 @@ mips24k_pmcn_write(unsigned int pmc, uin
 	return (reg);
 }
 
-static int
-mips24k_allocate_pmc(int cpu, int ri, struct pmc *pm,
-  const struct pmc_op_pmcallocate *a)
+uint32_t
+mips_get_perfctl(int cpu, int ri, uint32_t event, uint32_t caps)
 {
-	enum pmc_event pe;
-	uint32_t caps, config, counter;
-	int i;
-
-	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
-	    ("[mips,%d] illegal CPU value %d", __LINE__, cpu));
-	KASSERT(ri >= 0 && ri < mips24k_npmcs,
-	    ("[mips,%d] illegal row index %d", __LINE__, ri));
-
-	caps = a->pm_caps;
-	if (a->pm_class != PMC_CLASS_MIPS24K)
-		return (EINVAL);
-	pe = a->pm_ev;
-	for (i = 0; i < mips24k_event_codes_size; i++) {
-		if (mips24k_event_codes[i].pe_ev == pe) {
-			config = mips24k_event_codes[i].pe_code;
-			counter =  mips24k_event_codes[i].pe_counter;
-			break;
-		}
-	}
-	if (i == mips24k_event_codes_size)
-		return (EINVAL);
+	uint32_t config;
 
-	if ((counter != MIPS24K_ALL) && (counter != ri))
-		return (EINVAL);
+	config = event;
 
 	config <<= MIPS24K_PMC_SELECT;
 
 	if (caps & PMC_CAP_SYSTEM)
-		config |= (MIPS24K_PMC_SUPER_ENABLE | 
+		config |= (MIPS24K_PMC_SUPER_ENABLE |
 			   MIPS24K_PMC_KERNEL_ENABLE);
 	if (caps & PMC_CAP_USER)
 		config |= MIPS24K_PMC_USER_ENABLE;
@@ -256,374 +223,7 @@ mips24k_allocate_pmc(int cpu, int ri, st
 	if (caps & PMC_CAP_INTERRUPT)
 		config |= MIPS24K_PMC_INTERRUPT_ENABLE;
 
-	pm->pm_md.pm_mips24k.pm_mips24k_evsel = config;
-
-	PMCDBG(MDP,ALL,2,"mips-allocate ri=%d -> config=0x%x", ri, config);
-
-	return 0;
-}
-
-
-static int
-mips24k_read_pmc(int cpu, int ri, pmc_value_t *v)
-{
-	struct pmc *pm;
-	pmc_value_t tmp;
-
-	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
-	    ("[mips,%d] illegal CPU value %d", __LINE__, cpu));
-	KASSERT(ri >= 0 && ri < mips24k_npmcs,
-	    ("[mips,%d] illegal row index %d", __LINE__, ri));
-
-	pm  = mips24k_pcpu[cpu]->pc_mipspmcs[ri].phw_pmc;
-	tmp = mips24k_pmcn_read(ri);
-	PMCDBG(MDP,REA,2,"mips-read id=%d -> %jd", ri, tmp);
-	if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
-		*v = MIPS24K_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp);
-	else
-		*v = tmp;
-
-	return 0;
-}
-
-static int
-mips24k_write_pmc(int cpu, int ri, pmc_value_t v)
-{
-	struct pmc *pm;
-
-	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
-	    ("[mips,%d] illegal CPU value %d", __LINE__, cpu));
-	KASSERT(ri >= 0 && ri < mips24k_npmcs,
-	    ("[mips,%d] illegal row-index %d", __LINE__, ri));
-
-	pm  = mips24k_pcpu[cpu]->pc_mipspmcs[ri].phw_pmc;
-
-	if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
-		v = MIPS24K_RELOAD_COUNT_TO_PERFCTR_VALUE(v);
-	
-	PMCDBG(MDP,WRI,1,"mips-write cpu=%d ri=%d v=%jx", cpu, ri, v);
-
-	mips24k_pmcn_write(ri, v);
-
-	return 0;
-}
-
-static int
-mips24k_config_pmc(int cpu, int ri, struct pmc *pm)
-{
-	struct pmc_hw *phw;
-
-	PMCDBG(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm);
-
-	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
-	    ("[mips,%d] illegal CPU value %d", __LINE__, cpu));
-	KASSERT(ri >= 0 && ri < mips24k_npmcs,
-	    ("[mips,%d] illegal row-index %d", __LINE__, ri));
-
-	phw = &mips24k_pcpu[cpu]->pc_mipspmcs[ri];
-
-	KASSERT(pm == NULL || phw->phw_pmc == NULL,
-	    ("[mips,%d] pm=%p phw->pm=%p hwpmc not unconfigured",
-	    __LINE__, pm, phw->phw_pmc));
-
-	phw->phw_pmc = pm;
-
-	return 0;
-}
-
-static int
-mips24k_start_pmc(int cpu, int ri)
-{
-	uint32_t config;
-        struct pmc *pm;
-        struct pmc_hw *phw;
-
-	phw    = &mips24k_pcpu[cpu]->pc_mipspmcs[ri];
-	pm     = phw->phw_pmc;
-	config = pm->pm_md.pm_mips24k.pm_mips24k_evsel;
-
-	/* Enable the PMC. */
-	switch (ri) {
-	case 0:
-		mips_wr_perfcnt0(config);
-		break;
-	case 1:
-		mips_wr_perfcnt2(config);
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int
-mips24k_stop_pmc(int cpu, int ri)
-{
-        struct pmc *pm;
-        struct pmc_hw *phw;
-
-	phw    = &mips24k_pcpu[cpu]->pc_mipspmcs[ri];
-	pm     = phw->phw_pmc;
-
-	/*
-	 * Disable the PMCs.
-	 *
-	 * Clearing the entire register turns the counter off as well
-	 * as removes the previously sampled event.
-	 */
-	switch (ri) {
-	case 0:
-		mips_wr_perfcnt0(0);
-		break;
-	case 1:
-		mips_wr_perfcnt2(0);
-		break;
-	default:
-		break;
-	}
-	return 0;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list