Blob Blame History Raw
commit b1a3bf942376a3eaddc6f089c74bf5e322295822
Author: Stephane Eranian <eranian@gmail.com>
Date:   Tue May 6 14:42:23 2014 +0200

    Add ARM Cortex A57 support
    
    This patch adds support for ARM Cortex A57 processor
    for both 64 and 32 bit modes (armv8).
    
    Based on Table 11-24 from the "Cortex A57 Technical Reference Manual"
    
    The validation tests for A57 in 64-bit mode is also added.
    
    Signed-off-by: Stephane Eranian <eranian@gmail.com>

diff --git a/config.mk b/config.mk
index 457d943..9553cbe 100644
--- a/config.mk
+++ b/config.mk
@@ -66,6 +66,15 @@ endif
 ifeq (armv7,$(findstring armv7,$(ARCH)))
 override ARCH=arm
 endif
+ifeq (armv7,$(findstring armv7,$(ARCH)))
+override ARCH=arm
+endif
+ifeq (aarch32,$(findstring aarch32,$(ARCH)))
+override ARCH=arm
+endif
+ifeq (armv8l,$(findstring armv8l,$(ARCH)))
+override ARCH=arm
+endif
 ifeq (mips64,$(findstring mips64,$(ARCH)))
 override ARCH=mips
 endif
@@ -152,6 +161,14 @@ ifeq ($(ARCH),arm)
 CONFIG_PFMLIB_ARCH_ARM=y
 endif
 
+ifeq ($(ARCH),aarch64)
+CONFIG_PFMLIB_ARCH_ARM64=y
+endif
+
+ifeq ($(ARCH),arm64)
+CONFIG_PFMLIB_ARCH_ARM64=y
+endif
+
 ifeq ($(ARCH),s390x)
 CONFIG_PFMLIB_ARCH_S390X=y
 endif
