Merge pull request #1170 from dp-arm/dp/amu

Add support for Activity Monitors
diff --git a/Makefile b/Makefile
index 31ef769..fe18bc0 100644
--- a/Makefile
+++ b/Makefile
@@ -456,6 +456,7 @@
 $(eval $(call assert_boolean,CTX_INCLUDE_FPREGS))
 $(eval $(call assert_boolean,DEBUG))
 $(eval $(call assert_boolean,DISABLE_PEDANTIC))
+$(eval $(call assert_boolean,ENABLE_AMU))
 $(eval $(call assert_boolean,ENABLE_ASSERTIONS))
 $(eval $(call assert_boolean,ENABLE_PLAT_COMPAT))
 $(eval $(call assert_boolean,ENABLE_PMF))
@@ -495,6 +496,7 @@
 $(eval $(call add_define,COLD_BOOT_SINGLE_CPU))
 $(eval $(call add_define,CTX_INCLUDE_AARCH32_REGS))
 $(eval $(call add_define,CTX_INCLUDE_FPREGS))
+$(eval $(call add_define,ENABLE_AMU))
 $(eval $(call add_define,ENABLE_ASSERTIONS))
 $(eval $(call add_define,ENABLE_PLAT_COMPAT))
 $(eval $(call add_define,ENABLE_PMF))
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index fccdc8a..ebd0e71 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -50,6 +50,10 @@
 BL31_SOURCES		+=	lib/extensions/spe/spe.c
 endif
 
+ifeq (${ENABLE_AMU},1)
+BL31_SOURCES		+=	lib/extensions/amu/aarch64/amu.c
+endif
+
 BL31_LINKERFILE		:=	bl31/bl31.ld.S
 
 # Flag used to indicate if Crash reporting via console should be included
diff --git a/bl32/sp_min/sp_min.mk b/bl32/sp_min/sp_min.mk
index 39588ce..56489a3 100644
--- a/bl32/sp_min/sp_min.mk
+++ b/bl32/sp_min/sp_min.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -22,6 +22,10 @@
 BL32_SOURCES		+=	lib/pmf/pmf_main.c
 endif
 
+ifeq (${ENABLE_AMU}, 1)
+BL32_SOURCES		+=	lib/extensions/amu/aarch32/amu.c
+endif
+
 BL32_LINKERFILE	:=	bl32/sp_min/sp_min.ld.S
 
 # Include the platform-specific SP_MIN Makefile
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index 95fa22e..79d660d 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -321,6 +321,11 @@
    payload. Please refer to the "Booting an EL3 payload" section for more
    details.
 
+-  ``ENABLE_AMU``: Boolean option to enable Activity Monitor Unit extensions.
+   This is an optional architectural feature available on v8.4 onwards. Some
+   v8.2 implementations also implement an AMU and this option can be used to
+   enable this feature on those systems as well. Default is 0.
+
 -  ``ENABLE_ASSERTIONS``: This option controls whether or not calls to ``assert()``
    are compiled out. For debug builds, this option defaults to 1, and calls to
    ``assert()`` are left in place. For release builds, this option defaults to 0
diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h
index c894030..4d2a5fc 100644
--- a/include/lib/aarch32/arch.h
+++ b/include/lib/aarch32/arch.h
@@ -78,6 +78,11 @@
 /* CSSELR definitions */
 #define LEVEL_SHIFT		1
 
+/* ID_PFR0 definitions */
+#define ID_PFR0_AMU_SHIFT	U(20)
+#define ID_PFR0_AMU_LENGTH	U(4)
+#define ID_PFR0_AMU_MASK	U(0xf)
+
 /* ID_PFR1 definitions */
 #define ID_PFR1_VIRTEXT_SHIFT	12
 #define ID_PFR1_VIRTEXT_MASK	0xf
@@ -187,6 +192,7 @@
 /* HCPTR definitions */
 #define HCPTR_RES1		((1 << 13) | (1<<12) | 0x3ff)
 #define TCPAC_BIT		(1 << 31)
