Monday 27 February 2012

Kids! Want to use the ARM PMU event counters on DM3730?

There is a long-standing bug that prevents DM3730 users from using the ARM performance monitor counters on OMAP3 (my machine is a Beagle xM with a DM3730 on it).

The PMU counters are described in ARM DDI0344K, s. 3.2.42-3.2.51 and allow one to count interesting events such as data fetches, TLB and cache misses, and so on. There are four PMU counters and one cycle counter.

In order to access these from userspace, one must persuade a kernel module (or the kernel itself) to perform:

 {
     int fred = 1;
     asm("MCR p15,0,%[r], c9, c14, 0" : : [r] "r" (fred));
 }

However, if one does this in a 'stock' 3.2.0 kernel (or before, I guess), one will find that only the cycle counter works - the others are all stuck at whatever value you last wrote into them (not necessarily zero, oddly enough).

This is because the four performance unit counters are clocked from the EMU clock domain, which is in turn in the EMU power domain, which is turned off by the kernel shortly after boot, since nothing is currently using it.

The "right way" to turn it on again would be by calling clk_enable() on emu_src_clk. However, a bug in the power management subsystem means that whilst this will attempt to turn on the EMU domain clocks, it will fail to turn on the EMU power domain and the counters will remain stuck.

Since that bit of the kernel is in flux right now, a quick hack to get you going is to find arch/arm/mach-omap2/clockdomains3xxx_data.c and change:

static struct clockdomain emu_clkdm = {
.name  = "emu_clkdm",
.pwrdm  = { .name = "emu_pwrdm" },
.flags  = /* CLKDM_CAN_ENABLE_AUTO |  */ CLKDM_CAN_SWSUP,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK,
};

to

static struct clockdomain emu_clkdm = {
.name  = "emu_clkdm",
.pwrdm  = { .name = "emu_pwrdm" },
.flags  = /* CLKDM_CAN_ENABLE_AUTO |  *//*CLKDM_CAN_SWSUP*/ 0,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK,
};

Thus stopping the kernel from ever suspending that domain. No guarantees that this works over suspend/resume, but it at least allows you to clock the counters.

1 comment:

Lamda said...

Thanks for this advice Richard! it took me several hours to find this post!

I can see the event counters working smoothly now!

Thank you very much mate!

Post a Comment