This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

PMU in Cortex-A8 (OMAP 3530) - What am I doing wrong?

Note: This was originally posted on 1st June 2011 at http://forums.arm.com

I've been trying to use the PMU in the OMAP3530 (on a beagleboard) to do some profiling, but I don't seem to be able to get the 4 PMU counters to do anything - they always read 0. The cycle counter works well enough. Here's some disassembly from the code that I'm running:



...

;;    _setCounting(1)
ee19 1f1c    mrc  15, 0, r1, cr9, cr12, {0}
f041 0001    orr.w   r0, r1, #1
ee09 0f1c    mcr  15, 0, r0, cr9, cr12, {0}

;;    _resetClockCounter();
ee19 3f1c    mrc  15, 0, r3, cr9, cr12, {0}
f043 0704    orr.w   r7, r3, #4
ee09 7f1c    mcr  15, 0, r7, cr9, cr12, {0}

;;    _resetEventCounters();
ee19 6f1c    mrc  15, 0, r6, cr9, cr12, {0}
f046 0c02    orr.w   ip, r6, #2
ee09 cf1c    mcr  15, 0, ip, cr9, cr12, {0}

;;    _selectPerfCounter(0);
;;    _setPerfCounterFunction( count0func=0x8 );
2200            movs    r2, #0
ee09 2fbc    mcr  15, 0, r2, cr9, cr12, {5}
2108            movs    r1, #8
ee09 1f3d    mcr  15, 0, r1, cr9, cr13, {1}

;;    _selectPerfCounter(1);
;;    _setPerfCounterFunction( count1func=0xf );
2001            movs    r0, #1
ee09 0fbc    mcr  15, 0, r0, cr9, cr12, {5}
230f            movs    r3, #15
ee09 3f3d    mcr  15, 0, r3, cr9, cr13, {1}

;;    _selectPerfCounter(2);
;;    _setPerfCounterFunction( count2func=0x11 );
2702            movs    r7, #2
ee09 7fbc    mcr  15, 0, r7, cr9, cr12, {5}
2611            movs    r6, #17
ee09 6f3d    mcr  15, 0, r6, cr9, cr13, {1}

;;    _selectPerfCounter(3);
;;    _setPerfCounterFunction( count3func=0x40 );
2203            movs    r2, #3
ee09 2fbc    mcr  15, 0, r2, cr9, cr12, {5}
2140            movs    r1, #64 ; 0x40
ee09 1f3d    mcr  15, 0, r1, cr9, cr13, {1}

;;    _enableCounters(1, 1, 1, 1, 1);
200f            movs    r0, #15
f2c8 0000    movt    r0, #32768      ; 0x8000
ee09 0f3c    mcr  15, 0, r0, cr9, cr12, {1}

...


After this, when I read from the PMU registers, this is what I see:


PMNC:   41002001 
CNTENS: 8000000f       
CNTENC: 8000000f  
FLAG:   00000000  
CCNT:   0000009f 
PMCNT0: 00000000       
PMCNT1: 00000000       
PMCNT2: 00000000       
PMCNT3: 00000000       
USEREN: 00000001