diff --git a/include/perfmon/pfmlib.h b/include/perfmon/pfmlib.h
index dfdd471..b08df66 100644
--- a/include/perfmon/pfmlib.h
+++ b/include/perfmon/pfmlib.h
@@ -237,6 +237,8 @@ typedef enum {
 
 	PFM_PMU_INTEL_HSW_EP,		/* Intel Haswell EP */
 
+	PFM_PMU_ARM_CORTEX_A57,		/* ARM Cortex A57 (ARMv8) */
+
 	/* MUST ADD NEW PMU MODELS HERE */
 
 	PFM_PMU_MAX			/* end marker */
diff --git a/lib/Makefile b/lib/Makefile
index 531167e..6ca3287 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -139,10 +139,21 @@ SRCS += pfmlib_arm_perf_event.c
 endif
 
 INCARCH = $(INC_ARM)
-SRCS   += pfmlib_arm.c pfmlib_arm_armv7_pmuv1.c pfmlib_arm_armv6.c
+SRCS   += pfmlib_arm.c pfmlib_arm_armv7_pmuv1.c pfmlib_arm_armv6.c pfmlib_arm_armv8.c
 CFLAGS += -DCONFIG_PFMLIB_ARCH_ARM
 endif
 
+ifeq ($(CONFIG_PFMLIB_ARCH_ARM64),y)
+
+ifeq ($(SYS),Linux)
+SRCS += pfmlib_arm_perf_event.c
+endif
+
+INCARCH = $(INC_ARM64)
+SRCS   += pfmlib_arm.c pfmlib_arm_armv8.c
+CFLAGS += -DCONFIG_PFMLIB_ARCH_ARM64
+endif
+
 ifeq ($(CONFIG_PFMLIB_ARCH_MIPS),y)
 
 ifeq ($(SYS),Linux)
@@ -272,6 +283,8 @@ INC_ARM=pfmlib_arm_priv.h			\
 	events/arm_cortex_a9_events.h		\
 	events/arm_cortex_a15_events.h
 
+INC_ARM64=events/arm_cortex_a57_events.h
+
 INCDEP=$(INC_COMMON) $(INCARCH)
 
 all: $(TARGETS)
diff --git a/lib/events/arm_cortex_a57_events.h b/lib/events/arm_cortex_a57_events.h
new file mode 100644
index 0000000..9d1d407
--- /dev/null
+++ b/lib/events/arm_cortex_a57_events.h
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2014 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * 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.
+ *
+ * Cortex A57 r1p1
+ * based on Table 11-24 from the "Cortex A57 Technical Reference Manual"
+ */
+
+static const arm_entry_t arm_cortex_a57_pe[]={
+	{.name = "SW_INCR",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x00,
+	 .desc = "Instruction architecturally executed (condition check pass) Software increment"
+	},
+	{.name = "L1I_CACHE_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x01,
+	 .desc = "Level 1 instruction cache refill"
+	},
+	{.name = "L1I_TLB_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x02,
+	 .desc = "Level 1 instruction TLB refill"
+	},
+	{.name = "L1D_CACHE_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x03,
+	 .desc = "Level 1 data cache refill"
+	},
+	{.name = "L1D_CACHE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x04,
+	 .desc = "Level 1 data cache access"
+	},
+	{.name = "L1D_TLB_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x05,
+	 .desc = "Level 1 data TLB refill"
+	},
+
+	{.name = "INST_RETIRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x08,
+	 .desc = "Instruction architecturally executed"
+	},
+	{.name = "EXCEPTION_TAKEN",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x09,
+	 .desc = "Exception taken"
+	},
+	{.name = "EXCEPTION_RETURN",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x0a,
+	 .desc = "Instruction architecturally executed (condition check pass) Exception return"
+	},
+	{.name = "CID_WRITE_RETIRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x0b,
+	 .desc = "Instruction architecturally executed (condition check pass)  Write to CONTEXTIDR"
+	},
+
+	{.name = "BRANCH_MISPRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x10,
+	 .desc = "Mispredicted or not predicted branch speculatively executed"
+	},
+	{.name = "CPU_CYCLES",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x11,
+	 .desc = "Cycles"
+	},
+	{.name = "BRANCH_PRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x12,
+	 .desc = "Predictable branch speculatively executed"
+	},
+	{.name = "DATA_MEM_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x13,
+	 .desc = "Data memory access"
+	},
+	{.name = "L1I_CACHE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x14,
+	 .desc = "Level 1 instruction cache access"
+	},
+	{.name = "L1D_CACHE_WB",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x15,
+	 .desc = "Level 1 data cache WriteBack"
+	},
+	{.name = "L2D_CACHE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x16,
+	 .desc = "Level 2 data cache access"
+	},
+	{.name = "L2D_CACHE_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x17,
+	 .desc = "Level 2 data cache refill"
+	},
+	{.name = "L2D_CACHE_WB",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x18,
+	 .desc = "Level 2 data cache WriteBack"
+	},
+	{.name = "BUS_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x19,
+	 .desc = "Bus access"
+	},
+	{.name = "LOCAL_MEMORY_ERROR",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x1a,
+	 .desc = "Local memory error"
+	},
+	{.name = "INST_SPEC_EXEC",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x1b,
+	 .desc = "Instruction speculatively executed"
+	},
+	{.name = "TTBR_WRITE_RETIRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x1c,
+	 .desc = "Instruction architecturally executed (condition check pass)  Write to translation table base"
+	},
+	{.name = "BUS_CYCLES",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x1d,
+	 .desc = "Bus cycle"
+	},
+	{.name = "L1D_READ_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x40,
+	 .desc = "Level 1 data cache read access"
+	},
+	{.name = "L1D_WRITE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x41,
+	 .desc = "Level 1 data cache write access"
+	},
+	{.name = "L1D_READ_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x42,
+	 .desc = "Level 1 data cache read refill"
+	},
+	{.name = "L1D_WRITE_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x43,
+	 .desc = "Level 1 data cache write refill"
+	},
+	{.name = "L1D_WB_VICTIM",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x46,
+	 .desc = "Level 1 data cache writeback victim"
+	},
+	{.name = "L1D_WB_CLEAN_COHERENCY",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x47,
+	 .desc = "Level 1 data cache writeback cleaning and coherency"
+	},
+	{.name = "L1D_INVALIDATE",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x48,
+	 .desc = "Level 1 data cache invalidate"
+	},
+	{.name = "L1D_TLB_READ_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x4c,
+	 .desc = "Level 1 data TLB read refill"
+	},
+	{.name = "L1D_TLB_WRITE_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x4d,
+	 .desc = "Level 1 data TLB write refill"
+	},
+	{.name = "L2D_READ_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x50,
+	 .desc = "Level 2 data cache read access"
+	},
+	{.name = "L2D_WRITE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x51,
+	 .desc = "Level 2 data cache write access"
+	},
+	{.name = "L2D_READ_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x52,
+	 .desc = "Level 2 data cache read refill"
+	},
+	{.name = "L2D_WRITE_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x53,
+	 .desc = "Level 2 data cache write refill"
+	},
+	{.name = "L2D_WB_VICTIM",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x56,
+	 .desc = "Level 2 data cache writeback victim"
+	},
+	{.name = "L2D_WB_CLEAN_COHERENCY",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x57,
+	 .desc = "Level 2 data cache writeback cleaning and coherency"
+	},
+	{.name = "L2D_INVALIDATE",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x58,
+	 .desc = "Level 2 data cache invalidate"
+	},
+	{.name = "BUS_READ_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x60,
+	 .desc = "Bus read access"
+	},
+	{.name = "BUS_WRITE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x61,
+	 .desc = "Bus write access"
+	},
+	{.name = "BUS_NORMAL_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x62,
+	 .desc = "Bus normal access"
+	},
+	{.name = "BUS_NOT_NORMAL_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x63,
+	 .desc = "Bus not normal access"
+	},
+	{.name = "BUS_NORMAL_ACCESS_2",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x64,
+	 .desc = "Bus normal access"
+	},
+	{.name = "BUS_PERIPH_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x65,
+	 .desc = "Bus peripheral access"
+	},
+	{.name = "DATA_MEM_READ_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x66,
+	 .desc = "Data memory read access"
+	},
+	{.name = "DATA_MEM_WRITE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x67,
+	 .desc = "Data memory write access"
+	},
+	{.name = "UNALIGNED_READ_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x68,
+	 .desc = "Unaligned read access"
+	},
+	{.name = "UNALIGNED_WRITE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x69,
+	 .desc = "Unaligned read access"
+	},
+	{.name = "UNALIGNED_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x6a,
+	 .desc = "Unaligned access"
+	},
+	{.name = "INST_SPEC_EXEC_LDREX",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x6c,
+	 .desc = "LDREX exclusive instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_STREX_PASS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x6d,
+	 .desc = "STREX pass exclusive instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_STREX_FAIL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x6e,
+	 .desc = "STREX fail exclusive instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_LOAD",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x70,
+	 .desc = "Load instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_STORE",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x71,
+	 .desc = "Store instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_LOAD_STORE",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x72,
+	 .desc = "Load or store instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_INTEGER_INST",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x73,
+	 .desc = "Integer data processing instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_SIMD",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x74,
+	 .desc = "Advanced SIMD instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_VFP",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x75,
+	 .desc = "VFP instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_SOFT_PC",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x76,
+	 .desc = "Software of the PC instruction speculatively executed"
+	},
+	{.name = "BRANCH_SPEC_EXEC_IMM_BRANCH",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x78,
+	 .desc = "Immediate branch speculatively executed"
+	},
+	{.name = "BRANCH_SPEC_EXEC_RET",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x79,
+	 .desc = "Return branch speculatively executed"
+	},
+	{.name = "BRANCH_SPEC_EXEC_IND",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x7a,
+	 .desc = "Indirect branch speculatively executed"
+	},
+	{.name = "BARRIER_SPEC_EXEC_ISB",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x7c,
+	 .desc = "ISB barrier speculatively executed"
+	},
+	{.name = "BARRIER_SPEC_EXEC_DSB",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x7d,
+	 .desc = "DSB barrier speculatively executed"
+	},
+	{.name = "BARRIER_SPEC_EXEC_DMB",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x7e,
+	 .desc = "DMB barrier speculatively executed"
+	},
+	{.name = "EXCEPTION_UNDEF",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x81,
+	 .desc = "Exception taken, other synchronous"
+	},
+	{.name = "EXCEPTION_SVC",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x82,
+	 .desc = "Exception taken, supervisor call"
+	},
+	{.name = "EXCEPTION_PABORT",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x83,
+	 .desc = "Exception taken, instruction abort"
+	},
+	{.name = "EXCEPTION_DABORT",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x84,
+	 .desc = "Exception taken, data abort or SError"
+	},
+	{.name = "EXCEPTION_IRQ",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x86,
+	 .desc = "Exception taken, irq"
+	},
+	{.name = "EXCEPTION_FIQ",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x87,
+	 .desc = "Exception taken, irq"
+	},
+	{.name = "EXCEPTION_SMC",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x88,
+	 .desc = "Exception taken, secure monitor call"
+	},
+	{.name = "EXCEPTION_HVC",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x8a,
+	 .desc = "Exception taken, hypervisor call"
+	},
+	{.name = "EXCEPTION_TRAP_PABORT",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x8b,
+	 .desc = "Exception taken, instruction abort not taken locally"
+	},
+	{.name = "EXCEPTION_TRAP_DABORT",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x8c,
+	 .desc = "Exception taken, data abort or SError not taken locally"
+	},
+	{.name = "EXCEPTION_TRAP_OTHER",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x8d,
+	 .desc = "Exception taken, other traps not taken locally"
+	},
+	{.name = "EXCEPTION_TRAP_IRQ",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x8e,
+	 .desc = "Exception taken, irq not taken locally"
+	},
+	{.name = "EXCEPTION_TRAP_FIQ",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x8f,
+	 .desc = "Exception taken, fiq not taken locally"
+	},
+	{.name = "RC_LD_SPEC",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x90,
+	 .desc = "Release consistency instruction speculatively executed (load-acquire)",
+	},
+	{.name = "RC_ST_SPEC",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x91,
+	 .desc = "Release consistency instruction speculatively executed (store-release)",
+	},
+	/* END Cortex A47 specific events */
+};
diff --git a/lib/pfmlib_arm_armv8.c b/lib/pfmlib_arm_armv8.c
new file mode 100644
index 0000000..880d566
--- /dev/null
+++ b/lib/pfmlib_arm_armv8.c
@@ -0,0 +1,74 @@
+/*
+ * pfmlib_arm_armv8.c : support for ARMv8 processors
+ *
+ * Copyright (c) 2014 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * 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>
+
+/* private headers */
+#include "pfmlib_priv.h"			/* library private */
+#include "pfmlib_arm_priv.h"
+
+#include "events/arm_cortex_a57_events.h"    /* event tables */
+
+static int
+pfm_arm_detect_cortex_a57(void *this)
+{
+	int ret;
+
+	ret = pfm_arm_detect(this);
+	if (ret != PFM_SUCCESS)
+		return PFM_ERR_NOTSUPP;
+
+	if ((pfm_arm_cfg.implementer == 0x41) && /* ARM */
+		(pfm_arm_cfg.part == 0xc00)) { /* Cortex A57 */
+			return PFM_SUCCESS;
+	}
+	return PFM_ERR_NOTSUPP;
+}
+
+/* ARM Cortex A57 support */
+pfmlib_pmu_t arm_cortex_a57_support={
+	.desc			= "ARM Cortex A57",
+	.name			= "arm_ac57",
+	.pmu			= PFM_PMU_ARM_CORTEX_A57,
+	.pme_count		= LIBPFM_ARRAY_SIZE(arm_cortex_a57_pe),
+	.type			= PFM_PMU_TYPE_CORE,
+	.pe			= arm_cortex_a57_pe,
+
+	.pmu_detect		= pfm_arm_detect_cortex_a57,
+	.max_encoding		= 1,
+	.num_cntrs		= 6,
+
+	.get_event_encoding[PFM_OS_NONE] = pfm_arm_get_encoding,
+	 PFMLIB_ENCODE_PERF(pfm_arm_get_perf_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,
+	.validate_table		= pfm_arm_validate_table,
+	.get_event_info		= pfm_arm_get_event_info,
+	.get_event_attr_info	= pfm_arm_get_event_attr_info,
+	 PFMLIB_VALID_PERF_PATTRS(pfm_arm_perf_validate_pattrs),
+	.get_event_nattrs	= pfm_arm_get_event_nattrs,
+};
diff --git a/lib/pfmlib_arm_priv.h b/lib/pfmlib_arm_priv.h
index ef367b7..227508b 100644
--- a/lib/pfmlib_arm_priv.h
+++ b/lib/pfmlib_arm_priv.h
@@ -86,6 +86,9 @@ extern int pfm_arm_get_perf_encoding(void *this, pfmlib_event_desc_t *e);
 #define ARMV7_A15_ATTRS	(_ARM_ATTR_K|_ARM_ATTR_U|_ARM_ATTR_HV)
 #define ARMV7_A15_PLM	(PFM_PLM0|PFM_PLM3|PFM_PLMH)
 
+#define ARMV8_ATTRS	(_ARM_ATTR_K|_ARM_ATTR_U|_ARM_ATTR_HV)
+#define ARMV8_PLM	(PFM_PLM0|PFM_PLM3|PFM_PLMH)
+
 static inline int
 arm_has_plm(void *this, pfmlib_event_desc_t *e)
 {
diff --git a/lib/pfmlib_common.c b/lib/pfmlib_common.c
index 8e4b1a1..900d7de 100644
--- a/lib/pfmlib_common.c
+++ b/lib/pfmlib_common.c
@@ -199,7 +199,12 @@ static pfmlib_pmu_t *pfmlib_pmus[]=
 	&arm_cortex_a9_support,
 	&arm_cortex_a15_support,
 	&arm_1176_support,
+	&arm_cortex_a57_support,
 #endif
+#ifdef CONFIG_PFMLIB_ARCH_ARM64
+	&arm_cortex_a57_support,
+#endif
+
 #ifdef CONFIG_PFMLIB_ARCH_S390X
 	&s390x_cpum_cf_support,
 #endif
diff --git a/lib/pfmlib_priv.h b/lib/pfmlib_priv.h
index 715c4b0..3031d3b 100644
--- a/lib/pfmlib_priv.h
+++ b/lib/pfmlib_priv.h
@@ -332,6 +332,7 @@ extern pfmlib_pmu_t arm_cortex_a9_support;
 extern pfmlib_pmu_t arm_cortex_a9_support;
 extern pfmlib_pmu_t arm_cortex_a15_support;
 extern pfmlib_pmu_t arm_1176_support;
+extern pfmlib_pmu_t arm_cortex_a57_support;
 extern pfmlib_pmu_t mips_74k_support;
 extern pfmlib_pmu_t s390x_cpum_cf_support;
 
diff --git a/tests/Makefile b/tests/Makefile
index 7076fb7..7dd82c3 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -39,6 +39,10 @@ ifeq ($(CONFIG_PFMLIB_ARCH_ARM),y)
 SRCS += validate_arm.c
 endif
 
+ifeq ($(CONFIG_PFMLIB_ARCH_ARM64),y)
+SRCS += validate_arm64.c
+endif
+
 ifeq ($(CONFIG_PFMLIB_ARCH_POWERPC),y)
 SRCS += validate_power.c
 endif
diff --git a/tests/validate_arm.c b/tests/validate_arm.c
index fe97aa9..d6c0168 100644
--- a/tests/validate_arm.c
+++ b/tests/validate_arm.c
@@ -159,6 +159,34 @@ static const test_event_t arm_test_events[]={
 	  .codes[0] = 0x07,
 	  .fstr = "arm_1176::INSTR_EXEC",
 	},
+	{ SRC_LINE,
+	  .name = "arm_ac57::CPU_CYCLES",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000011,
+	  .fstr = "arm_ac57::CPU_CYCLES:k=1:u=1:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_ac57::CPU_CYCLES:k",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x88000011,
+	  .fstr = "arm_ac57::CPU_CYCLES:k=1:u=0:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_ac57::CPU_CYCLES:k:u",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000011,
+	  .fstr = "arm_ac57::CPU_CYCLES:k=1:u=1:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_ac57::INST_RETIRED",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000008,
+	  .fstr = "arm_ac57::INST_RETIRED:k=1:u=1:hv=0",
+	},
 };
 #define NUM_TEST_EVENTS (int)(sizeof(arm_test_events)/sizeof(test_event_t))
 
diff --git a/tests/validate_arm64.c b/tests/validate_arm64.c
new file mode 100644
index 0000000..0f0174c
--- /dev/null
+++ b/tests/validate_arm64.c
@@ -0,0 +1,138 @@
+/*
+ * validate_arm64.c - validate ARM64 event tables + encodings
+ *
+ * Copyright (c) 2014 Google, Inc
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <perfmon/pfmlib.h>
+
+#define MAX_ENCODING	1
+#define SRC_LINE	.line = __LINE__
+
+typedef struct {
+	const char *name;
+	const char *fstr;
+	uint64_t codes[MAX_ENCODING];
+	int ret, count, line;
+} test_event_t;
+
+static const test_event_t arm64_test_events[]={
+	{ SRC_LINE,
+	  .name = "arm_ac57::CPU_CYCLES",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000011,
+	  .fstr = "arm_ac57::CPU_CYCLES:k=1:u=1:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_ac57::CPU_CYCLES:k",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x88000011,
+	  .fstr = "arm_ac57::CPU_CYCLES:k=1:u=0:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_ac57::CPU_CYCLES:k:u",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000011,
+	  .fstr = "arm_ac57::CPU_CYCLES:k=1:u=1:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_ac57::INST_RETIRED",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000008,
+	  .fstr = "arm_ac57::INST_RETIRED:k=1:u=1:hv=0",
+	},
+};
+#define NUM_TEST_EVENTS (int)(sizeof(arm64_test_events)/sizeof(test_event_t))
+
+static int check_test_events(FILE *fp)
+{
+	const test_event_t *e;
+	char *fstr;
+	uint64_t *codes;
+	int count, i, j;
+	int ret, errors = 0;
+
+	for (i = 0, e = arm64_test_events; i < NUM_TEST_EVENTS; i++, e++) {
+		codes = NULL;
+		count = 0;
+		fstr = NULL;
+		ret = pfm_get_event_encoding(e->name, PFM_PLM0 | PFM_PLM3, &fstr, NULL, &codes, &count);
+		if (ret != e->ret) {
+			fprintf(fp,"Line %d, Event%d %s, ret=%s(%d) expected %s(%d)\n", e->line, i, e->name, pfm_strerror(ret), ret, pfm_strerror(e->ret), e->ret);
+			errors++;
+		} else {
+			if (ret != PFM_SUCCESS) {
+				if (fstr) {
+					fprintf(fp,"Line %d, Event%d %s, expected fstr NULL but it is not\n", e->line, i, e->name);
+					errors++;
+				}
+				if (count != 0) {
+					fprintf(fp,"Line %d, Event%d %s, expected count=0 instead of %d\n", e->line, i, e->name, count);
+					errors++;
+				}
+				if (codes) {
+					fprintf(fp,"Line %d, Event%d %s, expected codes[] NULL but it is not\n", e->line, i, e->name);
+					errors++;
+				}
+			} else {
+				if (count != e->count) {
+					fprintf(fp,"Line %d, Event%d %s, count=%d expected %d\n", e->line, i, e->name, count, e->count);
+					errors++;
+				}
+				for (j=0; j < count; j++) {
+					if (codes[j] != e->codes[j]) {
+						fprintf(fp,"Line %d, Event%d %s, codes[%d]=%#"PRIx64" expected %#"PRIx64"\n", e->line, i, e->name, j, codes[j], e->codes[j]);
+						errors++;
+					}
+				}
+				if (e->fstr && strcmp(fstr, e->fstr)) {
+					fprintf(fp,"Line %d, Event%d %s, fstr=%s expected %s\n", e->line, i, e->name, fstr, e->fstr);
+					errors++;
+				}
+			}
+		}
+		if (codes)
+			free(codes);
+		if (fstr)
+			free(fstr);
+	}
+	printf("\t %d ARM64 events: %d errors\n", i, errors);
+	return errors;
+}
+
+int
+validate_arch(FILE *fp)
+{
+	return check_test_events(fp);
+}
commit b95de18085dd74738752341e0004b3dd11f00a53
Author: Stephane Eranian <eranian@gmail.com>
Date:   Mon May 12 14:15:57 2014 +0200

    Add ARM Cortex A57 documentation
    
    Signed-off-by: Stephane Eranian <eranian@gmail.com>

diff --git a/docs/Makefile b/docs/Makefile
index ecf6769..9b79ec7 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -76,7 +76,11 @@ endif
 endif
 
 ifeq ($(CONFIG_PFMLIB_ARCH_ARM),y)
-ARCH_MAN += libpfm_arm_ac15.3 libpfm_arm_ac8.3 libpfm_arm_ac9.3
+ARCH_MAN += libpfm_arm_ac57.3 libpfm_arm_ac15.3 libpfm_arm_ac8.3 libpfm_arm_ac9.3
+endif
+
+ifeq ($(CONFIG_PFMLIB_ARCH_ARM64),y)
+ARCH_MAN += libpfm_arm_ac57.3
 endif
 
 
diff --git a/docs/man3/libpfm_arm_ac57.3 b/docs/man3/libpfm_arm_ac57.3
new file mode 100644
index 0000000..c471ff1
--- /dev/null
+++ b/docs/man3/libpfm_arm_ac57.3
@@ -0,0 +1,36 @@
+.TH LIBPFM 4  "May, 2014" "" "Linux Programmer's Manual"
+.SH NAME
+libpfm_arm_ac57 - support for Arm Cortex A57 PMU
+.SH SYNOPSIS
+.nf
+.B #include <perfmon/pfmlib.h>
+.sp
+.B PMU name: arm_ac57
+.B PMU desc: ARM Cortex A57
+.sp
+.SH DESCRIPTION
+The library supports the ARM Cortex A57 core PMU.
+
+This PMU supports 6 counters and privilege levels filtering.
+It can operate in both 32 and 64 bit modes.
+
+.SH MODIFIERS
+The following modifiers are supported on ARM Cortex A57:
+.TP
+.B u
+Measure at the user level. This corresponds to \fBPFM_PLM3\fR.
+This is a boolean modifier.
+.TP
+.B k
+Measure at the kernel level. This corresponds to \fBPFM_PLM0\fR.
+This is a boolean modifier.
+.TP
+.B hv
+Measure at the hypervisor level. This corresponds to \fBPFM_PLMH\fR.
+This is a boolean modifier.
+
+.SH AUTHORS
+.nf
+Stephane Eranian <eranian@gmail.com>
+.if
+.PP
commit 399aa947ca6f4c58acac8c6be52d2ad4e5268210
Author: Stephane Eranian <eranian@gmail.com>
Date:   Fri May 16 15:42:40 2014 +0200

    fix the ARM Cortex A57 detection
    
    This patch fixes the detection of ARM Cortex A57.
    Was using the wrong part number. Correct number
    is 0xD07.
    
    Signed-off-by: Stephane Eranian <eranian@gmail.com>

diff --git a/lib/pfmlib_arm_armv8.c b/lib/pfmlib_arm_armv8.c
index 880d566..4bc863b 100644
--- a/lib/pfmlib_arm_armv8.c
+++ b/lib/pfmlib_arm_armv8.c
@@ -42,7 +42,7 @@ pfm_arm_detect_cortex_a57(void *this)
 		return PFM_ERR_NOTSUPP;
 
 	if ((pfm_arm_cfg.implementer == 0x41) && /* ARM */
-		(pfm_arm_cfg.part == 0xc00)) { /* Cortex A57 */
+		(pfm_arm_cfg.part == 0xd07)) { /* Cortex A57 */
 			return PFM_SUCCESS;
 	}
 	return PFM_ERR_NOTSUPP;
commit 6d1faa5bd1c0564b24cf030f118cd9782e1b4e0c
Author: Stephane Eranian <eranian@gmail.com>
Date:   Thu May 22 18:44:47 2014 +0200

    Add missing arm_cortex_a57.h header dependency
    
    Was missing. We compile A57 for 32-bit arm as well.
    
    Signed-off-by: Stephane Eranian <eranian@gmail.com>

diff --git a/lib/Makefile b/lib/Makefile
index 6ca3287..585cc3e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -281,7 +281,8 @@ INC_ARM=events/arm_cortex_a8_events.h		\
 INC_ARM=pfmlib_arm_priv.h			\
 	events/arm_cortex_a8_events.h		\
 	events/arm_cortex_a9_events.h		\
-	events/arm_cortex_a15_events.h
+	events/arm_cortex_a15_events.h		\
+	events/arm_cortex_a57_events.h
 
 INC_ARM64=events/arm_cortex_a57_events.h
 
commit 6af79d5186b7593c4f7e41024b78453debceb45f
Author: Stephane Eranian <eranian@gmail.com>
Date:   Thu May 22 19:14:52 2014 +0200

    Add ARM Cortex A53 support
    
    This patch adds support for the ARM Cortex A53 core PMU as
    documented in r0p2 version f the Cortex-A53 MPCore processor
    technical reference manual Table 12.28.
    
    Support is provided for both 32 and 64-bit modes.
    
    Includes man page, and validation tests.
    
    Signed-off-by: Stephane Eranian <eranian@gmail.com>

diff --git a/README b/README
index 334c78a..e74238f 100644
--- a/README
+++ b/README
@@ -57,6 +57,7 @@ The library supports many PMUs. The current version can handle:
 		ARMV7 Cortex A8
 		ARMV7 Cortex A9
 		ARMV7 Cortex A15
+		ARMV8 Cortex A57, A53
 
 	- For SPARC
 		Ultra I, II
diff --git a/docs/Makefile b/docs/Makefile
index 9b79ec7..c7d797e 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -76,11 +76,16 @@ endif
 endif
 
 ifeq ($(CONFIG_PFMLIB_ARCH_ARM),y)
-ARCH_MAN += libpfm_arm_ac57.3 libpfm_arm_ac15.3 libpfm_arm_ac8.3 libpfm_arm_ac9.3
+ARCH_MAN += libpfm_arm_ac57.3 \
+	    libpfm_arm_ac53.3 \
+	    libpfm_arm_ac15.3 \
+	    libpfm_arm_ac8.3 \
+	    libpfm_arm_ac9.3
 endif
 
 ifeq ($(CONFIG_PFMLIB_ARCH_ARM64),y)
-ARCH_MAN += libpfm_arm_ac57.3
+ARCH_MAN += libpfm_arm_ac57.3 \
+	    libpfm_arm_ac53.3
 endif
 
 
diff --git a/docs/man3/libpfm_arm_ac53.3 b/docs/man3/libpfm_arm_ac53.3
new file mode 100644
index 0000000..319accc
--- /dev/null
+++ b/docs/man3/libpfm_arm_ac53.3
@@ -0,0 +1,36 @@
+.TH LIBPFM 4  "May, 2014" "" "Linux Programmer's Manual"
+.SH NAME
+libpfm_arm_ac53 - support for ARM Cortex A53 PMU
+.SH SYNOPSIS
+.nf
+.B #include <perfmon/pfmlib.h>
+.sp
+.B PMU name: arm_ac53
+.B PMU desc: ARM Cortex A53
+.sp
+.SH DESCRIPTION
+The library supports the ARM Cortex A53 core PMU.
+
+This PMU supports 6 counters and privilege levels filtering.
+It can operate in both 32 and 64 bit modes.
+
+.SH MODIFIERS
+The following modifiers are supported on ARM Cortex A53:
+.TP
+.B u
+Measure at the user level. This corresponds to \fBPFM_PLM3\fR.
+This is a boolean modifier.
+.TP
+.B k
+Measure at the kernel level. This corresponds to \fBPFM_PLM0\fR.
+This is a boolean modifier.
+.TP
+.B hv
+Measure at the hypervisor level. This corresponds to \fBPFM_PLMH\fR.
+This is a boolean modifier.
+
+.SH AUTHORS
+.nf
+Stephane Eranian <eranian@gmail.com>
+.if
+.PP
diff --git a/include/perfmon/pfmlib.h b/include/perfmon/pfmlib.h
index b08df66..a7ec026 100644
--- a/include/perfmon/pfmlib.h
+++ b/include/perfmon/pfmlib.h
@@ -238,6 +238,7 @@ typedef enum {
 	PFM_PMU_INTEL_HSW_EP,		/* Intel Haswell EP */
 
 	PFM_PMU_ARM_CORTEX_A57,		/* ARM Cortex A57 (ARMv8) */
+	PFM_PMU_ARM_CORTEX_A53,		/* ARM Cortex A53 (ARMv8) */
 
 	/* MUST ADD NEW PMU MODELS HERE */
 
diff --git a/lib/Makefile b/lib/Makefile
index 585cc3e..5aaf4b3 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -282,9 +282,11 @@ INC_ARM=pfmlib_arm_priv.h			\
 	events/arm_cortex_a8_events.h		\
 	events/arm_cortex_a9_events.h		\
 	events/arm_cortex_a15_events.h		\
-	events/arm_cortex_a57_events.h
+	events/arm_cortex_a57_events.h		\
+	events/arm_cortex_a53_events.h
 
-INC_ARM64=events/arm_cortex_a57_events.h
+INC_ARM64=events/arm_cortex_a57_events.h	\
+	  events/arm_cortex_a53_events.h
 
 INCDEP=$(INC_COMMON) $(INCARCH)
 
diff --git a/lib/events/arm_cortex_a53_events.h b/lib/events/arm_cortex_a53_events.h
new file mode 100644
index 0000000..c0d2bb6
--- /dev/null
+++ b/lib/events/arm_cortex_a53_events.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2014 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * 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.
+ *
+ * Cortex A53 r0p2
+ * based on Table 12.9 from the "Cortex A53 Technical Reference Manual"
+ */
+
+static const arm_entry_t arm_cortex_a53_pe[]={
+	{.name = "SW_INCR",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x00,
+	 .desc = "Instruction architecturally executed (condition check pass) Software increment"
+	},
+	{.name = "L1I_CACHE_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x01,
+	 .desc = "Level 1 instruction cache refill"
+	},
+	{.name = "L1I_TLB_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x02,
+	 .desc = "Level 1 instruction TLB refill"
+	},
+	{.name = "L1D_CACHE_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x03,
+	 .desc = "Level 1 data cache refill"
+	},
+	{.name = "L1D_CACHE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x04,
+	 .desc = "Level 1 data cache access"
+	},
+	{.name = "L1D_TLB_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x05,
+	 .desc = "Level 1 data TLB refill"
+	},
+	{.name = "LD_RETIRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x06,
+	 .desc = "Load Instruction architecturally executed, condition check",
+	},
+	{.name = "ST_RETIRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x07,
+	 .desc = "Store Instruction architecturally executed, condition check",
+	},
+	{.name = "INST_RETIRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x08,
+	 .desc = "Instruction architecturally executed"
+	},
+	{.name = "EXCEPTION_TAKEN",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x09,
+	 .desc = "Exception taken"
+	},
+	{.name = "EXCEPTION_RETURN",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x0a,
+	 .desc = "Instruction architecturally executed (condition check pass) Exception return"
+	},
+	{.name = "CID_WRITE_RETIRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x0b,
+	 .desc = "Change to Context ID retired",
+	},
+	{.name = "PC_WRITE_RETIRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x0c,
+	 .desc = "Write to CONTEXTIDR, instruction architecturally executed, condition check pass"
+	},
+	{.name = "BR_IMMED_RETIRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x0d,
+	 .desc = "Software chnage of the PC, instruction architecturally executed, condition check pass"
+	},
+	{.name = "UNALIGNED_LDST_RETIRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x0f,
+	 .desc = "Procedure return, instruction architecturally executed, condition check pass"
+	},
+	{.name = "BRANCH_MISPRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x10,
+	 .desc = "Mispredicted or not predicted branch speculatively executed"
+	},
+	{.name = "CPU_CYCLES",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x11,
+	 .desc = "Cycles"
+	},
+	{.name = "BRANCH_PRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x12,
+	 .desc = "Predictable branch speculatively executed"
+	},
+	{.name = "DATA_MEM_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x13,
+	 .desc = "Data memory access"
+	},
+	{.name = "L1I_CACHE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x14,
+	 .desc = "Level 1 instruction cache access"
+	},
+	{.name = "L1D_CACHE_WB",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x15,
+	 .desc = "Level 1 data cache WriteBack"
+	},
+	{.name = "L2D_CACHE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x16,
+	 .desc = "Level 2 data cache access"
+	},
+	{.name = "L2D_CACHE_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x17,
+	 .desc = "Level 2 data cache refill"
+	},
+	{.name = "L2D_CACHE_WB",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x18,
+	 .desc = "Level 2 data cache WriteBack"
+	},
+	{.name = "BUS_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x19,
+	 .desc = "Bus access"
+	},
+	{.name = "LOCAL_MEMORY_ERROR",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x1a,
+	 .desc = "Local memory error"
+	},
+	{.name = "BUS_CYCLES",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x1d,
+	 .desc = "Bus cycle"
+	},
+
+	{.name = "BUS_READ_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x60,
+	 .desc = "Bus read access"
+	},
+	{.name = "BUS_WRITE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x61,
+	 .desc = "Bus write access"
+	},
+
+	{.name = "BRANCH_SPEC_EXEC_IND",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x7a,
+	 .desc = "Indirect branch speculatively executed"
+	},
+
+	{.name = "EXCEPTION_IRQ",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x86,
+	 .desc = "Exception taken, irq"
+	},
+	{.name = "EXCEPTION_FIQ",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x87,
+	 .desc = "Exception taken, irq"
+	},
+};
diff --git a/lib/pfmlib_arm_armv8.c b/lib/pfmlib_arm_armv8.c
index 4bc863b..c38bd9b 100644
--- a/lib/pfmlib_arm_armv8.c
+++ b/lib/pfmlib_arm_armv8.c
@@ -30,7 +30,8 @@
 #include "pfmlib_priv.h"			/* library private */
 #include "pfmlib_arm_priv.h"
 
-#include "events/arm_cortex_a57_events.h"    /* event tables */
+#include "events/arm_cortex_a57_events.h"    /* A57 event tables */
+#include "events/arm_cortex_a53_events.h"    /* A53 event tables */
 
 static int
 pfm_arm_detect_cortex_a57(void *this)
@@ -48,6 +49,22 @@ pfm_arm_detect_cortex_a57(void *this)
 	return PFM_ERR_NOTSUPP;
 }
 
+static int
+pfm_arm_detect_cortex_a53(void *this)
+{
+	int ret;
+
+	ret = pfm_arm_detect(this);
+	if (ret != PFM_SUCCESS)
+		return PFM_ERR_NOTSUPP;
+
+	if ((pfm_arm_cfg.implementer == 0x41) && /* ARM */
+		(pfm_arm_cfg.part == 0xd03)) { /* Cortex A53 */
+			return PFM_SUCCESS;
+	}
+	return PFM_ERR_NOTSUPP;
+}
+
 /* ARM Cortex A57 support */
 pfmlib_pmu_t arm_cortex_a57_support={
 	.desc			= "ARM Cortex A57",
@@ -72,3 +89,28 @@ pfmlib_pmu_t arm_cortex_a57_support={
 	 PFMLIB_VALID_PERF_PATTRS(pfm_arm_perf_validate_pattrs),
 	.get_event_nattrs	= pfm_arm_get_event_nattrs,
 };
+
+/* ARM Cortex A53 support */
+pfmlib_pmu_t arm_cortex_a53_support={
+	.desc			= "ARM Cortex A53",
+	.name			= "arm_ac53",
+	.pmu			= PFM_PMU_ARM_CORTEX_A53,
+	.pme_count		= LIBPFM_ARRAY_SIZE(arm_cortex_a53_pe),
+	.type			= PFM_PMU_TYPE_CORE,
+	.pe			= arm_cortex_a53_pe,
+
+	.pmu_detect		= pfm_arm_detect_cortex_a53,
+	.max_encoding		= 1,
+	.num_cntrs		= 6,
+
+	.get_event_encoding[PFM_OS_NONE] = pfm_arm_get_encoding,
+	 PFMLIB_ENCODE_PERF(pfm_arm_get_perf_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,
+	.validate_table		= pfm_arm_validate_table,
+	.get_event_info		= pfm_arm_get_event_info,
+	.get_event_attr_info	= pfm_arm_get_event_attr_info,
+	 PFMLIB_VALID_PERF_PATTRS(pfm_arm_perf_validate_pattrs),
+	.get_event_nattrs	= pfm_arm_get_event_nattrs,
+};
diff --git a/lib/pfmlib_common.c b/lib/pfmlib_common.c
index 900d7de..ebe20da 100644
--- a/lib/pfmlib_common.c
+++ b/lib/pfmlib_common.c
@@ -200,9 +200,11 @@ static pfmlib_pmu_t *pfmlib_pmus[]=
 	&arm_cortex_a15_support,
 	&arm_1176_support,
 	&arm_cortex_a57_support,
+	&arm_cortex_a53_support,
 #endif
 #ifdef CONFIG_PFMLIB_ARCH_ARM64
 	&arm_cortex_a57_support,
+	&arm_cortex_a53_support,
 #endif
 
 #ifdef CONFIG_PFMLIB_ARCH_S390X
diff --git a/lib/pfmlib_priv.h b/lib/pfmlib_priv.h
index 3031d3b..5678cc0 100644
--- a/lib/pfmlib_priv.h
+++ b/lib/pfmlib_priv.h
@@ -333,6 +333,7 @@ extern pfmlib_pmu_t arm_cortex_a15_support;
 extern pfmlib_pmu_t arm_cortex_a15_support;
 extern pfmlib_pmu_t arm_1176_support;
 extern pfmlib_pmu_t arm_cortex_a57_support;
+extern pfmlib_pmu_t arm_cortex_a53_support;
 extern pfmlib_pmu_t mips_74k_support;
 extern pfmlib_pmu_t s390x_cpum_cf_support;
 
diff --git a/tests/validate_arm.c b/tests/validate_arm.c
index d6c0168..44eefd4 100644
--- a/tests/validate_arm.c
+++ b/tests/validate_arm.c
@@ -187,6 +187,48 @@ static const test_event_t arm_test_events[]={
 	  .codes[0] = 0x8000008,
 	  .fstr = "arm_ac57::INST_RETIRED:k=1:u=1:hv=0",
 	},
+	{ SRC_LINE,
+	  .name = "arm_ac53::CPU_CYCLES",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000011,
+	  .fstr = "arm_ac53::CPU_CYCLES:k=1:u=1:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_ac53::CPU_CYCLES:k",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x88000011,
+	  .fstr = "arm_ac53::CPU_CYCLES:k=1:u=0:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_ac53::CPU_CYCLES:k:u",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000011,
+	  .fstr = "arm_ac53::CPU_CYCLES:k=1:u=1:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_ac53::INST_RETIRED",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000008,
+	  .fstr = "arm_ac53::INST_RETIRED:k=1:u=1:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_ac53::LD_RETIRED",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000006,
+	  .fstr = "arm_ac53::LD_RETIRED:k=1:u=1:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_ac53::ST_RETIRED",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000007,
+	  .fstr = "arm_ac53::ST_RETIRED:k=1:u=1:hv=0",
+	},
 };
 #define NUM_TEST_EVENTS (int)(sizeof(arm_test_events)/sizeof(test_event_t))
 
diff --git a/tests/validate_arm64.c b/tests/validate_arm64.c
index 0f0174c..61400ac 100644
--- a/tests/validate_arm64.c
+++ b/tests/validate_arm64.c
@@ -72,6 +72,48 @@ static const test_event_t arm64_test_events[]={
 	  .codes[0] = 0x8000008,
 	  .fstr = "arm_ac57::INST_RETIRED:k=1:u=1:hv=0",
 	},
+	{ SRC_LINE,
+	  .name = "arm_ac53::CPU_CYCLES",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000011,
+	  .fstr = "arm_ac53::CPU_CYCLES:k=1:u=1:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_ac53::CPU_CYCLES:k",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x88000011,
+	  .fstr = "arm_ac53::CPU_CYCLES:k=1:u=0:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_ac53::CPU_CYCLES:k:u",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000011,
+	  .fstr = "arm_ac53::CPU_CYCLES:k=1:u=1:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_ac53::INST_RETIRED",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000008,
+	  .fstr = "arm_ac53::INST_RETIRED:k=1:u=1:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_ac53::LD_RETIRED",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000006,
+	  .fstr = "arm_ac53::LD_RETIRED:k=1:u=1:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_ac53::ST_RETIRED",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000007,
+	  .fstr = "arm_ac53::ST_RETIRED:k=1:u=1:hv=0",
+	},
 };
 #define NUM_TEST_EVENTS (int)(sizeof(arm64_test_events)/sizeof(test_event_t))
 
Return-Path: wcohen@redhat.com
Received: from zmta06.collab.prod.int.phx2.redhat.com (LHLO
 zmta06.collab.prod.int.phx2.redhat.com) (10.5.81.13) by
 zmail12.collab.prod.int.phx2.redhat.com with LMTP; Wed, 4 Jun 2014 10:54:07
 -0400 (EDT)
Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25])
	by zmta06.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1EC57167B59
	for <wcohen@mail.corp.redhat.com>; Wed,  4 Jun 2014 10:54:07 -0400 (EDT)
