Hello

the below patch implements support for some ARM processors, notably
the armv7 Cortex A8 and Cortex A9.

The counter event values are very simple, it's just an 8-bit value.  No
masks of any sort.

This implementation skips the user/kernel/hv masks, as there's no way to 
set those on armv7.  I'm not sure if that's the right thing to do.
The perf_examples won't work because of this.  (in addition to having
PERF_PLM3 set, it appears they may also nead PEF_PLMH set for some 
reason).

I've tested this on a beagleboard I have, which is a Cortex A8 and it 
works fine.

Vince
vweav...@eecs.utk.edu

diff -urN libpfm4/config.mk libpfm4.arm/config.mk
--- libpfm4/config.mk   2010-08-19 17:36:29.442596286 -0400
+++ libpfm4.arm/config.mk       2010-08-18 15:27:45.178960121 -0400
@@ -51,6 +51,9 @@
 ifeq (sparc64,$(findstring sparc64,$(ARCH)))
 override ARCH=sparc
 endif
+ifeq (armv7,$(findstring armv7,$(ARCH)))
+override ARCH=arm
+endif
 
 #
 # CONFIG_PFMLIB_SHARED: y=compile static and shared versions, n=static only
@@ -122,6 +125,10 @@
 CONFIG_PFMLIB_ARCH_SPARC=y
 endif
 
+ifeq ($(ARCH),arm)
+CONFIG_PFMLIB_ARCH_ARM=y
+endif
+
 ifeq ($(XTPE_COMPILE_TARGET),linux)
 CONFIG_PFMLIB_ARCH_CRAYXT=y
 endif
diff -urN libpfm4/include/perfmon/pfmlib.h libpfm4.arm/include/perfmon/pfmlib.h
--- libpfm4/include/perfmon/pfmlib.h    2010-08-19 17:36:32.702016963 -0400
+++ libpfm4.arm/include/perfmon/pfmlib.h        2010-08-19 13:56:18.378389436 
-0400
@@ -115,6 +115,9 @@
        PFM_PMU_INTEL_WSM,              /* Intel Westmere */
        PFM_PMU_INTEL_WSM_UNC,          /* Intel Westmere uncore PMU */
 
+        PFM_PMU_ARM_CORTEX_A8,          /* ARM Cortex A8 */
+        PFM_PMU_ARM_CORTEX_A9,          /* ARM Cortex A9 */   
+   
        /* MUST ADD NEW PMU MODELS HERE */
 
        PFM_PMU_MAX                     /* end marker */
