1380559c1SDimitris Papastamos /* 2380559c1SDimitris Papastamos * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3380559c1SDimitris Papastamos * 4380559c1SDimitris Papastamos * SPDX-License-Identifier: BSD-3-Clause 5380559c1SDimitris Papastamos */ 6380559c1SDimitris Papastamos 7380559c1SDimitris Papastamos #include <amu.h> 8*0767d50eSDimitris Papastamos #include <amu_private.h> 9380559c1SDimitris Papastamos #include <arch.h> 10380559c1SDimitris Papastamos #include <arch_helpers.h> 11*0767d50eSDimitris Papastamos #include <assert.h> 12*0767d50eSDimitris Papastamos #include <debug.h> 13380559c1SDimitris Papastamos 14*0767d50eSDimitris Papastamos #define AMU_GROUP0_NR_COUNTERS 4 15*0767d50eSDimitris Papastamos 16*0767d50eSDimitris Papastamos int amu_supported(void) 17380559c1SDimitris Papastamos { 18380559c1SDimitris Papastamos uint64_t features; 19380559c1SDimitris Papastamos 20380559c1SDimitris Papastamos features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT; 21*0767d50eSDimitris Papastamos return (features & ID_AA64PFR0_AMU_MASK) == 1; 22*0767d50eSDimitris Papastamos } 23*0767d50eSDimitris Papastamos 24*0767d50eSDimitris Papastamos /* 25*0767d50eSDimitris Papastamos * Enable counters. This function is meant to be invoked 26*0767d50eSDimitris Papastamos * by the context management library before exiting from EL3. 27*0767d50eSDimitris Papastamos */ 28*0767d50eSDimitris Papastamos void amu_enable(int el2_unused) 29*0767d50eSDimitris Papastamos { 30380559c1SDimitris Papastamos uint64_t v; 31380559c1SDimitris Papastamos 32*0767d50eSDimitris Papastamos if (!amu_supported()) { 33*0767d50eSDimitris Papastamos WARN("Cannot enable AMU - not supported\n"); 34*0767d50eSDimitris Papastamos return; 35*0767d50eSDimitris Papastamos } 36*0767d50eSDimitris Papastamos 37380559c1SDimitris Papastamos if (el2_unused) { 38380559c1SDimitris Papastamos /* 39380559c1SDimitris Papastamos * CPTR_EL2.TAM: Set to zero so any accesses to 40380559c1SDimitris Papastamos * the Activity Monitor registers do not trap to EL2. 41380559c1SDimitris Papastamos */ 42380559c1SDimitris Papastamos v = read_cptr_el2(); 43380559c1SDimitris Papastamos v &= ~CPTR_EL2_TAM_BIT; 44380559c1SDimitris Papastamos write_cptr_el2(v); 45380559c1SDimitris Papastamos } 46380559c1SDimitris Papastamos 47380559c1SDimitris Papastamos /* 48380559c1SDimitris Papastamos * CPTR_EL3.TAM: Set to zero so that any accesses to 49380559c1SDimitris Papastamos * the Activity Monitor registers do not trap to EL3. 50380559c1SDimitris Papastamos */ 51380559c1SDimitris Papastamos v = read_cptr_el3(); 52380559c1SDimitris Papastamos v &= ~TAM_BIT; 53380559c1SDimitris Papastamos write_cptr_el3(v); 54380559c1SDimitris Papastamos 55380559c1SDimitris Papastamos /* Enable group 0 counters */ 56380559c1SDimitris Papastamos write_amcntenset0_el0(AMU_GROUP0_COUNTERS_MASK); 5759902b7cSDimitris Papastamos /* Enable group 1 counters */ 5859902b7cSDimitris Papastamos write_amcntenset1_el0(AMU_GROUP1_COUNTERS_MASK); 59380559c1SDimitris Papastamos } 60*0767d50eSDimitris Papastamos 61*0767d50eSDimitris Papastamos /* Read the group 0 counter identified by the given `idx`. */ 62*0767d50eSDimitris Papastamos uint64_t amu_group0_cnt_read(int idx) 63*0767d50eSDimitris Papastamos { 64*0767d50eSDimitris Papastamos assert(amu_supported()); 65*0767d50eSDimitris Papastamos assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS); 66*0767d50eSDimitris Papastamos 67*0767d50eSDimitris Papastamos return amu_group0_cnt_read_internal(idx); 68*0767d50eSDimitris Papastamos } 69*0767d50eSDimitris Papastamos 70*0767d50eSDimitris Papastamos /* Write the group 0 counter identified by the given `idx` with `val`. */ 71*0767d50eSDimitris Papastamos void amu_group0_cnt_write(int idx, uint64_t val) 72*0767d50eSDimitris Papastamos { 73*0767d50eSDimitris Papastamos assert(amu_supported()); 74*0767d50eSDimitris Papastamos assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS); 75*0767d50eSDimitris Papastamos 76*0767d50eSDimitris Papastamos amu_group0_cnt_write_internal(idx, val); 77*0767d50eSDimitris Papastamos isb(); 78*0767d50eSDimitris Papastamos } 79*0767d50eSDimitris Papastamos 80*0767d50eSDimitris Papastamos /* Read the group 1 counter identified by the given `idx`. */ 81*0767d50eSDimitris Papastamos uint64_t amu_group1_cnt_read(int idx) 82*0767d50eSDimitris Papastamos { 83*0767d50eSDimitris Papastamos assert(amu_supported()); 84*0767d50eSDimitris Papastamos assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS); 85*0767d50eSDimitris Papastamos 86*0767d50eSDimitris Papastamos return amu_group1_cnt_read_internal(idx); 87*0767d50eSDimitris Papastamos } 88*0767d50eSDimitris Papastamos 89*0767d50eSDimitris Papastamos /* Write the group 1 counter identified by the given `idx` with `val`. */ 90*0767d50eSDimitris Papastamos void amu_group1_cnt_write(int idx, uint64_t val) 91*0767d50eSDimitris Papastamos { 92*0767d50eSDimitris Papastamos assert(amu_supported()); 93*0767d50eSDimitris Papastamos assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS); 94*0767d50eSDimitris Papastamos 95*0767d50eSDimitris Papastamos amu_group1_cnt_write_internal(idx, val); 96*0767d50eSDimitris Papastamos isb(); 97*0767d50eSDimitris Papastamos } 98*0767d50eSDimitris Papastamos 99*0767d50eSDimitris Papastamos /* 100*0767d50eSDimitris Papastamos * Program the event type register for the given `idx` with 101*0767d50eSDimitris Papastamos * the event number `val`. 102*0767d50eSDimitris Papastamos */ 103*0767d50eSDimitris Papastamos void amu_group1_set_evtype(int idx, unsigned int val) 104*0767d50eSDimitris Papastamos { 105*0767d50eSDimitris Papastamos assert(amu_supported()); 106*0767d50eSDimitris Papastamos assert (idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS); 107*0767d50eSDimitris Papastamos 108*0767d50eSDimitris Papastamos amu_group1_set_evtype_internal(idx, val); 109*0767d50eSDimitris Papastamos isb(); 110380559c1SDimitris Papastamos } 111