+#define TAM_BIT			(1 << 30)
 #define TTA_BIT			(1 << 20)
 #define TCP11_BIT		(1 << 10)
 #define TCP10_BIT		(1 << 10)
@@ -407,6 +413,7 @@
 #define DCISW		p15, 0, c7, c6, 2
 #define CTR		p15, 0, c0, c0, 1
 #define CNTFRQ		p15, 0, c14, c0, 0
+#define ID_PFR0		p15, 0, c0, c1, 0
 #define ID_PFR1		p15, 0, c0, c1, 1
 #define MAIR0		p15, 0, c10, c2, 0
 #define MAIR1		p15, 0, c10, c2, 1
@@ -525,4 +532,28 @@
 
 #define MAKE_MAIR_NORMAL_MEMORY(inner, outer)	((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT))
 
+/*******************************************************************************
+ * Definitions for system register interface to AMU for ARMv8.4 onwards
+ ******************************************************************************/
+#define AMCR		p15, 0, c13, c2, 0
+#define AMCFGR		p15, 0, c13, c2, 1
+#define AMCGCR		p15, 0, c13, c2, 2
+#define AMUSERENR	p15, 0, c13, c2, 3
+#define AMCNTENCLR0	p15, 0, c13, c2, 4
+#define AMCNTENSET0	p15, 0, c13, c2, 5
+#define AMCNTENCLR1	p15, 0, c13, c3, 0
+#define AMCNTENSET1	p15, 0, c13, c1, 1
+
+/* Activity Monitor Group 0 Event Counter Registers */
+#define AMEVCNTR00	p15, 0, c0
+#define AMEVCNTR01	p15, 1, c0
+#define AMEVCNTR02	p15, 2, c0
+#define AMEVCNTR03	p15, 3, c0
+
+/* Activity Monitor Group 0 Event Type Registers */
+#define AMEVTYPER00	p15, 0, c13, c6, 0
+#define AMEVTYPER01	p15, 0, c13, c6, 1
+#define AMEVTYPER02	p15, 0, c13, c6, 2
+#define AMEVTYPER03	p15, 0, c13, c6, 3
+
 #endif /* __ARCH_H__ */
diff --git a/include/lib/aarch32/arch_helpers.h b/include/lib/aarch32/arch_helpers.h
index 42309d5..0230195 100644
--- a/include/lib/aarch32/arch_helpers.h
+++ b/include/lib/aarch32/arch_helpers.h
@@ -227,6 +227,7 @@
  ******************************************************************************/
 DEFINE_COPROCR_READ_FUNC(mpidr, MPIDR)
 DEFINE_COPROCR_READ_FUNC(midr, MIDR)
+DEFINE_COPROCR_READ_FUNC(id_pfr0, ID_PFR0)
 DEFINE_COPROCR_READ_FUNC(id_pfr1, ID_PFR1)
 DEFINE_COPROCR_READ_FUNC(isr, ISR)
 DEFINE_COPROCR_READ_FUNC(clidr, CLIDR)
@@ -281,6 +282,11 @@
 DEFINE_COPROCR_RW_FUNCS(nmrr, NMRR)
 DEFINE_COPROCR_RW_FUNCS(dacr, DACR)
 
+DEFINE_COPROCR_RW_FUNCS(amcntenset0, AMCNTENSET0)
+DEFINE_COPROCR_RW_FUNCS(amcntenset1, AMCNTENSET1)
+DEFINE_COPROCR_RW_FUNCS(amcntenclr0, AMCNTENCLR0)
+DEFINE_COPROCR_RW_FUNCS(amcntenclr1, AMCNTENCLR1)
+
 /*
  * TLBI operation prototypes
  */
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 4b31f16..65e9fc1 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -110,6 +110,9 @@
 #define ID_AA64PFR0_EL1_SHIFT	U(4)
 #define ID_AA64PFR0_EL2_SHIFT	U(8)
 #define ID_AA64PFR0_EL3_SHIFT	U(12)
+#define ID_AA64PFR0_AMU_SHIFT	U(44)
+#define ID_AA64PFR0_AMU_LENGTH	U(4)
+#define ID_AA64PFR0_AMU_MASK	U(0xf)
 #define ID_AA64PFR0_ELX_MASK	U(0xf)
 
 /* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */
