AMU: Implement support for aarch32

The `ENABLE_AMU` build option can be used to enable the
architecturally defined AMU counters.  At present, there is no support
for the auxiliary counter group.

Change-Id: Ifc7532ef836f83e629f2a146739ab61e75c4abc8
Signed-off-by: Dimitris Papastamos <dimitris.papastamos@arm.com>
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/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/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/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);
+	}
+}