Hi folks,

Attached is a patch that does a more-optimal rank based allocation of
PMU registers for MIPS. Basically assign registers with lower available
resources first.

This will help those of you running on MIPS variants with more than 2
counters...(keep in mind that the previous version of the kernel patch
only has support for 2.)

Phil


? oprofile2pfm.pl
? examples/multiplex
? examples/multiplex2
? examples/notify_self
? examples/notify_self2
? examples/notify_self3
? examples/notify_standalone
? examples/pfmsetup
? examples/self
? examples/self_standalone
? examples/self_view
? examples/set_notify
? examples/showevtinfo
? examples/showreginfo
? examples/smpl_standalone
? examples/syst
? examples/task
? examples/task_attach
? examples/task_attach_timeout
? examples/task_smpl
? examples/task_smpl_user
? examples/whichpmu
? lib/libpfm.so.3.2.0
? lib/pfmlib_common.lo
? lib/pfmlib_gen_mips64.lo
? lib/pfmlib_os.lo
? lib/pfmlib_priv.lo
Index: lib/pfmlib_gen_mips64.c
===================================================================
RCS file: /cvsroot/perfmon2/libpfm/lib/pfmlib_gen_mips64.c,v
retrieving revision 1.13
diff -r1.13 pfmlib_gen_mips64.c
192a193,214
> static void stuff_regs(pfmlib_event_t *e, int plm, pfmlib_reg_t *pc, pfmlib_reg_t *pd, int cntr, int j)
> {
>   pfm_gen_mips64_sel_reg_t reg;
>   reg.val    = 0; /* assume reserved bits are zerooed */
>   /* if plm is 0, then assume not specified per-event and use default */
>   plm = e[j].plm ? e[j].plm : plm;
>   reg.sel_usr = plm & PFM_PLM3 ? 1 : 0;
>   reg.sel_os  = plm & PFM_PLM2 ? 1 : 0;
>   reg.sel_sup = plm & PFM_PLM1 ? 1 : 0;
>   reg.sel_exl = plm & PFM_PLM0 ? 1 : 0;
>   reg.sel_int = 1; /* force int to 1 */
> 
>   reg.sel_event_mask = (gen_mips64_pe[e[j].event].pme_entry_code.pme_code.pme_emask 
> 			>> (cntr*8)) & 0xff;
>   DPRINT(("sel_event_mask is 0x%x\n",reg.sel_event_mask));
>   pc[j].reg_num     = cntr;
>   pc[j].reg_value   = reg.val;
>   pc[j].reg_addr    = cntr*2;
> 
>   pd[j].reg_num  = cntr;
>   pd[j].reg_addr = cntr*2 + 1;
> }
201d222
< 	pfm_gen_mips64_sel_reg_t reg;
204,206c225
< 	unsigned long plm;
< 	unsigned int j, cnt = inp->pfp_event_count;
< 	unsigned int assign[PMU_GEN_MIPS64_NUM_COUNTERS];
---
> 	unsigned int i, j, cnt = inp->pfp_event_count;
222,223c241,243
< 	/* First find out which events live on only 1 counter. */
< 	for (j=0; j < cnt ; j++ ) 
---
> 	/* Do rank based allocation, counters that live on 1 reg 
> 	   before counters that live on 2 regs etc. */
> 	for (i=1;i<=PMU_GEN_MIPS64_NUM_COUNTERS;i++)
225,256c245,266
< 	    unsigned long tmp = gen_mips64_pe[e[j].event].pme_counters;
< 	    if (pfmlib_popcnt(tmp) != 1)
< 	      assign[j] = 0;
< 	    else 
< 	      assign[j] = tmp;
< 	  }
< 
< 	/* Assign them first */
< 	for (j=0; j < cnt ; j++ ) {
< 	  if ((assign[j] & used) == 0) {
< 	        uint32_t cntr;
< 		reg.val    = 0; /* assume reserved bits are zerooed */
< 		/* if plm is 0, then assume not specified per-event and use default */
< 		plm = e[j].plm ? e[j].plm : inp->pfp_dfl_plm;
< 		reg.sel_usr = plm & PFM_PLM3 ? 1 : 0;
< 		reg.sel_os  = plm & PFM_PLM2 ? 1 : 0;
< 		reg.sel_sup = plm & PFM_PLM1 ? 1 : 0;
< 		reg.sel_exl = plm & PFM_PLM0 ? 1 : 0;
< 		reg.sel_int = 1; /* force int to 1 */
< 		cntr = ffs(assign[j]) - 1;
< 
< 		reg.sel_event_mask = (gen_mips64_pe[e[j].event].pme_entry_code.pme_code.pme_emask >> (cntr*8)) & 0xff;
< 
< 		pc[j].reg_num     = cntr;
< 		pc[j].reg_value   = reg.val;
< 		pc[j].reg_addr    = cntr*2;
< 
< 		pd[j].reg_num  = cntr;
< 		pd[j].reg_addr = cntr*2 + 1;
< 
< 		used |= (1 << cntr);
< 		DPRINT(("Degree 1: Used counters %x\n",used));
---
> 	    for (j=0; j < cnt;j++) 
> 	      {
> 		unsigned int cntr, avail;
> 		if (pfmlib_popcnt(gen_mips64_pe[e[j].event].pme_counters) == i)
> 		  {
> 		    /* These counters can be used for this event */
> 		    avail = ~used & gen_mips64_pe[e[j].event].pme_counters;
> 		    DPRINT(("%d: Counters available %x\n",i,avail));
> 		    if (avail == 0x0)
> 		      return PFMLIB_ERR_NOASSIGN;
> 
> 		    /* Pick one, mark as used*/
> 		    cntr = ffs(avail) - 1;
> 		    DPRINT(("%d: Chose counter %d\n",i,cntr));
> 	    
> 		    /* Update registers */
> 		    stuff_regs(e,inp->pfp_dfl_plm,pc,pd,cntr,j);
> 		    
> 		    used |= (1 << cntr);
> 		    DPRINT(("%d: Used counters %x\n",i, used));
> 		  }
> 	      }
258,296d267
< 	  else {
< 	    return PFMLIB_ERR_NOASSIGN;
< 	  }
< 	}
< 
< 	/* Now assign those that live on two counters. */
< 	for (j=0; j < cnt ; j++ ) {
< 	  if (assign[j] == 0) {
< 	    /* Which counters are available */
< 	    unsigned int cntr, avail = (~used & 0xf);
< 	    DPRINT(("Counters available: %x\n",avail));
< 	    if (avail == 0x0)
< 	      return PFMLIB_ERR_NOASSIGN;
< 	    /* Pick one */
< 	    reg.val    = 0; /* assume reserved bits are zerooed */
< 	    /* if plm is 0, then assume not specified per-event and use default */
< 	    plm = e[j].plm ? e[j].plm : inp->pfp_dfl_plm;
< 	    reg.sel_usr = plm & PFM_PLM3 ? 1 : 0;
< 	    reg.sel_os  = plm & PFM_PLM2 ? 1 : 0;
< 	    reg.sel_sup = plm & PFM_PLM1 ? 1 : 0;
< 	    reg.sel_exl = plm & PFM_PLM0 ? 1 : 0;
< 	    reg.sel_int = 1; /* force int to 1 */
< 	    cntr = ffs(avail) - 1;
< 	    avail = 1 << cntr;
< 	    DPRINT(("Selected counter %d\n",avail));
< 
< 	    reg.sel_event_mask = (gen_mips64_pe[e[j].event].pme_entry_code.pme_code.pme_emask >> (cntr*8)) & 0xff;
< 
< 	    pc[j].reg_num     = cntr;
< 	    pc[j].reg_value   = reg.val;
< 	    pc[j].reg_addr    = cntr*2;
< 
< 	    pd[j].reg_num  = cntr;
< 	    pd[j].reg_addr = cntr*2 + 1;
< 
< 	    used |= (1 << cntr);
< 	    DPRINT(("Degree N: Used counters %x\n",used));
< 	  }
< 	}
_______________________________________________
perfmon mailing list
[email protected]
http://www.hpl.hp.com/hosted/linux/mail-archives/perfmon/

Reply via email to