blob: 491edde3fa44f50e85504b75065a191104ebf548 [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
johpow01b7d752a2020-10-08 17:29:11 -05002 * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <amu.h>
8#include <amu_private.h>
9#include <arch.h>
10#include <arch_helpers.h>
11#include <assert.h>
12
johpow01b7d752a2020-10-08 17:29:11 -050013/*
14 * Get AMU version value from aa64pfr0.
15 * Return values
16 * ID_AA64PFR0_AMU_V1: FEAT_AMUv1 supported (introduced in ARM v8.4)
17 * ID_AA64PFR0_AMU_V1P1: FEAT_AMUv1p1 supported (introduced in ARM v8.6)
18 * ID_AA64PFR0_AMU_NOT_SUPPORTED: not supported
19 */
20unsigned int amu_get_version(void)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020021{
johpow01b7d752a2020-10-08 17:29:11 -050022 return (unsigned int)(read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT) &
23 ID_AA64PFR0_AMU_MASK;
24}
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020025
johpow01b7d752a2020-10-08 17:29:11 -050026/* Check if group 1 counters is implemented */
27int amu_group1_supported(void)
28{
29 uint64_t features = read_amcfgr_el0() >> AMCFGR_EL0_NCG_SHIFT;
30
31 return (features & AMCFGR_EL0_NCG_MASK) == 1U;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020032}
33
34/* Read the group 0 counter identified by the given `idx`. */
johpow01b7d752a2020-10-08 17:29:11 -050035uint64_t amu_group0_cnt_read(unsigned int idx)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020036{
johpow01b7d752a2020-10-08 17:29:11 -050037 assert(amu_get_version() != ID_AA64PFR0_AMU_NOT_SUPPORTED);
38 assert(idx < AMU_GROUP0_NR_COUNTERS);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020039
40 return amu_group0_cnt_read_internal(idx);
41}
42
johpow01b7d752a2020-10-08 17:29:11 -050043/*
44 * Read the group 0 offset register for a given index. Index must be 0, 2, or
45 * 3, the register for 1 does not exist.
46 *
47 * Using this function requires v8.6 FEAT_AMUv1p1 support.
48 */
49uint64_t amu_group0_voffset_read(unsigned int idx)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020050{
johpow01b7d752a2020-10-08 17:29:11 -050051 assert(amu_get_version() >= ID_AA64PFR0_AMU_V1P1);
52 assert(idx < AMU_GROUP0_NR_COUNTERS);
53 assert(idx != 1U);
54
55 return amu_group0_voffset_read_internal(idx);
56}
57
58/*
59 * Write the group 0 offset register for a given index. Index must be 0, 2, or
60 * 3, the register for 1 does not exist.
61 *
62 * Using this function requires v8.6 FEAT_AMUv1p1 support.
63 */
64void amu_group0_voffset_write(unsigned int idx, uint64_t val)
65{
66 assert(amu_get_version() >= ID_AA64PFR0_AMU_V1P1);
67 assert(idx < AMU_GROUP0_NR_COUNTERS);
68 assert(idx != 1U);
69
70 amu_group0_voffset_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(unsigned int idx)
76{
77 assert(amu_get_version() != ID_AA64PFR0_AMU_NOT_SUPPORTED);
Juan Pablo Condec3cf2da2024-04-01 13:57:19 -050078 assert(amu_group1_supported());
79 assert(idx < amu_group1_num_counters());
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020080
81 return amu_group1_cnt_read_internal(idx);
82}
johpow01b7d752a2020-10-08 17:29:11 -050083
Juan Pablo Condec3cf2da2024-04-01 13:57:19 -050084/* Return the number of counters available for group 1 */
85uint64_t amu_group1_num_counters(void)
86{
87 assert(amu_get_version() != ID_AA64PFR0_AMU_NOT_SUPPORTED);
88 assert(amu_group1_supported());
89
90 uint64_t num_counters = amu_group1_num_counters_internal();
91 if (num_counters < AMU_GROUP1_NR_COUNTERS) {
92 return num_counters;
93 }
94 return AMU_GROUP1_NR_COUNTERS;
95}
96
97/* Return the type for group 1 counter with index `idx`. */
98uint64_t amu_group1_evtype_read(unsigned int idx)
99{
100 assert(amu_get_version() != ID_AA64PFR0_AMU_NOT_SUPPORTED);
101 assert(amu_group1_supported());
102 assert(idx < amu_group1_num_counters());
103
104 return amu_group1_evtype_read_internal(idx);
105}
106
107/* Set the type for group 1 counter with index `idx`. */
108void amu_group1_evtype_write(unsigned int idx, uint64_t val)
109{
110 assert(amu_get_version() != ID_AA64PFR0_AMU_NOT_SUPPORTED);
111 assert(amu_group1_supported());
112 assert(idx < amu_group1_num_counters());
113
114 amu_group1_evtype_write_internal(idx, val);
115}
116
117/*
118 * Return whether group 1 counter at index `idx` is implemented.
119 *
120 * Using this function requires v8.6 FEAT_AMUv1p1 support.
121 */
122uint64_t amu_group1_is_counter_implemented(unsigned int idx)
123{
124 assert(amu_get_version() >= ID_AA64PFR0_AMU_V1P1);
125 assert(amu_group1_supported());
126
127 return amu_group1_is_cnt_impl_internal(idx);
128}
129
johpow01b7d752a2020-10-08 17:29:11 -0500130/*
131 * Read the group 1 offset register for a given index.
132 *
133 * Using this function requires v8.6 FEAT_AMUv1p1 support.
134 */
135uint64_t amu_group1_voffset_read(unsigned int idx)
136{
137 assert(amu_get_version() >= ID_AA64PFR0_AMU_V1P1);
138 assert(amu_group1_supported());
139 assert(idx < AMU_GROUP1_NR_COUNTERS);
140 assert(((read_amcg1idr_el0() >> AMCG1IDR_VOFF_SHIFT) &
141 (1U << idx)) != 0U);
142
143 return amu_group1_voffset_read_internal(idx);
144}
145
146/*
147 * Write the group 1 offset register for a given index.
148 *
149 * Using this function requires v8.6 FEAT_AMUv1p1 support.
150 */
151void amu_group1_voffset_write(unsigned int idx, uint64_t val)
152{
153 assert(amu_get_version() >= ID_AA64PFR0_AMU_V1P1);
154 assert(amu_group1_supported());
155 assert(idx < AMU_GROUP1_NR_COUNTERS);
156 assert(((read_amcg1idr_el0() >> AMCG1IDR_VOFF_SHIFT) &
157 (1U << idx)) != 0U);
158
159 amu_group1_voffset_write_internal(idx, val);
160 isb();
161}