blob: 27936a2e179b3c9c1923a70bb5134b3467353d7a [file] [log] [blame]
Dimitris Papastamose08005a2017-10-12 13:02:29 +01001/*
2 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <amu.h>
Dimitris Papastamos525c37a2017-11-13 09:49:45 +00008#include <amu_private.h>
Dimitris Papastamose08005a2017-10-12 13:02:29 +01009#include <arch.h>
10#include <arch_helpers.h>
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000011#include <assert.h>
12#include <debug.h>
Dimitris Papastamose08005a2017-10-12 13:02:29 +010013
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000014#define AMU_GROUP0_NR_COUNTERS 4
15
16int amu_supported(void)
Dimitris Papastamose08005a2017-10-12 13:02:29 +010017{
18 uint64_t features;
19
20 features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT;
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000021 return (features & ID_AA64PFR0_AMU_MASK) == 1;
22}
23
24/*
25 * Enable counters. This function is meant to be invoked
26 * by the context management library before exiting from EL3.
27 */
28void amu_enable(int el2_unused)
29{
30 uint64_t v;
Dimitris Papastamose08005a2017-10-12 13:02:29 +010031
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000032 if (!amu_supported()) {
33 WARN("Cannot enable AMU - not supported\n");
34 return;
35 }
Dimitris Papastamose08005a2017-10-12 13:02:29 +010036
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000037 if (el2_unused) {
Dimitris Papastamose08005a2017-10-12 13:02:29 +010038 /*
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000039 * CPTR_EL2.TAM: Set to zero so any accesses to
40 * the Activity Monitor registers do not trap to EL2.
Dimitris Papastamose08005a2017-10-12 13:02:29 +010041 */
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000042 v = read_cptr_el2();
43 v &= ~CPTR_EL2_TAM_BIT;
44 write_cptr_el2(v);
Dimitris Papastamose08005a2017-10-12 13:02:29 +010045 }
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000046
47 /*
48 * CPTR_EL3.TAM: Set to zero so that any accesses to
49 * the Activity Monitor registers do not trap to EL3.
50 */
51 v = read_cptr_el3();
52 v &= ~TAM_BIT;
53 write_cptr_el3(v);
54
55 /* Enable group 0 counters */
56 write_amcntenset0_el0(AMU_GROUP0_COUNTERS_MASK);
57 /* Enable group 1 counters */
58 write_amcntenset1_el0(AMU_GROUP1_COUNTERS_MASK);
59}
60
61/* Read the group 0 counter identified by the given `idx`. */
62uint64_t amu_group0_cnt_read(int idx)
63{
64 assert(amu_supported());
65 assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS);
66
67 return amu_group0_cnt_read_internal(idx);
68}
69
70/* Write the group 0 counter identified by the given `idx` with `val`. */
71void amu_group0_cnt_write(int idx, uint64_t val)
72{
73 assert(amu_supported());
74 assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS);
75
76 amu_group0_cnt_write_internal(idx, val);
77 isb();
78}
79
80/* Read the group 1 counter identified by the given `idx`. */
81uint64_t amu_group1_cnt_read(int idx)
82{
83 assert(amu_supported());
84 assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
85
86 return amu_group1_cnt_read_internal(idx);
87}
88
89/* Write the group 1 counter identified by the given `idx` with `val`. */
90void amu_group1_cnt_write(int idx, uint64_t val)
91{
92 assert(amu_supported());
93 assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
94
95 amu_group1_cnt_write_internal(idx, val);
96 isb();
97}
98
99/*
100 * Program the event type register for the given `idx` with
101 * the event number `val`.
102 */
103void amu_group1_set_evtype(int idx, unsigned int val)
104{
105 assert(amu_supported());
106 assert (idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
107
108 amu_group1_set_evtype_internal(idx, val);
109 isb();
Dimitris Papastamose08005a2017-10-12 13:02:29 +0100110}