blob: 82d2e186403f202ed0a3f3614c512b8def79e5ed [file] [log] [blame]
Dimitris Papastamosdda48b02017-10-17 14:03:14 +01001/*
Dimitris Papastamos7c4a6e62018-01-15 14:52:57 +00002 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
Dimitris Papastamosdda48b02017-10-17 14:03:14 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00007#include <stdbool.h>
8
Dimitris Papastamosdda48b02017-10-17 14:03:14 +01009#include <arch.h>
10#include <arch_helpers.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000011#include <lib/el3_runtime/pubsub_events.h>
12#include <lib/extensions/amu.h>
13#include <lib/extensions/amu_private.h>
14#include <plat/common/platform.h>
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +000015
16#define AMU_GROUP0_NR_COUNTERS 4
17
18struct amu_ctx {
19 uint64_t group0_cnts[AMU_GROUP0_NR_COUNTERS];
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000020 uint64_t group1_cnts[AMU_GROUP1_NR_COUNTERS];
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +000021};
22
23static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT];
Dimitris Papastamosdda48b02017-10-17 14:03:14 +010024
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010025bool amu_supported(void)
Dimitris Papastamosdda48b02017-10-17 14:03:14 +010026{
27 uint64_t features;
28
29 features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT;
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010030 return (features & ID_PFR0_AMU_MASK) == 1U;
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000031}
32
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010033void amu_enable(bool el2_unused)
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000034{
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010035 if (!amu_supported())
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000036 return;
Dimitris Papastamosdda48b02017-10-17 14:03:14 +010037
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000038 if (el2_unused) {
39 uint64_t v;
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000040 /*
41 * Non-secure access from EL0 or EL1 to the Activity Monitor
42 * registers do not trap to EL2.
43 */
44 v = read_hcptr();
45 v &= ~TAM_BIT;
46 write_hcptr(v);
Dimitris Papastamosdda48b02017-10-17 14:03:14 +010047 }
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000048
49 /* Enable group 0 counters */
50 write_amcntenset0(AMU_GROUP0_COUNTERS_MASK);
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000051
52 /* Enable group 1 counters */
53 write_amcntenset1(AMU_GROUP1_COUNTERS_MASK);
54}
55
56/* Read the group 0 counter identified by the given `idx`. */
57uint64_t amu_group0_cnt_read(int idx)
58{
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010059 assert(amu_supported());
60 assert((idx >= 0) && (idx < AMU_GROUP0_NR_COUNTERS));
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000061
62 return amu_group0_cnt_read_internal(idx);
63}
64
65/* Write the group 0 counter identified by the given `idx` with `val`. */
66void amu_group0_cnt_write(int idx, uint64_t val)
67{
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010068 assert(amu_supported());
69 assert((idx >= 0) && (idx < AMU_GROUP0_NR_COUNTERS));
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000070
71 amu_group0_cnt_write_internal(idx, val);
72 isb();
73}
74
75/* Read the group 1 counter identified by the given `idx`. */
76uint64_t amu_group1_cnt_read(int idx)
77{
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010078 assert(amu_supported());
79 assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000080
81 return amu_group1_cnt_read_internal(idx);
82}
83
84/* Write the group 1 counter identified by the given `idx` with `val`. */
85void amu_group1_cnt_write(int idx, uint64_t val)
86{
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010087 assert(amu_supported());
88 assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000089
90 amu_group1_cnt_write_internal(idx, val);
91 isb();
92}
93
94void amu_group1_set_evtype(int idx, unsigned int val)
95{
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010096 assert(amu_supported());
97 assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000098
99 amu_group1_set_evtype_internal(idx, val);
100 isb();
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000101}
102
103static void *amu_context_save(const void *arg)
104{
105 struct amu_ctx *ctx;
Joel Hutton0dcdd8d2017-12-21 15:21:20 +0000106 int i;
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000107
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +0100108 if (!amu_supported())
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000109 return (void *)-1;
110
111 ctx = &amu_ctxs[plat_my_core_pos()];
112
113 /* Assert that group 0 counter configuration is what we expect */
Dimitris Papastamos430f1152018-02-20 11:16:44 +0000114 assert(read_amcntenset0() == AMU_GROUP0_COUNTERS_MASK &&
115 read_amcntenset1() == AMU_GROUP1_COUNTERS_MASK);
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000116
117 /*
118 * Disable group 0 counters to avoid other observers like SCP sampling
119 * counter values from the future via the memory mapped view.
120 */
121 write_amcntenclr0(AMU_GROUP0_COUNTERS_MASK);
Joel Hutton0dcdd8d2017-12-21 15:21:20 +0000122 write_amcntenclr1(AMU_GROUP1_COUNTERS_MASK);
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000123 isb();
124
Joel Hutton0dcdd8d2017-12-21 15:21:20 +0000125 for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++)
126 ctx->group0_cnts[i] = amu_group0_cnt_read(i);
127
128 for (i = 0; i < AMU_GROUP1_NR_COUNTERS; i++)
129 ctx->group1_cnts[i] = amu_group1_cnt_read(i);
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000130
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +0100131 return (void *)0;
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000132}
133
134static void *amu_context_restore(const void *arg)
135{
136 struct amu_ctx *ctx;
Joel Hutton0dcdd8d2017-12-21 15:21:20 +0000137 int i;
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000138
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +0100139 if (!amu_supported())
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000140 return (void *)-1;
141
142 ctx = &amu_ctxs[plat_my_core_pos()];
143
144 /* Counters were disabled in `amu_context_save()` */
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +0100145 assert((read_amcntenset0() == 0U) && (read_amcntenset1() == 0U));
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000146
147 /* Restore group 0 counters */
Joel Hutton0dcdd8d2017-12-21 15:21:20 +0000148 for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++)
149 amu_group0_cnt_write(i, ctx->group0_cnts[i]);
150 for (i = 0; i < AMU_GROUP1_NR_COUNTERS; i++)
151 amu_group1_cnt_write(i, ctx->group1_cnts[i]);
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000152
153 /* Enable group 0 counters */
154 write_amcntenset0(AMU_GROUP0_COUNTERS_MASK);
155
Joel Hutton0dcdd8d2017-12-21 15:21:20 +0000156 /* Enable group 1 counters */
157 write_amcntenset1(AMU_GROUP1_COUNTERS_MASK);
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +0100158 return (void *)0;
Dimitris Papastamosdda48b02017-10-17 14:03:14 +0100159}
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000160
161SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save);
162SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, amu_context_restore);