diff -urN libpfm4/lib/events/arm_events.h libpfm4.arm/lib/events/arm_events.h
--- libpfm4/lib/events/arm_events.h     1969-12-31 19:00:00.000000000 -0500
+++ libpfm4.arm/lib/events/arm_events.h 2010-08-19 17:41:33.717940514 -0400
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 2010 University of Tennessee
+ * Contributed by Vince Weaver <vweav...@utk.edu>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
copies
+ * of the Software, and to permit persons to whom the Software is furnished to 
do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in 
all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR 
A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of libpfm, a performance monitoring support library for
+ * applications on Linux.
+ */
+
+/* the various counter names are the same as those given in the */
+/* file linux-2.6/arch/arm/kernel/perf_event.c                  */
+
+#define ARMV7_COMMON \
+   {.name = "PMNC_SW_INCR", \
+    .code = 0x00, \
+    .desc = "Incremented by writes to the Software Increment Register" \
+   }, \
+   {.name = "IFETCH_MISS", \
+    .code = 0x01, \
+    .desc = "Instruction fetches that cause lowest-level cache miss" \
+   }, \
+   {.name = "ITLB_MISS", \
+    .code = 0x02, \
+    .desc = "Instruction fetches that cause lowest-level TLB miss" \
+   }, \
+   {.name = "DCACHE_REFILL", \
+    .code = 0x03, \
+    .desc = "Data read or writes that cause lowest-level cache miss" \
+   }, \
+   {.name = "DCACHE_ACCESS", \
+    .code = 0x04, \
+    .desc = "Data read or writes that cause lowest-level cache access" \
+   }, \
+   {.name = "DTLB_REFILL", \
+    .code = 0x05, \
+    .desc = "Data read or writes that cause lowest-level TLB refill" \
+   }, \
+   {.name = "DREAD", \
+    .code = 0x06, \
+    .desc = "Data read architecturally executed" \
+   }, \
+   {.name = "DWRITE", \
+    .code = 0x07, \
+    .desc = "Data write architecturally executed" \
+   }, \
+   {.name = "EXC_TAKEN", \
+    .code = 0x09, \
+    .desc = "Counts each exception taken" \
+   }, \
+   {.name = "EXC_EXECUTED", \
+    .code = 0x0a, \
+    .desc = "Exception returns architecturally executed" \
+   }, \
+   {.name = "CID_WRITE", \
+    .code = 0x0b, \
+    .desc = "Instruction writes to Context ID Register, architecturally 
executed" \
+   }, \
+   {.name = "PC_WRITE", \
+    .code = 0x0c, \
+    .desc = "Software change of PC.  Equivelant to branches" \
+   }, \
+   {.name = "PC_IMM_BRANCH", \
+    .code = 0x0d, \
+    .desc = "Immedidate branches architecturally executed" \
+   }, \
+   {.name = "UNALIGNED_ACCESS", \
+    .code = 0x0f, \
+    .desc = "Unaligned accesses architecturally executed" \
+   }, \
+   {.name = "PC_BRANCH_MIS_PRED", \
+    .code = 0x10, \
+    .desc = "Branches mispredicted or not predicted" \
+   }, \
+   {.name = "CLOCK_CYCLES",  /* this isn't in the Cortex-A8 tech doc */ \
+    .code = 0x11,            /* but is in linux kernel */ \
+    .desc = "Clock cycles" \
+   }, \
+   {.name = "PC_BRANCH_MIS_USED", \
+    .code = 0x12, \
+    .desc = "Branches that could have been predicted" \
+   }, \
+   {.name = "CPU_CYCLES", \
+    .code = 0xff, \
+    .desc = "CPU cycles" \
+   },
+
+/*
+ * Cortex A8 Event Table
+ */
+static const arm_entry_t arm_cortex_a8_pe []={
+   ARMV7_COMMON
+   {.name = "INSTR_EXECUTED",
+    .code = 0x08,
+    .desc = "Instructions architecturally executed"
+   },
+   {.name = "PC_PROC_RETURN",
+    .code = 0x0e,
+    .desc = "Procedure returns architecturally executed"
+   },
+   {.name = "WRITE_BUFFER_FULL",
+    .code = 0x40,
+    .desc = "Cycles Write buffer full"
+   },   
+   {.name = "L2_STORE_MERGED",
+    .code = 0x41,
+    .desc = "Stores merged in L2"
+   },
+   {.name = "L2_STORE_BUFF",
+    .code = 0x42,
+    .desc = "Bufferable store transactions to L2"
+   },
+   {.name = "L2_ACCESS",
+    .code = 0x43,
+    .desc = "Accesses to L2 cache"
+   },
+   {.name = "L2_CACHE_MISS",
+    .code = 0x44,
+    .desc = "L2 cache misses"
+   },
+   {.name = "AXI_READ_CYCLES",
+    .code = 0x45,
+    .desc = "Cycles with active AXI read channel transactions"
+   },
+   {.name = "AXI_WRITE_CYCLES",
+    .code = 0x46,
+    .desc = "Cycles with Active AXI write channel transactions"
+   },
+   {.name = "MEMORY_REPLAY",
+    .code = 0x47,
+    .desc = "Memory replay events"
+   },
+   {.name = "UNALIGNED_ACCESS_REPLAY",
+    .code = 0x48,
+    .desc = "Unaligned accesses causing replays"
+   },
+   {.name = "L1_DATA_MISS",
+    .code = 0x49,
+    .desc = "L1 data misses due to hashing algorithm"
+   },
+   {.name = "L1_INST_MISS",
+    .code = 0x4a,
+    .desc = "L1 instruction misses due to hashing algorithm"
+   },
+   {.name = "L1_DATA_COLORING",
+    .code = 0x4b,
+    .desc = "L1 data access where page color alias occurs"
+   },
+   {.name = "L1_NEON_DATA",
+    .code = 0x4c,
+    .desc = "NEON accesses that hit in L1 cache"
+   },
+   {.name = "L1_NEON_CACH_DATA",
+    .code = 0x4d,
+    .desc = "NEON cache accesses for L1 cache"
+   },
+   {.name = "L2_NEON",
+    .code = 0x4e,
+    .desc = "L2 accesses caused by NEON"
+   },
+   {.name = "L2_NEON_HIT",
+    .code = 0x4f,
+    .desc = "L2 hits caused by NEON"
+   },
+   {.name = "L1_INST",
+    .code = 0x50,
+    .desc = "L1 instruction cache accesses"
+   },
+   {.name = "PC_RETURN_MIS_PRED",
+    .code = 0x51,
+    .desc = "Return stack mispredictions"
+   },   
+   {.name = "PC_BRANCH_FAILED",
+    .code = 0x52,
+    .desc = "Branch prediction failures"
+   },
+   {.name = "PC_BRANCH_TAKEN",
+    .code = 0x53,
+    .desc = "Branches predicted taken"
+   },
+   {.name = "PC_BRANCH_EXECUTED",
+    .code = 0x54,
+    .desc = "Taken branches executed"
+   },   
+   {.name = "OP_EXECUTED",
+    .code = 0x55,
+    .desc = "Operations excuted (includes sub-ops in multi-cycle instructions)"
+   },
+   {.name = "CYCLES_INST_STALL",
+    .code = 0x56,
+    .desc = "Cycles no instruction is available for issue"
+   },
+   {.name = "CYCLES_INST",
+    .code = 0x57,
+    .desc = "Number of instructions issued in cycle"
+   },
+   {.name = "CYCLES_NEON_DATA_STALL",
+    .code = 0x58,
+    .desc = "Cycles stalled waiting on NEON MRC data"
+   },   
+   {.name = "CYCLES_NEON_INST_STALL",
+    .code = 0x59,
+    .desc = "Cycles stalled due to full NEON queues"
+   },
+   {.name = "NEON_CYCLES",
+    .code = 0x5a,
+    .desc = "Cycles NEON and integer processors both not idle"
+   },   
+   {.name = "PMU0_EVENTS",
+    .code = 0x70,
+    .desc = "External PMUEXTIN[0] event"
+   },      
+   {.name = "PMU1_EVENTS",
+    .code = 0x71,
+    .desc = "External PMUEXTIN[1] event"
+   },         
+   {.name = "PMU_EVENTS",
+    .code = 0x72,
+    .desc = "External PMUEXTIN[0] or PMUEXTIN[1] event"
+   },            
+};
+
+#define ARM_CORTEX_A8_EVENT_COUNT      
(sizeof(arm_cortex_a8_pe)/sizeof(arm_entry_t))
+
+
+/*
+ * Cortex A9 Event Table
+ */
+static const arm_entry_t arm_cortex_a9_pe []={
+   ARMV7_COMMON
+   {.name = "JAVA_HW_BYTECODE_EXEC",
+    .code = 0x40,
+    .desc = ""
+   },
+   {.name = "JAVA_SW_BYTECODE_EXEC",
+    .code = 0x41,
+    .desc = ""
+   },
+   {.name = "JAZELLE_BRANCH_EXEC",
+    .code = 0x42,
+    .desc = ""
+   },
+   {.name = "COHERENT_LINE_MISS",
+    .code = 0x50,
+    .desc = ""
+   },      
+   {.name = "COHERENT_LINE_HIT",
+    .code = 0x51,
+    .desc = ""
+   },
+   {.name = "ICACHE_DEP_STALL_CYCLES",
+    .code = 0x60,
+    .desc = ""
+   },
+   {.name = "DCACHE_DEP_STALL_CYCLES",
+    .code = 0x61,
+    .desc = ""
+   },
+   {.name = "TLB_MISS_DEP_STALL_CYCLES",
+    .code = 0x62,
+    .desc = ""
+   },      
+   {.name = "STREX_EXECUTED_PASSED",
+    .code = 0x63,
+    .desc = ""
+   },
+   {.name = "STREX_EXECUTED_FAILED",
+    .code = 0x64,
+    .desc = ""
+   },
+   {.name = "DATA_EVICTION",
+    .code = 0x65,
+    .desc = ""
+   },
+   {.name = "ISSUE_STAGE_NO_INST",
+    .code = 0x66,
+    .desc = ""
+   },
+   {.name = "ISSUE_STAGE_EMPTY",
+    .code = 0x67,
+    .desc = ""
+   },   
+   {.name = "INST_OUT_OF_RENAME_STAGE",
+    .code = 0x68,
+    .desc = ""
+   },
+   {.name = "PREDICTABLE_FUNCT_RETURNS",
+    .code = 0x6e,
+    .desc = ""
+   },
+   {.name = "MAIN_UNIT_EXECUTED_INST",
+    .code = 0x70,
+    .desc = ""
+   },
+   {.name = "SECOND_UNIT_EXECUTED_INST",
+    .code = 0x71,
+    .desc = ""
+   },
+   {.name = "LD_ST_UNIT_EXECUTED_INST",
+    .code = 0x72,
+    .desc = ""
+   },
+   {.name = "FP_EXECUTED_INST",
+    .code = 0x73,
+    .desc = ""
+   },
+   {.name = "NEON_EXECUTED_INST",
+    .code = 0x74,
+    .desc = ""
+   },
+   {.name = "PLD_FULL_DEP_STALL_CYCLES",
+    .code = 0x80,
+    .desc = ""
+   },
+   {.name = "DATA_WR_DEP_STALL_CYCLES",
+    .code = 0x81,
+    .desc = ""
+   },
+   {.name = "ITLB_MISS_DEP_STALL_CYCLES",
+    .code = 0x82,
+    .desc = ""
+   },
+   {.name = "DTLB_MISS_DEP_STALL_CYCLES",
+    .code = 0x83,
+    .desc = ""
+   },
+   {.name = "MICRO_ITLB_MISS_DEP_STALL_CYCLES",
+    .code = 0x84,
+    .desc = ""
+   },   
+   {.name = "MICRO_DTLB_MISS_DEP_STALL_CYCLES",
+    .code = 0x85,
+    .desc = ""
+   },      
+   {.name = "DMB_DEP_STALL_CYCLES",
+    .code = 0x86,
+    .desc = ""
+   },
+   {.name = "INTGR_CLK_ENABLED_CYCLES",
+    .code = 0x8a,
+    .desc = ""
+   },
+   {.name = "DATA_ENGINE_CLK_EN_CYCLES",
+    .code = 0x8b,
+    .desc = ""
+   },      
+   {.name = "ISB_INST",
+    .code = 0x90,
+    .desc = ""
+   },
+   {.name = "DSB_INST",
+    .code = 0x91,
+    .desc = ""
+   },
+   {.name = "DMB_INST",
+    .code = 0x92,
+    .desc = ""
+   },
+   {.name = "EXT_INTERRUPTS",
+    .code = 0x93,
+    .desc = ""
+   },
+   {.name = "PLE_CACHE_LINE_RQST_COMPLETED",
+    .code = 0xa0,
+    .desc = ""
+   },
+   {.name = "PLE_CACHE_LINE_RQST_SKIPPED",
+    .code = 0xa1,
+    .desc = ""
+   },
+   {.name = "PLE_FIFO_FLUSH",
+    .code = 0xa2,
+    .desc = ""
+   },
+   {.name = "PLE_RQST_COMPLETED",
+    .code = 0xa3,
+    .desc = ""
+   },
+   {.name = "PLE_FIFO_OVERFLOW",
+    .code = 0xa4,
+    .desc = ""
+   },
+   {.name = "PLE_RQST_PROG",
+    .code = 0xa5,
+    .desc = ""
+   },
+};
+
+#define ARM_CORTEX_A9_EVENT_COUNT      
(sizeof(arm_cortex_a9_pe)/sizeof(arm_entry_t))
diff -urN libpfm4/lib/Makefile libpfm4.arm/lib/Makefile
--- libpfm4/lib/Makefile        2010-08-19 17:36:32.926237122 -0400
+++ libpfm4.arm/lib/Makefile    2010-08-18 15:24:39.150016806 -0400
@@ -95,6 +95,12 @@
 CFLAGS += -DCONFIG_PFMLIB_ARCH_SPARC
 endif
 
+ifeq ($(CONFIG_PFMLIB_ARCH_ARM),y)
+INCARCH = $(INC_ARM)
+SRCS   += pfmlib_arm.c
+CFLAGS += -DCONFIG_PFMLIB_ARCH_ARM
+endif
+
 ifeq ($(CONFIG_PFMLIB_ARCH_CRAYXT),y)
 CFLAGS += -DCONFIG_PFMLIB_ARCH_CRAYXT
 endif
diff -urN libpfm4/lib/pfmlib_arm.c libpfm4.arm/lib/pfmlib_arm.c
--- libpfm4/lib/pfmlib_arm.c    1969-12-31 19:00:00.000000000 -0500
+++ libpfm4.arm/lib/pfmlib_arm.c        2010-08-19 17:32:38.325949786 -0400
@@ -0,0 +1,282 @@
+/*
+ * pfmlib_arm.c :      support for ARM chips
+ * 
+ * Copyright (c) 2010 University of Tennessee
+ * Contributed by Vince Weaver <vweav...@utk.edu>
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
copies
+ * of the Software, and to permit persons to whom the Software is furnished to 
do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in 
all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR 
A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+/* private headers */
+#include "pfmlib_priv.h"                       /* library private */
+#include "pfmlib_arm_priv.h"
+#include "events/arm_events.h"                  /* event tables */
+
+pfm_arm_config_t pfm_arm_cfg;
+
+static int
+pfm_arm_detect(void)
+{
+
+       int ret;
+       char buffer[128];
+
+       ret = pfmlib_getcpuinfo_attr("CPU implementer", buffer, sizeof(buffer));
+       if (ret == -1)
+               return PFM_ERR_NOTSUPP;
+
+        pfm_arm_cfg.implementer = strtol(buffer, NULL, 16);
+   
+   
+       ret = pfmlib_getcpuinfo_attr("CPU part", buffer, sizeof(buffer));
+       if (ret == -1)
+               return PFM_ERR_NOTSUPP;
+
+       pfm_arm_cfg.part = strtol(buffer, NULL, 16);
+
+       ret = pfmlib_getcpuinfo_attr("CPU architecture", buffer, 
sizeof(buffer));
+       if (ret == -1)
+               return PFM_ERR_NOTSUPP;
+
+       pfm_arm_cfg.architecture = strtol(buffer, NULL, 16);
+   
+       return PFM_SUCCESS;
+}
+   
+   
+int
+pfm_arm_detect_cortex_a8(void *this)
+{
+
+       int ret;
+
+        ret=pfm_arm_detect();
+        if (ret!=PFM_SUCCESS) return PFM_ERR_NOTSUPP;
+   
+        if ((pfm_arm_cfg.implementer==0x41) && /* ARM */
+            (pfm_arm_cfg.part==0xc08)) { /* Cortex-A8 */
+          return PFM_SUCCESS;     
+       }
+   
+       return PFM_ERR_NOTSUPP;   
+}
+
+int
+pfm_arm_detect_cortex_a9(void *this)
+{
+
+       int ret;
+
+        ret=pfm_arm_detect();
+        if (ret!=PFM_SUCCESS) return PFM_ERR_NOTSUPP;
+   
+        if ((pfm_arm_cfg.implementer==0x41) && /* ARM */
+            (pfm_arm_cfg.part==0xc09)) { /* Cortex-A8 */
+          return PFM_SUCCESS;     
+       }
+   
+       return PFM_ERR_NOTSUPP;   
+}
+
+int
+pfm_arm_get_encoding(void *this, pfmlib_event_desc_t *e, uint64_t *codes, int 
*count, pfmlib_perf_attr_t *attrs)
+{
+
+       const arm_entry_t *pe = this_pe(this);
+       pfm_arm_reg_t reg;
+
+       reg.val = pe[e->event].code;
+        evt_strcat(e->fstr, "%s", pe[e->event].name);
+  
+       *codes = reg.val;
+       *count = 1;
+
+        pfm_arm_display_reg(reg, e->fstr);
+   
+       return PFM_SUCCESS;
+}
+
+int
+pfm_arm_get_event_first(void *this)
+{
+       return 0;
+}
+
+int
+pfm_arm_get_event_next(void *this, int idx)
+{
+       pfmlib_pmu_t *p = this;
+
+       if (idx >= (p->pme_count-1))
+               return -1;
+
+       return idx+1;
+}
+
+int
+pfm_arm_event_is_valid(void *this, int pidx)
+{
+       pfmlib_pmu_t *p = this;
+       return pidx >= 0 && pidx < p->pme_count;
+}
+
+void
+pfm_arm_display_reg(pfm_arm_reg_t reg, char *fstr)
+{
+
+       /*
+        * handle generic counters
+        */
+       __pfm_vbprintf("[0x%"PRIx64" ",
+                       reg.val);
+       __pfm_vbprintf("] %s\n", fstr);
+
+}
+
+int
+pfm_arm_get_event_perf_type(void *this, int pidx)
+{
+       return PERF_TYPE_RAW;
+}
+
+int
+pfm_arm_validate_table(void *this, FILE *fp)
+{
+
+       pfmlib_pmu_t *pmu = this;
+       const arm_entry_t *pe = this_pe(this);
+       int i, error = 0;
+
+       if (!pmu->atdesc) {
+               fprintf(fp, "pmu: %s missing attr_desc\n", pmu->name);
+               error++;
+       }
+
+       for(i=0; i < pmu->pme_count; i++) {
+
+               if (!pe[i].name) {
+                       fprintf(fp, "pmu: %s event%d: :: no name\n", pmu->name, 
i);
+                       error++;
+               }
+
+               if (!pe[i].desc) {
+                       fprintf(fp, "pmu: %s event%d: %s :: no description\n", 
pmu->name, i, pe[i].name);
+                       error++;
+               }
+
+       }
+
+       return error ? PFM_ERR_INVAL : PFM_SUCCESS;
+}
+
+int
+pfm_arm_get_event_attr_info(void *this, int pidx, int attr_idx, 
pfm_event_attr_info_t *info)
+{
+
+       int numasks;
+
+       numasks = 0;
+
+       info->idx = attr_idx;
+       info->dfl_val64 = 0;
+
+       return PFM_SUCCESS;
+}
+
+int
+pfm_arm_get_event_info(void *this, int idx, pfm_event_info_t *info)
+{
+
+       const arm_entry_t *pe = this_pe(this);
+
+       /*
+        * pmu and idx filled out by caller
+        */
+       info->name  = pe[idx].name;
+       info->desc  = pe[idx].desc;
+       info->code  = pe[idx].code;
+       info->equiv = pe[idx].equiv;
+
+       /* unit masks + modifiers */
+       info->nattrs  = 0;
+
+       return PFM_SUCCESS;
+}
+
+const pfmlib_attr_desc_t arm_mods[]={
+   PFM_ATTR_B("u", "monitor at priv level 1, 2, 3"),       /* monitor priv 
+                                                           * level 1, 2, 3 */
+   PFM_ATTR_B("k", "monitor at priv level 0"),             /* monitor priv 
+                                                           * level 0 */
+   PFM_ATTR_NULL /* end-marker to avoid exporting number of entries */
+};
+
+
+/* Cortex A8 support */
+pfmlib_pmu_t arm_cortex_a8_support={
+       .desc                   = "ARM Cortex A8",
+       .name                   = "ac8",
+       .pmu                    = PFM_PMU_ARM_CORTEX_A8,
+       .pme_count              = ARM_CORTEX_A8_EVENT_COUNT,
+       .pe                     = arm_cortex_a8_pe,
+       .atdesc                 = arm_mods,
+
+       .pmu_detect             = pfm_arm_detect_cortex_a8,
+       .max_encoding           = 1,
+
+       .get_event_encoding     = pfm_arm_get_encoding,
+       .get_event_first        = pfm_arm_get_event_first,
+       .get_event_next         = pfm_arm_get_event_next,
+       .event_is_valid         = pfm_arm_event_is_valid,
+       .get_event_perf_type    = pfm_arm_get_event_perf_type,
+       .validate_table         = pfm_arm_validate_table,
+       .get_event_info         = pfm_arm_get_event_info,
+       .get_event_attr_info    = pfm_arm_get_event_attr_info,
+};
+
+   
+
+/* Cortex A9 support */
+pfmlib_pmu_t arm_cortex_a9_support={
+       .desc                   = "ARM Cortex A9",
+       .name                   = "ac9",
+       .pmu                    = PFM_PMU_ARM_CORTEX_A9,
+       .pme_count              = ARM_CORTEX_A9_EVENT_COUNT,
+       .pe                     = arm_cortex_a9_pe,
+       .atdesc                 = arm_mods,
+
+       .pmu_detect             = pfm_arm_detect_cortex_a9,
+       .max_encoding           = 1,
+
+       .get_event_encoding     = pfm_arm_get_encoding,
+       .get_event_first        = pfm_arm_get_event_first,
+       .get_event_next         = pfm_arm_get_event_next,
+       .event_is_valid         = pfm_arm_event_is_valid,
+       .get_event_perf_type    = pfm_arm_get_event_perf_type,
+       .validate_table         = pfm_arm_validate_table,
+       .get_event_info         = pfm_arm_get_event_info,
+       .get_event_attr_info    = pfm_arm_get_event_attr_info,
+};
+
diff -urN libpfm4/lib/pfmlib_arm_priv.h libpfm4.arm/lib/pfmlib_arm_priv.h
--- libpfm4/lib/pfmlib_arm_priv.h       1969-12-31 19:00:00.000000000 -0500
+++ libpfm4.arm/lib/pfmlib_arm_priv.h   2010-08-19 17:44:30.057938524 -0400
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2010 University of Tennessee
+ * Contributed by Vince Weaver <vweav...@utk.edu>
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
copies
+ * of the Software, and to permit persons to whom the Software is furnished to 
do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in 
all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR 
A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of libpfm, a performance monitoring support library for
+ * applications on Linux.
+ */
+#ifndef __PFMLIB_ARM_PRIV_H__
+#define __PFMLIB_ARM_PRIV_H__
+
+/*
+ * This file contains the definitions used for ARM processors
+ */
+
+/*
+ *  * unit mask description
+ *  */
+typedef struct {
+           const char              *uname; /* unit mask name */
+           const char              *udesc; /* unit umask description */
+           const char              *uequiv;/* name of event from which this 
one is 
+                                           * derived, NULL if none */
+           uint64_t                ucntmsk;/* supported counters for umask (if 
set,
+                                           *  supersedes cntmsk) */
+           unsigned int            ucode;  /* unit mask code */
+           unsigned int            uflags; /* unit mask flags */
+           unsigned int            umodel; /* only available on this PMU model 
*/
+           unsigned int            grpid;  /* unit mask group id */
+           unsigned int            grpmsk; /* indicate which umask bits used 
by gro
+                                           * up */
+           unsigned int            modhw;  /* hardwired modifiers, cannot be 
change
+                                           * d */
+} arm_umask_t;
+
+
+
+/*
+ * event description
+ */
+typedef struct {
+       const char                      *name;  /* event name */
+       const char                      *desc;  /* event description */
+       const char                      *equiv; /* name of event from which 
this one is derived, NULL if none */
+       unsigned int                    code;   /* event code */
+} arm_entry_t;
+
+typedef union pfm_arm_reg {
+       unsigned long long val;                 /* complete register value */
+       struct {
+               unsigned long sel_event_select:8;       /* counter */
+               unsigned long long sel_res2:56;
+       } perfevtsel;
+} pfm_arm_reg_t;
+
+/* let's define some handy shortcuts! */
+#define sel_event_select perfevtsel.sel_event_select
+#define sel_unit_mask   perfevtsel.sel_unit_mask
+#define sel_usr                 perfevtsel.sel_usr
+#define sel_os          perfevtsel.sel_os
+#define sel_edge        perfevtsel.sel_edge
+#define sel_pc          perfevtsel.sel_pc
+#define sel_int                 perfevtsel.sel_int
+#define sel_en          perfevtsel.sel_en
+#define sel_inv                 perfevtsel.sel_inv
+#define sel_cnt_mask    perfevtsel.sel_cnt_mask
+#define sel_anythr      perfevtsel.sel_anythr
+
+typedef struct {
+       int implementer;
+       int architecture;
+       int part;
+} pfm_arm_config_t;
+
+extern pfm_arm_config_t pfm_arm_cfg;
+
+extern int pfm_arm_detect_cortex_a8(void *this);
+extern int pfm_arm_detect_cortex_a9(void *this);
+extern void pfm_arm_display_reg(pfm_arm_reg_t reg, char *fstr);
+extern int pfm_arm_add_defaults(void *this, int pidx, char *umask_str, 
unsigned int msk, unsigned int *umask);
+
+extern int pfm_arm_event_is_valid(void *this, int pidx);
+extern int pfm_arm_get_encoding(void *this, pfmlib_event_desc_t *e, uint64_t 
*codes, int *count, pfmlib_perf_attr_t *attrs);
+extern int pfm_arm_get_event_first(void *this);
+extern int pfm_arm_get_event_next(void *this, int idx);
+extern int pfm_arm_get_event_umask_first(void *this, int idx);
+extern int pfm_arm_get_event_umask_next(void *this, int idx, int attr);
+extern int pfm_arm_get_event_perf_type(void *this, int pidx);
+extern int pfm_arm_validate_table(void *this, FILE *fp);
+extern int pfm_arm_get_event_attr_info(void *this, int idx, int attr_idx, 
pfm_event_attr_info_t *info);
+extern int pfm_arm_get_event_info(void *this, int idx, pfm_event_info_t *info);
+extern int pfm_arm_attr2mod(void *this, int pidx, int attr_idx);
+#endif /* __PFMLIB_ARM_PRIV_H__ */
diff -urN libpfm4/lib/pfmlib_common.c libpfm4.arm/lib/pfmlib_common.c
--- libpfm4/lib/pfmlib_common.c 2010-08-19 17:36:37.182805367 -0400
+++ libpfm4.arm/lib/pfmlib_common.c     2010-08-19 13:57:16.325978189 -0400
@@ -101,6 +101,11 @@
        &cell_support,
 #endif
 
+#ifdef CONFIG_PFMLIB_ARCH_ARM
+       &arm_cortex_a8_support,
+       &arm_cortex_a9_support,   
+#endif
+   
 #ifdef __linux__
        &perf_event_support,
 #endif
diff -urN libpfm4/lib/pfmlib_priv.h libpfm4.arm/lib/pfmlib_priv.h
--- libpfm4/lib/pfmlib_priv.h   2010-08-19 17:36:40.182017287 -0400
+++ libpfm4.arm/lib/pfmlib_priv.h       2010-08-19 13:57:35.274016620 -0400
@@ -174,6 +174,8 @@
 extern pfmlib_pmu_t perf_event_support;
 extern pfmlib_pmu_t intel_wsm_support;
 extern pfmlib_pmu_t intel_wsm_unc_support;
+extern pfmlib_pmu_t arm_cortex_a8_support;
+extern pfmlib_pmu_t arm_cortex_a9_support;
 
 extern char *pfmlib_forced_pmu;
 

------------------------------------------------------------------------------
This SF.net email is sponsored by 

Make an app they can't live without
Enter the BlackBerry Developer Challenge
http://p.sf.net/sfu/RIM-dev2dev 
_______________________________________________
perfmon2-devel mailing list
perfmon2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/perfmon2-devel

Reply via email to