@@ -295,6 +298,7 @@
 
 /* CPTR_EL3 definitions */
 #define TCPAC_BIT		(U(1) << 31)
+#define TAM_BIT			(U(1) << 30)
 #define TTA_BIT			(U(1) << 20)
 #define TFP_BIT			(U(1) << 10)
 #define CPTR_EL3_RESET_VAL	U(0x0)
@@ -302,6 +306,7 @@
 /* CPTR_EL2 definitions */
 #define CPTR_EL2_RES1		((U(1) << 13) | (U(1) << 12) | (U(0x3ff)))
 #define CPTR_EL2_TCPAC_BIT	(U(1) << 31)
+#define CPTR_EL2_TAM_BIT	(U(1) << 30)
 #define CPTR_EL2_TTA_BIT	(U(1) << 20)
 #define CPTR_EL2_TFP_BIT	(U(1) << 10)
 #define CPTR_EL2_RESET_VAL	CPTR_EL2_RES1
@@ -610,4 +615,28 @@
  ******************************************************************************/
 #define PMBLIMITR_EL1		S3_0_C9_C10_0
 
+/*******************************************************************************
+ * Definitions for system register interface to AMU for ARMv8.4 onwards
+ ******************************************************************************/
+#define AMCR_EL0		S3_3_C13_C2_0
+#define AMCFGR_EL0		S3_3_C13_C2_1
+#define AMCGCR_EL0		S3_3_C13_C2_2
+#define AMUSERENR_EL0		S3_3_C13_C2_3
+#define AMCNTENCLR0_EL0		S3_3_C13_C2_4
+#define AMCNTENSET0_EL0		S3_3_C13_C2_5
+#define AMCNTENCLR1_EL0		S3_3_C13_C3_0
+#define AMCNTENSET1_EL0		S3_3_C13_C3_1
+
+/* Activity Monitor Group 0 Event Counter Registers */
+#define AMEVCNTR00_EL0		S3_3_C13_C4_0
+#define AMEVCNTR01_EL0		S3_3_C13_C4_1
+#define AMEVCNTR02_EL0		S3_3_C13_C4_2
+#define AMEVCNTR03_EL0		S3_3_C13_C4_3
+
+/* Activity Monitor Group 0 Event Type Registers */
+#define AMEVTYPER00_EL0		S3_3_C13_C6_0
+#define AMEVTYPER01_EL0		S3_3_C13_C6_1
+#define AMEVTYPER02_EL0		S3_3_C13_C6_2
+#define AMEVTYPER03_EL0		S3_3_C13_C6_3
+
 #endif /* __ARCH_H__ */
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index 46d9a1c..b6be167 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -322,6 +322,11 @@
 DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir1_el1, ICC_EOIR1_EL1)
 DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_sgi0r_el1, ICC_SGI0R_EL1)
 
+DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr0_el0, AMCNTENCLR0_EL0)
+DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset0_el0, AMCNTENSET0_EL0)
+DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr1_el0, AMCNTENCLR1_EL0)
+DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset1_el0, AMCNTENSET1_EL0)
+
 DEFINE_RENAME_SYSREG_RW_FUNCS(pmblimitr_el1, PMBLIMITR_EL1)
 
 #define IS_IN_EL(x) \
diff --git a/include/lib/cpus/aarch64/cortex_a75.h b/include/lib/cpus/aarch64/cortex_a75.h
index 1ffe20b..d68c957 100644
--- a/include/lib/cpus/aarch64/cortex_a75.h
+++ b/include/lib/cpus/aarch64/cortex_a75.h
@@ -19,4 +19,38 @@
 /* Definitions of register field mask in CORTEX_A75_CPUPWRCTLR_EL1 */
 #define CORTEX_A75_CORE_PWRDN_EN_MASK	0x1
 