Received: from santana.rdu.redhat.com (dhcp129-21.rdu.redhat.com [10.13.129.21])
	by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s54Es62r009804;
	Wed, 4 Jun 2014 10:54:06 -0400
From: William Cohen <wcohen@redhat.com>
To: perfmon2-devel@lists.sourceforge.net
Cc: William Cohen <wcohen@redhat.com>
Subject: [PATCH] Add support for Applied Micro X-Gene processor
Date: Wed,  4 Jun 2014 10:54:04 -0400
Message-Id: <1401893644-22326-1-git-send-email-wcohen@redhat.com>
X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25

---
 README                        |   1 +
 docs/Makefile                 |   6 +-
 docs/man3/libpfm_arm_xgene.3  |  39 ++++
 include/perfmon/pfmlib.h      |   1 +
 lib/events/arm_xgene_events.h | 515 ++++++++++++++++++++++++++++++++++++++++++
 lib/pfmlib_arm_armv8.c        |  42 ++++
 lib/pfmlib_common.c           |   2 +
 lib/pfmlib_priv.h             |   1 +
 tests/validate_arm64.c        |  28 +++
 9 files changed, 633 insertions(+), 2 deletions(-)
 create mode 100644 docs/man3/libpfm_arm_xgene.3
 create mode 100644 lib/events/arm_xgene_events.h

