Vince,

Thanks for the patch, it looks very good.

However I have one comment:

   The event table has the encoding that is specific to perf_events. This means
   the table can only be used with perf_events. That is not the approach taken
   by libpfm4. I am trying hard to make the core of the library
OS-agnostic. That
   means the table should have the official encodings of the event. If you need
   an OS specific encoding, then you need to add a shim layer specific to the OS
   to make the conversion.

   It is not clear to me why they've decided to go with their own
event encoding rather
   than just use ARM's encodings + RAW. It is too late to change this
now, unfortunately.

On Fri, Aug 20, 2010 at 12:00 AM, Vince Weaver <vweav...@eecs.utk.edu> wrote:
> 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
>

------------------------------------------------------------------------------
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