/* * * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software * Foundation, and any use by you of this program is subject to the terms * of such GNU licence. * * A copy of the licence is included with the program, and can also be obtained * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef _KBASE_GATOR_API_H_ #define _KBASE_GATOR_API_H_ /** * @brief This file describes the API used by Gator to fetch hardware counters. */ /* This define is used by the gator kernel module compile to select which DDK * API calling convention to use. If not defined (legacy DDK) gator assumes * version 1. The version to DDK release mapping is: * Version 1 API: DDK versions r1px, r2px * Version 2 API: DDK versions r3px, r4px * Version 3 API: DDK version r5p0 and newer * * API Usage * ========= * * 1] Call kbase_gator_hwcnt_init_names() to return the list of short counter * names for the GPU present in this device. * * 2] Create a kbase_gator_hwcnt_info structure and set the counter enables for * the counters you want enabled. The enables can all be set for simplicity in * most use cases, but disabling some will let you minimize bandwidth impact. * * 3] Call kbase_gator_hwcnt_init() using the above structure, to create a * counter context. On successful return the DDK will have populated the * structure with a variety of useful information. * * 4] Call kbase_gator_hwcnt_dump_irq() to queue a non-blocking request for a * counter dump. If this returns a non-zero value the request has been queued, * otherwise the driver has been unable to do so (typically because of another * user of the instrumentation exists concurrently). * * 5] Call kbase_gator_hwcnt_dump_complete() to test whether the previously * requested dump has been succesful. If this returns non-zero the counter dump * has resolved, but the value of *success must also be tested as the dump * may have not been successful. If it returns zero the counter dump was * abandoned due to the device being busy (typically because of another * user of the instrumentation exists concurrently). * * 6] Process the counters stored in the buffer pointed to by ... * * kbase_gator_hwcnt_info->kernel_dump_buffer * * In pseudo code you can find all of the counters via this approach: * * * hwcnt_info # pointer to kbase_gator_hwcnt_info structure * hwcnt_name # pointer to name list * * u32 * hwcnt_data = (u32*)hwcnt_info->kernel_dump_buffer * * # Iterate over each 64-counter block in this GPU configuration * for( i = 0; i < hwcnt_info->nr_hwc_blocks; i++) { * hwc_type type = hwcnt_info->hwc_layout[i]; * * # Skip reserved type blocks - they contain no counters at all * if( type == RESERVED_BLOCK ) { * continue; * } * * size_t name_offset = type * 64; * size_t data_offset = i * 64; * * # Iterate over the names of the counters in this block type * for( j = 0; j < 64; j++) { * const char * name = hwcnt_name[name_offset+j]; * * # Skip empty name strings - there is no counter here * if( name[0] == '\0' ) { * continue; * } * * u32 data = hwcnt_data[data_offset+j]; * * printk( "COUNTER: %s DATA: %u\n", name, data ); * } * } * * * Note that in most implementations you typically want to either SUM or * AVERAGE multiple instances of the same counter if, for example, you have * multiple shader cores or multiple L2 caches. The most sensible view for * analysis is to AVERAGE shader core counters, but SUM L2 cache and MMU * counters. * * 7] Goto 4, repeating until you want to stop collecting counters. * * 8] Release the dump resources by calling kbase_gator_hwcnt_term(). * * 9] Release the name table resources by calling * kbase_gator_hwcnt_term_names(). This function must only be called if * init_names() returned a non-NULL value. **/ #define MALI_DDK_GATOR_API_VERSION 3 enum hwc_type { JM_BLOCK = 0, TILER_BLOCK, SHADER_BLOCK, MMU_L2_BLOCK, RESERVED_BLOCK }; struct kbase_gator_hwcnt_info { /* Passed from Gator to kbase */ /* the bitmask of enabled hardware counters for each counter block */ uint16_t bitmask[4]; /* Passed from kbase to Gator */ /* ptr to counter dump memory */ void *kernel_dump_buffer; /* size of counter dump memory */ uint32_t size; /* the ID of the Mali device */ uint32_t gpu_id; /* the number of shader cores in the GPU */ uint32_t nr_cores; /* the number of core groups */ uint32_t nr_core_groups; /* the memory layout of the performance counters */ enum hwc_type *hwc_layout; /* the total number of hardware couter blocks */ uint32_t nr_hwc_blocks; }; /** * @brief Opaque block of Mali data which Gator needs to return to the API later. */ struct kbase_gator_hwcnt_handles; /** * @brief Initialize the resources Gator needs for performance profiling. * * @param in_out_info A pointer to a structure containing the enabled counters passed from Gator and all the Mali * specific information that will be returned to Gator. On entry Gator must have populated the * 'bitmask' field with the counters it wishes to enable for each class of counter block. * Each entry in the array corresponds to a single counter class based on the "hwc_type" * enumeration, and each bit corresponds to an enable for 4 sequential counters (LSB enables * the first 4 counters in the block, and so on). See the GPU counter array as returned by * kbase_gator_hwcnt_get_names() for the index values of each counter for the curernt GPU. * * @return Pointer to an opaque handle block on success, NULL on error. */ extern struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info *in_out_info); /** * @brief Free all resources once Gator has finished using performance counters. * * @param in_out_info A pointer to a structure containing the enabled counters passed from Gator and all the * Mali specific information that will be returned to Gator. * @param opaque_handles A wrapper structure for kbase structures. */ extern void kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info *in_out_info, struct kbase_gator_hwcnt_handles *opaque_handles); /** * @brief Poll whether a counter dump is successful. * * @param opaque_handles A wrapper structure for kbase structures. * @param[out] success Non-zero on success, zero on failure. * * @return Zero if the dump is still pending, non-zero if the dump has completed. Note that a * completed dump may not have dumped succesfully, so the caller must test for both * a completed and successful dump before processing counters. */ extern uint32_t kbase_gator_instr_hwcnt_dump_complete(struct kbase_gator_hwcnt_handles *opaque_handles, uint32_t * const success); /** * @brief Request the generation of a new counter dump. * * @param opaque_handles A wrapper structure for kbase structures. * * @return Zero if the hardware device is busy and cannot handle the request, non-zero otherwise. */ extern uint32_t kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles *opaque_handles); /** * @brief This function is used to fetch the names table based on the Mali device in use. * * @param[out] total_counters The total number of counters short names in the Mali devices' list. * * @return Pointer to an array of strings of length *total_counters. */ extern const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_counters); /** * @brief This function is used to terminate the use of the names table. * * This function must only be called if the initial call to kbase_gator_hwcnt_init_names returned a non-NULL value. */ extern void kbase_gator_hwcnt_term_names(void); #endif