blob: 585d908f77c2eb6c7edff5cd77ee6bc04d64c7e1 [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
7#include <amu.h>
Joel Hutton0dcdd8d2017-12-21 15:21:20 +00008#include <amu_private.h>
Dimitris Papastamosdda48b02017-10-17 14:03:14 +01009#include <arch.h>
10#include <arch_helpers.h>
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +000011#include <platform.h>
12#include <pubsub_events.h>
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010013#include <stdbool.h>
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +000014
15#define AMU_GROUP0_NR_COUNTERS 4
16
17struct amu_ctx {
18 uint64_t group0_cnts[AMU_GROUP0_NR_COUNTERS];
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000019 uint64_t group1_cnts[AMU_GROUP1_NR_COUNTERS];
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +000020};
21
22static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT];
Dimitris Papastamosdda48b02017-10-17 14:03:14 +010023
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010024bool amu_supported(void)
Dimitris Papastamosdda48b02017-10-17 14:03:14 +010025{
26 uint64_t features;
27
28 features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT;
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010029 return (features & ID_PFR0_AMU_MASK) == 1U;
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000030}
31
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010032void amu_enable(bool el2_unused)
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000033{
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010034 if (!amu_supported())
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000035 return;
Dimitris Papastamosdda48b02017-10-17 14:03:14 +010036
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000037 if (el2_unused) {
38 uint64_t v;
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000039 /*
40 * Non-secure access from EL0 or EL1 to the Activity Monitor
41 * registers do not trap to EL2.
42 */
43 v = read_hcptr();
44 v &= ~TAM_BIT;
45 write_hcptr(v);
Dimitris Papastamosdda48b02017-10-17 14:03:14 +010046 }
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000047
48 /* Enable group 0 counters */
49 write_amcntenset0(AMU_GROUP0_COUNTERS_MASK);
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000050
51 /* Enable group 1 counters */
52 write_amcntenset1(AMU_GROUP1_COUNTERS_MASK);
53}
54
55/* Read the group 0 counter identified by the given `idx`. */
56uint64_t amu_group0_cnt_read(int idx)
57{
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010058 assert(amu_supported());
59 assert((idx >= 0) && (idx < AMU_GROUP0_NR_COUNTERS));
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000060
61 return amu_group0_cnt_read_internal(idx);
62}
63
64/* Write the group 0 counter identified by the given `idx` with `val`. */
65void amu_group0_cnt_write(int idx, uint64_t val)
66{
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010067 assert(amu_supported());
68 assert((idx >= 0) && (idx < AMU_GROUP0_NR_COUNTERS));
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000069
70 amu_group0_cnt_write_internal(idx, val);
71 isb();
72}
73
74/* Read the group 1 counter identified by the given `idx`. */
75uint64_t amu_group1_cnt_read(int idx)
76{
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010077 assert(amu_supported());
78 assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000079
80 return amu_group1_cnt_read_internal(idx);
81}
82
83/* Write the group 1 counter identified by the given `idx` with `val`. */
84void amu_group1_cnt_write(int idx, uint64_t val)
85{
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010086 assert(amu_supported());
87 assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000088
89 amu_group1_cnt_write_internal(idx, val);
90 isb();
91}
92
93void amu_group1_set_evtype(int idx, unsigned int val)
94{
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +010095 assert(amu_supported());
96 assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
Joel Hutton0dcdd8d2017-12-21 15:21:20 +000097
98 amu_group1_set_evtype_internal(idx, val);
99 isb();
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000100}
101
102static void *amu_context_save(const void *arg)
103{
104 struct amu_ctx *ctx;
Joel Hutton0dcdd8d2017-12-21 15:21:20 +0000105 int i;
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000106
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +0100107 if (!amu_supported())
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000108 return (void *)-1;
109
110 ctx = &amu_ctxs[plat_my_core_pos()];
111
112 /* Assert that group 0 counter configuration is what we expect */
Dimitris Papastamos430f1152018-02-20 11:16:44 +0000113 assert(read_amcntenset0() == AMU_GROUP0_COUNTERS_MASK &&
114 read_amcntenset1() == AMU_GROUP1_COUNTERS_MASK);
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000115
116 /*
117 * Disable group 0 counters to avoid other observers like SCP sampling
118 * counter values from the future via the memory mapped view.
119 */
120 write_amcntenclr0(AMU_GROUP0_COUNTERS_MASK);
Joel Hutton0dcdd8d2017-12-21 15:21:20 +0000121 write_amcntenclr1(AMU_GROUP1_COUNTERS_MASK);
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000122 isb();
123
Joel Hutton0dcdd8d2017-12-21 15:21:20 +0000124 for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++)
125 ctx->group0_cnts[i] = amu_group0_cnt_read(i);
126
127 for (i = 0; i < AMU_GROUP1_NR_COUNTERS; i++)
128 ctx->group1_cnts[i] = amu_group1_cnt_read(i);
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000129
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +0100130 return (void *)0;
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000131}
132
133static void *amu_context_restore(const void *arg)
134{
135 struct amu_ctx *ctx;
Joel Hutton0dcdd8d2017-12-21 15:21:20 +0000136 int i;
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000137
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +0100138 if (!amu_supported())
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000139 return (void *)-1;
140
141 ctx = &amu_ctxs[plat_my_core_pos()];
142
143 /* Counters were disabled in `amu_context_save()` */
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +0100144 assert((read_amcntenset0() == 0U) && (read_amcntenset1() == 0U));
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000145
146 /* Restore group 0 counters */
Joel Hutton0dcdd8d2017-12-21 15:21:20 +0000147 for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++)
148 amu_group0_cnt_write(i, ctx->group0_cnts[i]);
149 for (i = 0; i < AMU_GROUP1_NR_COUNTERS; i++)
150 amu_group1_cnt_write(i, ctx->group1_cnts[i]);
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000151
152 /* Enable group 0 counters */
153 write_amcntenset0(AMU_GROUP0_COUNTERS_MASK);
154
Joel Hutton0dcdd8d2017-12-21 15:21:20 +0000155 /* Enable group 1 counters */
156 write_amcntenset1(AMU_GROUP1_COUNTERS_MASK);
Antonio Nino Diaz033b4bb2018-10-25 16:52:26 +0100157 return (void *)0;
Dimitris Papastamosdda48b02017-10-17 14:03:14 +0100158}
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000159
160SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save);
161SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, amu_context_restore);