Any ideas what I'm doing wrong here?
Parents
  • Note: This was originally posted on 16th September 2011 at http://forums.arm.com


    Hi TedM,

    I am experiencing the same problems of not getting the performance counters to work - they always contain 0. But I have this problem also in the kernel. I'm working with the OMAP3430-based Nokia N900 phone which uses the ARM Cortex A-8. Maybe you have some idea of what I am doing wrong here? Here is my code, running in the init-method of a kernel module, thus in privileged mode:

    ...

    As you can see, the cycle counter works just fine, but the first event counter, which should count the number of issues instructions (0x55), contains 0. As far as I can see, both PMNC and CNTENS indicate that the counter should be active. I have even made sure the kernel does not put any hardware to sleep when idling, to avoid loosing state, although it should anyway not happen printk().

    I was hoping maybe you have some idea of what is wrong here. Did you gain any recent insights wrt. secured privileged mode? Could this be the issue also with my code? I did not figure out how to put the CPU in this mode, as I thought that running in privileged mode in the kernel was sufficient...



    I've played around with this a bit longer, and here's what I've learned:

    - You're absolutely right about kernel mode. I successfully tested the counters in U-Boot and erroneously concluded that they would work in kernel mode under any conditions. I've since tried the counters in a Linux kernel module, and they don't work there either. To date, the only circumstances that I've been able to make them work on the OMAP3530 is in U-Boot - they're non-functional in Linux in kernel mode and user mode. I seem to recall that the ARMv7 docs make a distinction between the kernel mode that the CPU runs in once the OS has booted up, versus the pseudo-kernel mode that the CPU is in in it's reset state, so perhaps the counters are just plain broken under kernel mode.

    - The counters stop working sometime during the Linux boot process. They work quite nicely in U-Boot just before U-Boot calls the linux kernel entry point. By the time the first C code gets executed in the linux kernel in start_kernel(), the counters have stopped working. Something in the ARM boot assembly code fubars the counters. I've looked over the assembly code carefully and I can't see anything that looks strange.

    - I've since moved my development on to a different TI chip (a CortexA8 DaVinci chip) and that chip has working performance counters. They work in linux kernel modules, and they work in user mode as long as the USEREN bit is set - just as documented. Just to be clear, my counter code hasn't changed at all - it works on the DaVinci chip but not on the OMAP3530.

    - I'm not sure that secure vs non-secure has anything to do with it. I've looked at the docs more carefully and it seems to imply that the counters should always be working in the non-secure kernel mode. There are settings that determine whether the counters will work in secure mode (probably to prevent nonsecure code from profiling and thus gaining insights into secure code), but I don't think that that applies here.

    My guess at this point is that the OMAP 3XXX chips are just plain broken. I'm thinking that something bad happens when the MMU is turned on and that that breaks the counters. The next step I guess would be to isolate where in head.S the counters stop working.
Reply
  • Note: This was originally posted on 16th September 2011 at http://forums.arm.com


    Hi TedM,

    I am experiencing the same problems of not getting the performance counters to work - they always contain 0. But I have this problem also in the kernel. I'm working with the OMAP3430-based Nokia N900 phone which uses the ARM Cortex A-8. Maybe you have some idea of what I am doing wrong here? Here is my code, running in the init-method of a kernel module, thus in privileged mode:

    ...

    As you can see, the cycle counter works just fine, but the first event counter, which should count the number of issues instructions (0x55), contains 0. As far as I can see, both PMNC and CNTENS indicate that the counter should be active. I have even made sure the kernel does not put any hardware to sleep when idling, to avoid loosing state, although it should anyway not happen printk().

    I was hoping maybe you have some idea of what is wrong here. Did you gain any recent insights wrt. secured privileged mode? Could this be the issue also with my code? I did not figure out how to put the CPU in this mode, as I thought that running in privileged mode in the kernel was sufficient...



    I've played around with this a bit longer, and here's what I've learned:

    - You're absolutely right about kernel mode. I successfully tested the counters in U-Boot and erroneously concluded that they would work in kernel mode under any conditions. I've since tried the counters in a Linux kernel module, and they don't work there either. To date, the only circumstances that I've been able to make them work on the OMAP3530 is in U-Boot - they're non-functional in Linux in kernel mode and user mode. I seem to recall that the ARMv7 docs make a distinction between the kernel mode that the CPU runs in once the OS has booted up, versus the pseudo-kernel mode that the CPU is in in it's reset state, so perhaps the counters are just plain broken under kernel mode.

    - The counters stop working sometime during the Linux boot process. They work quite nicely in U-Boot just before U-Boot calls the linux kernel entry point. By the time the first C code gets executed in the linux kernel in start_kernel(), the counters have stopped working. Something in the ARM boot assembly code fubars the counters. I've looked over the assembly code carefully and I can't see anything that looks strange.

    - I've since moved my development on to a different TI chip (a CortexA8 DaVinci chip) and that chip has working performance counters. They work in linux kernel modules, and they work in user mode as long as the USEREN bit is set - just as documented. Just to be clear, my counter code hasn't changed at all - it works on the DaVinci chip but not on the OMAP3530.

    - I'm not sure that secure vs non-secure has anything to do with it. I've looked at the docs more carefully and it seems to imply that the counters should always be working in the non-secure kernel mode. There are settings that determine whether the counters will work in secure mode (probably to prevent nonsecure code from profiling and thus gaining insights into secure code), but I don't think that that applies here.

    My guess at this point is that the OMAP 3XXX chips are just plain broken. I'm thinking that something bad happens when the MMU is turned on and that that breaks the counters. The next step I guess would be to isolate where in head.S the counters stop working.
Children
No data