2 * Copyright (C) ARM Limited 2012-2014. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
12 #include <linux/module.h>
13 #include <linux/time.h>
14 #include <linux/math64.h>
15 #include <linux/slab.h>
18 /* Mali Midgard DDK includes */
19 #if defined(MALI_SIMPLE_API)
20 /* Header with wrapper functions to kbase structures and functions */
21 #include "mali/mali_kbase_gator_api.h"
22 #elif defined(MALI_DIR_MIDGARD)
23 /* New DDK Directory structure with kernel/drivers/gpu/arm/midgard */
24 #include "mali_linux_trace.h"
25 #include "mali_kbase.h"
26 #include "mali_kbase_mem_linux.h"
28 /* Old DDK Directory structure with kernel/drivers/gpu/arm/t6xx */
29 #include "linux/mali_linux_trace.h"
30 #include "kbase/src/common/mali_kbase.h"
31 #include "kbase/src/linux/mali_kbase_mem_linux.h"
34 /* If API version is not specified then assume API version 1. */
35 #ifndef MALI_DDK_GATOR_API_VERSION
36 #define MALI_DDK_GATOR_API_VERSION 1
39 #if (MALI_DDK_GATOR_API_VERSION != 1) && (MALI_DDK_GATOR_API_VERSION != 2) && (MALI_DDK_GATOR_API_VERSION != 3)
40 #error MALI_DDK_GATOR_API_VERSION is invalid (must be 1 for r1/r2 DDK, or 2 for r3/r4 DDK, or 3 for r5 and later DDK).
43 #include "gator_events_mali_common.h"
48 #if MALI_DDK_GATOR_API_VERSION == 3
49 static uint32_t (*kbase_gator_instr_hwcnt_dump_irq_symbol)(struct kbase_gator_hwcnt_handles *);
50 static uint32_t (*kbase_gator_instr_hwcnt_dump_complete_symbol)(struct kbase_gator_hwcnt_handles *, uint32_t *const);
51 static struct kbase_gator_hwcnt_handles *(*kbase_gator_hwcnt_init_symbol)(struct kbase_gator_hwcnt_info *);
52 static void (*kbase_gator_hwcnt_term_symbol)(struct kbase_gator_hwcnt_info *, struct kbase_gator_hwcnt_handles *);
55 static struct kbase_device *(*kbase_find_device_symbol)(int);
56 static struct kbase_context *(*kbase_create_context_symbol)(struct kbase_device *);
57 static void (*kbase_destroy_context_symbol)(struct kbase_context *);
59 #if MALI_DDK_GATOR_API_VERSION == 1
60 static void *(*kbase_va_alloc_symbol)(struct kbase_context *, u32);
61 static void (*kbase_va_free_symbol)(struct kbase_context *, void *);
62 #elif MALI_DDK_GATOR_API_VERSION == 2
63 static void *(*kbase_va_alloc_symbol)(struct kbase_context *, u32, struct kbase_hwc_dma_mapping *);
64 static void (*kbase_va_free_symbol)(struct kbase_context *, struct kbase_hwc_dma_mapping *);
67 static mali_error (*kbase_instr_hwcnt_enable_symbol)(struct kbase_context *, struct kbase_uk_hwcnt_setup *);
68 static mali_error (*kbase_instr_hwcnt_disable_symbol)(struct kbase_context *);
69 static mali_error (*kbase_instr_hwcnt_clear_symbol)(struct kbase_context *);
70 static mali_error (*kbase_instr_hwcnt_dump_irq_symbol)(struct kbase_context *);
71 static mali_bool (*kbase_instr_hwcnt_dump_complete_symbol)(struct kbase_context *, mali_bool *);
73 static long shader_present_low;
76 /** The interval between reads, in ns.
78 * Earlier we introduced a 'hold off for 1ms after last read' to
79 * resolve MIDBASE-2178 and MALINE-724. However, the 1ms hold off is
80 * too long if no context switches occur as there is a race between
81 * this value and the tick of the read clock in gator which is also
82 * 1ms. If we 'miss' the current read, the counter values are
83 * effectively 'spread' over 2ms and the values seen are half what
84 * they should be (since Streamline averages over sample time). In the
85 * presence of context switches this spread can vary and markedly
86 * affect the counters. Currently there is no 'proper' solution to
87 * this, but empirically we have found that reducing the minimum read
88 * interval to 950us causes the counts to be much more stable.
90 static const int READ_INTERVAL_NSEC = 950000;
93 #include "gator_events_mali_midgard_hw_test.c"
96 #if MALI_DDK_GATOR_API_VERSION != 3
97 /* Blocks for HW counters */
106 static const char *mali_name;
108 /* Counters for Mali-Midgard:
110 * For HW counters we need strings to create /dev/gator/events files.
111 * Enums are not needed because the position of the HW name in the array is the same
112 * of the corresponding value in the received block of memory.
113 * HW counters are requested by calculating a bitmask, passed then to the driver.
114 * Every millisecond a HW counters dump is requested, and if the previous has been completed they are read.
117 /* Hardware Counters */
118 #if MALI_DDK_GATOR_API_VERSION == 3
120 static const char *const *hardware_counter_names;
121 static int number_of_hardware_counters;
125 static const char *const hardware_counter_names[] = {
133 "GPU_ACTIVE", /* 6 */
262 "SHADER_CORE_ACTIVE",
265 "FRAG_PRIMATIVES_DROPPED",
269 "FRAG_CYCLES_TRISETUP",
272 "FRAG_DUMMY_THREADS",
274 "FRAG_QUADS_EZS_TEST",
275 "FRAG_QUADS_EZS_KILLED",
276 "FRAG_QUADS_LZS_TEST",
277 "FRAG_QUADS_LZS_KILLED",
278 "FRAG_CYCLE_NO_TILE",
284 "COMPUTE_CYCLES_DESC",
295 "LS_REISSUE_ATTRIB_MISS",
318 "AXI_TLB_TRANSACTION",
377 "L2_EXT_WRITE_SMALL",
381 "L2_EXT_RD_BUF_FULL",
391 static const int number_of_hardware_counters = ARRAY_SIZE(hardware_counter_names);
395 #define GET_HW_BLOCK(c) (((c) >> 6) & 0x3)
396 #define GET_COUNTER_OFFSET(c) ((c) & 0x3f)
398 #if MALI_DDK_GATOR_API_VERSION == 3
399 /* Opaque handles for kbase_context and kbase_hwc_dma_mapping */
400 static struct kbase_gator_hwcnt_handles *handles;
402 /* Information about hardware counters */
403 static struct kbase_gator_hwcnt_info *in_out_info;
406 /* Memory to dump hardware counters into */
407 static void *kernel_dump_buffer;
409 #if MALI_DDK_GATOR_API_VERSION == 2
410 /* DMA state used to manage lifetime of the buffer */
411 struct kbase_hwc_dma_mapping kernel_dump_buffer_handle;
414 /* kbase context and device */
415 static struct kbase_context *kbcontext;
416 static struct kbase_device *kbdevice;
419 * The following function has no external prototype in older DDK
420 * revisions. When the DDK is updated then this should be removed.
422 struct kbase_device *kbase_find_device(int minor);
425 static volatile bool kbase_device_busy;
426 static unsigned int num_hardware_counters_enabled;
428 /* gatorfs variables for counter enable state */
429 static struct mali_counter *counters;
431 /* An array used to return the data we recorded as key,value pairs */
432 static int *counter_dump;
434 extern struct mali_counter mali_activity[3];
436 static const char *const mali_activity_names[] = {
442 #define SYMBOL_GET(FUNCTION, ERROR_COUNT) \
444 if (FUNCTION ## _symbol) { \
445 pr_err("gator: mali " #FUNCTION " symbol was already registered\n"); \
448 FUNCTION ## _symbol = symbol_get(FUNCTION); \
449 if (!FUNCTION ## _symbol) { \
450 pr_err("gator: mali online " #FUNCTION " symbol not found\n"); \
456 #define SYMBOL_CLEANUP(FUNCTION) \
458 if (FUNCTION ## _symbol) { \
459 symbol_put(FUNCTION); \
460 FUNCTION ## _symbol = NULL; \
465 * Execute symbol_get for all the Mali symbols and check for success.
466 * @return the number of symbols not loaded.
468 static int init_symbols(void)
471 #if MALI_DDK_GATOR_API_VERSION == 3
472 SYMBOL_GET(kbase_gator_instr_hwcnt_dump_irq, error_count);
473 SYMBOL_GET(kbase_gator_instr_hwcnt_dump_complete, error_count);
474 SYMBOL_GET(kbase_gator_hwcnt_init, error_count);
475 SYMBOL_GET(kbase_gator_hwcnt_term, error_count);
477 SYMBOL_GET(kbase_find_device, error_count);
478 SYMBOL_GET(kbase_create_context, error_count);
479 SYMBOL_GET(kbase_va_alloc, error_count);
480 SYMBOL_GET(kbase_instr_hwcnt_enable, error_count);
481 SYMBOL_GET(kbase_instr_hwcnt_clear, error_count);
482 SYMBOL_GET(kbase_instr_hwcnt_dump_irq, error_count);
483 SYMBOL_GET(kbase_instr_hwcnt_dump_complete, error_count);
484 SYMBOL_GET(kbase_instr_hwcnt_disable, error_count);
485 SYMBOL_GET(kbase_va_free, error_count);
486 SYMBOL_GET(kbase_destroy_context, error_count);
493 * Execute symbol_put for all the registered Mali symbols.
495 static void clean_symbols(void)
497 #if MALI_DDK_GATOR_API_VERSION == 3
498 SYMBOL_CLEANUP(kbase_gator_instr_hwcnt_dump_irq);
499 SYMBOL_CLEANUP(kbase_gator_instr_hwcnt_dump_complete);
500 SYMBOL_CLEANUP(kbase_gator_hwcnt_init);
501 SYMBOL_CLEANUP(kbase_gator_hwcnt_term);
503 SYMBOL_CLEANUP(kbase_find_device);
504 SYMBOL_CLEANUP(kbase_create_context);
505 SYMBOL_CLEANUP(kbase_va_alloc);
506 SYMBOL_CLEANUP(kbase_instr_hwcnt_enable);
507 SYMBOL_CLEANUP(kbase_instr_hwcnt_clear);
508 SYMBOL_CLEANUP(kbase_instr_hwcnt_dump_irq);
509 SYMBOL_CLEANUP(kbase_instr_hwcnt_dump_complete);
510 SYMBOL_CLEANUP(kbase_instr_hwcnt_disable);
511 SYMBOL_CLEANUP(kbase_va_free);
512 SYMBOL_CLEANUP(kbase_destroy_context);
517 * Determines whether a read should take place
518 * @param current_time The current time, obtained from getnstimeofday()
519 * @param prev_time_s The number of seconds at the previous read attempt.
520 * @param next_read_time_ns The time (in ns) when the next read should be allowed.
522 * Note that this function has been separated out here to allow it to be tested.
524 static int is_read_scheduled(const struct timespec *current_time, u32 *prev_time_s, s32 *next_read_time_ns)
526 /* If the current ns count rolls over a second, roll the next read time too. */
527 if (current_time->tv_sec != *prev_time_s)
528 *next_read_time_ns = *next_read_time_ns - NSEC_PER_SEC;
530 /* Abort the read if the next read time has not arrived. */
531 if (current_time->tv_nsec < *next_read_time_ns)
534 /* Set the next read some fixed time after this one, and update the read timestamp. */
535 *next_read_time_ns = current_time->tv_nsec + READ_INTERVAL_NSEC;
537 *prev_time_s = current_time->tv_sec;
541 static int start(void)
543 #if MALI_DDK_GATOR_API_VERSION != 3
544 struct kbase_uk_hwcnt_setup setup;
545 unsigned long long shadersPresent = 0;
546 u16 bitmask[] = { 0, 0, 0, 0 };
551 #if MALI_DDK_GATOR_API_VERSION == 3
552 /* Setup HW counters */
553 num_hardware_counters_enabled = 0;
555 /* Declare and initialise kbase_gator_hwcnt_info structure */
556 in_out_info = kmalloc(sizeof(*in_out_info), GFP_KERNEL);
557 for (cnt = 0; cnt < ARRAY_SIZE(in_out_info->bitmask); cnt++)
558 in_out_info->bitmask[cnt] = 0;
560 /* Calculate enable bitmasks based on counters_enabled array */
561 for (cnt = 0; cnt < number_of_hardware_counters; cnt++) {
562 if (counters[cnt].enabled) {
563 int block = GET_HW_BLOCK(cnt);
564 int enable_bit = GET_COUNTER_OFFSET(cnt) / 4;
566 in_out_info->bitmask[block] |= (1 << enable_bit);
567 pr_debug("gator: Mali-Midgard: hardware counter %s selected [%d]\n", hardware_counter_names[cnt], cnt);
568 num_hardware_counters_enabled++;
572 /* Create a kbase context for HW counters */
573 if (num_hardware_counters_enabled > 0) {
574 if (init_symbols() > 0) {
576 /* No Mali driver code entrypoints found - not a fault. */
580 handles = kbase_gator_hwcnt_init_symbol(in_out_info);
585 kbase_device_busy = false;
590 /* Setup HW counters */
591 num_hardware_counters_enabled = 0;
593 /* Calculate enable bitmasks based on counters_enabled array */
594 for (cnt = 0; cnt < number_of_hardware_counters; cnt++) {
595 const struct mali_counter *counter = &counters[cnt];
597 if (counter->enabled) {
598 int block = GET_HW_BLOCK(cnt);
599 int enable_bit = GET_COUNTER_OFFSET(cnt) / 4;
601 bitmask[block] |= (1 << enable_bit);
602 pr_debug("gator: Mali-Midgard: hardware counter %s selected [%d]\n", hardware_counter_names[cnt], cnt);
603 num_hardware_counters_enabled++;
607 /* Create a kbase context for HW counters */
608 if (num_hardware_counters_enabled > 0) {
609 if (init_symbols() > 0) {
611 /* No Mali driver code entrypoints found - not a fault. */
615 kbdevice = kbase_find_device_symbol(-1);
617 /* If we already got a context, fail */
619 pr_debug("gator: Mali-Midgard: error context already present\n");
623 /* kbcontext will only be valid after all the Mali symbols are loaded successfully */
624 kbcontext = kbase_create_context_symbol(kbdevice);
626 pr_debug("gator: Mali-Midgard: error creating kbase context\n");
630 /* See if we can get the number of shader cores */
631 shadersPresent = kbdevice->shader_present_bitmap;
632 shader_present_low = (unsigned long)shadersPresent;
635 * The amount of memory needed to store the dump (bytes)
636 * DUMP_SIZE = number of core groups
637 * * number of blocks (always 8 for midgard)
638 * * number of counters per block (always 64 for midgard)
639 * * number of bytes per counter (always 4 in midgard)
640 * For a Mali-Midgard with a single core group = 1 * 8 * 64 * 4 = 2048
641 * For a Mali-Midgard with a dual core group = 2 * 8 * 64 * 4 = 4096
643 #if MALI_DDK_GATOR_API_VERSION == 1
644 kernel_dump_buffer = kbase_va_alloc_symbol(kbcontext, 4096);
645 #elif MALI_DDK_GATOR_API_VERSION == 2
646 kernel_dump_buffer = kbase_va_alloc_symbol(kbcontext, 4096, &kernel_dump_buffer_handle);
648 if (!kernel_dump_buffer) {
649 pr_debug("gator: Mali-Midgard: error trying to allocate va\n");
650 goto destroy_context;
653 setup.dump_buffer = (uintptr_t)kernel_dump_buffer;
654 setup.jm_bm = bitmask[JM_BLOCK];
655 setup.tiler_bm = bitmask[TILER_BLOCK];
656 setup.shader_bm = bitmask[SHADER_BLOCK];
657 setup.mmu_l2_bm = bitmask[MMU_BLOCK];
658 /* These counters do not exist on Mali-T60x */
659 setup.l3_cache_bm = 0;
661 /* Use kbase API to enable hardware counters and provide dump buffer */
662 err = kbase_instr_hwcnt_enable_symbol(kbcontext, &setup);
663 if (err != MALI_ERROR_NONE) {
664 pr_debug("gator: Mali-Midgard: can't setup hardware counters\n");
667 pr_debug("gator: Mali-Midgard: hardware counters enabled\n");
668 kbase_instr_hwcnt_clear_symbol(kbcontext);
669 pr_debug("gator: Mali-Midgard: hardware counters cleared\n");
671 kbase_device_busy = false;
677 #if MALI_DDK_GATOR_API_VERSION == 1
678 kbase_va_free_symbol(kbcontext, kernel_dump_buffer);
679 #elif MALI_DDK_GATOR_API_VERSION == 2
680 kbase_va_free_symbol(kbcontext, &kernel_dump_buffer_handle);
684 kbase_destroy_context_symbol(kbcontext);
692 static void stop(void)
695 #if MALI_DDK_GATOR_API_VERSION == 3
696 struct kbase_gator_hwcnt_handles *temp_hand;
698 struct kbase_context *temp_kbcontext;
701 pr_debug("gator: Mali-Midgard: stop\n");
703 /* Set all counters as disabled */
704 for (cnt = 0; cnt < number_of_hardware_counters; cnt++)
705 counters[cnt].enabled = 0;
707 /* Destroy the context for HW counters */
708 #if MALI_DDK_GATOR_API_VERSION == 3
709 if (num_hardware_counters_enabled > 0 && handles != NULL) {
711 * Set the global variable to NULL before destroying it, because
712 * other function will check this before using it.
717 kbase_gator_hwcnt_term_symbol(in_out_info, temp_hand);
722 if (num_hardware_counters_enabled > 0 && kbcontext != NULL) {
724 * Set the global variable to NULL before destroying it, because
725 * other function will check this before using it.
727 temp_kbcontext = kbcontext;
730 kbase_instr_hwcnt_disable_symbol(temp_kbcontext);
732 #if MALI_DDK_GATOR_API_VERSION == 1
733 kbase_va_free_symbol(temp_kbcontext, kernel_dump_buffer);
734 #elif MALI_DDK_GATOR_API_VERSION == 2
735 kbase_va_free_symbol(temp_kbcontext, &kernel_dump_buffer_handle);
738 kbase_destroy_context_symbol(temp_kbcontext);
741 pr_debug("gator: Mali-Midgard: hardware counters stopped\n");
747 static int read_counter(const int cnt, const int len, const struct mali_counter *counter)
749 const int block = GET_HW_BLOCK(cnt);
750 const int counter_offset = GET_COUNTER_OFFSET(cnt);
752 #if MALI_DDK_GATOR_API_VERSION == 3
753 const char *block_base_address = (char *)in_out_info->kernel_dump_buffer;
755 int shader_core_count = 0;
758 for (i = 0; i < in_out_info->nr_hwc_blocks; i++) {
759 if (block == in_out_info->hwc_layout[i]) {
760 value += *((u32 *)(block_base_address + (0x100 * i)) + counter_offset);
761 if (block == SHADER_BLOCK)
766 if (shader_core_count > 1)
767 value /= shader_core_count;
769 const char *block_base_address = (char *)kernel_dump_buffer + vithar_blocks[block];
771 /* If counter belongs to shader block need to take into account all cores */
772 if (block == SHADER_BLOCK) {
774 int shader_core_count = 0;
778 for (i = 0; i < 4; i++) {
779 if ((shader_present_low >> i) & 1) {
780 value += *((u32 *)(block_base_address + (0x100 * i)) + counter_offset);
785 for (i = 0; i < 4; i++) {
786 if ((shader_present_low >> (i+4)) & 1) {
787 value += *((u32 *)(block_base_address + (0x100 * i) + 0x800) + counter_offset);
792 /* Need to total by number of cores to produce an average */
793 if (shader_core_count != 0)
794 value /= shader_core_count;
796 value = *((u32 *)block_base_address + counter_offset);
800 counter_dump[len + 0] = counter->key;
801 counter_dump[len + 1] = value;
806 static int read(int **buffer, bool sched_switch)
812 struct timespec current_time;
813 static u32 prev_time_s;
814 static s32 next_read_time_ns;
816 if (!on_primary_core() || sched_switch)
819 getnstimeofday(¤t_time);
822 * Discard reads unless a respectable time has passed. This
823 * reduces the load on the GPU without sacrificing accuracy on
824 * the Streamline display.
826 if (!is_read_scheduled(¤t_time, &prev_time_s, &next_read_time_ns))
830 * Report the HW counters
831 * Only process hardware counters if at least one of the hardware counters is enabled.
833 if (num_hardware_counters_enabled > 0) {
834 #if MALI_DDK_GATOR_API_VERSION != 3
835 const unsigned int vithar_blocks[] = {
836 0x700, /* VITHAR_JOB_MANAGER, Block 0 */
837 0x400, /* VITHAR_TILER, Block 1 */
838 0x000, /* VITHAR_SHADER_CORE, Block 2 */
839 0x500 /* VITHAR_MEMORY_SYSTEM, Block 3 */
843 #if MALI_DDK_GATOR_API_VERSION == 3
847 /* Mali symbols can be called safely since a kbcontext is valid */
848 if (kbase_gator_instr_hwcnt_dump_complete_symbol(handles, &success) == MALI_TRUE) {
853 /* Mali symbols can be called safely since a kbcontext is valid */
854 if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success) == MALI_TRUE) {
856 kbase_device_busy = false;
858 if (success == MALI_TRUE) {
859 /* Cycle through hardware counters and accumulate totals */
860 for (cnt = 0; cnt < number_of_hardware_counters; cnt++) {
861 const struct mali_counter *counter = &counters[cnt];
863 if (counter->enabled)
864 len += read_counter(cnt, len, counter);
869 if (!kbase_device_busy) {
870 kbase_device_busy = true;
871 #if MALI_DDK_GATOR_API_VERSION == 3
872 kbase_gator_instr_hwcnt_dump_irq_symbol(handles);
874 kbase_instr_hwcnt_dump_irq_symbol(kbcontext);
879 /* Update the buffer */
881 *buffer = counter_dump;
886 static int create_files(struct super_block *sb, struct dentry *root)
890 * Create the filesystem for all events
892 for (event = 0; event < ARRAY_SIZE(mali_activity); event++) {
893 if (gator_mali_create_file_system("Midgard", mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0)
897 for (event = 0; event < number_of_hardware_counters; event++) {
898 if (gator_mali_create_file_system(mali_name, hardware_counter_names[event], sb, root, &counters[event], NULL) != 0)
905 static void shutdown(void)
907 #if MALI_DDK_GATOR_API_VERSION == 3
908 void (*kbase_gator_hwcnt_term_names_symbol)(void) = NULL;
915 #if MALI_DDK_GATOR_API_VERSION == 3
916 SYMBOL_GET(kbase_gator_hwcnt_term_names, error_count);
918 number_of_hardware_counters = -1;
919 hardware_counter_names = NULL;
920 if (kbase_gator_hwcnt_term_names_symbol != NULL) {
921 kbase_gator_hwcnt_term_names_symbol();
922 pr_err("Released symbols\n");
925 SYMBOL_CLEANUP(kbase_gator_hwcnt_term_names);
929 static struct gator_interface gator_events_mali_midgard_interface = {
930 .shutdown = shutdown,
931 .create_files = create_files,
937 int gator_events_mali_midgard_hw_init(void)
939 #if MALI_DDK_GATOR_API_VERSION == 3
940 const char *const *(*kbase_gator_hwcnt_init_names_symbol)(uint32_t *) = NULL;
944 pr_debug("gator: Mali-Midgard: sw_counters init\n");
947 test_all_is_read_scheduled();
950 #if MALI_DDK_GATOR_API_VERSION == 3
951 SYMBOL_GET(kbase_gator_hwcnt_init_names, error_count);
952 if (error_count > 0) {
953 SYMBOL_CLEANUP(kbase_gator_hwcnt_init_names);
957 number_of_hardware_counters = -1;
958 hardware_counter_names = kbase_gator_hwcnt_init_names_symbol(&number_of_hardware_counters);
960 SYMBOL_CLEANUP(kbase_gator_hwcnt_init_names);
962 if ((hardware_counter_names == NULL) || (number_of_hardware_counters <= 0)) {
963 pr_err("gator: Error reading hardware counters names: got %d names\n", number_of_hardware_counters);
967 mali_name = "Midgard";
970 counters = kmalloc(sizeof(*counters)*number_of_hardware_counters, GFP_KERNEL);
971 counter_dump = kmalloc(sizeof(*counter_dump)*number_of_hardware_counters*2, GFP_KERNEL);
973 gator_mali_initialise_counters(mali_activity, ARRAY_SIZE(mali_activity));
974 gator_mali_initialise_counters(counters, number_of_hardware_counters);
976 return gator_events_install(&gator_events_mali_midgard_interface);