1 /* 2 * Copyright (c) 2017-2018, 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> 10 #include <platform.h> 11 #include <pubsub_events.h> 12 13 #define AMU_GROUP0_NR_COUNTERS 4 14 15 struct amu_ctx { 16 uint64_t group0_cnts[AMU_GROUP0_NR_COUNTERS]; 17 }; 18 19 static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT]; 20 21 void amu_enable(int el2_unused) 22 { 23 uint64_t features; 24 25 features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT; 26 if ((features & ID_PFR0_AMU_MASK) != 1) 27 return; 28 29 if (el2_unused) { 30 uint64_t v; 31 32 /* 33 * Non-secure access from EL0 or EL1 to the Activity Monitor 34 * registers do not trap to EL2. 35 */ 36 v = read_hcptr(); 37 v &= ~TAM_BIT; 38 write_hcptr(v); 39 } 40 41 /* Enable group 0 counters */ 42 write_amcntenset0(AMU_GROUP0_COUNTERS_MASK); 43 } 44 45 static void *amu_context_save(const void *arg) 46 { 47 struct amu_ctx *ctx; 48 uint64_t features; 49 50 features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT; 51 if ((features & ID_PFR0_AMU_MASK) != 1) 52 return (void *)-1; 53 54 ctx = &amu_ctxs[plat_my_core_pos()]; 55 56 /* Assert that group 0 counter configuration is what we expect */ 57 assert(read_amcntenset0() == AMU_GROUP0_COUNTERS_MASK); 58 59 /* 60 * Disable group 0 counters to avoid other observers like SCP sampling 61 * counter values from the future via the memory mapped view. 62 */ 63 write_amcntenclr0(AMU_GROUP0_COUNTERS_MASK); 64 isb(); 65 66 ctx->group0_cnts[0] = read64_amevcntr00(); 67 ctx->group0_cnts[1] = read64_amevcntr01(); 68 ctx->group0_cnts[2] = read64_amevcntr02(); 69 ctx->group0_cnts[3] = read64_amevcntr03(); 70 71 return 0; 72 } 73 74 static void *amu_context_restore(const void *arg) 75 { 76 struct amu_ctx *ctx; 77 uint64_t features; 78 79 features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT; 80 if ((features & ID_PFR0_AMU_MASK) != 1) 81 return (void *)-1; 82 83 ctx = &amu_ctxs[plat_my_core_pos()]; 84 85 /* Counters were disabled in `amu_context_save()` */ 86 assert(read_amcntenset0() == 0); 87 88 /* Restore group 0 counters */ 89 if (AMU_GROUP0_COUNTERS_MASK & (1U << 0)) 90 write64_amevcntr00(ctx->group0_cnts[0]); 91 if (AMU_GROUP0_COUNTERS_MASK & (1U << 1)) 92 write64_amevcntr01(ctx->group0_cnts[1]); 93 if (AMU_GROUP0_COUNTERS_MASK & (1U << 2)) 94 write64_amevcntr02(ctx->group0_cnts[2]); 95 if (AMU_GROUP0_COUNTERS_MASK & (1U << 3)) 96 write64_amevcntr03(ctx->group0_cnts[3]); 97 isb(); 98 99 /* Enable group 0 counters */ 100 write_amcntenset0(AMU_GROUP0_COUNTERS_MASK); 101 102 return 0; 103 } 104 105 SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save); 106 SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, amu_context_restore); 107