diff --git a/README b/README
index e74238f..f6f45c9 100644
--- a/README
+++ b/README
@@ -58,6 +58,7 @@ The library supports many PMUs. The current version can handle:
 		ARMV7 Cortex A9
 		ARMV7 Cortex A15
 		ARMV8 Cortex A57, A53
+		Applied Micro X-Gene
 
 	- For SPARC
 		Ultra I, II
diff --git a/docs/Makefile b/docs/Makefile
index c7d797e..4ae4bae 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -76,7 +76,8 @@ endif
 endif
 
 ifeq ($(CONFIG_PFMLIB_ARCH_ARM),y)
-ARCH_MAN += libpfm_arm_ac57.3 \
+ARCH_MAN += libpfm_arm_xgene.3 \
+	    libpfm_arm_ac57.3 \
 	    libpfm_arm_ac53.3 \
 	    libpfm_arm_ac15.3 \
 	    libpfm_arm_ac8.3 \
@@ -85,7 +86,8 @@ ARCH_MAN += libpfm_arm_ac57.3 \
 endif
 
 ifeq ($(CONFIG_PFMLIB_ARCH_ARM64),y)
-ARCH_MAN += libpfm_arm_ac57.3 \
+ARCH_MAN += libpfm_arm_xgene.3 \
+	    libpfm_arm_ac57.3 \
 	    libpfm_arm_ac53.3
 endif
 
