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

Time measurement using Performance Monitors Register on Cortex-A72

Hi all,

I am writing the Bare Metal program on ARM Cortex-A72. I follow some examples to configure the Performance Monitors Registers to do timing measurement.

The initializing step is as below:

Set bit EN, ER, CR (bit 0, 2, 3) of PMUSERENR_EL0 to 1

Set bit E, C, P (bit 0, 1, 2) of PMCR_EL0 to 1

Set bit C (bit 31) of PMCNTENSET_EL0 to 1

After initalize, I read back the register value is:

  • PMUSERENR_EL0 : 0xD
  • PMCR_EL0 : 0x41023001
  • PMCNTENSET_EL0 : 0x80000000

However, when I read the counter by reading the register PMCCNTR_EL0, I always get 0.

May I know any wrong with the setting? Or can you suggest any way to resolve it? Thanks a lot for your help

Parents
  • Hi Willy Wolff,

    Thanks a lot for your answer.

    I also got the answer from another source and just share it here in case any other needs:

    static void enable_cycle_counter_el0(void)
    {
    	uint64_t val;
    	/* Disable cycle counter overflow interrupt */
    	asm volatile("msr pmintenset_el1, %0" : : "r" ((uint64_t)(0 << 31)));
    	/* Enable cycle counter */
    	asm volatile("msr pmcntenset_el0, %0" :: "r" (1 << 31));
    	/* Enable user-mode access to cycle counters. */
    	asm volatile("msr pmuserenr_el0, %0" :: "r" ((1 << 0) | (1 << 2)));
    	/* Clear cycle counter and start */
    	asm volatile("mrs %0, pmcr_el0" : "=r" (val));
    	val |= ((1 << 0) | (1 << 2));
    	asm volatile("isb");
    	asm volatile("msr pmcr_el0, %0" :: "r" (val));
    	val = (1 << 27);
    	asm volatile("msr pmccfiltr_el0, %0" :: "r" (val));
    }
    
    static inline uint64_t read_pmccntr(void)
    {
    	uint64_t val;
    	asm volatile("mrs %0, pmccntr_el0" : "=r"(val));
    	return val;
    }

Reply
  • Hi Willy Wolff,

    Thanks a lot for your answer.

    I also got the answer from another source and just share it here in case any other needs:

    static void enable_cycle_counter_el0(void)
    {
    	uint64_t val;
    	/* Disable cycle counter overflow interrupt */
    	asm volatile("msr pmintenset_el1, %0" : : "r" ((uint64_t)(0 << 31)));
    	/* Enable cycle counter */
    	asm volatile("msr pmcntenset_el0, %0" :: "r" (1 << 31));
    	/* Enable user-mode access to cycle counters. */
    	asm volatile("msr pmuserenr_el0, %0" :: "r" ((1 << 0) | (1 << 2)));
    	/* Clear cycle counter and start */
    	asm volatile("mrs %0, pmcr_el0" : "=r" (val));
    	val |= ((1 << 0) | (1 << 2));
    	asm volatile("isb");
    	asm volatile("msr pmcr_el0, %0" :: "r" (val));
    	val = (1 << 27);
    	asm volatile("msr pmccfiltr_el0, %0" :: "r" (val));
    }
    
    static inline uint64_t read_pmccntr(void)
    {
    	uint64_t val;
    	asm volatile("mrs %0, pmccntr_el0" : "=r"(val));
    	return val;
    }

Children
No data