Re: [perfmon2] libpfm4 ARM support
Status: Beta
Brought to you by:
seranian
From: Vince W. <vwe...@ee...> - 2010-08-27 21:57:16
|
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 <vwe...@ut...> + * + * 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 <vwe...@ut...> + * + * 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 <vwe...@ut...> + * + * 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 <vwe...@ut...> + * + * 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 <vwe...@ut...> + * + * 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; |