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