+/*******************************************************************************
+ * CPU Activity Monitor Unit register specific definitions.
+ ******************************************************************************/
+#define CPUAMCNTENCLR_EL0	S3_3_C15_C9_7
+#define CPUAMCNTENSET_EL0	S3_3_C15_C9_6
+#define CPUAMCFGR_EL0		S3_3_C15_C10_6
+#define CPUAMUSERENR_EL0	S3_3_C15_C10_7
+
+/* Activity Monitor Event Counter Registers */
+#define CPUAMEVCNTR0_EL0	S3_3_C15_C9_0
+#define CPUAMEVCNTR1_EL0	S3_3_C15_C9_1
+#define CPUAMEVCNTR2_EL0	S3_3_C15_C9_2
+#define CPUAMEVCNTR3_EL0	S3_3_C15_C9_3
+#define CPUAMEVCNTR4_EL0	S3_3_C15_C9_4
+
+/* Activity Monitor Event Type Registers */
+#define CPUAMEVTYPER0_EL0	S3_3_C15_C10_0
+#define CPUAMEVTYPER1_EL0	S3_3_C15_C10_1
+#define CPUAMEVTYPER2_EL0	S3_3_C15_C10_2
+#define CPUAMEVTYPER3_EL0	S3_3_C15_C10_3
+#define CPUAMEVTYPER4_EL0	S3_3_C15_C10_4
+
+#define CORTEX_A75_ACTLR_AMEN_BIT	(U(1) << 4)
+
+/*
+ * The Cortex-A75 core implements five counters, 0-4. Events 0, 1, 2, are
+ * fixed and are enabled (Group 0). Events 3 and 4 (Group 1) are
+ * programmable by programming the appropriate Event count bits in
+ * CPUAMEVTYPER<n> register and are disabled by default. Platforms may
+ * enable this with suitable programming.
+ */
+#define CORTEX_A75_AMU_GROUP0_MASK	0x7
+#define CORTEX_A75_AMU_GROUP1_MASK	(0 << 3)
+
 #endif /* __CORTEX_A75_H__ */
diff --git a/include/lib/extensions/amu.h b/include/lib/extensions/amu.h
new file mode 100644
index 0000000..bbefe8f
--- /dev/null
+++ b/include/lib/extensions/amu.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __AMU_H__
+#define __AMU_H__
+
+/* Enable all group 0 counters */
+#define AMU_GROUP0_COUNTERS_MASK	0xf
+
+void amu_enable(int el2_unused);
+
+#endif /* __AMU_H__ */
diff --git a/lib/cpus/aarch64/cortex_a75.S b/lib/cpus/aarch64/cortex_a75.S
index 1f4500c..4cab9e4 100644
--- a/lib/cpus/aarch64/cortex_a75.S
+++ b/lib/cpus/aarch64/cortex_a75.S
@@ -11,6 +11,33 @@
 #include <plat_macros.S>
 #include <cortex_a75.h>
 