diff --git a/docs/man3/libpfm_arm_xgene.3 b/docs/man3/libpfm_arm_xgene.3
new file mode 100644
index 0000000..a0a84bc
--- /dev/null
+++ b/docs/man3/libpfm_arm_xgene.3
@@ -0,0 +1,39 @@
+.TH LIBPFM 4  "May, 2014" "" "Linux Programmer's Manual"
+.SH NAME
+libpfm_arm_ac57 - support for Applied Micro X-Gene PMU
+.SH SYNOPSIS
+.nf
+.B #include <perfmon/pfmlib.h>
+.sp
+.B PMU name: arm_xgene
+.B PMU desc: Applied Micro X-Gene
+.sp
+.SH DESCRIPTION
+The library supports the Applied Micro X-Gene PMU.
+
+This PMU supports 6 counters and privilege levels filtering.
+It can operate in both 32 and 64 bit modes.
+
+.SH MODIFIERS
+The following modifiers are supported on Applied Micro X-Gene:
+.TP
+.B u
+Measure at the user level. This corresponds to \fBPFM_PLM3\fR.
+This is a boolean modifier.
+.TP
+.B k
+Measure at the kernel level. This corresponds to \fBPFM_PLM0\fR.
+This is a boolean modifier.
+.TP
+.B hv
+Measure at the hypervisor level. This corresponds to \fBPFM_PLMH\fR.
+This is a boolean modifier.
+
+.SH AUTHORS
+.nf
+Stephane Eranian <eranian@gmail.com>
+.if
+.nf
+William Cohen <wcohen@redhat.com>
+.if
+.PP
diff --git a/include/perfmon/pfmlib.h b/include/perfmon/pfmlib.h
index a7ec026..b7b312e 100644
--- a/include/perfmon/pfmlib.h
+++ b/include/perfmon/pfmlib.h
@@ -239,6 +239,7 @@ typedef enum {
 
 	PFM_PMU_ARM_CORTEX_A57,		/* ARM Cortex A57 (ARMv8) */
 	PFM_PMU_ARM_CORTEX_A53,		/* ARM Cortex A53 (ARMv8) */
+	PFM_PMU_ARM_XGENE,		/* Applied Micro X-Gene (ARMv8) */
 
 	/* MUST ADD NEW PMU MODELS HERE */
 
diff --git a/lib/events/arm_xgene_events.h b/lib/events/arm_xgene_events.h
new file mode 100644
index 0000000..856dac1
--- /dev/null
+++ b/lib/events/arm_xgene_events.h
@@ -0,0 +1,515 @@
+/*
+ * Copyright (c) 2014 Google Inc. All rights reserved
+ * Copyright (c) 2014 Red Hat Inc. All rights reserved
+ * Contributed by William Cohen <wcohen@redhat.com>
+ *
+ * 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.
+ *
+ * Applied Micro X-Gene
+ * based on Mustang (X-Gene) Software User Guide 15.1.2 CPU PMU Event list
+ */
+
+static const arm_entry_t arm_xgene_pe[]={
+	{.name = "SW_INCR",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x00,
+	 .desc = "Instruction architecturally executed (condition check pass) Software increment"
+	},
+	{.name = "L1I_CACHE_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x01,
+	 .desc = "Level 1 instruction cache refill"
+	},
+	{.name = "L1I_TLB_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x02,
+	 .desc = "Level 1 instruction TLB refill"
+	},
+	{.name = "L1D_CACHE_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x03,
+	 .desc = "Level 1 data cache refill"
+	},
+	{.name = "L1D_CACHE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x04,
+	 .desc = "Level 1 data cache access"
+	},
+	{.name = "L1D_TLB_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x05,
+	 .desc = "Level 1 data TLB refill"
+	},
+	{.name = "INST_RETIRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x08,
+	 .desc = "Instruction architecturally executed"
+	},
+	{.name = "EXCEPTION_TAKEN",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x09,
+	 .desc = "Exception taken"
+	},
+	{.name = "EXCEPTION_RETURN",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x0a,
+	 .desc = "Instruction architecturally executed (condition check pass) Exception return"
+	},
+	{.name = "CID_WRITE_RETIRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x0b,
+	 .desc = "Change to Context ID retired",
+	},
+	{.name = "BRANCH_MISPRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x10,
+	 .desc = "Mispredicted or not predicted branch speculatively executed"
+	},
+	{.name = "CPU_CYCLES",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x11,
+	 .desc = "Cycles"
+	},
+	{.name = "BRANCH_PRED",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x12,
+	 .desc = "Predictable branch speculatively executed"
+	},
+	{.name = "DATA_MEM_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x13,
+	 .desc = "Data memory access"
+	},
+	{.name = "L1I_CACHE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x14,
+	 .desc = "Level 1 instruction cache access"
+	},
+	{.name = "L2D_CACHE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x16,
+	 .desc = "Level 2 data cache access"
+	},
+	{.name = "L2D_CACHE_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x17,
+	 .desc = "Level 2 data cache refill"
+	},
+	{.name = "L2D_CACHE_WB",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x18,
+	 .desc = "Level 2 data cache WriteBack"
+	},
+	{.name = "BUS_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x19,
+	 .desc = "Bus access"
+	},
+	{.name = "LOCAL_MEMORY_ERROR",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x1a,
+	 .desc = "Local memory error"
+	},
+
+	{.name = "L1D_READ_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x40,
+	 .desc = "Level 1 data cache read access"
+	},
+	{.name = "L1D_WRITE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x41,
+	 .desc = "Level 1 data cache write access"
+	},
+	{.name = "L1D_READ_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x42,
+	 .desc = "Level 1 data cache read refill"
+	},
+	{.name = "L1D_INVALIDATE",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x48,
+	 .desc = "Level 1 data cache invalidate"
+	},
+	{.name = "L1D_TLB_READ_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x4c,
+	 .desc = "Level 1 data TLB read refill"
+	},
+	{.name = "L1D_TLB_WRITE_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x4d,
+	 .desc = "Level 1 data TLB write refill"
+	},
+	{.name = "L2D_READ_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x50,
+	 .desc = "Level 2 data cache read access"
+	},
+	{.name = "L2D_WRITE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x51,
+	 .desc = "Level 2 data cache write access"
+	},
+	{.name = "L2D_READ_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x52,
+	 .desc = "Level 2 data cache read refill"
+	},
+	{.name = "L2D_WRITE_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x53,
+	 .desc = "Level 2 data cache write refill"
+	},
+	{.name = "L2D_WB_VICTIM",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x56,
+	 .desc = "Level 2 data cache writeback victim"
+	},
+	{.name = "L2D_WB_CLEAN_COHERENCY",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x57,
+	 .desc = "Level 2 data cache writeback cleaning and coherency"
+	},
+	{.name = "L2D_INVALIDATE",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x58,
+	 .desc = "Level 2 data cache invalidate"
+	},
+	{.name = "BUS_READ_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x60,
+	 .desc = "Bus read access"
+	},
+	{.name = "BUS_WRITE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x61,
+	 .desc = "Bus write access"
+	},
+	{.name = "BUS_NORMAL_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x62,
+	 .desc = "Bus normal access"
+	},
+	{.name = "BUS_NOT_NORMAL_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x63,
+	 .desc = "Bus not normal access"
+	},
+	{.name = "BUS_NORMAL_ACCESS_2",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x64,
+	 .desc = "Bus normal access"
+	},
+	{.name = "BUS_PERIPH_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x65,
+	 .desc = "Bus peripheral access"
+	},
+	{.name = "DATA_MEM_READ_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x66,
+	 .desc = "Data memory read access"
+	},
+	{.name = "DATA_MEM_WRITE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x67,
+	 .desc = "Data memory write access"
+	},
+	{.name = "UNALIGNED_READ_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x68,
+	 .desc = "Unaligned read access"
+	},
+	{.name = "UNALIGNED_WRITE_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x69,
+	 .desc = "Unaligned read access"
+	},
+	{.name = "UNALIGNED_ACCESS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x6a,
+	 .desc = "Unaligned access"
+	},
+	{.name = "INST_SPEC_EXEC_LDREX",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x6c,
+	 .desc = "LDREX exclusive instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_STREX_PASS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x6d,
+	 .desc = "STREX pass exclusive instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_STREX_FAIL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x6e,
+	 .desc = "STREX fail exclusive instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_LOAD",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x70,
+	 .desc = "Load instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_STORE",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x71,
+	 .desc = "Store instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_LOAD_STORE",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x72,
+	 .desc = "Load or store instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_INTEGER_INST",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x73,
+	 .desc = "Integer data processing instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_SIMD",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x74,
+	 .desc = "Advanced SIMD instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_VFP",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x75,
+	 .desc = "VFP instruction speculatively executed"
+	},
+	{.name = "INST_SPEC_EXEC_SOFT_PC",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x76,
+	 .desc = "Software of the PC instruction speculatively executed"
+	},
+	{.name = "BRANCH_SPEC_EXEC_IMM_BRANCH",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x78,
+	 .desc = "Immediate branch speculatively executed"
+	},
+	{.name = "BRANCH_SPEC_EXEC_RET",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x79,
+	 .desc = "Return branch speculatively executed"
+	},
+	{.name = "BRANCH_SPEC_EXEC_IND",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x7a,
+	 .desc = "Indirect branch speculatively executed"
+	},
+	{.name = "BARRIER_SPEC_EXEC_ISB",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x7c,
+	 .desc = "ISB barrier speculatively executed"
+	},
+	{.name = "BARRIER_SPEC_EXEC_DSB",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x7d,
+	 .desc = "DSB barrier speculatively executed"
+	},
+	{.name = "BARRIER_SPEC_EXEC_DMB",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x7e,
+	 .desc = "DMB barrier speculatively executed"
+	},
+	{.name = "EXCEPTION_UNDEF",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x81,
+	 .desc = "Exception taken, other synchronous"
+	},
+	{.name = "EXCEPTION_SVC",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x82,
+	 .desc = "Exception taken, supervisor call"
+	},
+	{.name = "EXCEPTION_PABORT",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x83,
+	 .desc = "Exception taken, instruction abort"
+	},
+	{.name = "EXCEPTION_DABORT",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x84,
+	 .desc = "Exception taken, data abort or SError"
+	},
+	{.name = "EXCEPTION_IRQ",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x86,
+	 .desc = "Exception taken, irq"
+	},
+	{.name = "EXCEPTION_FIQ",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x87,
+	 .desc = "Exception taken, irq"
+	},
+	{.name = "EXCEPTION_HVC",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x8a,
+	 .desc = "Exception taken, hypervisor call"
+	},
+	{.name = "EXCEPTION_TRAP_PABORT",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x8b,
+	 .desc = "Exception taken, instruction abort not taken locally"
+	},
+	{.name = "EXCEPTION_TRAP_DABORT",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x8c,
+	 .desc = "Exception taken, data abort or SError not taken locally"
+	},
+	{.name = "EXCEPTION_TRAP_OTHER",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x8d,
+	 .desc = "Exception taken, other traps not taken locally"
+	},
+	{.name = "EXCEPTION_TRAP_IRQ",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x8e,
+	 .desc = "Exception taken, irq not taken locally"
+	},
+	{.name = "EXCEPTION_TRAP_FIQ",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x8f,
+	 .desc = "Exception taken, fiq not taken locally"
+	},
+	{.name = "RC_LD_SPEC",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x90,
+	 .desc = "Release consistency instruction speculatively executed (load-acquire)",
+	},
+	{.name = "RC_ST_SPEC",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x91,
+	 .desc = "Release consistency instruction speculatively executed (store-release)",
+	},
+	{.name = "INST_SPEC_EXEC_NOP",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x100,
+	 .desc = "Operation speculatively executed - NOP",
+	},
+	{.name = "FSU_CLOCK_OFF",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x101,
+	 .desc = "FSU clocking gated off cycle",
+	},
+	{.name = "BTB_MISPREDICT",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x102,
+	 .desc = "BTB misprediction",
+	},
+	{.name = "ITB_MISS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x103,
+	 .desc = "ITB miss",
+	},
+	{.name = "DTB_MISS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x104,
+	 .desc = "DTB miss",
+	},
+	{.name = "L1D_CACHE_LATE_MISS",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x105,
+	 .desc = "L1 data cache late miss",
+	},
+	{.name = "L1D_CACHE_PREFETCH",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x106,
+	 .desc = "L1 data cache prefetch request",
+	},
+	{.name = "L2_CACHE_PREFETCH",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x107,
+	 .desc = "L2 data prefetch request",
+	},
+	{.name = "STALLED_CYCLES_FRONTEND",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x108,
+	 .desc = "Decode starved for instruction cycle",
+	},
+	{.name = "STALLED_CYCLES_BACKEND",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x109,
+	 .desc = "Op dispatch stalled cycle",
+	},
+	{.name = "IXA_NO_ISSUE",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x10A,
+	 .desc = "IXA Op non-issue",
+	},
+	{.name = "IXB_NO_ISSUE",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x10B,
+	 .desc = "IXB Op non-issue",
+	},
+	{.name = "BX_NO_ISSUE",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x10C,
+	 .desc = "BX Op non-issue",
+	},
+	{.name = "LX_NO_ISSUE",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x10D,
+	 .desc = "LX Op non-issue",
+	},
+	{.name = "SX_NO_ISSUE",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x10E,
+	 .desc = "SX Op non-issue",
+	},
+	{.name = "FX_NO_ISSUE",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x10F,
+	 .desc = "FX Op non-issue",
+	},
+	{.name = "WAIT_CYCLES",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x110,
+	 .desc = "Wait state cycle",
+	},
+	{.name = "L1_STAGE2_TLB_REFILL",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x111,
+	 .desc = "L1 stage-2 TLB refill",
+	},
+	{.name = "PAGE_WALK_L0_STAGE1_HIT",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x112,
+	 .desc = "Page Walk Cache level-0 stage-1 hit",
+	},
+	{.name = "PAGE_WALK_L1_STAGE1_HIT",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x113,
+	 .desc = "Page Walk Cache level-1 stage-1 hit",
+	},
+	{.name = "PAGE_WALK_L2_STAGE1_HIT",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x114,
+	 .desc = "Page Walk Cache level-2 stage-1 hit",
+	},
+	{.name = "PAGE_WALK_L1_STAGE2_HIT",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x115,
+	 .desc = "Page Walk Cache level-1 stage-2 hit",
+	},
+	{.name = "PAGE_WALK_L2_STAGE2_HIT",
+	 .modmsk = ARMV8_ATTRS,
+	 .code = 0x116,
+	 .desc = "Page Walk Cache level-2 stage-2 hit",
+	},
+	/* END Applied Micro X-Gene specific events */
+};
diff --git a/lib/pfmlib_arm_armv8.c b/lib/pfmlib_arm_armv8.c
index c38bd9b..3619508 100644
--- a/lib/pfmlib_arm_armv8.c
+++ b/lib/pfmlib_arm_armv8.c
@@ -32,6 +32,7 @@
 
 #include "events/arm_cortex_a57_events.h"    /* A57 event tables */
 #include "events/arm_cortex_a53_events.h"    /* A53 event tables */
+#include "events/arm_xgene_events.h"         /* Applied Micro X-Gene tables */
 
 static int
 pfm_arm_detect_cortex_a57(void *this)
@@ -65,6 +66,22 @@ pfm_arm_detect_cortex_a53(void *this)
 	return PFM_ERR_NOTSUPP;
 }
 
