summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYogesh Tillu <yogesh.tillu@linaro.org>2015-04-13 13:12:57 +0530
committerYogesh Tillu <yogesh.tillu@linaro.org>2015-04-15 08:02:18 +0530
commitc2d000e20ceac2a1d8e6111f5a01def9dc294d0b (patch)
treea049bea2c2d41df81448573dda32ce7b3881880a
parent5bfdec46898d6e9ce6cd9371fcf676ce1856c14e (diff)
perf_rc_mmap:
Added support for all perf hw counter Added getopt support for argument Added print_usage for help Reviewed-by: Anders Roxell <anders.roxell@linaro.org> Signed-off-by: Yogesh Tillu <yogesh.tillu@linaro.org>
-rw-r--r--perf_rc_mmap.c109
1 files changed, 80 insertions, 29 deletions
diff --git a/perf_rc_mmap.c b/perf_rc_mmap.c
index 2c404dc..180ddd7 100644
--- a/perf_rc_mmap.c
+++ b/perf_rc_mmap.c
@@ -20,29 +20,42 @@
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
-#define barrier() asm volatile("dmb ish" ::: "memory")
-#define isb() asm volatile("isb" ::: "memory")
+#include <getopt.h>
+#define barrier() asm volatile("dmb ish" : : : "memory")
+#define isb() asm volatile("isb" : : : "memory")
+#define ARMV8_PMCNTENSET_EL0_ENABLE (1<<31) /**< Enable Perf count reg */
static int fddev = -1;
-__attribute__((constructor)) static void
-init(void)
+static unsigned long page_size;
+
+static int counter_init(unsigned int counter)
{
static struct perf_event_attr attr;
attr.type = PERF_TYPE_HARDWARE;
- attr.config = PERF_COUNT_HW_CPU_CYCLES;
+ if (counter < 0 || counter > PERF_COUNT_HW_MAX)
+ return -1;
+
+ attr.config = counter;
fddev = syscall(__NR_perf_event_open, &attr, 0, -1, -1, 0);
-}
+ if (fddev == -1) {
+ fprintf(stderr,
+ "Error opening perf_event_open for counter %llx\n",
+ attr.config);
+ return -1;
+ }
-__attribute__((destructor)) static void
-fini(void)
-{
- close(fddev);
+ return 0;
}
-#define ARMV8_PMCNTENSET_EL0_ENABLE (1<<31) /**< Enable Perf count reg */
static unsigned long rdpmc(unsigned int counter)
{
unsigned long int ret;
- asm volatile("mrs %0, pmccntr_el0" : "=r" (ret));
+ if (counter == PERF_COUNT_HW_CPU_CYCLES)
+ asm volatile("mrs %0, pmccntr_el0" : "=r" (ret));
+ else {
+ asm volatile("msr pmselr_el0, %0" : : "r" ((counter-1)));
+ asm volatile("mrs %0, pmxevcntr_el0" : "=r" (ret));
+ }
+
isb();
return ret;
}
@@ -62,11 +75,12 @@ static unsigned long mmap_read_self(void *addr)
pmc = rdpmc(idx - 1);
barrier();
} while (pc->lock != seq);
+
count = pmc;
return count;
}
-/* Simple loop body to keep things interested. Make sure it gets inlined. */
+/* loop body to keep things interested. Make sure it gets inlined. */
static inline int
loop(int* __restrict__ a, int* __restrict__ b, int n)
{
@@ -75,44 +89,74 @@ loop(int* __restrict__ a, int* __restrict__ b, int n)
for (i = 0; i < n; ++i)
if (a[i] > b[i])
sum += a[i] + 5;
+
return sum;
}
-static unsigned long page_size;
-
-int main(int ac, char **av)
+void print_usage(char *argv)
{
- long long time_start = 0;
- long long time_end = 0;
+ printf("Usage: %s -c perf_hw_counter -n length\n"
+ "%s - read perf hardware counters from userspace\n\n"
+ "-c\t perf_hw_counter is enum value of hw counter for platform\n"
+ "Refer to 'enum perf_hw_id'[file <linux/perf_event.h>] for hw\n"
+ "counter enum value in range of 0 to PERF_COUNT_HW_MAX\n"
+ "-n\t Length size array will implement busyloop\n"
+ "e.g.\n"
+ "\t%s -c 0 -n 64\n", argv, argv, argv);
+}
+int main(int ac, char *argv[])
+{
+ int option = 0;
int *a = NULL;
int *b = NULL;
- int len = 0;
- int i, sum = 0;
+ int len = -1, cnt = -1;
+ int i, result, sum = 0;
void *addr; /* mmaped address */
unsigned long start_count, stop_count;
- if (ac != 2)
- return -1;
- len = atoi(av[1]);
- printf("%s: len = %d\n", av[0], len);
+
+ while ((option = getopt(ac, argv, "c:n:")) != -1) {
+ switch (option) {
+ case 'c':
+ cnt = atoi(optarg);
+ break;
+ case 'n':
+ len = atoi(optarg);
+ break;
+ default:
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (len == -1 || cnt == -1) {
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ if (counter_init(cnt) < 0) {
+ printf("Error: Counter Invalid\n");
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
a = malloc(len*sizeof(*a));
b = malloc(len*sizeof(*b));
-
for (i = 0; i < len; ++i) {
a[i] = i+128;
b[i] = i+64;
}
page_size = sysconf(_SC_PAGESIZE);
-
/*Allocate memory for the page size */
addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fddev, 0);
if (addr == (void *)(-1)) {
printf("Error: mmap() syscall returned with (%s)\n",
strerror(errno));
- return 0;
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
}
+
i = 0;
start_count = stop_count = 0;
/* --------------------Critical section-------------- */
@@ -121,21 +165,28 @@ int main(int ac, char **av)
sum = loop(a, b, len);
mmap_read_self(addr);
}
+
stop_count = mmap_read_self(addr);
/* --------------------End Critical section-------------- */
- printf("sum=%d Avg count [ Loop + Read ] is = %ld\n", sum,
+ result = (stop_count-start_count)/1000;
+ printf("\nsum=%d Avg count [ Loop + Read ] = %ld\n", sum,
(stop_count-start_count)/1000);
start_count = stop_count = 0;
/* --------------------Critical section-------------- */
start_count = mmap_read_self(addr);
for (i = 0; i < 1000; i++)
sum = loop(a, b, len);
+
stop_count = mmap_read_self(addr);
/* --------------------End Critical section-------------- */
- printf("sum=%d Avg count [ Loop ] \t is = %ld\n", sum,
+ printf("sum=%d Avg count [ Loop ] = %ld\n", sum,
(stop_count-start_count)/1000);
+ printf("\n--------------------------------------------------------\n");
+ printf("\tDelay[cpucycles]=%d", result-((stop_count-start_count)/1000));
+ printf("\n--------------------------------------------------------\n");
munmap(addr, page_size);
free(a);
free(b);
+ close(fddev);
return 0;
}