2 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
4 * SPDX-License-Identifier: BSD-3-Clause
8 #include <amu_private.h>
10 #include <arch_helpers.h>
12 #include <pubsub_events.h>
15 #define AMU_GROUP0_NR_COUNTERS 4
18 uint64_t group0_cnts
[AMU_GROUP0_NR_COUNTERS
];
19 uint64_t group1_cnts
[AMU_GROUP1_NR_COUNTERS
];
22 static struct amu_ctx amu_ctxs
[PLATFORM_CORE_COUNT
];
24 bool amu_supported(void)
28 features
= read_id_pfr0() >> ID_PFR0_AMU_SHIFT
;
29 return (features
& ID_PFR0_AMU_MASK
) == 1U;
32 void amu_enable(bool el2_unused
)
40 * Non-secure access from EL0 or EL1 to the Activity Monitor
41 * registers do not trap to EL2.
48 /* Enable group 0 counters */
49 write_amcntenset0(AMU_GROUP0_COUNTERS_MASK
);
51 /* Enable group 1 counters */
52 write_amcntenset1(AMU_GROUP1_COUNTERS_MASK
);
55 /* Read the group 0 counter identified by the given `idx`. */
56 uint64_t amu_group0_cnt_read(int idx
)
58 assert(amu_supported());
59 assert((idx
>= 0) && (idx
< AMU_GROUP0_NR_COUNTERS
));
61 return amu_group0_cnt_read_internal(idx
);
64 /* Write the group 0 counter identified by the given `idx` with `val`. */
65 void amu_group0_cnt_write(int idx
, uint64_t val
)
67 assert(amu_supported());
68 assert((idx
>= 0) && (idx
< AMU_GROUP0_NR_COUNTERS
));
70 amu_group0_cnt_write_internal(idx
, val
);
74 /* Read the group 1 counter identified by the given `idx`. */
75 uint64_t amu_group1_cnt_read(int idx
)
77 assert(amu_supported());
78 assert((idx
>= 0) && (idx
< AMU_GROUP1_NR_COUNTERS
));
80 return amu_group1_cnt_read_internal(idx
);
83 /* Write the group 1 counter identified by the given `idx` with `val`. */
84 void amu_group1_cnt_write(int idx
, uint64_t val
)
86 assert(amu_supported());
87 assert((idx
>= 0) && (idx
< AMU_GROUP1_NR_COUNTERS
));
89 amu_group1_cnt_write_internal(idx
, val
);
93 void amu_group1_set_evtype(int idx
, unsigned int val
)
95 assert(amu_supported());
96 assert((idx
>= 0) && (idx
< AMU_GROUP1_NR_COUNTERS
));
98 amu_group1_set_evtype_internal(idx
, val
);
102 static void *amu_context_save(const void *arg
)
107 if (!amu_supported())
110 ctx
= &amu_ctxs
[plat_my_core_pos()];
112 /* Assert that group 0 counter configuration is what we expect */
113 assert(read_amcntenset0() == AMU_GROUP0_COUNTERS_MASK
&&
114 read_amcntenset1() == AMU_GROUP1_COUNTERS_MASK
);
117 * Disable group 0 counters to avoid other observers like SCP sampling
118 * counter values from the future via the memory mapped view.
120 write_amcntenclr0(AMU_GROUP0_COUNTERS_MASK
);
121 write_amcntenclr1(AMU_GROUP1_COUNTERS_MASK
);
124 for (i
= 0; i
< AMU_GROUP0_NR_COUNTERS
; i
++)
125 ctx
->group0_cnts
[i
] = amu_group0_cnt_read(i
);
127 for (i
= 0; i
< AMU_GROUP1_NR_COUNTERS
; i
++)
128 ctx
->group1_cnts
[i
] = amu_group1_cnt_read(i
);
133 static void *amu_context_restore(const void *arg
)
138 if (!amu_supported())
141 ctx
= &amu_ctxs
[plat_my_core_pos()];
143 /* Counters were disabled in `amu_context_save()` */
144 assert((read_amcntenset0() == 0U) && (read_amcntenset1() == 0U));
146 /* Restore group 0 counters */
147 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
]);
152 /* Enable group 0 counters */
153 write_amcntenset0(AMU_GROUP0_COUNTERS_MASK
);
155 /* Enable group 1 counters */
156 write_amcntenset1(AMU_GROUP1_COUNTERS_MASK
);
160 SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start
, amu_context_save
);
161 SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish
, amu_context_restore
);