Hello here's an updated patch. I think I've addressed all of your comments.
Some things that are different: + I added descriptions for the Coretex A9 events + I named the cortex specific file with the awkward pfmlib_arm_armv7_pmuv1.c rather than arm_cortex.c, because techncially what is implemented by the Cortex chips is the ARMv7 PMUv1 counter interface. It turns out there is a PMUv2 on the way that does have separate user/kernel specifiers among other things, but I don't know of any chips that support that yet. Vince diff -urpN libpfm4.stock/config.mk libpfm4.vmw/config.mk --- libpfm4.stock/config.mk 2010-08-27 15:12:22.650348609 -0400 +++ libpfm4.vmw/config.mk 2010-08-27 15:16:00.285929701 -0400 @@ -51,6 +51,9 @@ endif 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 @@ ifeq ($(ARCH),sparc) 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 -urpN libpfm4.stock/include/perfmon/pfmlib.h libpfm4.vmw/include/perfmon/pfmlib.h --- libpfm4.stock/include/perfmon/pfmlib.h 2010-08-27 15:12:26.133952131 -0400 +++ libpfm4.vmw/include/perfmon/pfmlib.h 2010-08-27 15:16:00.473938170 -0400 @@ -126,6 +126,9 @@ typedef enum { PFM_PMU_AMD64_FAM10H_SHANGHAI, /* AMD AMD64 Fam10h Shanghai RevC */ PFM_PMU_AMD64_FAM10H_ISTANBUL, /* AMD AMD64 Fam10h Istanbul RevD */ + 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 -urpN libpfm4.stock/lib/events/arm_cortex_a8_events.h libpfm4.vmw/lib/events/arm_cortex_a8_events.h --- libpfm4.stock/lib/events/arm_cortex_a8_events.h 1969-12-31 19:00:00.000000000 -0500 +++ libpfm4.vmw/lib/events/arm_cortex_a8_events.h 2010-08-27 16:39:17.998023806 -0400 @@ -0,0 +1,235 @@ +/* + * 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 */ + +/* + * Cortex A8 Event Table + */ +static const arm_entry_t arm_cortex_a8_pe []={ + {.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 = "INSTR_EXECUTED", + .code = 0x08, + .desc = "Instructions 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 = "PC_PROC_RETURN", + .code = 0x0e, + .desc = "Procedure returns 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 = "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" + }, + {.name = "CPU_CYCLES", + .code = 0xff, + .desc = "CPU cycles" + }, +}; + +#define ARM_CORTEX_A8_EVENT_COUNT (sizeof(arm_cortex_a8_pe)/sizeof(arm_entry_t)) diff -urpN libpfm4.stock/lib/events/arm_cortex_a9_events.h libpfm4.vmw/lib/events/arm_cortex_a9_events.h --- libpfm4.stock/lib/events/arm_cortex_a9_events.h 1969-12-31 19:00:00.000000000 -0500 +++ libpfm4.vmw/lib/events/arm_cortex_a9_events.h 2010-08-27 17:07:43.763543623 -0400 @@ -0,0 +1,264 @@ +/* + * 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 */ + +/* + * Cortex A9 Event Table + * based on Table 9-2 from the "Cortex A9 Technical Reference Manual + */ +static const arm_entry_t arm_cortex_a9_pe []={ + {.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", + .code = 0x11, + .desc = "Clock cycles" + }, + {.name = "PC_BRANCH_MIS_USED", + .code = 0x12, + .desc = "Branches that could have been predicted" + }, + {.name = "JAVA_HW_BYTECODE_EXEC", + .code = 0x40, + .desc = "Java bytecodes decoded, including speculative" + }, + {.name = "JAVA_SW_BYTECODE_EXEC", + .code = 0x41, + .desc = "Software Java bytecodes decoded, including speculative" + }, + {.name = "JAZELLE_BRANCH_EXEC", + .code = 0x42, + .desc = "Jazelle backward branches executed" + }, + {.name = "COHERENT_LINE_MISS", + .code = 0x50, + .desc = "Coherent linefill misses which also miss on other processors" + }, + {.name = "COHERENT_LINE_HIT", + .code = 0x51, + .desc = "Coherent linefill requests that hit on another processor" + }, + {.name = "ICACHE_DEP_STALL_CYCLES", + .code = 0x60, + .desc = "Cycles processor is stalled waiting for instruction cache" + }, + {.name = "DCACHE_DEP_STALL_CYCLES", + .code = 0x61, + .desc = "Cycles processor is stalled waiting for data cache" + }, + {.name = "TLB_MISS_DEP_STALL_CYCLES", + .code = 0x62, + .desc = "Cycles processor is stalled waiting for completion of TLB walk" + }, + {.name = "STREX_EXECUTED_PASSED", + .code = 0x63, + .desc = "Number of STREX instructions executed and passed" + }, + {.name = "STREX_EXECUTED_FAILED", + .code = 0x64, + .desc = "Number of STREX instructions executed and failed" + }, + {.name = "DATA_EVICTION", + .code = 0x65, + .desc = "Data eviction requests due to linefill in data cache" + }, + {.name = "ISSUE_STAGE_NO_INST", + .code = 0x66, + .desc = "Cycles the issue stage does not dispatch any instructions" + }, + {.name = "ISSUE_STAGE_EMPTY", + .code = 0x67, + .desc = "Cycles where issue stage is empty" + }, + {.name = "INST_OUT_OF_RENAME_STAGE", + .code = 0x68, + .desc = "Number of instructions going through register renaming stage" + }, + {.name = "PREDICTABLE_FUNCT_RETURNS", + .code = 0x6e, + .desc = "Number of predictable function returns whose condition codes do not fail" + }, + {.name = "MAIN_UNIT_EXECUTED_INST", + .code = 0x70, + .desc = "Instructions executed in the main execution pipeline" + }, + {.name = "SECOND_UNIT_EXECUTED_INST", + .code = 0x71, + .desc = "Instructions executed in the second execution pipeline" + }, + {.name = "LD_ST_UNIT_EXECUTED_INST", + .code = 0x72, + .desc = "Instructions executed in the Load/Store unit" + }, + {.name = "FP_EXECUTED_INST", + .code = 0x73, + .desc = "Floating point instructions going through register renaming stage" + }, + {.name = "NEON_EXECUTED_INST", + .code = 0x74, + .desc = "NEON instructions going through register renaming stage" + }, + {.name = "PLD_FULL_DEP_STALL_CYCLES", + .code = 0x80, + .desc = "Cycles processor is stalled because PLD slots are full" + }, + {.name = "DATA_WR_DEP_STALL_CYCLES", + .code = 0x81, + .desc = "Cycles processor is stalled due to writes to external memory" + }, + {.name = "ITLB_MISS_DEP_STALL_CYCLES", + .code = 0x82, + .desc = "Cycles stalled due to main instruction TLB miss" + }, + {.name = "DTLB_MISS_DEP_STALL_CYCLES", + .code = 0x83, + .desc = "Cycles stalled due to main data TLB miss" + }, + {.name = "MICRO_ITLB_MISS_DEP_STALL_CYCLES", + .code = 0x84, + .desc = "Cycles stalled due to micro instruction TLB miss" + }, + {.name = "MICRO_DTLB_MISS_DEP_STALL_CYCLES", + .code = 0x85, + .desc = "Cycles stalled due to micro data TLB miss" + }, + {.name = "DMB_DEP_STALL_CYCLES", + .code = 0x86, + .desc = "Cycles stalled due to DMB memory barrier" + }, + {.name = "INTGR_CLK_ENABLED_CYCLES", + .code = 0x8a, + .desc = "Cycles during which integer core clock is enabled" + }, + {.name = "DATA_ENGINE_CLK_EN_CYCLES", + .code = 0x8b, + .desc = "Cycles during which Data Engine clock is enabled" + }, + {.name = "ISB_INST", + .code = 0x90, + .desc = "Number of ISB instructions architecturally executed" + }, + {.name = "DSB_INST", + .code = 0x91, + .desc = "Number of DSB instructions architecturally executed" + }, + {.name = "DMB_INST", + .code = 0x92, + .desc = "Number of DMB instructions architecturally executed" + }, + {.name = "EXT_INTERRUPTS", + .code = 0x93, + .desc = "Number of External interrupts" + }, + {.name = "PLE_CACHE_LINE_RQST_COMPLETED", + .code = 0xa0, + .desc = "PLE cache line requests completed" + }, + {.name = "PLE_CACHE_LINE_RQST_SKIPPED", + .code = 0xa1, + .desc = "PLE cache line requests skipped" + }, + {.name = "PLE_FIFO_FLUSH", + .code = 0xa2, + .desc = "PLE FIFO flushes" + }, + {.name = "PLE_RQST_COMPLETED", + .code = 0xa3, + .desc = "PLE requests completed" + }, + {.name = "PLE_FIFO_OVERFLOW", + .code = 0xa4, + .desc = "PLE FIFO overflows" + }, + {.name = "PLE_RQST_PROG", + .code = 0xa5, + .desc = "PLE requests programmed" + }, + {.name = "CPU_CYCLES", + .code = 0xff, + .desc = "CPU cycles" + }, +}; + +#define ARM_CORTEX_A9_EVENT_COUNT (sizeof(arm_cortex_a9_pe)/sizeof(arm_entry_t)) diff -urpN libpfm4.stock/lib/Makefile libpfm4.vmw/lib/Makefile --- libpfm4.stock/lib/Makefile 2010-08-27 15:12:26.386017639 -0400 +++ libpfm4.vmw/lib/Makefile 2010-08-27 17:33:54.222017393 -0400 @@ -96,6 +96,12 @@ INCARCH = $(INC_SPARC) CFLAGS += -DCONFIG_PFMLIB_ARCH_SPARC endif +ifeq ($(CONFIG_PFMLIB_ARCH_ARM),y) +INCARCH = $(INC_ARM) +SRCS += pfmlib_arm.c pfmlib_arm_armv7_pmuv1.c +CFLAGS += -DCONFIG_PFMLIB_ARCH_ARM +endif + ifeq ($(CONFIG_PFMLIB_ARCH_CRAYXT),y) CFLAGS += -DCONFIG_PFMLIB_ARCH_CRAYXT endif diff -urpN libpfm4.stock/lib/pfmlib_arm_armv7_pmuv1.c libpfm4.vmw/lib/pfmlib_arm_armv7_pmuv1.c --- libpfm4.stock/lib/pfmlib_arm_armv7_pmuv1.c 1969-12-31 19:00:00.000000000 -0500 +++ libpfm4.vmw/lib/pfmlib_arm_armv7_pmuv1.c 2010-08-27 17:28:40.110016564 -0400 @@ -0,0 +1,117 @@ +/* + * 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_cortex_a8_events.h" /* event tables */ +#include "events/arm_cortex_a9_events.h" + +pfm_arm_config_t pfm_arm_cfg; + +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; +} + +/* 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, + + .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, + + .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 -urpN libpfm4.stock/lib/pfmlib_arm.c libpfm4.vmw/lib/pfmlib_arm.c --- libpfm4.stock/lib/pfmlib_arm.c 1969-12-31 19:00:00.000000000 -0500 +++ libpfm4.vmw/lib/pfmlib_arm.c 2010-08-27 17:33:34.454016763 -0400 @@ -0,0 +1,186 @@ +/* + * 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" + +pfm_arm_config_t pfm_arm_cfg; + +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_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; + + 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; +} + diff -urpN libpfm4.stock/lib/pfmlib_arm_priv.h libpfm4.vmw/lib/pfmlib_arm_priv.h --- libpfm4.stock/lib/pfmlib_arm_priv.h 1969-12-31 19:00:00.000000000 -0500 +++ libpfm4.vmw/lib/pfmlib_arm_priv.h 2010-08-27 17:34:40.850993990 -0400 @@ -0,0 +1,77 @@ +/* + * 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 + */ + + +/* + * 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 int val; /* complete register value */ + + struct { + unsigned int sel:8; /* counter */ + unsigned int reserved:24; + } evtsel; +} pfm_arm_reg_t; + +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 int pfm_arm_detect(); +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 -urpN libpfm4.stock/lib/pfmlib_common.c libpfm4.vmw/lib/pfmlib_common.c --- libpfm4.stock/lib/pfmlib_common.c 2010-08-27 15:12:30.689928686 -0400 +++ libpfm4.vmw/lib/pfmlib_common.c 2010-08-27 15:16:00.957951330 -0400 @@ -119,6 +119,11 @@ static pfmlib_pmu_t *pfmlib_pmus[]= &cell_support, #endif +#ifdef CONFIG_PFMLIB_ARCH_ARM + &arm_cortex_a8_support, + &arm_cortex_a9_support, +#endif + #ifdef __linux__ &perf_event_support, #endif diff -urpN libpfm4.stock/lib/pfmlib_priv.h libpfm4.vmw/lib/pfmlib_priv.h --- libpfm4.stock/lib/pfmlib_priv.h 2010-08-27 15:12:33.758024225 -0400 +++ libpfm4.vmw/lib/pfmlib_priv.h 2010-08-27 15:16:01.085929694 -0400 @@ -185,6 +185,8 @@ extern pfmlib_pmu_t cell_support; 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; ------------------------------------------------------------------------------ Sell apps to millions through the Intel(R) Atom(Tm) Developer Program Be part of this innovative community and reach millions of netbook users worldwide. Take advantage of special opportunities to increase revenue and speed time-to-market. Join now, and jumpstart your future. http://p.sf.net/sfu/intel-atom-d2d _______________________________________________ perfmon2-devel mailing list perfmon2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/perfmon2-devel