+static int
+pfm_arm_detect_xgene(void *this)
+{
+	int ret;
+
+	ret = pfm_arm_detect(this);
+	if (ret != PFM_SUCCESS)
+		return PFM_ERR_NOTSUPP;
+
+	if ((pfm_arm_cfg.implementer == 0x50) && /* Applied Micro */
+		(pfm_arm_cfg.part == 0x000)) { /* Applied Micro X-Gene */
+			return PFM_SUCCESS;
+	}
+	return PFM_ERR_NOTSUPP;
+}
+
 /* ARM Cortex A57 support */
 pfmlib_pmu_t arm_cortex_a57_support={
 	.desc			= "ARM Cortex A57",
@@ -114,3 +131,28 @@ pfmlib_pmu_t arm_cortex_a53_support={
 	 PFMLIB_VALID_PERF_PATTRS(pfm_arm_perf_validate_pattrs),
 	.get_event_nattrs	= pfm_arm_get_event_nattrs,
 };
+
+/* Applied Micro X-Gene support */
+pfmlib_pmu_t arm_xgene_support={
+	.desc			= "Applied Micro X-Gene",
+	.name			= "arm_xgene",
+	.pmu			= PFM_PMU_ARM_XGENE,
+	.pme_count		= LIBPFM_ARRAY_SIZE(arm_xgene_pe),
+	.type			= PFM_PMU_TYPE_CORE,
+	.pe			= arm_xgene_pe,
+
+	.pmu_detect		= pfm_arm_detect_xgene,
+	.max_encoding		= 1,
+	.num_cntrs		= 6,
+
+	.get_event_encoding[PFM_OS_NONE] = pfm_arm_get_encoding,
+	 PFMLIB_ENCODE_PERF(pfm_arm_get_perf_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,
+	.validate_table		= pfm_arm_validate_table,
+	.get_event_info		= pfm_arm_get_event_info,
+	.get_event_attr_info	= pfm_arm_get_event_attr_info,
+	 PFMLIB_VALID_PERF_PATTRS(pfm_arm_perf_validate_pattrs),
+	.get_event_nattrs	= pfm_arm_get_event_nattrs,
+};
diff --git a/lib/pfmlib_common.c b/lib/pfmlib_common.c
index ebe20da..569ce85 100644
--- a/lib/pfmlib_common.c
+++ b/lib/pfmlib_common.c
@@ -201,10 +201,12 @@ static pfmlib_pmu_t *pfmlib_pmus[]=
 	&arm_1176_support,
 	&arm_cortex_a57_support,
 	&arm_cortex_a53_support,
+	&arm_xgene_support,
 #endif
 #ifdef CONFIG_PFMLIB_ARCH_ARM64
 	&arm_cortex_a57_support,
 	&arm_cortex_a53_support,
+	&arm_xgene_support,
 #endif
 
 #ifdef CONFIG_PFMLIB_ARCH_S390X
diff --git a/lib/pfmlib_priv.h b/lib/pfmlib_priv.h
index 5678cc0..1666bcb 100644
--- a/lib/pfmlib_priv.h
+++ b/lib/pfmlib_priv.h
@@ -334,6 +334,7 @@ extern pfmlib_pmu_t arm_1176_support;
 extern pfmlib_pmu_t arm_1176_support;
 extern pfmlib_pmu_t arm_cortex_a57_support;
 extern pfmlib_pmu_t arm_cortex_a53_support;
+extern pfmlib_pmu_t arm_xgene_support;
 extern pfmlib_pmu_t mips_74k_support;
 extern pfmlib_pmu_t s390x_cpum_cf_support;
 
diff --git a/tests/validate_arm64.c b/tests/validate_arm64.c
index 61400ac..f4593de 100644
--- a/tests/validate_arm64.c
+++ b/tests/validate_arm64.c
@@ -114,6 +114,34 @@ static const test_event_t arm64_test_events[]={
 	  .codes[0] = 0x8000007,
 	  .fstr = "arm_ac53::ST_RETIRED:k=1:u=1:hv=0",
 	},
+	{ SRC_LINE,
+	  .name = "arm_xgene::CPU_CYCLES",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000011,
+	  .fstr = "arm_xgene::CPU_CYCLES:k=1:u=1:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_xgene::CPU_CYCLES:k",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x88000011,
+	  .fstr = "arm_xgene::CPU_CYCLES:k=1:u=0:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_xgene::CPU_CYCLES:k:u",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000011,
+	  .fstr = "arm_xgene::CPU_CYCLES:k=1:u=1:hv=0",
+	},
+	{ SRC_LINE,
+	  .name = "arm_xgene::INST_RETIRED",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8000008,
+	  .fstr = "arm_xgene::INST_RETIRED:k=1:u=1:hv=0",
+	},
 };
 #define NUM_TEST_EVENTS (int)(sizeof(arm64_test_events)/sizeof(test_event_t))
 
-- 
1.9.3