+func cortex_a75_reset_func
+#if ENABLE_AMU
+	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
+	mrs	x0, actlr_el3
+	orr	x0, x0, #CORTEX_A75_ACTLR_AMEN_BIT
+	msr	actlr_el3, x0
+	isb
+
+	/* Make sure accesses from EL0/EL1 are not trapped to EL2 */
+	mrs	x0, actlr_el2
+	orr	x0, x0, #CORTEX_A75_ACTLR_AMEN_BIT
+	msr	actlr_el2, x0
+	isb
+
+	/* Enable group0 counters */
+	mov	x0, #CORTEX_A75_AMU_GROUP0_MASK
+	msr	CPUAMCNTENSET_EL0, x0
+	isb
+
+	/* Enable group1 counters */
+	mov	x0, #CORTEX_A75_AMU_GROUP1_MASK
+	msr	CPUAMCNTENSET_EL0, x0
+	isb
+#endif
+	ret
+endfunc cortex_a75_reset_func
+
 	/* ---------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ---------------------------------------------
@@ -47,5 +74,5 @@
 endfunc cortex_a75_cpu_reg_dump
 
 declare_cpu_ops cortex_a75, CORTEX_A75_MIDR, \
-	CPU_NO_RESET_FUNC, \
+	cortex_a75_reset_func, \
 	cortex_a75_core_pwr_dwn
diff --git a/lib/el3_runtime/aarch32/context_mgmt.c b/lib/el3_runtime/aarch32/context_mgmt.c
index a8672d6..76e440e 100644
--- a/lib/el3_runtime/aarch32/context_mgmt.c
+++ b/lib/el3_runtime/aarch32/context_mgmt.c
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <amu.h>
 #include <arch.h>
 #include <arch_helpers.h>
 #include <assert.h>
@@ -132,6 +133,9 @@
 static void enable_extensions_nonsecure(int el2_unused)
 {
 #if IMAGE_BL32
+#if ENABLE_AMU
+	amu_enable(el2_unused);
+#endif
 #endif
 }
 
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 8f1523f..b892729 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <amu.h>
 #include <arch.h>
 #include <arch_helpers.h>
 #include <assert.h>
@@ -220,6 +221,10 @@
 #if ENABLE_SPE_FOR_LOWER_ELS
 	spe_enable(el2_unused);
 #endif
+
+#if ENABLE_AMU
+	amu_enable(el2_unused);
+#endif
 #endif
 }
 
diff --git a/lib/extensions/amu/aarch32/amu.c b/lib/extensions/amu/aarch32/amu.c
new file mode 100644
index 0000000..d450bd6
--- /dev/null
+++ b/lib/extensions/amu/aarch32/amu.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <amu.h>
+#include <arch.h>
+#include <arch_helpers.h>
+
+void amu_enable(int el2_unused)
+{
+	uint64_t features;
+
+	features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT;
+	if ((features & ID_PFR0_AMU_MASK) == 1) {
+		if (el2_unused) {
+			uint64_t v;
+
+			/*
+			 * Non-secure access from EL0 or EL1 to the Activity Monitor
+			 * registers do not trap to EL2.
+			 */
+			v = read_hcptr();
+			v &= ~TAM_BIT;
+			write_hcptr(v);
+		}
+
+		/* Enable group 0 counters */
+		write_amcntenset0(AMU_GROUP0_COUNTERS_MASK);
+	}
+}
diff --git a/lib/extensions/amu/aarch64/amu.c b/lib/extensions/amu/aarch64/amu.c
new file mode 100644
index 0000000..007b349
--- /dev/null
+++ b/lib/extensions/amu/aarch64/amu.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <amu.h>
+#include <arch.h>
+#include <arch_helpers.h>
+
+void amu_enable(int el2_unused)
+{
+	uint64_t features;
+
+	features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT;
+	if ((features & ID_AA64PFR0_AMU_MASK) == 1) {
+		uint64_t v;
+
+		if (el2_unused) {
+			/*
+			 * CPTR_EL2.TAM: Set to zero so any accesses to
+			 * the Activity Monitor registers do not trap to EL2.
+			 */
+			v = read_cptr_el2();
+			v &= ~CPTR_EL2_TAM_BIT;
+			write_cptr_el2(v);
+		}
+
+		/*
+		 * CPTR_EL3.TAM: Set to zero so that any accesses to
+		 * the Activity Monitor registers do not trap to EL3.
+		 */
+		v = read_cptr_el3();
+		v &= ~TAM_BIT;
+		write_cptr_el3(v);
+
+		/* Enable group 0 counters */
+		write_amcntenset0_el0(AMU_GROUP0_COUNTERS_MASK);
+	}
+}
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index b7ce051..9f7abed 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -156,3 +156,5 @@
 ifeq (${ARCH},aarch32)
     override ENABLE_SPE_FOR_LOWER_ELS := 0
 endif
+
+ENABLE_AMU			:= 0
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 1b50296..7edbd3d 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -147,6 +147,9 @@
 # Disable the PSCI platform compatibility layer
 ENABLE_PLAT_COMPAT	:= 	0
 
+# Enable Activity Monitor Unit extensions by default
+ENABLE_AMU			:=	1
+
 ifneq (${ENABLE_STACK_PROTECTOR},0)
 PLAT_BL_COMMON_SOURCES	+=	plat/arm/board/fvp/fvp_stack_protector.c
 endif