Hi Everyone,
i need help about timing measurements on Cortex-A72 (Arm v8) 64-bit running Linux.
i have been trying to read cycle counter (i have got root priviledges on machine), but i can't.
my c code is :
#define _GNU_SOURCE#include <stdbool.h>#include <stdio.h>#include <stdlib.h>#include <sched.h>#include <unistd.h>#include <inttypes.h>#include <getopt.h>#include <sched.h>#include <assert.h>#include <sys/stat.h>#include <fcntl.h>#define ARMV8_PMCR_E (1 << 0) /* Enable all counters */#define ARMV8_PMCR_P (1 << 1) /* Reset all counters */#define ARMV8_PMCR_C (1 << 2) /* Cycle counter reset */#define ARMV8_PMUSERENR_EN (1 << 0) /* EL0 access enable */#define ARMV8_PMUSERENR_CR (1 << 2) /* Cycle counter read enable */#define ARMV8_PMUSERENR_ER (1 << 3) /* Event counter read enable */#define ARMV8_PMCNTENSET_EL0_EN (1 << 31) /* Performance Monitors Count Enable Set register */void arm_v8_flush(void* address){ asm volatile ("DC CIVAC, %0" :: "r"(address)); asm volatile ("DSB ISH"); asm volatile ("ISB");}void arm_v8_access_memory(void* pointer){ volatile uint32_t value; asm volatile ("LDR %0, [%1]\n\t" : "=r" (value) : "r" (pointer) );}void arm_v8_memory_barrier(void){ asm volatile ("DSB SY"); asm volatile ("ISB");}void arm_v8_prefetch(void* pointer){ asm volatile ("PRFM PLDL3KEEP, [%x0]" :: "p" (pointer)); asm volatile ("PRFM PLDL2KEEP, [%x0]" :: "p" (pointer)); asm volatile ("PRFM PLDL1KEEP, [%x0]" :: "p" (pointer));}uint64_t arm_v8_get_timing(void) { uint64_t result = 0; asm volatile("MRS %0, PMCCNTR_EL0" : "=r" (result)); return result;}void arm_v8_timing_init(void) { uint32_t value = 0; /* Enable Performance Counter */ asm volatile("MRS %0, PMCR_EL0" : "=r" (value)); value |= ARMV8_PMCR_E; /* Enable */ value |= ARMV8_PMCR_C; /* Cycle counter reset */ value |= ARMV8_PMCR_P; /* Reset all counters */ asm volatile("MSR PMCR_EL0, %0" : : "r" (value)); /* Enable cycle counter register */ asm volatile("MRS %0, PMCNTENSET_EL0" : "=r" (value)); value |= ARMV8_PMCNTENSET_EL0_EN; asm volatile("MSR PMCNTENSET_EL0, %0" : : "r" (value));}void arm_v8_timing_terminate(void){ uint32_t value = 0; uint32_t mask = 0; /* Disable Performance Counter */ asm volatile("MRS %0, PMCR_EL0" : "=r" (value)); mask = 0; mask |= ARMV8_PMCR_E; /* Enable */ mask |= ARMV8_PMCR_C; /* Cycle counter reset */ mask |= ARMV8_PMCR_P; /* Reset all counters */ asm volatile("MSR PMCR_EL0, %0" : : "r" (value & ~mask)); /* Disable cycle counter register */ asm volatile("MRS %0, PMCNTENSET_EL0" : "=r" (value)); mask = 0; mask |= ARMV8_PMCNTENSET_EL0_EN; asm volatile("MSR PMCNTENSET_EL0, %0" : : "r" (value & ~mask));} void arm_v8_reset_timing(void) { uint32_t value = 0; asm volatile("MRS %0, PMCR_EL0" : "=r" (value)); value |= ARMV8_PMCR_C; /* Cycle counter reset */ asm volatile("MSR PMCR_EL0, %0" : : "r" (value));}int main(){ int x =10; arm_v8_timing_init(); arm_v8_memory_barrier(); uint64_t time = arm_v8_get_timing(); arm_v8_memory_barrier(); arm_v8_access_memory(&x); arm_v8_memory_barrier(); uint64_t time2 = arm_v8_get_timing(); arm_v8_memory_barrier(); uint64_t delta = time2 - time; arm_v8_timing_terminate(); }
Running the code with root priviledges the compiler gives me : Ilegal instruction.
why ?
thank you.
Thank you for the answer, i got it using a kernel module to enable the user space to read cycle counter.