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/