xref: /rk3399_ARM-atf/lib/extensions/amu/aarch32/amu.c (revision 09d40e0e08283a249e7dce0e106c07c5141f9b7e)
1ef69e1eaSDimitris Papastamos /*
2c6cc9ac3SDimitris Papastamos  * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
3ef69e1eaSDimitris Papastamos  *
4ef69e1eaSDimitris Papastamos  * SPDX-License-Identifier: BSD-3-Clause
5ef69e1eaSDimitris Papastamos  */
6ef69e1eaSDimitris Papastamos 
7*09d40e0eSAntonio Nino Diaz #include <stdbool.h>
8*09d40e0eSAntonio Nino Diaz 
9ef69e1eaSDimitris Papastamos #include <arch.h>
10ef69e1eaSDimitris Papastamos #include <arch_helpers.h>
11*09d40e0eSAntonio Nino Diaz #include <lib/el3_runtime/pubsub_events.h>
12*09d40e0eSAntonio Nino Diaz #include <lib/extensions/amu.h>
13*09d40e0eSAntonio Nino Diaz #include <lib/extensions/amu_private.h>
14*09d40e0eSAntonio Nino Diaz #include <plat/common/platform.h>
15b6eb3932SDimitris Papastamos 
16b6eb3932SDimitris Papastamos #define AMU_GROUP0_NR_COUNTERS	4
17b6eb3932SDimitris Papastamos 
18b6eb3932SDimitris Papastamos struct amu_ctx {
19b6eb3932SDimitris Papastamos 	uint64_t group0_cnts[AMU_GROUP0_NR_COUNTERS];
20c70da546SJoel Hutton 	uint64_t group1_cnts[AMU_GROUP1_NR_COUNTERS];
21b6eb3932SDimitris Papastamos };
22b6eb3932SDimitris Papastamos 
23b6eb3932SDimitris Papastamos static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT];
24ef69e1eaSDimitris Papastamos 
2540daecc1SAntonio Nino Diaz bool amu_supported(void)
26ef69e1eaSDimitris Papastamos {
27ef69e1eaSDimitris Papastamos 	uint64_t features;
28ef69e1eaSDimitris Papastamos 
29ef69e1eaSDimitris Papastamos 	features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT;
3040daecc1SAntonio Nino Diaz 	return (features & ID_PFR0_AMU_MASK) == 1U;
31c70da546SJoel Hutton }
32c70da546SJoel Hutton 
3340daecc1SAntonio Nino Diaz void amu_enable(bool el2_unused)
34c70da546SJoel Hutton {
3540daecc1SAntonio Nino Diaz 	if (!amu_supported())
360767d50eSDimitris Papastamos 		return;
370767d50eSDimitris Papastamos 
38ef69e1eaSDimitris Papastamos 	if (el2_unused) {
39ef69e1eaSDimitris Papastamos 		uint64_t v;
40ef69e1eaSDimitris Papastamos 		/*
41ef69e1eaSDimitris Papastamos 		 * Non-secure access from EL0 or EL1 to the Activity Monitor
42ef69e1eaSDimitris Papastamos 		 * registers do not trap to EL2.
43ef69e1eaSDimitris Papastamos 		 */
44ef69e1eaSDimitris Papastamos 		v = read_hcptr();
45ef69e1eaSDimitris Papastamos 		v &= ~TAM_BIT;
46ef69e1eaSDimitris Papastamos 		write_hcptr(v);
47ef69e1eaSDimitris Papastamos 	}
48ef69e1eaSDimitris Papastamos 
49ef69e1eaSDimitris Papastamos 	/* Enable group 0 counters */
50ef69e1eaSDimitris Papastamos 	write_amcntenset0(AMU_GROUP0_COUNTERS_MASK);
51c70da546SJoel Hutton 
52c70da546SJoel Hutton 	/* Enable group 1 counters */
53c70da546SJoel Hutton 	write_amcntenset1(AMU_GROUP1_COUNTERS_MASK);
54c70da546SJoel Hutton }
55c70da546SJoel Hutton 
56c70da546SJoel Hutton /* Read the group 0 counter identified by the given `idx`. */
57c70da546SJoel Hutton uint64_t amu_group0_cnt_read(int idx)
58c70da546SJoel Hutton {
5940daecc1SAntonio Nino Diaz 	assert(amu_supported());
6040daecc1SAntonio Nino Diaz 	assert((idx >= 0) && (idx < AMU_GROUP0_NR_COUNTERS));
61c70da546SJoel Hutton 
62c70da546SJoel Hutton 	return amu_group0_cnt_read_internal(idx);
63c70da546SJoel Hutton }
64c70da546SJoel Hutton 
65c70da546SJoel Hutton /* Write the group 0 counter identified by the given `idx` with `val`. */
66c70da546SJoel Hutton void amu_group0_cnt_write(int idx, uint64_t val)
67c70da546SJoel Hutton {
6840daecc1SAntonio Nino Diaz 	assert(amu_supported());
6940daecc1SAntonio Nino Diaz 	assert((idx >= 0) && (idx < AMU_GROUP0_NR_COUNTERS));
70c70da546SJoel Hutton 
71c70da546SJoel Hutton 	amu_group0_cnt_write_internal(idx, val);
72c70da546SJoel Hutton 	isb();
73c70da546SJoel Hutton }
74c70da546SJoel Hutton 
75c70da546SJoel Hutton /* Read the group 1 counter identified by the given `idx`. */
76c70da546SJoel Hutton uint64_t amu_group1_cnt_read(int idx)
77c70da546SJoel Hutton {
7840daecc1SAntonio Nino Diaz 	assert(amu_supported());
7940daecc1SAntonio Nino Diaz 	assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
80c70da546SJoel Hutton 
81c70da546SJoel Hutton 	return amu_group1_cnt_read_internal(idx);
82c70da546SJoel Hutton }
83c70da546SJoel Hutton 
84c70da546SJoel Hutton /* Write the group 1 counter identified by the given `idx` with `val`. */
85c70da546SJoel Hutton void amu_group1_cnt_write(int idx, uint64_t val)
86c70da546SJoel Hutton {
8740daecc1SAntonio Nino Diaz 	assert(amu_supported());
8840daecc1SAntonio Nino Diaz 	assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
89c70da546SJoel Hutton 
90c70da546SJoel Hutton 	amu_group1_cnt_write_internal(idx, val);
91c70da546SJoel Hutton 	isb();
92c70da546SJoel Hutton }
93c70da546SJoel Hutton 
94c70da546SJoel Hutton void amu_group1_set_evtype(int idx, unsigned int val)
95c70da546SJoel Hutton {
9640daecc1SAntonio Nino Diaz 	assert(amu_supported());
9740daecc1SAntonio Nino Diaz 	assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
98c70da546SJoel Hutton 
99c70da546SJoel Hutton 	amu_group1_set_evtype_internal(idx, val);
100c70da546SJoel Hutton 	isb();
101ef69e1eaSDimitris Papastamos }
102b6eb3932SDimitris Papastamos 
103b6eb3932SDimitris Papastamos static void *amu_context_save(const void *arg)
104b6eb3932SDimitris Papastamos {
105b6eb3932SDimitris Papastamos 	struct amu_ctx *ctx;
106c70da546SJoel Hutton 	int i;
107b6eb3932SDimitris Papastamos 
10840daecc1SAntonio Nino Diaz 	if (!amu_supported())
109b6eb3932SDimitris Papastamos 		return (void *)-1;
110b6eb3932SDimitris Papastamos 
111b6eb3932SDimitris Papastamos 	ctx = &amu_ctxs[plat_my_core_pos()];
112b6eb3932SDimitris Papastamos 
113b6eb3932SDimitris Papastamos 	/* Assert that group 0 counter configuration is what we expect */
114e6e17ee8SDimitris Papastamos 	assert(read_amcntenset0() == AMU_GROUP0_COUNTERS_MASK &&
115e6e17ee8SDimitris Papastamos 	       read_amcntenset1() == AMU_GROUP1_COUNTERS_MASK);
116b6eb3932SDimitris Papastamos 
117b6eb3932SDimitris Papastamos 	/*
118b6eb3932SDimitris Papastamos 	 * Disable group 0 counters to avoid other observers like SCP sampling
119b6eb3932SDimitris Papastamos 	 * counter values from the future via the memory mapped view.
120b6eb3932SDimitris Papastamos 	 */
121b6eb3932SDimitris Papastamos 	write_amcntenclr0(AMU_GROUP0_COUNTERS_MASK);
122c70da546SJoel Hutton 	write_amcntenclr1(AMU_GROUP1_COUNTERS_MASK);
123b6eb3932SDimitris Papastamos 	isb();
124b6eb3932SDimitris Papastamos 
125c70da546SJoel Hutton 	for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++)
126c70da546SJoel Hutton 		ctx->group0_cnts[i] = amu_group0_cnt_read(i);
127c70da546SJoel Hutton 
128c70da546SJoel Hutton 	for (i = 0; i < AMU_GROUP1_NR_COUNTERS; i++)
129c70da546SJoel Hutton 		ctx->group1_cnts[i] = amu_group1_cnt_read(i);
130b6eb3932SDimitris Papastamos 
13140daecc1SAntonio Nino Diaz 	return (void *)0;
132b6eb3932SDimitris Papastamos }
133b6eb3932SDimitris Papastamos 
134b6eb3932SDimitris Papastamos static void *amu_context_restore(const void *arg)
135b6eb3932SDimitris Papastamos {
136b6eb3932SDimitris Papastamos 	struct amu_ctx *ctx;
137c70da546SJoel Hutton 	int i;
138b6eb3932SDimitris Papastamos 
13940daecc1SAntonio Nino Diaz 	if (!amu_supported())
140b6eb3932SDimitris Papastamos 		return (void *)-1;
141b6eb3932SDimitris Papastamos 
142b6eb3932SDimitris Papastamos 	ctx = &amu_ctxs[plat_my_core_pos()];
143b6eb3932SDimitris Papastamos 
144b6eb3932SDimitris Papastamos 	/* Counters were disabled in `amu_context_save()` */
14540daecc1SAntonio Nino Diaz 	assert((read_amcntenset0() == 0U) && (read_amcntenset1() == 0U));
146b6eb3932SDimitris Papastamos 
147b6eb3932SDimitris Papastamos 	/* Restore group 0 counters */
148c70da546SJoel Hutton 	for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++)
149c70da546SJoel Hutton 		amu_group0_cnt_write(i, ctx->group0_cnts[i]);
150c70da546SJoel Hutton 	for (i = 0; i < AMU_GROUP1_NR_COUNTERS; i++)
151c70da546SJoel Hutton 		amu_group1_cnt_write(i, ctx->group1_cnts[i]);
152b6eb3932SDimitris Papastamos 
153b6eb3932SDimitris Papastamos 	/* Enable group 0 counters */
154b6eb3932SDimitris Papastamos 	write_amcntenset0(AMU_GROUP0_COUNTERS_MASK);
155b6eb3932SDimitris Papastamos 
156c70da546SJoel Hutton 	/* Enable group 1 counters */
157c70da546SJoel Hutton 	write_amcntenset1(AMU_GROUP1_COUNTERS_MASK);
15840daecc1SAntonio Nino Diaz 	return (void *)0;
159b6eb3932SDimitris Papastamos }
160b6eb3932SDimitris Papastamos 
161b6eb3932SDimitris Papastamos SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save);
162b6eb3932SDimitris Papastamos SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, amu_context_restore);
163