| /* |
| * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| */ |
| |
| #ifndef PMF_H |
| #define PMF_H |
| |
| #include <cassert.h> |
| #include <pmf_helpers.h> |
| #include <utils_def.h> |
| |
| /* |
| * Constants used for/by PMF services. |
| */ |
| #define PMF_ARM_TIF_IMPL_ID U(0x41) |
| #define PMF_TID_SHIFT 0 |
| #define PMF_TID_MASK (U(0xFF) << PMF_TID_SHIFT) |
| #define PMF_SVC_ID_SHIFT 10 |
| #define PMF_SVC_ID_MASK (U(0x3F) << PMF_SVC_ID_SHIFT) |
| #define PMF_IMPL_ID_SHIFT 24 |
| #define PMF_IMPL_ID_MASK (U(0xFF) << PMF_IMPL_ID_SHIFT) |
| |
| /* |
| * Flags passed to PMF_REGISTER_SERVICE |
| */ |
| #define PMF_STORE_ENABLE (1 << 0) |
| #define PMF_DUMP_ENABLE (1 << 1) |
| |
| /* |
| * Flags passed to PMF_GET_TIMESTAMP_XXX |
| * and PMF_CAPTURE_TIMESTAMP |
| */ |
| #define PMF_CACHE_MAINT (U(1) << 0) |
| #define PMF_NO_CACHE_MAINT U(0) |
| |
| /* |
| * Defines for PMF SMC function ids. |
| */ |
| #define PMF_SMC_GET_TIMESTAMP_32 U(0x82000010) |
| #define PMF_SMC_GET_TIMESTAMP_64 U(0xC2000010) |
| #define PMF_NUM_SMC_CALLS 2 |
| |
| /* |
| * The macros below are used to identify |
| * PMF calls from the SMC function ID. |
| */ |
| #define PMF_FID_MASK U(0xffe0) |
| #define PMF_FID_VALUE U(0) |
| #define is_pmf_fid(_fid) (((_fid) & PMF_FID_MASK) == PMF_FID_VALUE) |
| |
| /* Following are the supported PMF service IDs */ |
| #define PMF_PSCI_STAT_SVC_ID 0 |
| #define PMF_RT_INSTR_SVC_ID 1 |
| |
| #if ENABLE_PMF |
| /* |
| * Convenience macros for capturing time-stamp. |
| */ |
| #define PMF_DECLARE_CAPTURE_TIMESTAMP(_name) \ |
| void pmf_capture_timestamp_with_cache_maint_ ## _name( \ |
| unsigned int tid, \ |
| unsigned long long ts); \ |
| void pmf_capture_timestamp_ ## _name( \ |
| unsigned int tid, \ |
| unsigned long long ts); |
| |
| #define PMF_CAPTURE_TIMESTAMP(_name, _tid, _flags) \ |
| do { \ |
| unsigned long long ts = read_cntpct_el0(); \ |
| if (((_flags) & PMF_CACHE_MAINT) != 0U) \ |
| pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), ts);\ |
| else \ |
| pmf_capture_timestamp_ ## _name((_tid), ts); \ |
| } while (0) |
| |
| #define PMF_CAPTURE_AND_GET_TIMESTAMP(_name, _tid, _flags, _tsval) \ |
| do { \ |
| (_tsval) = read_cntpct_el0(); \ |
| CASSERT(sizeof(_tsval) == sizeof(unsigned long long), invalid_tsval_size);\ |
| if (((_flags) & PMF_CACHE_MAINT) != 0U) \ |
| pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), (_tsval));\ |
| else \ |
| pmf_capture_timestamp_ ## _name((_tid), (_tsval));\ |
| } while (0) |
| |
| #define PMF_WRITE_TIMESTAMP(_name, _tid, _flags, _wrval) \ |
| do { \ |
| CASSERT(sizeof(_wrval) == sizeof(unsigned long long), invalid_wrval_size);\ |
| if (((_flags) & PMF_CACHE_MAINT) != 0U) \ |
| pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), (_wrval));\ |
| else \ |
| pmf_capture_timestamp_ ## _name((_tid), (_wrval));\ |
| } while (0) |
| |
| /* |
| * Convenience macros for retrieving time-stamp. |
| */ |
| #define PMF_DECLARE_GET_TIMESTAMP(_name) \ |
| unsigned long long pmf_get_timestamp_by_index_ ## _name(\ |
| unsigned int tid, \ |
| unsigned int cpuid, \ |
| unsigned int flags); \ |
| unsigned long long pmf_get_timestamp_by_mpidr_ ## _name(\ |
| unsigned int tid, \ |
| u_register_t mpidr, \ |
| unsigned int flags); |
| |
| #define PMF_GET_TIMESTAMP_BY_MPIDR(_name, _tid, _mpidr, _flags, _tsval)\ |
| _tsval = pmf_get_timestamp_by_mpidr_ ## _name(_tid, _mpidr, _flags) |
| |
| #define PMF_GET_TIMESTAMP_BY_INDEX(_name, _tid, _cpuid, _flags, _tsval)\ |
| _tsval = pmf_get_timestamp_by_index_ ## _name(_tid, _cpuid, _flags) |
| |
| /* Convenience macros to register a PMF service.*/ |
| /* |
| * This macro is used to register a PMF Service. It allocates PMF memory |
| * and defines default service-specific PMF functions. |
| */ |
| #define PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags) \ |
| PMF_ALLOCATE_TIMESTAMP_MEMORY(_name, _totalid) \ |
| PMF_DEFINE_CAPTURE_TIMESTAMP(_name, _flags) \ |
| PMF_DEFINE_GET_TIMESTAMP(_name) |
| |
| /* |
| * This macro is used to register a PMF service, including an |
| * SMC interface to that service. |
| */ |
| #define PMF_REGISTER_SERVICE_SMC(_name, _svcid, _totalid, _flags)\ |
| PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags) \ |
| PMF_DEFINE_SERVICE_DESC(_name, PMF_ARM_TIF_IMPL_ID, \ |
| _svcid, _totalid, NULL, \ |
| pmf_get_timestamp_by_mpidr_ ## _name) |
| |
| /* |
| * This macro is used to register a PMF service that has an SMC interface |
| * but provides its own service-specific PMF functions. |
| */ |
| #define PMF_REGISTER_SERVICE_SMC_OWN(_name, _implid, _svcid, _totalid, \ |
| _init, _getts) \ |
| PMF_DEFINE_SERVICE_DESC(_name, _implid, _svcid, _totalid, \ |
| _init, _getts) |
| |
| #else |
| |
| #define PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags) |
| #define PMF_REGISTER_SERVICE_SMC(_name, _svcid, _totalid, _flags) |
| #define PMF_REGISTER_SERVICE_SMC_OWN(_name, _implid, _svcid, _totalid, \ |
| _init, _getts) |
| #define PMF_DECLARE_CAPTURE_TIMESTAMP(_name) |
| #define PMF_DECLARE_GET_TIMESTAMP(_name) |
| #define PMF_CAPTURE_TIMESTAMP(_name, _tid, _flags) |
| #define PMF_GET_TIMESTAMP_BY_MPIDR(_name, _tid, _mpidr, _flags, _tsval) |
| #define PMF_GET_TIMESTAMP_BY_INDEX(_name, _tid, _cpuid, _flags, _tsval) |
| |
| #endif /* ENABLE_PMF */ |
| |
| /******************************************************************************* |
| * Function & variable prototypes |
| ******************************************************************************/ |
| /* PMF common functions */ |
| int pmf_get_timestamp_smc(unsigned int tid, |
| u_register_t mpidr, |
| unsigned int flags, |
| unsigned long long *ts_value); |
| int pmf_setup(void); |
| uintptr_t pmf_smc_handler(unsigned int smc_fid, |
| u_register_t x1, |
| u_register_t x2, |
| u_register_t x3, |
| u_register_t x4, |
| void *cookie, |
| void *handle, |
| u_register_t flags); |
| |
| #endif /* PMF_H */ |