1 /* 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 <amu_private.h> 9 #include <arch.h> 10 #include <arch_helpers.h> 11 #include <assert.h> 12 #include <debug.h> 13 14 #define AMU_GROUP0_NR_COUNTERS 4 15 16 int amu_supported(void) 17 { 18 uint64_t features; 19 20 features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT; 21 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 */ 28 void amu_enable(int el2_unused) 29 { 30 uint64_t v; 31 32 if (!amu_supported()) { 33 WARN("Cannot enable AMU - not supported\n"); 34 return; 35 } 36 37 if (el2_unused) { 38 /* 39 * CPTR_EL2.TAM: Set to zero so any accesses to 40 * the Activity Monitor registers do not trap to EL2. 41 */ 42 v = read_cptr_el2(); 43 v &= ~CPTR_EL2_TAM_BIT; 44 write_cptr_el2(v); 45 } 46 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`. */ 62 uint64_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`. */ 71 void 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`. */ 81 uint64_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`. */ 90 void 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 */ 103 void 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(); 110 } 111