blob: 55462cbf218060ca2bde1da11afa842216cc1457 [file] [log] [blame]
Dimitris Papastamosdda48b02017-10-17 14:03:14 +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>
8#include <arch.h>
9#include <arch_helpers.h>
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000010#include <debug.h>
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +000011#include <platform.h>
12#include <pubsub_events.h>
13
14#define AMU_GROUP0_NR_COUNTERS 4
15
16struct amu_ctx {
17 uint64_t group0_cnts[AMU_GROUP0_NR_COUNTERS];
18};
19
20static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT];
Dimitris Papastamosdda48b02017-10-17 14:03:14 +010021
22void amu_enable(int el2_unused)
23{
24 uint64_t features;
25
26 features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT;
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000027 if ((features & ID_PFR0_AMU_MASK) != 1) {
28 WARN("Cannot enable AMU - not supported\n");
29 return;
30 }
Dimitris Papastamosdda48b02017-10-17 14:03:14 +010031
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000032 if (el2_unused) {
33 uint64_t v;
Dimitris Papastamosdda48b02017-10-17 14:03:14 +010034
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000035 /*
36 * Non-secure access from EL0 or EL1 to the Activity Monitor
37 * registers do not trap to EL2.
38 */
39 v = read_hcptr();
40 v &= ~TAM_BIT;
41 write_hcptr(v);
Dimitris Papastamosdda48b02017-10-17 14:03:14 +010042 }
Dimitris Papastamos525c37a2017-11-13 09:49:45 +000043
44 /* Enable group 0 counters */
45 write_amcntenset0(AMU_GROUP0_COUNTERS_MASK);
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +000046}
47
48static void *amu_context_save(const void *arg)
49{
50 struct amu_ctx *ctx;
51 uint64_t features;
52
53 features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT;
54 if ((features & ID_PFR0_AMU_MASK) != 1)
55 return (void *)-1;
56
57 ctx = &amu_ctxs[plat_my_core_pos()];
58
59 /* Assert that group 0 counter configuration is what we expect */
60 assert(read_amcntenset0() == AMU_GROUP0_COUNTERS_MASK);
61
62 /*
63 * Disable group 0 counters to avoid other observers like SCP sampling
64 * counter values from the future via the memory mapped view.
65 */
66 write_amcntenclr0(AMU_GROUP0_COUNTERS_MASK);
67 isb();
68
69 ctx->group0_cnts[0] = read64_amevcntr00();
70 ctx->group0_cnts[1] = read64_amevcntr01();
71 ctx->group0_cnts[2] = read64_amevcntr02();
72 ctx->group0_cnts[3] = read64_amevcntr03();
73
74 return 0;
75}
76
77static void *amu_context_restore(const void *arg)
78{
79 struct amu_ctx *ctx;
80 uint64_t features;
81
82 features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT;
83 if ((features & ID_PFR0_AMU_MASK) != 1)
84 return (void *)-1;
85
86 ctx = &amu_ctxs[plat_my_core_pos()];
87
88 /* Counters were disabled in `amu_context_save()` */
89 assert(read_amcntenset0() == 0);
90
91 /* Restore group 0 counters */
92 if (AMU_GROUP0_COUNTERS_MASK & (1U << 0))
93 write64_amevcntr00(ctx->group0_cnts[0]);
94 if (AMU_GROUP0_COUNTERS_MASK & (1U << 1))
95 write64_amevcntr01(ctx->group0_cnts[1]);
96 if (AMU_GROUP0_COUNTERS_MASK & (1U << 2))
97 write64_amevcntr02(ctx->group0_cnts[2]);
98 if (AMU_GROUP0_COUNTERS_MASK & (1U << 3))
99 write64_amevcntr03(ctx->group0_cnts[3]);
100 isb();
101
102 /* Enable group 0 counters */
103 write_amcntenset0(AMU_GROUP0_COUNTERS_MASK);
104
105 return 0;
Dimitris Papastamosdda48b02017-10-17 14:03:14 +0100106}
Dimitris Papastamoseaf3e6d2017-11-28 13:47:06 +0000107
108SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save);
109SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, amu_context_restore);