mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
gator: Version 5.17
Signed-off-by: Jon Medhurst <tixy@linaro.org> Signed-off-by: Alex Shi <alex.shi@linaro.org> Conflicts: drivers/gator/Makefile
This commit is contained in:
@@ -12,24 +12,40 @@ gator-y := gator_main.o \
|
||||
gator_events_net.o \
|
||||
gator_events_block.o \
|
||||
gator_events_meminfo.o \
|
||||
gator_events_perf_pmu.o
|
||||
gator_events_perf_pmu.o \
|
||||
gator_events_mmapped.o \
|
||||
|
||||
gator-y += gator_events_mmaped.o
|
||||
# Convert the old GATOR_WITH_MALI_SUPPORT to the new kernel flags
|
||||
ifneq ($(GATOR_WITH_MALI_SUPPORT),)
|
||||
CONFIG_GATOR_WITH_MALI_SUPPORT := y
|
||||
ifeq ($(GATOR_WITH_MALI_SUPPORT),MALI_T6xx)
|
||||
CONFIG_GATOR_MALI_4XXMP := n
|
||||
CONFIG_GATOR_MALI_T6XX := y
|
||||
else
|
||||
CONFIG_GATOR_MALI_4XXMP := y
|
||||
CONFIG_GATOR_MALI_T6XX := n
|
||||
endif
|
||||
EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT)
|
||||
ifneq ($(GATOR_MALI_INTERFACE_STYLE),)
|
||||
EXTRA_CFLAGS += -DGATOR_MALI_INTERFACE_STYLE=$(GATOR_MALI_INTERFACE_STYLE)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_GATOR_WITH_MALI_SUPPORT),y)
|
||||
|
||||
ifeq ($(CONFIG_GATOR_MALI_T6XX),y)
|
||||
gator-y += gator_events_mali_t6xx.o \
|
||||
ifeq ($(CONFIG_GATOR_MALI_T6XX),y)
|
||||
gator-y += gator_events_mali_t6xx.o \
|
||||
gator_events_mali_t6xx_hw.o
|
||||
include $(M)/mali_t6xx.mk
|
||||
else
|
||||
gator-y += gator_events_mali_4xx.o
|
||||
endif
|
||||
gator-y += gator_events_mali_common.o
|
||||
include $(src)/mali_t6xx.mk
|
||||
else
|
||||
gator-y += gator_events_mali_4xx.o
|
||||
endif
|
||||
gator-y += gator_events_mali_common.o
|
||||
|
||||
ccflags-y += -I$(CONFIG_GATOR_MALI_PATH)
|
||||
ccflags-$(CONFIG_GATOR_MALI_400MP) += -DMALI_SUPPORT=MALI_400
|
||||
ccflags-$(CONFIG_GATOR_MALI_T6XX) += -DMALI_SUPPORT=MALI_T6xx
|
||||
ifneq ($(CONFIG_GATOR_MALI_PATH),)
|
||||
ccflags-y += -I$(CONFIG_GATOR_MALI_PATH)
|
||||
endif
|
||||
ccflags-$(CONFIG_GATOR_MALI_4XXMP) += -DMALI_SUPPORT=MALI_4xx
|
||||
ccflags-$(CONFIG_GATOR_MALI_T6XX) += -DMALI_SUPPORT=MALI_T6xx
|
||||
endif
|
||||
|
||||
# GATOR_TEST controls whether to include (=1) or exclude (=0) test code.
|
||||
@@ -44,22 +60,6 @@ gator-$(CONFIG_ARM) += gator_events_armv6.o \
|
||||
|
||||
gator-$(CONFIG_ARM64) += gator_events_ccn-504.o
|
||||
|
||||
$(obj)/gator_main.o: $(obj)/gator_events.h
|
||||
|
||||
clean-files := gator_events.h
|
||||
|
||||
# Note, in the recipe below we use "cd $(srctree) && cd $(src)" rather than
|
||||
# "cd $(srctree)/$(src)" because under DKMS $(src) is an absolute path, and we
|
||||
# can't just use $(src) because for normal kernel builds this is relative to
|
||||
# $(srctree)
|
||||
|
||||
chk_events.h = :
|
||||
quiet_chk_events.h = echo ' CHK $@'
|
||||
silent_chk_events.h = :
|
||||
$(obj)/gator_events.h: FORCE
|
||||
@$($(quiet)chk_events.h)
|
||||
$(Q)cd $(srctree) && cd $(src) ; $(CONFIG_SHELL) gator_events.sh $(abspath $@)
|
||||
|
||||
else
|
||||
|
||||
all:
|
||||
@@ -70,7 +70,7 @@ all:
|
||||
$(error)
|
||||
|
||||
clean:
|
||||
rm -f *.o .*.cmd gator_events.h modules.order Module.symvers gator.ko gator.mod.c
|
||||
rm -f *.o .*.cmd modules.order Module.symvers gator.ko gator.mod.c
|
||||
rm -rf .tmp_versions
|
||||
|
||||
endif
|
||||
|
||||
@@ -112,14 +112,10 @@ struct gator_interface {
|
||||
void (*offline_dispatch)(int cpu, bool migrate); // called in process context but may not be running on core 'cpu'
|
||||
int (*read)(int **buffer);
|
||||
int (*read64)(long long **buffer);
|
||||
int (*read_proc)(long long **buffer, struct task_struct *);
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
// gator_events_init is used as a search term in gator_events.sh
|
||||
#define gator_events_init(initfn) \
|
||||
static inline int __gator_events_init_test(void) \
|
||||
{ return initfn(); }
|
||||
|
||||
int gator_events_install(struct gator_interface *interface);
|
||||
int gator_events_get_key(void);
|
||||
u32 gator_cpuid(void);
|
||||
|
||||
@@ -29,11 +29,27 @@ static void kannotate_write(const char *ptr, unsigned int size)
|
||||
}
|
||||
}
|
||||
|
||||
static void marshal_u16(char *buf, u16 val) {
|
||||
buf[0] = val & 0xff;
|
||||
buf[1] = (val >> 8) & 0xff;
|
||||
}
|
||||
|
||||
static void marshal_u32(char *buf, u32 val) {
|
||||
buf[0] = val & 0xff;
|
||||
buf[1] = (val >> 8) & 0xff;
|
||||
buf[2] = (val >> 16) & 0xff;
|
||||
buf[3] = (val >> 24) & 0xff;
|
||||
}
|
||||
|
||||
void gator_annotate_channel(int channel, const char *str)
|
||||
{
|
||||
int str_size = strlen(str) & 0xffff;
|
||||
long long header = ESCAPE_CODE | (STRING_ANNOTATION << 8) | (channel << 16) | ((long long)str_size << 48);
|
||||
kannotate_write((char *)&header, sizeof(header));
|
||||
const u16 str_size = strlen(str) & 0xffff;
|
||||
char header[8];
|
||||
header[0] = ESCAPE_CODE;
|
||||
header[1] = STRING_ANNOTATION;
|
||||
marshal_u32(header + 2, channel);
|
||||
marshal_u16(header + 6, str_size);
|
||||
kannotate_write(header, sizeof(header));
|
||||
kannotate_write(str, str_size);
|
||||
}
|
||||
|
||||
@@ -48,14 +64,14 @@ EXPORT_SYMBOL(gator_annotate);
|
||||
|
||||
void gator_annotate_channel_color(int channel, int color, const char *str)
|
||||
{
|
||||
int str_size = (strlen(str) + 4) & 0xffff;
|
||||
const u16 str_size = (strlen(str) + 4) & 0xffff;
|
||||
char header[12];
|
||||
header[0] = ESCAPE_CODE;
|
||||
header[1] = STRING_ANNOTATION;
|
||||
*(u32 *)(&header[2]) = channel;
|
||||
*(u16 *)(&header[6]) = str_size;
|
||||
*(u32 *)(&header[8]) = color;
|
||||
kannotate_write((char *)&header, sizeof(header));
|
||||
marshal_u32(header + 2, channel);
|
||||
marshal_u16(header + 6, str_size);
|
||||
marshal_u32(header + 8, color);
|
||||
kannotate_write(header, sizeof(header));
|
||||
kannotate_write(str, str_size - 4);
|
||||
}
|
||||
|
||||
@@ -70,8 +86,12 @@ EXPORT_SYMBOL(gator_annotate_color);
|
||||
|
||||
void gator_annotate_channel_end(int channel)
|
||||
{
|
||||
long long header = ESCAPE_CODE | (STRING_ANNOTATION << 8) | (channel << 16);
|
||||
kannotate_write((char *)&header, sizeof(header));
|
||||
char header[8];
|
||||
header[0] = ESCAPE_CODE;
|
||||
header[1] = STRING_ANNOTATION;
|
||||
marshal_u32(header + 2, channel);
|
||||
marshal_u16(header + 6, 0);
|
||||
kannotate_write(header, sizeof(header));
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(gator_annotate_channel_end);
|
||||
@@ -85,14 +105,14 @@ EXPORT_SYMBOL(gator_annotate_end);
|
||||
|
||||
void gator_annotate_name_channel(int channel, int group, const char* str)
|
||||
{
|
||||
int str_size = strlen(str) & 0xffff;
|
||||
const u16 str_size = strlen(str) & 0xffff;
|
||||
char header[12];
|
||||
header[0] = ESCAPE_CODE;
|
||||
header[1] = NAME_CHANNEL_ANNOTATION;
|
||||
*(u32 *)(&header[2]) = channel;
|
||||
*(u32 *)(&header[6]) = group;
|
||||
*(u16 *)(&header[10]) = str_size;
|
||||
kannotate_write((char *)&header, sizeof(header));
|
||||
marshal_u32(header + 2, channel);
|
||||
marshal_u32(header + 6, group);
|
||||
marshal_u16(header + 10, str_size);
|
||||
kannotate_write(header, sizeof(header));
|
||||
kannotate_write(str, str_size);
|
||||
}
|
||||
|
||||
@@ -100,9 +120,13 @@ EXPORT_SYMBOL(gator_annotate_name_channel);
|
||||
|
||||
void gator_annotate_name_group(int group, const char* str)
|
||||
{
|
||||
int str_size = strlen(str) & 0xffff;
|
||||
long long header = ESCAPE_CODE | (NAME_GROUP_ANNOTATION << 8) | (group << 16) | ((long long)str_size << 48);
|
||||
kannotate_write((char *)&header, sizeof(header));
|
||||
const u16 str_size = strlen(str) & 0xffff;
|
||||
char header[8];
|
||||
header[0] = ESCAPE_CODE;
|
||||
header[1] = NAME_GROUP_ANNOTATION;
|
||||
marshal_u32(header + 2, group);
|
||||
marshal_u16(header + 6, str_size);
|
||||
kannotate_write(header, sizeof(header));
|
||||
kannotate_write(str, str_size);
|
||||
}
|
||||
|
||||
@@ -110,11 +134,16 @@ EXPORT_SYMBOL(gator_annotate_name_group);
|
||||
|
||||
void gator_annotate_visual(const char *data, unsigned int length, const char *str)
|
||||
{
|
||||
int str_size = strlen(str) & 0xffff;
|
||||
int visual_annotation = ESCAPE_CODE | (VISUAL_ANNOTATION << 8) | (str_size << 16);
|
||||
kannotate_write((char *)&visual_annotation, sizeof(visual_annotation));
|
||||
const u16 str_size = strlen(str) & 0xffff;
|
||||
char header[4];
|
||||
char header_length[4];
|
||||
header[0] = ESCAPE_CODE;
|
||||
header[1] = VISUAL_ANNOTATION;
|
||||
marshal_u16(header + 2, str_size);
|
||||
marshal_u32(header_length, length);
|
||||
kannotate_write(header, sizeof(header));
|
||||
kannotate_write(str, str_size);
|
||||
kannotate_write((char *)&length, sizeof(length));
|
||||
kannotate_write(header_length, sizeof(header_length));
|
||||
kannotate_write(data, length);
|
||||
}
|
||||
|
||||
@@ -122,17 +151,23 @@ EXPORT_SYMBOL(gator_annotate_visual);
|
||||
|
||||
void gator_annotate_marker(void)
|
||||
{
|
||||
int header = ESCAPE_CODE | (MARKER_ANNOTATION << 8);
|
||||
kannotate_write((char *)&header, sizeof(header));
|
||||
char header[4];
|
||||
header[0] = ESCAPE_CODE;
|
||||
header[1] = MARKER_ANNOTATION;
|
||||
marshal_u16(header + 2, 0);
|
||||
kannotate_write(header, sizeof(header));
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(gator_annotate_marker);
|
||||
|
||||
void gator_annotate_marker_str(const char *str)
|
||||
{
|
||||
int str_size = strlen(str) & 0xffff;
|
||||
int header = ESCAPE_CODE | (MARKER_ANNOTATION << 8) | (str_size << 16);
|
||||
kannotate_write((char *)&header, sizeof(header));
|
||||
const u16 str_size = strlen(str) & 0xffff;
|
||||
char header[4];
|
||||
header[0] = ESCAPE_CODE;
|
||||
header[1] = MARKER_ANNOTATION;
|
||||
marshal_u16(header + 2, str_size);
|
||||
kannotate_write(header, sizeof(header));
|
||||
kannotate_write(str, str_size);
|
||||
}
|
||||
|
||||
@@ -140,17 +175,25 @@ EXPORT_SYMBOL(gator_annotate_marker_str);
|
||||
|
||||
void gator_annotate_marker_color(int color)
|
||||
{
|
||||
long long header = (ESCAPE_CODE | (MARKER_ANNOTATION << 8) | 0x00040000 | ((long long)color << 32));
|
||||
kannotate_write((char *)&header, sizeof(header));
|
||||
char header[8];
|
||||
header[0] = ESCAPE_CODE;
|
||||
header[1] = MARKER_ANNOTATION;
|
||||
marshal_u16(header + 2, 4);
|
||||
marshal_u32(header + 4, color);
|
||||
kannotate_write(header, sizeof(header));
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(gator_annotate_marker_color);
|
||||
|
||||
void gator_annotate_marker_color_str(int color, const char *str)
|
||||
{
|
||||
int str_size = (strlen(str) + 4) & 0xffff;
|
||||
long long header = ESCAPE_CODE | (MARKER_ANNOTATION << 8) | (str_size << 16) | ((long long)color << 32);
|
||||
kannotate_write((char *)&header, sizeof(header));
|
||||
const u16 str_size = (strlen(str) + 4) & 0xffff;
|
||||
char header[8];
|
||||
header[0] = ESCAPE_CODE;
|
||||
header[1] = MARKER_ANNOTATION;
|
||||
marshal_u16(header + 2, str_size);
|
||||
marshal_u32(header + 4, color);
|
||||
kannotate_write(header, sizeof(header));
|
||||
kannotate_write(str, str_size - 4);
|
||||
}
|
||||
|
||||
|
||||
@@ -132,13 +132,21 @@ static int report_trace(struct stackframe *frame, void *d)
|
||||
|
||||
// Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile
|
||||
// #define GATOR_KERNEL_STACK_UNWINDING
|
||||
|
||||
#if (defined(__arm__) || defined(__aarch64__)) && !defined(GATOR_KERNEL_STACK_UNWINDING)
|
||||
// Disabled by default
|
||||
MODULE_PARM_DESC(kernel_stack_unwinding, "Allow kernel stack unwinding.");
|
||||
bool kernel_stack_unwinding = 0;
|
||||
module_param(kernel_stack_unwinding, bool, 0644);
|
||||
#endif
|
||||
|
||||
static void kernel_backtrace(int cpu, struct pt_regs *const regs)
|
||||
{
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
#ifdef GATOR_KERNEL_STACK_UNWINDING
|
||||
int depth = gator_backtrace_depth;
|
||||
#else
|
||||
int depth = 1;
|
||||
int depth = (kernel_stack_unwinding ? gator_backtrace_depth : 1);
|
||||
#endif
|
||||
struct stackframe frame;
|
||||
if (depth == 0)
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
*/
|
||||
|
||||
#define COOKIEMAP_ENTRIES 1024 /* must be power of 2 */
|
||||
#define TRANSLATE_SIZE 256
|
||||
#define TRANSLATE_BUFFER_SIZE 512 // must be a power of 2 - 512/4 = 128 entries
|
||||
#define TRANSLATE_TEXT_SIZE 256
|
||||
#define MAX_COLLISIONS 2
|
||||
|
||||
static uint32_t *gator_crc32_table;
|
||||
@@ -22,7 +23,7 @@ static DEFINE_PER_CPU(int, translate_buffer_read);
|
||||
static DEFINE_PER_CPU(int, translate_buffer_write);
|
||||
static DEFINE_PER_CPU(void **, translate_buffer);
|
||||
|
||||
static inline uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq);
|
||||
static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq);
|
||||
static void wq_cookie_handler(struct work_struct *unused);
|
||||
DECLARE_WORK(cookie_work, wq_cookie_handler);
|
||||
static struct timer_list app_process_wake_up_timer;
|
||||
@@ -107,11 +108,13 @@ static void cookiemap_add(uint64_t key, uint32_t value)
|
||||
values[0] = value;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PREEMPT_RT_FULL
|
||||
static void translate_buffer_write_ptr(int cpu, void *x)
|
||||
{
|
||||
per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_write, cpu)++] = x;
|
||||
per_cpu(translate_buffer_write, cpu) &= translate_buffer_mask;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void *translate_buffer_read_ptr(int cpu)
|
||||
{
|
||||
@@ -124,7 +127,7 @@ static void wq_cookie_handler(struct work_struct *unused)
|
||||
{
|
||||
struct task_struct *task;
|
||||
char *text;
|
||||
int cpu = get_physical_cpu();
|
||||
int cpu = get_physical_cpu(), cookie;
|
||||
unsigned int commit;
|
||||
|
||||
mutex_lock(&start_mutex);
|
||||
@@ -134,7 +137,8 @@ static void wq_cookie_handler(struct work_struct *unused)
|
||||
while (per_cpu(translate_buffer_read, cpu) != commit) {
|
||||
task = (struct task_struct *)translate_buffer_read_ptr(cpu);
|
||||
text = (char *)translate_buffer_read_ptr(cpu);
|
||||
get_cookie(cpu, task, text, true);
|
||||
cookie = get_cookie(cpu, task, text, true);
|
||||
marshal_link(cookie, task->tgid, task->pid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,15 +160,16 @@ static int translate_app_process(const char **text, int cpu, struct task_struct
|
||||
struct mm_struct *mm;
|
||||
struct page *page = NULL;
|
||||
struct vm_area_struct *page_vma;
|
||||
int bytes, offset, retval = 0, ptr;
|
||||
int bytes, offset, retval = 0;
|
||||
char *buf = per_cpu(translate_text, cpu);
|
||||
|
||||
#ifndef CONFIG_PREEMPT_RT_FULL
|
||||
// Push work into a work queue if in atomic context as the kernel functions below might sleep
|
||||
// Rely on the in_interrupt variable rather than in_irq() or in_interrupt() kernel functions, as the value of these functions seems
|
||||
// inconsistent during a context switch between android/linux versions
|
||||
if (!from_wq) {
|
||||
// Check if already in buffer
|
||||
ptr = per_cpu(translate_buffer_read, cpu);
|
||||
int ptr = per_cpu(translate_buffer_read, cpu);
|
||||
while (ptr != per_cpu(translate_buffer_write, cpu)) {
|
||||
if (per_cpu(translate_buffer, cpu)[ptr] == (void *)task)
|
||||
goto out;
|
||||
@@ -174,9 +179,11 @@ static int translate_app_process(const char **text, int cpu, struct task_struct
|
||||
translate_buffer_write_ptr(cpu, (void *)task);
|
||||
translate_buffer_write_ptr(cpu, (void *)*text);
|
||||
|
||||
// Not safe to call in RT-Preempt full in schedule switch context
|
||||
mod_timer(&app_process_wake_up_timer, jiffies + 1);
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
mm = get_task_mm(task);
|
||||
if (!mm)
|
||||
@@ -186,8 +193,8 @@ static int translate_app_process(const char **text, int cpu, struct task_struct
|
||||
addr = mm->arg_start;
|
||||
len = mm->arg_end - mm->arg_start;
|
||||
|
||||
if (len > TRANSLATE_SIZE)
|
||||
len = TRANSLATE_SIZE;
|
||||
if (len > TRANSLATE_TEXT_SIZE)
|
||||
len = TRANSLATE_TEXT_SIZE;
|
||||
|
||||
down_read(&mm->mmap_sem);
|
||||
while (len) {
|
||||
@@ -225,7 +232,7 @@ out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static inline uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq)
|
||||
static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq)
|
||||
{
|
||||
unsigned long flags, cookie;
|
||||
uint64_t key;
|
||||
@@ -312,8 +319,7 @@ static int cookies_initialize(void)
|
||||
uint32_t crc, poly;
|
||||
int i, j, cpu, size, err = 0;
|
||||
|
||||
int translate_buffer_size = 512; // must be a power of 2
|
||||
translate_buffer_mask = translate_buffer_size / sizeof(per_cpu(translate_buffer, 0)[0]) - 1;
|
||||
translate_buffer_mask = TRANSLATE_BUFFER_SIZE / sizeof(per_cpu(translate_buffer, 0)[0]) - 1;
|
||||
|
||||
for_each_present_cpu(cpu) {
|
||||
per_cpu(cookie_next_key, cpu) = nr_cpu_ids + cpu;
|
||||
@@ -334,7 +340,7 @@ static int cookies_initialize(void)
|
||||
}
|
||||
memset(per_cpu(cookie_values, cpu), 0, size);
|
||||
|
||||
per_cpu(translate_buffer, cpu) = (void **)kmalloc(translate_buffer_size, GFP_KERNEL);
|
||||
per_cpu(translate_buffer, cpu) = (void **)kmalloc(TRANSLATE_BUFFER_SIZE, GFP_KERNEL);
|
||||
if (!per_cpu(translate_buffer, cpu)) {
|
||||
err = -ENOMEM;
|
||||
goto cookie_setup_error;
|
||||
@@ -343,7 +349,7 @@ static int cookies_initialize(void)
|
||||
per_cpu(translate_buffer_write, cpu) = 0;
|
||||
per_cpu(translate_buffer_read, cpu) = 0;
|
||||
|
||||
per_cpu(translate_text, cpu) = (char *)kmalloc(TRANSLATE_SIZE, GFP_KERNEL);
|
||||
per_cpu(translate_text, cpu) = (char *)kmalloc(TRANSLATE_TEXT_SIZE, GFP_KERNEL);
|
||||
if (!per_cpu(translate_text, cpu)) {
|
||||
err = -ENOMEM;
|
||||
goto cookie_setup_error;
|
||||
@@ -353,6 +359,10 @@ static int cookies_initialize(void)
|
||||
// build CRC32 table
|
||||
poly = 0x04c11db7;
|
||||
gator_crc32_table = (uint32_t *)kmalloc(256 * sizeof(uint32_t), GFP_KERNEL);
|
||||
if (!gator_crc32_table) {
|
||||
err = -ENOMEM;
|
||||
goto cookie_setup_error;
|
||||
}
|
||||
for (i = 0; i < 256; i++) {
|
||||
crc = i;
|
||||
for (j = 8; j > 0; j--) {
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
EVENTS=`grep gator_events_init *.c | sed 's/.\+gator_events_init(\(.\+\)).\+/\1/'`
|
||||
|
||||
(
|
||||
echo /\* This file is auto generated \*/
|
||||
echo
|
||||
for EVENT in $EVENTS; do
|
||||
echo __weak int $EVENT\(void\)\;
|
||||
done
|
||||
echo
|
||||
echo static int \(*gator_events_list[]\)\(void\) = {
|
||||
for EVENT in $EVENTS; do
|
||||
echo \ $EVENT,
|
||||
done
|
||||
echo }\;
|
||||
) > $1.tmp
|
||||
|
||||
cmp -s $1 $1.tmp && rm $1.tmp || mv $1.tmp $1
|
||||
@@ -234,11 +234,4 @@ int gator_events_armv6_init(void)
|
||||
return gator_events_install(&gator_events_armv6_interface);
|
||||
}
|
||||
|
||||
gator_events_init(gator_events_armv6_init);
|
||||
|
||||
#else
|
||||
int gator_events_armv6_init(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -309,11 +309,4 @@ int gator_events_armv7_init(void)
|
||||
return gator_events_install(&gator_events_armv7_interface);
|
||||
}
|
||||
|
||||
gator_events_init(gator_events_armv7_init);
|
||||
|
||||
#else
|
||||
int gator_events_armv7_init(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -151,5 +151,3 @@ int gator_events_block_init(void)
|
||||
|
||||
return gator_events_install(&gator_events_block_interface);
|
||||
}
|
||||
|
||||
gator_events_init(gator_events_block_init);
|
||||
|
||||
@@ -6,23 +6,16 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* WARNING: This code is an experimental implementation of the CCN-504 hardware
|
||||
* counters which has not been tested on the hardware. Commented debug
|
||||
* statements are present and can be uncommented for diagnostic purposes.
|
||||
******************************************************************************/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "gator.h"
|
||||
|
||||
#define PERIPHBASE 0x2E000000
|
||||
|
||||
#define NUM_REGIONS 256
|
||||
#define REGION_SIZE (64*1024)
|
||||
#define REGION_DEBUG 1
|
||||
#define REGION_XP 64
|
||||
#define NUM_XPS 11
|
||||
|
||||
// DT (Debug) region
|
||||
#define PMEVCNTSR0 0x0150
|
||||
@@ -34,27 +27,86 @@
|
||||
|
||||
// XP region
|
||||
#define DT_CONFIG 0x0300
|
||||
#define DT_CONTROL 0x0370
|
||||
|
||||
// Multiple
|
||||
#define PMU_EVENT_SEL 0x0600
|
||||
#define OLY_ID 0xFF00
|
||||
|
||||
#define CCNT 4
|
||||
#define CNTMAX (4 + 1)
|
||||
#define CNTMAX (CCNT + 1)
|
||||
|
||||
#define get_pmu_event_id(event) (((event) >> 0) & 0xFF)
|
||||
#define get_node_type(event) (((event) >> 8) & 0xFF)
|
||||
#define get_region(event) (((event) >> 16) & 0xFF)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
|
||||
|
||||
// From kernel/params.c
|
||||
#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \
|
||||
int param_set_##name(const char *val, struct kernel_param *kp) \
|
||||
{ \
|
||||
tmptype l; \
|
||||
int ret; \
|
||||
\
|
||||
if (!val) return -EINVAL; \
|
||||
ret = strtolfn(val, 0, &l); \
|
||||
if (ret == -EINVAL || ((type)l != l)) \
|
||||
return -EINVAL; \
|
||||
*((type *)kp->arg) = l; \
|
||||
return 0; \
|
||||
} \
|
||||
int param_get_##name(char *buffer, struct kernel_param *kp) \
|
||||
{ \
|
||||
return sprintf(buffer, format, *((type *)kp->arg)); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// From kernel/params.c
|
||||
#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \
|
||||
int param_set_##name(const char *val, const struct kernel_param *kp) \
|
||||
{ \
|
||||
tmptype l; \
|
||||
int ret; \
|
||||
\
|
||||
ret = strtolfn(val, 0, &l); \
|
||||
if (ret < 0 || ((type)l != l)) \
|
||||
return ret < 0 ? ret : -EINVAL; \
|
||||
*((type *)kp->arg) = l; \
|
||||
return 0; \
|
||||
} \
|
||||
int param_get_##name(char *buffer, const struct kernel_param *kp) \
|
||||
{ \
|
||||
return scnprintf(buffer, PAGE_SIZE, format, \
|
||||
*((type *)kp->arg)); \
|
||||
} \
|
||||
struct kernel_param_ops param_ops_##name = { \
|
||||
.set = param_set_##name, \
|
||||
.get = param_get_##name, \
|
||||
}; \
|
||||
EXPORT_SYMBOL(param_set_##name); \
|
||||
EXPORT_SYMBOL(param_get_##name); \
|
||||
EXPORT_SYMBOL(param_ops_##name)
|
||||
|
||||
#endif
|
||||
|
||||
STANDARD_PARAM_DEF(u64, u64, "%llu", u64, strict_strtoull);
|
||||
|
||||
// From include/linux/moduleparam.h
|
||||
#define param_check_u64(name, p) __param_check(name, p, u64)
|
||||
|
||||
MODULE_PARM_DESC(ccn504_addr, "CCN-504 physical base address");
|
||||
static unsigned long ccn504_addr = 0;
|
||||
module_param(ccn504_addr, ulong, 0444);
|
||||
static u64 ccn504_addr = 0;
|
||||
module_param(ccn504_addr, u64, 0444);
|
||||
|
||||
static void __iomem *gator_events_ccn504_base;
|
||||
static bool gator_events_ccn504_global_enabled;
|
||||
static unsigned long gator_events_ccn504_enabled[CNTMAX];
|
||||
static unsigned long gator_events_ccn504_event[CNTMAX];
|
||||
static unsigned long gator_events_ccn504_key[CNTMAX];
|
||||
static int gator_events_ccn504_buffer[2*CNTMAX];
|
||||
static int gator_events_ccn504_prev[CNTMAX];
|
||||
|
||||
static void gator_events_ccn504_create_shutdown(void)
|
||||
{
|
||||
@@ -96,7 +148,6 @@ static void gator_events_ccn504_set_dt_config(int xp_node_id, int event_num, int
|
||||
|
||||
dt_config = readl(gator_events_ccn504_base + (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG);
|
||||
dt_config |= (value + event_num) << (4*event_num);
|
||||
//printk(KERN_ERR "%s(%s:%i) writel %x %x\n", __FUNCTION__, __FILE__, __LINE__, dt_config, (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG);
|
||||
writel(dt_config, gator_events_ccn504_base + (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG);
|
||||
}
|
||||
|
||||
@@ -104,6 +155,20 @@ static int gator_events_ccn504_start(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
gator_events_ccn504_global_enabled = 0;
|
||||
for (i = 0; i < CNTMAX; ++i) {
|
||||
if (gator_events_ccn504_enabled[i]) {
|
||||
gator_events_ccn504_global_enabled = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!gator_events_ccn504_global_enabled) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&gator_events_ccn504_prev, 0x80, sizeof(gator_events_ccn504_prev));
|
||||
|
||||
// Disable INTREQ on overflow
|
||||
// [6] ovfl_intr_en = 0
|
||||
// perhaps set to 1?
|
||||
@@ -112,9 +177,22 @@ static int gator_events_ccn504_start(void)
|
||||
// [4:1] cntcfg = 0
|
||||
// Enable PMU features
|
||||
// [0] pmu_en = 1
|
||||
//printk(KERN_ERR "%s(%s:%i) writel %x %x\n", __FUNCTION__, __FILE__, __LINE__, 0x1, REGION_DEBUG*REGION_SIZE + PMCR);
|
||||
writel(0x1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMCR);
|
||||
|
||||
// Configure the XPs
|
||||
for (i = 0; i < NUM_XPS; ++i) {
|
||||
int dt_control;
|
||||
|
||||
// Pass on all events
|
||||
writel(0, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONFIG);
|
||||
|
||||
// Enable PMU capability
|
||||
// [0] dt_enable = 1
|
||||
dt_control = readl(gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONTROL);
|
||||
dt_control |= 0x1;
|
||||
writel(dt_control, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONTROL);
|
||||
}
|
||||
|
||||
// Assume no other pmu_event_sel registers are set
|
||||
|
||||
// cycle counter does not need to be enabled
|
||||
@@ -134,15 +212,14 @@ static int gator_events_ccn504_start(void)
|
||||
pmu_event_id = get_pmu_event_id(gator_events_ccn504_event[i]);
|
||||
node_type = get_node_type(gator_events_ccn504_event[i]);
|
||||
region = get_region(gator_events_ccn504_event[i]);
|
||||
//printk(KERN_ERR "%s(%s:%i) pmu_event_id: %x node_type: %x region: %x\n", __FUNCTION__, __FILE__, __LINE__, pmu_event_id, node_type, region);
|
||||
|
||||
// Verify the node_type
|
||||
oly_id_whole = readl(gator_events_ccn504_base + region*REGION_SIZE + OLY_ID);
|
||||
oly_id = oly_id_whole & 0x1F;
|
||||
node_id = (oly_id_whole >> 8) & 0x7F;
|
||||
if ((oly_id != node_type) ||
|
||||
((node_type == 0x16) && ((oly_id == 0x14) || (oly_id == 0x15) || (oly_id == 0x16) || (oly_id == 0x18) || (oly_id == 0x19) || (oly_id == 0x1A)))) {
|
||||
printk(KERN_ERR "%s(%s:%i) oly_id is %x expected %x\n", __FUNCTION__, __FILE__, __LINE__, oly_id, node_type);
|
||||
((node_type == 0x16) && ((oly_id != 0x14) && (oly_id != 0x15) && (oly_id != 0x16) && (oly_id != 0x18) && (oly_id != 0x19) && (oly_id != 0x1A)))) {
|
||||
printk(KERN_ERR "gator: oly_id is 0x%x expected 0x%x\n", oly_id, node_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -160,7 +237,6 @@ static int gator_events_ccn504_start(void)
|
||||
gator_events_ccn504_set_dt_config(node_id/2, i, (node_id & 1) == 0 ? 0x8 : 0xC);
|
||||
break;
|
||||
}
|
||||
//printk(KERN_ERR "%s(%s:%i) writel %x %x\n", __FUNCTION__, __FILE__, __LINE__, pmu_event_sel, region*REGION_SIZE + PMU_EVENT_SEL);
|
||||
writel(pmu_event_sel, gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL);
|
||||
}
|
||||
|
||||
@@ -171,21 +247,25 @@ static void gator_events_ccn504_stop(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!gator_events_ccn504_global_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// cycle counter does not need to be disabled
|
||||
for (i = 0; i < CCNT; ++i) {
|
||||
int node_type;
|
||||
int region;
|
||||
|
||||
node_type = get_node_type(gator_events_ccn504_event[i]);
|
||||
if (!gator_events_ccn504_enabled[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
region = get_region(gator_events_ccn504_event[i]);
|
||||
|
||||
//printk(KERN_ERR "%s(%s:%i) writel %x %x\n", __FUNCTION__, __FILE__, __LINE__, 0, region*REGION_SIZE + PMU_EVENT_SEL);
|
||||
writel(0, gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL);
|
||||
}
|
||||
|
||||
// Clear dt_config
|
||||
for (i = 0; i < 11; ++i) {
|
||||
//printk(KERN_ERR "%s(%s:%i) writel %x %x\n", __FUNCTION__, __FILE__, __LINE__, 0, (REGION_XP + i)*REGION_SIZE + DT_CONFIG);
|
||||
for (i = 0; i < NUM_XPS; ++i) {
|
||||
writel(0, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONFIG);
|
||||
}
|
||||
}
|
||||
@@ -194,27 +274,20 @@ static int gator_events_ccn504_read(int **buffer)
|
||||
{
|
||||
int i;
|
||||
int len = 0;
|
||||
int value;
|
||||
|
||||
if (!on_primary_core()) {
|
||||
if (!on_primary_core() || !gator_events_ccn504_global_enabled) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Verify the pmsr register is zero
|
||||
//i = 0;
|
||||
while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) != 0) {
|
||||
//++i;
|
||||
}
|
||||
//printk(KERN_ERR "%s(%s:%i) %i\n", __FUNCTION__, __FILE__, __LINE__, i);
|
||||
while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) != 0);
|
||||
|
||||
// Request a PMU snapshot
|
||||
writel(1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR_REQ);
|
||||
|
||||
// Wait for the snapshot
|
||||
//i = 0;
|
||||
while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) == 0) {
|
||||
//++i;
|
||||
}
|
||||
//printk(KERN_ERR "%s(%s:%i) %i\n", __FUNCTION__, __FILE__, __LINE__, i);
|
||||
while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) == 0);
|
||||
|
||||
// Read the shadow registers
|
||||
for (i = 0; i < CNTMAX; ++i) {
|
||||
@@ -222,8 +295,12 @@ static int gator_events_ccn504_read(int **buffer)
|
||||
continue;
|
||||
}
|
||||
|
||||
gator_events_ccn504_buffer[len++] = gator_events_ccn504_key[i];
|
||||
gator_events_ccn504_buffer[len++] = readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + (i == CCNT ? PMCCNTRSR : PMEVCNTSR0 + 8*i));
|
||||
value = readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + (i == CCNT ? PMCCNTRSR : PMEVCNTSR0 + 8*i));
|
||||
if (gator_events_ccn504_prev[i] != 0x80808080) {
|
||||
gator_events_ccn504_buffer[len++] = gator_events_ccn504_key[i];
|
||||
gator_events_ccn504_buffer[len++] = value - gator_events_ccn504_prev[i];
|
||||
}
|
||||
gator_events_ccn504_prev[i] = value;
|
||||
|
||||
// Are the counters registers cleared when read? Is that what the cntr_rst bit on the pmcr register does?
|
||||
}
|
||||
@@ -231,20 +308,12 @@ static int gator_events_ccn504_read(int **buffer)
|
||||
// Clear the PMU snapshot status
|
||||
writel(1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR_CLR);
|
||||
|
||||
if (buffer)
|
||||
*buffer = gator_events_ccn504_buffer;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void __maybe_unused gator_events_ccn504_enumerate(int pos, int size)
|
||||
{
|
||||
int i;
|
||||
u32 oly_id;
|
||||
|
||||
for (i = pos; i < pos + size; ++i) {
|
||||
oly_id = readl(gator_events_ccn504_base + i*REGION_SIZE + OLY_ID);
|
||||
printk(KERN_ERR "%s(%s:%i) %i %08x\n", __FUNCTION__, __FILE__, __LINE__, i, oly_id);
|
||||
}
|
||||
}
|
||||
|
||||
static struct gator_interface gator_events_ccn504_interface = {
|
||||
.shutdown = gator_events_ccn504_create_shutdown,
|
||||
.create_files = gator_events_ccn504_create_files,
|
||||
@@ -263,36 +332,9 @@ int gator_events_ccn504_init(void)
|
||||
|
||||
gator_events_ccn504_base = ioremap(ccn504_addr, NUM_REGIONS*REGION_SIZE);
|
||||
if (gator_events_ccn504_base == NULL) {
|
||||
printk(KERN_ERR "%s(%s:%i) ioremap returned NULL\n", __FUNCTION__, __FILE__, __LINE__);
|
||||
printk(KERN_ERR "gator: ioremap returned NULL\n");
|
||||
return -1;
|
||||
}
|
||||
//printk(KERN_ERR "%s(%s:%i)\n", __FUNCTION__, __FILE__, __LINE__);
|
||||
|
||||
// Test - can memory be read
|
||||
{
|
||||
//gator_events_ccn504_enumerate(0, NUM_REGIONS);
|
||||
|
||||
#if 0
|
||||
// DT
|
||||
gator_events_ccn504_enumerate(1, 1);
|
||||
// HN-F
|
||||
gator_events_ccn504_enumerate(32, 8);
|
||||
// XP
|
||||
gator_events_ccn504_enumerate(64, 11);
|
||||
// RN-I
|
||||
gator_events_ccn504_enumerate(128, 1);
|
||||
gator_events_ccn504_enumerate(130, 1);
|
||||
gator_events_ccn504_enumerate(134, 1);
|
||||
gator_events_ccn504_enumerate(140, 1);
|
||||
gator_events_ccn504_enumerate(144, 1);
|
||||
gator_events_ccn504_enumerate(148, 1);
|
||||
// SBAS
|
||||
gator_events_ccn504_enumerate(129, 1);
|
||||
gator_events_ccn504_enumerate(137, 1);
|
||||
gator_events_ccn504_enumerate(139, 1);
|
||||
gator_events_ccn504_enumerate(147, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
for (i = 0; i < CNTMAX; ++i) {
|
||||
gator_events_ccn504_enabled[i] = 0;
|
||||
@@ -302,5 +344,3 @@ int gator_events_ccn504_init(void)
|
||||
|
||||
return gator_events_install(&gator_events_ccn504_interface);
|
||||
}
|
||||
|
||||
gator_events_init(gator_events_ccn504_init);
|
||||
|
||||
@@ -163,5 +163,3 @@ int gator_events_irq_init(void)
|
||||
|
||||
return gator_events_install(&gator_events_irq_interface);
|
||||
}
|
||||
|
||||
gator_events_init(gator_events_irq_init);
|
||||
|
||||
@@ -206,5 +206,3 @@ int gator_events_l2c310_init(void)
|
||||
|
||||
return gator_events_install(&gator_events_l2c310_interface);
|
||||
}
|
||||
|
||||
gator_events_init(gator_events_l2c310_init);
|
||||
|
||||
@@ -415,25 +415,12 @@ static void mali_counter_initialize(void)
|
||||
int i;
|
||||
int core_id;
|
||||
|
||||
mali_osk_fb_control_set_type *mali_set_fb_event;
|
||||
mali_profiling_control_type *mali_control;
|
||||
|
||||
init_counters(COUNTER_L2_0_C0, COUNTER_L2_0_C0 + (2 * n_l2_cores) - 1);
|
||||
init_counters(COUNTER_VP_0_C0, COUNTER_VP_0_C0 + (2 * n_vp_cores) - 1);
|
||||
init_counters(COUNTER_FP_0_C0, COUNTER_FP_0_C0 + (2 * n_fp_cores) - 1);
|
||||
|
||||
mali_set_fb_event = symbol_get(_mali_osk_fb_control_set);
|
||||
|
||||
if (mali_set_fb_event) {
|
||||
pr_debug("gator: mali online _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event);
|
||||
|
||||
mali_set_fb_event(0, (counter_enabled[COUNTER_FILMSTRIP] ? 1 : 0));
|
||||
|
||||
symbol_put(_mali_osk_fb_control_set);
|
||||
} else {
|
||||
printk("gator: mali online _mali_osk_fb_control_set symbol not found\n");
|
||||
}
|
||||
|
||||
/* Generic control interface for Mali DDK. */
|
||||
mali_control = symbol_get(_mali_profiling_control);
|
||||
if (mali_control) {
|
||||
@@ -491,7 +478,6 @@ static void mali_counter_initialize(void)
|
||||
static void mali_counter_deinitialize(void)
|
||||
{
|
||||
mali_profiling_set_event_type *mali_set_hw_event;
|
||||
mali_osk_fb_control_set_type *mali_set_fb_event;
|
||||
mali_profiling_control_type *mali_control;
|
||||
|
||||
mali_set_hw_event = symbol_get(_mali_profiling_set_event);
|
||||
@@ -509,23 +495,11 @@ static void mali_counter_deinitialize(void)
|
||||
printk("gator: mali offline _mali_profiling_set_event symbol not found\n");
|
||||
}
|
||||
|
||||
mali_set_fb_event = symbol_get(_mali_osk_fb_control_set);
|
||||
|
||||
if (mali_set_fb_event) {
|
||||
pr_debug("gator: mali offline _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event);
|
||||
|
||||
mali_set_fb_event(0, 0);
|
||||
|
||||
symbol_put(_mali_osk_fb_control_set);
|
||||
} else {
|
||||
printk("gator: mali offline _mali_osk_fb_control_set symbol not found\n");
|
||||
}
|
||||
|
||||
/* Generic control interface for Mali DDK. */
|
||||
mali_control = symbol_get(_mali_profiling_control);
|
||||
|
||||
if (mali_control) {
|
||||
pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_set_fb_event);
|
||||
pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_control);
|
||||
|
||||
/* Reset the DDK state - disable counter collection */
|
||||
mali_control(SW_COUNTER_ENABLE, 0);
|
||||
@@ -747,5 +721,3 @@ int gator_events_mali_init(void)
|
||||
|
||||
return gator_events_install(&gator_events_mali_interface);
|
||||
}
|
||||
|
||||
gator_events_init(gator_events_mali_init);
|
||||
|
||||
@@ -28,7 +28,7 @@ extern const char *gator_mali_get_mali_name(void)
|
||||
}
|
||||
}
|
||||
|
||||
extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, mali_counter *counter)
|
||||
extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, mali_counter *counter, unsigned long *event)
|
||||
{
|
||||
int err;
|
||||
char buf[255];
|
||||
@@ -56,6 +56,13 @@ extern int gator_mali_create_file_system(const char *mali_name, const char *even
|
||||
pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ro_ulong for: %s (%s)", event_name, buf);
|
||||
return -1;
|
||||
}
|
||||
if (event != NULL) {
|
||||
err = gatorfs_create_ulong(sb, dir, "event", event);
|
||||
if (err != 0) {
|
||||
pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ro_ulong for: %s (%s)", event_name, buf);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -43,7 +43,6 @@ typedef struct {
|
||||
* Mali-4xx
|
||||
*/
|
||||
typedef int mali_profiling_set_event_type(unsigned int, int);
|
||||
typedef void mali_osk_fb_control_set_type(unsigned int, unsigned int);
|
||||
typedef void mali_profiling_control_type(unsigned int, unsigned int);
|
||||
typedef void mali_profiling_get_counters_type(unsigned int *, unsigned int *, unsigned int *, unsigned int *);
|
||||
|
||||
@@ -51,7 +50,6 @@ typedef void mali_profiling_get_counters_type(unsigned int *, unsigned int *, un
|
||||
* Driver entry points for functions called directly by gator.
|
||||
*/
|
||||
extern int _mali_profiling_set_event(unsigned int, int);
|
||||
extern void _mali_osk_fb_control_set(unsigned int, unsigned int);
|
||||
extern void _mali_profiling_control(unsigned int, unsigned int);
|
||||
extern void _mali_profiling_get_counters(unsigned int *, unsigned int *, unsigned int *, unsigned int *);
|
||||
|
||||
@@ -75,7 +73,7 @@ extern const char *gator_mali_get_mali_name(void);
|
||||
*
|
||||
* @return 0 if entry point was created, non-zero if not.
|
||||
*/
|
||||
extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, mali_counter *counter);
|
||||
extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, mali_counter *counter, unsigned long *event);
|
||||
|
||||
/**
|
||||
* Initializes the counter array.
|
||||
|
||||
@@ -109,12 +109,14 @@ enum {
|
||||
#define NUMBER_OF_SOFTWARE_COUNTERS (sizeof(software_counter_names) / sizeof(software_counter_names[0]))
|
||||
#define FIRST_ACCUMULATOR (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS)
|
||||
#define NUMBER_OF_ACCUMULATORS (sizeof(accumulators_names) / sizeof(accumulators_names[0]))
|
||||
#define NUMBER_OF_EVENTS (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS)
|
||||
#define FILMSTRIP (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS)
|
||||
#define NUMBER_OF_EVENTS (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS + 1)
|
||||
|
||||
/*
|
||||
* gatorfs variables for counter enable state
|
||||
*/
|
||||
static mali_counter counters[NUMBER_OF_EVENTS];
|
||||
static unsigned long filmstrip_event;
|
||||
|
||||
/* An array used to return the data we recorded
|
||||
* as key,value pairs hence the *2
|
||||
@@ -285,28 +287,37 @@ static int create_files(struct super_block *sb, struct dentry *root)
|
||||
*/
|
||||
int counter_index = 0;
|
||||
const char *mali_name = gator_mali_get_mali_name();
|
||||
mali_profiling_control_type *mali_control;
|
||||
|
||||
for (event = FIRST_TIMELINE_EVENT; event < FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS; event++) {
|
||||
if (gator_mali_create_file_system(mali_name, timeline_event_names[counter_index], sb, root, &counters[event]) != 0) {
|
||||
if (gator_mali_create_file_system(mali_name, timeline_event_names[counter_index], sb, root, &counters[event], NULL) != 0) {
|
||||
return -1;
|
||||
}
|
||||
counter_index++;
|
||||
}
|
||||
counter_index = 0;
|
||||
for (event = FIRST_SOFTWARE_COUNTER; event < FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS; event++) {
|
||||
if (gator_mali_create_file_system(mali_name, software_counter_names[counter_index], sb, root, &counters[event]) != 0) {
|
||||
if (gator_mali_create_file_system(mali_name, software_counter_names[counter_index], sb, root, &counters[event], NULL) != 0) {
|
||||
return -1;
|
||||
}
|
||||
counter_index++;
|
||||
}
|
||||
counter_index = 0;
|
||||
for (event = FIRST_ACCUMULATOR; event < FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS; event++) {
|
||||
if (gator_mali_create_file_system(mali_name, accumulators_names[counter_index], sb, root, &counters[event]) != 0) {
|
||||
if (gator_mali_create_file_system(mali_name, accumulators_names[counter_index], sb, root, &counters[event], NULL) != 0) {
|
||||
return -1;
|
||||
}
|
||||
counter_index++;
|
||||
}
|
||||
|
||||
mali_control = symbol_get(_mali_profiling_control);
|
||||
if (mali_control) {
|
||||
if (gator_mali_create_file_system(mali_name, "Filmstrip_cnt0", sb, root, &counters[FILMSTRIP], &filmstrip_event) != 0) {
|
||||
return -1;
|
||||
}
|
||||
symbol_put(_mali_profiling_control);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -350,6 +361,7 @@ static int register_tracepoints(void)
|
||||
static int start(void)
|
||||
{
|
||||
unsigned int cnt;
|
||||
mali_profiling_control_type *mali_control;
|
||||
|
||||
/* Clean all data for the next capture */
|
||||
for (cnt = 0; cnt < NUMBER_OF_TIMELINE_EVENTS; cnt++) {
|
||||
@@ -370,6 +382,30 @@ static int start(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Generic control interface for Mali DDK. */
|
||||
mali_control = symbol_get(_mali_profiling_control);
|
||||
if (mali_control) {
|
||||
/* The event attribute in the XML file keeps the actual frame rate. */
|
||||
unsigned int enabled = counters[FILMSTRIP].enabled ? 1 : 0;
|
||||
unsigned int rate = filmstrip_event & 0xff;
|
||||
unsigned int resize_factor = (filmstrip_event >> 8) & 0xff;
|
||||
|
||||
pr_debug("gator: mali online _mali_profiling_control symbol @ %p\n", mali_control);
|
||||
|
||||
#define FBDUMP_CONTROL_ENABLE (1)
|
||||
#define FBDUMP_CONTROL_RATE (2)
|
||||
#define FBDUMP_CONTROL_RESIZE_FACTOR (4)
|
||||
mali_control(FBDUMP_CONTROL_ENABLE, enabled);
|
||||
mali_control(FBDUMP_CONTROL_RATE, rate);
|
||||
mali_control(FBDUMP_CONTROL_RESIZE_FACTOR, resize_factor);
|
||||
|
||||
pr_debug("gator: sent mali_control enabled=%d, rate=%d, resize_factor=%d\n", enabled, rate, resize_factor);
|
||||
|
||||
symbol_put(_mali_profiling_control);
|
||||
} else {
|
||||
printk("gator: mali online _mali_profiling_control symbol not found\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the first timestamp for calculating the sample interval. The first interval could be quite long,
|
||||
* since it will be the time between 'start' and the first 'read'.
|
||||
@@ -382,6 +418,8 @@ static int start(void)
|
||||
|
||||
static void stop(void)
|
||||
{
|
||||
mali_profiling_control_type *mali_control;
|
||||
|
||||
pr_debug("gator: Mali-T6xx: stop\n");
|
||||
|
||||
/*
|
||||
@@ -402,6 +440,18 @@ static void stop(void)
|
||||
|
||||
GATOR_UNREGISTER_TRACE(mali_total_alloc_pages_change);
|
||||
pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint deactivated\n");
|
||||
|
||||
/* Generic control interface for Mali DDK. */
|
||||
mali_control = symbol_get(_mali_profiling_control);
|
||||
if (mali_control) {
|
||||
pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_control);
|
||||
|
||||
mali_control(FBDUMP_CONTROL_ENABLE, 0);
|
||||
|
||||
symbol_put(_mali_profiling_control);
|
||||
} else {
|
||||
printk("gator: mali offline _mali_profiling_control symbol not found\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int read(int **buffer)
|
||||
@@ -508,5 +558,3 @@ extern int gator_events_mali_t6xx_init(void)
|
||||
|
||||
return gator_events_install(&gator_events_mali_t6xx_interface);
|
||||
}
|
||||
|
||||
gator_events_init(gator_events_mali_t6xx_init);
|
||||
|
||||
@@ -63,6 +63,8 @@ static kbase_instr_hwcnt_disable_type *kbase_instr_hwcnt_disable_symbol;
|
||||
static kbase_va_free_type *kbase_va_free_symbol;
|
||||
static kbase_destroy_context_type *kbase_destroy_context_symbol;
|
||||
|
||||
static long shader_present_low = 0;
|
||||
|
||||
/** The interval between reads, in ns.
|
||||
*
|
||||
* Earlier we introduced
|
||||
@@ -496,6 +498,7 @@ static int start(void)
|
||||
mali_error err;
|
||||
int cnt;
|
||||
u16 bitmask[] = { 0, 0, 0, 0 };
|
||||
unsigned long long shadersPresent = 0;
|
||||
|
||||
/* Setup HW counters */
|
||||
num_hardware_counters_enabled = 0;
|
||||
@@ -539,6 +542,11 @@ static int start(void)
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
/* See if we can get the number of shader cores */
|
||||
shadersPresent = kbdevice->shader_present_bitmap;
|
||||
shader_present_low = (unsigned long)shadersPresent;
|
||||
|
||||
/*
|
||||
* The amount of memory needed to store the dump (bytes)
|
||||
* DUMP_SIZE = number of core groups
|
||||
@@ -679,21 +687,41 @@ static int read(int **buffer)
|
||||
kbase_device_busy = false;
|
||||
|
||||
if (success == MALI_TRUE) {
|
||||
/* Cycle through hardware counters and accumulate totals */
|
||||
for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) {
|
||||
const mali_counter *counter = &counters[cnt];
|
||||
if (counter->enabled) {
|
||||
const int block = GET_HW_BLOCK(cnt);
|
||||
const int counter_offset = GET_COUNTER_OFFSET(cnt);
|
||||
const u32 *counter_block = (u32 *) ((uintptr_t)kernel_dump_buffer + vithar_blocks[block]);
|
||||
const u32 *counter_address = counter_block + counter_offset;
|
||||
|
||||
value = *counter_address;
|
||||
const char* block_base_address = (char*)kernel_dump_buffer + vithar_blocks[block];
|
||||
|
||||
/* If counter belongs to shader block need to take into account all cores */
|
||||
if (block == SHADER_BLOCK) {
|
||||
/* (counter_address + 0x000) has already been accounted-for above. */
|
||||
value += *(counter_address + 0x100);
|
||||
value += *(counter_address + 0x200);
|
||||
value += *(counter_address + 0x300);
|
||||
int i = 0;
|
||||
int shader_core_count = 0;
|
||||
value = 0;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if ((shader_present_low >> i) & 1) {
|
||||
value += *((u32*) (block_base_address + (0x100 * i)) + counter_offset);
|
||||
shader_core_count++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if((shader_present_low >> (i+4)) & 1) {
|
||||
value += *((u32*)(block_base_address + (0x100 * i) + 0x800) + counter_offset);
|
||||
shader_core_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Need to total by number of cores to produce an average */
|
||||
if (shader_core_count != 0) {
|
||||
value /= shader_core_count;
|
||||
}
|
||||
} else {
|
||||
value = *((u32*)block_base_address + counter_offset);
|
||||
}
|
||||
|
||||
counter_dump[len++] = counter->key;
|
||||
@@ -727,7 +755,7 @@ static int create_files(struct super_block *sb, struct dentry *root)
|
||||
const char *mali_name = gator_mali_get_mali_name();
|
||||
|
||||
for (event = 0; event < NUMBER_OF_HARDWARE_COUNTERS; event++) {
|
||||
if (gator_mali_create_file_system(mali_name, hardware_counter_names[counter_index], sb, root, &counters[event]) != 0)
|
||||
if (gator_mali_create_file_system(mali_name, hardware_counter_names[counter_index], sb, root, &counters[event], NULL) != 0)
|
||||
return -1;
|
||||
counter_index++;
|
||||
}
|
||||
@@ -754,5 +782,3 @@ int gator_events_mali_t6xx_hw_init(void)
|
||||
|
||||
return gator_events_install(&gator_events_mali_t6xx_interface);
|
||||
}
|
||||
|
||||
gator_events_init(gator_events_mali_t6xx_hw_init);
|
||||
|
||||
@@ -8,27 +8,62 @@
|
||||
*/
|
||||
|
||||
#include "gator.h"
|
||||
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <trace/events/kmem.h>
|
||||
#include <linux/hardirq.h>
|
||||
|
||||
#define MEMINFO_MEMFREE 0
|
||||
#define MEMINFO_MEMUSED 1
|
||||
#define MEMINFO_BUFFERRAM 2
|
||||
#define MEMINFO_TOTAL 3
|
||||
enum {
|
||||
MEMINFO_MEMFREE,
|
||||
MEMINFO_MEMUSED,
|
||||
MEMINFO_BUFFERRAM,
|
||||
MEMINFO_TOTAL,
|
||||
};
|
||||
|
||||
static ulong meminfo_global_enabled;
|
||||
enum {
|
||||
PROC_SIZE,
|
||||
PROC_SHARE,
|
||||
PROC_TEXT,
|
||||
PROC_DATA,
|
||||
PROC_COUNT,
|
||||
};
|
||||
|
||||
static const char * const meminfo_names[] = {
|
||||
"Linux_meminfo_memfree",
|
||||
"Linux_meminfo_memused",
|
||||
"Linux_meminfo_bufferram",
|
||||
};
|
||||
|
||||
static const char * const proc_names[] = {
|
||||
"Linux_proc_statm_size",
|
||||
"Linux_proc_statm_share",
|
||||
"Linux_proc_statm_text",
|
||||
"Linux_proc_statm_data",
|
||||
};
|
||||
|
||||
static bool meminfo_global_enabled;
|
||||
static ulong meminfo_enabled[MEMINFO_TOTAL];
|
||||
static ulong meminfo_key[MEMINFO_TOTAL];
|
||||
static unsigned long long meminfo_buffer[MEMINFO_TOTAL * 2];
|
||||
static ulong meminfo_keys[MEMINFO_TOTAL];
|
||||
static long long meminfo_buffer[2 * (MEMINFO_TOTAL + 2)];
|
||||
static int meminfo_length = 0;
|
||||
static unsigned int mem_event = 0;
|
||||
static bool new_data_avail;
|
||||
|
||||
static void wq_sched_handler(struct work_struct *wsptr);
|
||||
DECLARE_WORK(work, wq_sched_handler);
|
||||
static struct timer_list meminfo_wake_up_timer;
|
||||
static void meminfo_wake_up_handler(unsigned long unused_data);
|
||||
static bool proc_global_enabled;
|
||||
static ulong proc_enabled[PROC_COUNT];
|
||||
static ulong proc_keys[PROC_COUNT];
|
||||
static DEFINE_PER_CPU(long long, proc_buffer[2 * (PROC_COUNT + 3)]);
|
||||
|
||||
static int gator_meminfo_func(void *data);
|
||||
static bool gator_meminfo_run;
|
||||
// Initialize semaphore unlocked to initialize memory values
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
|
||||
static DECLARE_MUTEX(gator_meminfo_sem);
|
||||
#else
|
||||
static DEFINE_SEMAPHORE(gator_meminfo_sem);
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
|
||||
GATOR_DEFINE_PROBE(mm_page_free_direct, TP_PROTO(struct page *page, unsigned int order))
|
||||
@@ -36,7 +71,7 @@ GATOR_DEFINE_PROBE(mm_page_free_direct, TP_PROTO(struct page *page, unsigned int
|
||||
GATOR_DEFINE_PROBE(mm_page_free, TP_PROTO(struct page *page, unsigned int order))
|
||||
#endif
|
||||
{
|
||||
mem_event++;
|
||||
up(&gator_meminfo_sem);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
|
||||
@@ -45,12 +80,12 @@ GATOR_DEFINE_PROBE(mm_pagevec_free, TP_PROTO(struct page *page, int cold))
|
||||
GATOR_DEFINE_PROBE(mm_page_free_batched, TP_PROTO(struct page *page, int cold))
|
||||
#endif
|
||||
{
|
||||
mem_event++;
|
||||
up(&gator_meminfo_sem);
|
||||
}
|
||||
|
||||
GATOR_DEFINE_PROBE(mm_page_alloc, TP_PROTO(struct page *page, unsigned int order, gfp_t gfp_flags, int migratetype))
|
||||
{
|
||||
mem_event++;
|
||||
up(&gator_meminfo_sem);
|
||||
}
|
||||
|
||||
static int gator_events_meminfo_create_files(struct super_block *sb, struct dentry *root)
|
||||
@@ -59,24 +94,21 @@ static int gator_events_meminfo_create_files(struct super_block *sb, struct dent
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MEMINFO_TOTAL; i++) {
|
||||
switch (i) {
|
||||
case MEMINFO_MEMFREE:
|
||||
dir = gatorfs_mkdir(sb, root, "Linux_meminfo_memfree");
|
||||
break;
|
||||
case MEMINFO_MEMUSED:
|
||||
dir = gatorfs_mkdir(sb, root, "Linux_meminfo_memused");
|
||||
break;
|
||||
case MEMINFO_BUFFERRAM:
|
||||
dir = gatorfs_mkdir(sb, root, "Linux_meminfo_bufferram");
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
dir = gatorfs_mkdir(sb, root, meminfo_names[i]);
|
||||
if (!dir) {
|
||||
return -1;
|
||||
}
|
||||
gatorfs_create_ulong(sb, dir, "enabled", &meminfo_enabled[i]);
|
||||
gatorfs_create_ro_ulong(sb, dir, "key", &meminfo_key[i]);
|
||||
gatorfs_create_ro_ulong(sb, dir, "key", &meminfo_keys[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < PROC_COUNT; ++i) {
|
||||
dir = gatorfs_mkdir(sb, root, proc_names[i]);
|
||||
if (!dir) {
|
||||
return -1;
|
||||
}
|
||||
gatorfs_create_ulong(sb, dir, "enabled", &proc_enabled[i]);
|
||||
gatorfs_create_ro_ulong(sb, dir, "key", &proc_keys[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -86,13 +118,26 @@ static int gator_events_meminfo_start(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
new_data_avail = true;
|
||||
new_data_avail = false;
|
||||
meminfo_global_enabled = 0;
|
||||
for (i = 0; i < MEMINFO_TOTAL; i++) {
|
||||
if (meminfo_enabled[i]) {
|
||||
meminfo_global_enabled = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
proc_global_enabled = 0;
|
||||
for (i = 0; i < PROC_COUNT; ++i) {
|
||||
if (proc_enabled[i]) {
|
||||
proc_global_enabled = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (meminfo_enabled[MEMINFO_MEMUSED]) {
|
||||
proc_global_enabled = 1;
|
||||
}
|
||||
|
||||
if (meminfo_global_enabled == 0)
|
||||
return 0;
|
||||
|
||||
@@ -111,9 +156,16 @@ static int gator_events_meminfo_start(void)
|
||||
if (GATOR_REGISTER_TRACE(mm_page_alloc))
|
||||
goto mm_page_alloc_exit;
|
||||
|
||||
setup_timer(&meminfo_wake_up_timer, meminfo_wake_up_handler, 0);
|
||||
// Start worker thread
|
||||
gator_meminfo_run = true;
|
||||
// Since the mutex starts unlocked, memory values will be initialized
|
||||
if (IS_ERR(kthread_run(gator_meminfo_func, NULL, "gator_meminfo")))
|
||||
goto kthread_run_exit;
|
||||
|
||||
return 0;
|
||||
|
||||
kthread_run_exit:
|
||||
GATOR_UNREGISTER_TRACE(mm_page_alloc);
|
||||
mm_page_alloc_exit:
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
|
||||
GATOR_UNREGISTER_TRACE(mm_pagevec_free);
|
||||
@@ -132,8 +184,6 @@ mm_page_free_exit:
|
||||
|
||||
static void gator_events_meminfo_stop(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (meminfo_global_enabled) {
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
|
||||
GATOR_UNREGISTER_TRACE(mm_page_free_direct);
|
||||
@@ -144,68 +194,75 @@ static void gator_events_meminfo_stop(void)
|
||||
#endif
|
||||
GATOR_UNREGISTER_TRACE(mm_page_alloc);
|
||||
|
||||
del_timer_sync(&meminfo_wake_up_timer);
|
||||
}
|
||||
|
||||
meminfo_global_enabled = 0;
|
||||
for (i = 0; i < MEMINFO_TOTAL; i++) {
|
||||
meminfo_enabled[i] = 0;
|
||||
// Stop worker thread
|
||||
gator_meminfo_run = false;
|
||||
up(&gator_meminfo_sem);
|
||||
}
|
||||
}
|
||||
|
||||
// Must be run in process context as the kernel function si_meminfo() can sleep
|
||||
static void wq_sched_handler(struct work_struct *wsptr)
|
||||
static int gator_meminfo_func(void *data)
|
||||
{
|
||||
struct sysinfo info;
|
||||
int i, len;
|
||||
unsigned long long value;
|
||||
|
||||
meminfo_length = len = 0;
|
||||
|
||||
si_meminfo(&info);
|
||||
for (i = 0; i < MEMINFO_TOTAL; i++) {
|
||||
if (meminfo_enabled[i]) {
|
||||
switch (i) {
|
||||
case MEMINFO_MEMFREE:
|
||||
value = info.freeram * PAGE_SIZE;
|
||||
break;
|
||||
case MEMINFO_MEMUSED:
|
||||
value = (info.totalram - info.freeram) * PAGE_SIZE;
|
||||
break;
|
||||
case MEMINFO_BUFFERRAM:
|
||||
value = info.bufferram * PAGE_SIZE;
|
||||
break;
|
||||
default:
|
||||
value = 0;
|
||||
break;
|
||||
}
|
||||
meminfo_buffer[len++] = (unsigned long long)meminfo_key[i];
|
||||
meminfo_buffer[len++] = value;
|
||||
for (;;) {
|
||||
if (down_killable(&gator_meminfo_sem)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Eat up any pending events
|
||||
while (!down_trylock(&gator_meminfo_sem));
|
||||
|
||||
if (!gator_meminfo_run) {
|
||||
break;
|
||||
}
|
||||
|
||||
meminfo_length = len = 0;
|
||||
|
||||
si_meminfo(&info);
|
||||
for (i = 0; i < MEMINFO_TOTAL; i++) {
|
||||
if (meminfo_enabled[i]) {
|
||||
switch (i) {
|
||||
case MEMINFO_MEMFREE:
|
||||
value = info.freeram * PAGE_SIZE;
|
||||
break;
|
||||
case MEMINFO_MEMUSED:
|
||||
// pid -1 means system wide
|
||||
meminfo_buffer[len++] = 1;
|
||||
meminfo_buffer[len++] = -1;
|
||||
// Emit value
|
||||
meminfo_buffer[len++] = meminfo_keys[MEMINFO_MEMUSED];
|
||||
meminfo_buffer[len++] = (info.totalram - info.freeram) * PAGE_SIZE;
|
||||
// Clear pid
|
||||
meminfo_buffer[len++] = 1;
|
||||
meminfo_buffer[len++] = 0;
|
||||
continue;
|
||||
case MEMINFO_BUFFERRAM:
|
||||
value = info.bufferram * PAGE_SIZE;
|
||||
break;
|
||||
default:
|
||||
value = 0;
|
||||
break;
|
||||
}
|
||||
meminfo_buffer[len++] = meminfo_keys[i];
|
||||
meminfo_buffer[len++] = value;
|
||||
}
|
||||
}
|
||||
|
||||
meminfo_length = len;
|
||||
new_data_avail = true;
|
||||
}
|
||||
|
||||
meminfo_length = len;
|
||||
new_data_avail = true;
|
||||
}
|
||||
|
||||
static void meminfo_wake_up_handler(unsigned long unused_data)
|
||||
{
|
||||
// had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
|
||||
schedule_work(&work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gator_events_meminfo_read(long long **buffer)
|
||||
{
|
||||
static unsigned int last_mem_event = 0;
|
||||
|
||||
if (!on_primary_core() || !meminfo_global_enabled)
|
||||
return 0;
|
||||
|
||||
if (last_mem_event != mem_event) {
|
||||
last_mem_event = mem_event;
|
||||
mod_timer(&meminfo_wake_up_timer, jiffies + 1);
|
||||
}
|
||||
|
||||
if (!new_data_avail)
|
||||
return 0;
|
||||
|
||||
@@ -217,11 +274,97 @@ static int gator_events_meminfo_read(long long **buffer)
|
||||
return meminfo_length;
|
||||
}
|
||||
|
||||
static int gator_events_meminfo_read_proc(long long **buffer, struct task_struct *task)
|
||||
{
|
||||
struct mm_struct *mm;
|
||||
u64 share = 0;
|
||||
int i;
|
||||
long long value;
|
||||
int len = 0;
|
||||
int cpu = get_physical_cpu();
|
||||
long long *buf = per_cpu(proc_buffer, cpu);
|
||||
|
||||
if (!proc_global_enabled) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Collect the memory stats of the process instead of the thread
|
||||
if (task->group_leader != NULL) {
|
||||
task = task->group_leader;
|
||||
}
|
||||
|
||||
// get_task_mm/mmput is not needed in this context because the task and it's mm are required as part of the sched_switch
|
||||
mm = task->mm;
|
||||
if (mm == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Derived from task_statm in fs/proc/task_mmu.c
|
||||
if (meminfo_enabled[MEMINFO_MEMUSED] || proc_enabled[PROC_SHARE]) {
|
||||
share = get_mm_counter(mm,
|
||||
#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 32)
|
||||
file_rss
|
||||
#else
|
||||
MM_FILEPAGES
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
// key of 1 indicates a pid
|
||||
buf[len++] = 1;
|
||||
buf[len++] = task->pid;
|
||||
|
||||
for (i = 0; i < PROC_COUNT; ++i) {
|
||||
if (proc_enabled[i]) {
|
||||
switch (i) {
|
||||
case PROC_SIZE:
|
||||
value = mm->total_vm;
|
||||
break;
|
||||
case PROC_SHARE:
|
||||
value = share;
|
||||
break;
|
||||
case PROC_TEXT:
|
||||
value = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> PAGE_SHIFT;
|
||||
break;
|
||||
case PROC_DATA:
|
||||
value = mm->total_vm - mm->shared_vm;
|
||||
break;
|
||||
}
|
||||
|
||||
buf[len++] = proc_keys[i];
|
||||
buf[len++] = value * PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
if (meminfo_enabled[MEMINFO_MEMUSED]) {
|
||||
value = share + get_mm_counter(mm,
|
||||
#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 32)
|
||||
anon_rss
|
||||
#else
|
||||
MM_ANONPAGES
|
||||
#endif
|
||||
);
|
||||
// Send resident for this pid
|
||||
buf[len++] = meminfo_keys[MEMINFO_MEMUSED];
|
||||
buf[len++] = value * PAGE_SIZE;
|
||||
}
|
||||
|
||||
// Clear pid
|
||||
buf[len++] = 1;
|
||||
buf[len++] = 0;
|
||||
|
||||
if (buffer)
|
||||
*buffer = buf;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static struct gator_interface gator_events_meminfo_interface = {
|
||||
.create_files = gator_events_meminfo_create_files,
|
||||
.start = gator_events_meminfo_start,
|
||||
.stop = gator_events_meminfo_stop,
|
||||
.read64 = gator_events_meminfo_read,
|
||||
.read_proc = gator_events_meminfo_read_proc,
|
||||
};
|
||||
|
||||
int gator_events_meminfo_init(void)
|
||||
@@ -231,10 +374,14 @@ int gator_events_meminfo_init(void)
|
||||
meminfo_global_enabled = 0;
|
||||
for (i = 0; i < MEMINFO_TOTAL; i++) {
|
||||
meminfo_enabled[i] = 0;
|
||||
meminfo_key[i] = gator_events_get_key();
|
||||
meminfo_keys[i] = gator_events_get_key();
|
||||
}
|
||||
|
||||
proc_global_enabled = 0;
|
||||
for (i = 0; i < PROC_COUNT; ++i) {
|
||||
proc_enabled[i] = 0;
|
||||
proc_keys[i] = gator_events_get_key();
|
||||
}
|
||||
|
||||
return gator_events_install(&gator_events_meminfo_interface);
|
||||
}
|
||||
|
||||
gator_events_init(gator_events_meminfo_init);
|
||||
|
||||
@@ -11,12 +11,18 @@
|
||||
* To add them to the events.xml, create an events-mmap.xml with the
|
||||
* following contents and rebuild gatord:
|
||||
*
|
||||
* <counter_set name="mmaped_cnt" count="3"/>
|
||||
* <category name="mmaped" counter_set="mmaped_cnt" per_cpu="no">
|
||||
* <counter_set name="mmapped_cnt" count="3"/>
|
||||
* <category name="mmapped" counter_set="mmapped_cnt" per_cpu="no">
|
||||
* <event event="0x0" title="Simulated1" name="Sine" display="maximum" average_selection="yes" description="Sort-of-sine"/>
|
||||
* <event event="0x1" title="Simulated2" name="Triangle" display="maximum" average_selection="yes" description="Triangular wave"/>
|
||||
* <event event="0x2" title="Simulated3" name="PWM" display="maximum" average_selection="yes" description="PWM Signal"/>
|
||||
* </category>
|
||||
*
|
||||
* When adding custom events, be sure do the following
|
||||
* - add any needed .c files to the gator driver Makefile
|
||||
* - call gator_events_install in the events init function
|
||||
* - add the init function to GATOR_EVENTS_LIST in gator_main.c
|
||||
* - add a new events-*.xml file to the gator daemon and rebuild
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
@@ -25,79 +31,71 @@
|
||||
|
||||
#include "gator.h"
|
||||
|
||||
#define MMAPED_COUNTERS_NUM 3
|
||||
#define MMAPPED_COUNTERS_NUM 3
|
||||
|
||||
static int mmapped_global_enabled;
|
||||
|
||||
static struct {
|
||||
unsigned long enabled;
|
||||
unsigned long event;
|
||||
unsigned long key;
|
||||
} mmaped_counters[MMAPED_COUNTERS_NUM];
|
||||
} mmapped_counters[MMAPPED_COUNTERS_NUM];
|
||||
|
||||
static int mmaped_buffer[MMAPED_COUNTERS_NUM * 2];
|
||||
static int mmapped_buffer[MMAPPED_COUNTERS_NUM * 2];
|
||||
|
||||
#ifdef TODO
|
||||
static void __iomem *mmaped_base;
|
||||
#endif
|
||||
|
||||
#ifndef TODO
|
||||
static s64 prev_time;
|
||||
#endif
|
||||
|
||||
/* Adds mmaped_cntX directories and enabled, event, and key files to /dev/gator/events */
|
||||
static int gator_events_mmaped_create_files(struct super_block *sb,
|
||||
/* Adds mmapped_cntX directories and enabled, event, and key files to /dev/gator/events */
|
||||
static int gator_events_mmapped_create_files(struct super_block *sb,
|
||||
struct dentry *root)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MMAPED_COUNTERS_NUM; i++) {
|
||||
for (i = 0; i < MMAPPED_COUNTERS_NUM; i++) {
|
||||
char buf[16];
|
||||
struct dentry *dir;
|
||||
|
||||
snprintf(buf, sizeof(buf), "mmaped_cnt%d", i);
|
||||
snprintf(buf, sizeof(buf), "mmapped_cnt%d", i);
|
||||
dir = gatorfs_mkdir(sb, root, buf);
|
||||
if (WARN_ON(!dir))
|
||||
return -1;
|
||||
gatorfs_create_ulong(sb, dir, "enabled",
|
||||
&mmaped_counters[i].enabled);
|
||||
&mmapped_counters[i].enabled);
|
||||
gatorfs_create_ulong(sb, dir, "event",
|
||||
&mmaped_counters[i].event);
|
||||
&mmapped_counters[i].event);
|
||||
gatorfs_create_ro_ulong(sb, dir, "key",
|
||||
&mmaped_counters[i].key);
|
||||
&mmapped_counters[i].key);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gator_events_mmaped_start(void)
|
||||
static int gator_events_mmapped_start(void)
|
||||
{
|
||||
#ifdef TODO
|
||||
for (i = 0; i < MMAPED_COUNTERS_NUM; i++)
|
||||
writel(mmaped_counters[i].event,
|
||||
mmaped_base + COUNTERS_CONFIG_OFFSET[i]);
|
||||
|
||||
writel(ENABLED, COUNTERS_CONTROL_OFFSET);
|
||||
#endif
|
||||
|
||||
#ifndef TODO
|
||||
int i;
|
||||
struct timespec ts;
|
||||
|
||||
getnstimeofday(&ts);
|
||||
prev_time = timespec_to_ns(&ts);
|
||||
#endif
|
||||
|
||||
mmapped_global_enabled = 0;
|
||||
for (i = 0; i < MMAPPED_COUNTERS_NUM; i++) {
|
||||
if (mmapped_counters[i].enabled) {
|
||||
mmapped_global_enabled = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gator_events_mmaped_stop(void)
|
||||
static void gator_events_mmapped_stop(void)
|
||||
{
|
||||
#ifdef TODO
|
||||
writel(DISABLED, COUNTERS_CONTROL_OFFSET);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef TODO
|
||||
/* This function "simulates" counters, generating values of fancy
|
||||
* functions like sine or triangle... */
|
||||
static int mmaped_simulate(int counter, int delta_in_us)
|
||||
static int mmapped_simulate(int counter, int delta_in_us)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
@@ -157,73 +155,55 @@ static int mmaped_simulate(int counter, int delta_in_us)
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int gator_events_mmaped_read(int **buffer)
|
||||
static int gator_events_mmapped_read(int **buffer)
|
||||
{
|
||||
int i;
|
||||
int len = 0;
|
||||
#ifndef TODO
|
||||
int delta_in_us;
|
||||
struct timespec ts;
|
||||
s64 time;
|
||||
#endif
|
||||
|
||||
/* System wide counters - read from one core only */
|
||||
if (!on_primary_core())
|
||||
if (!on_primary_core() || !mmapped_global_enabled)
|
||||
return 0;
|
||||
|
||||
#ifndef TODO
|
||||
getnstimeofday(&ts);
|
||||
time = timespec_to_ns(&ts);
|
||||
delta_in_us = (int)(time - prev_time) / 1000;
|
||||
prev_time = time;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < MMAPED_COUNTERS_NUM; i++) {
|
||||
if (mmaped_counters[i].enabled) {
|
||||
mmaped_buffer[len++] = mmaped_counters[i].key;
|
||||
#ifdef TODO
|
||||
mmaped_buffer[len++] =
|
||||
readl(mmaped_base + COUNTERS_VALUE_OFFSET[i]);
|
||||
#else
|
||||
mmaped_buffer[len++] =
|
||||
mmaped_simulate(mmaped_counters[i].event,
|
||||
for (i = 0; i < MMAPPED_COUNTERS_NUM; i++) {
|
||||
if (mmapped_counters[i].enabled) {
|
||||
mmapped_buffer[len++] = mmapped_counters[i].key;
|
||||
mmapped_buffer[len++] =
|
||||
mmapped_simulate(mmapped_counters[i].event,
|
||||
delta_in_us);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer)
|
||||
*buffer = mmaped_buffer;
|
||||
*buffer = mmapped_buffer;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static struct gator_interface gator_events_mmaped_interface = {
|
||||
.create_files = gator_events_mmaped_create_files,
|
||||
.start = gator_events_mmaped_start,
|
||||
.stop = gator_events_mmaped_stop,
|
||||
.read = gator_events_mmaped_read,
|
||||
static struct gator_interface gator_events_mmapped_interface = {
|
||||
.create_files = gator_events_mmapped_create_files,
|
||||
.start = gator_events_mmapped_start,
|
||||
.stop = gator_events_mmapped_stop,
|
||||
.read = gator_events_mmapped_read,
|
||||
};
|
||||
|
||||
/* Must not be static! */
|
||||
int __init gator_events_mmaped_init(void)
|
||||
int __init gator_events_mmapped_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef TODO
|
||||
mmaped_base = ioremap(COUNTERS_PHYS_ADDR, SZ_4K);
|
||||
if (!mmaped_base)
|
||||
return -ENOMEM;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < MMAPED_COUNTERS_NUM; i++) {
|
||||
mmaped_counters[i].enabled = 0;
|
||||
mmaped_counters[i].key = gator_events_get_key();
|
||||
for (i = 0; i < MMAPPED_COUNTERS_NUM; i++) {
|
||||
mmapped_counters[i].enabled = 0;
|
||||
mmapped_counters[i].key = gator_events_get_key();
|
||||
}
|
||||
|
||||
return gator_events_install(&gator_events_mmaped_interface);
|
||||
return gator_events_install(&gator_events_mmapped_interface);
|
||||
}
|
||||
|
||||
gator_events_init(gator_events_mmaped_init);
|
||||
@@ -73,6 +73,8 @@ static void calculate_delta(int *rx, int *tx)
|
||||
|
||||
static int gator_events_net_create_files(struct super_block *sb, struct dentry *root)
|
||||
{
|
||||
// Network counters are not currently supported in RT-Preempt full because mod_timer is used
|
||||
#ifndef CONFIG_PREEMPT_RT_FULL
|
||||
struct dentry *dir;
|
||||
|
||||
dir = gatorfs_mkdir(sb, root, "Linux_net_rx");
|
||||
@@ -88,6 +90,7 @@ static int gator_events_net_create_files(struct super_block *sb, struct dentry *
|
||||
}
|
||||
gatorfs_create_ulong(sb, dir, "enabled", &nettx_enabled);
|
||||
gatorfs_create_ro_ulong(sb, dir, "key", &nettx_key);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -167,5 +170,3 @@ int gator_events_net_init(void)
|
||||
|
||||
return gator_events_install(&gator_events_net_interface);
|
||||
}
|
||||
|
||||
gator_events_init(gator_events_net_init);
|
||||
|
||||
@@ -6,13 +6,18 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include "gator.h"
|
||||
|
||||
// gator_events_armvX.c is used for Linux 2.6.x
|
||||
#if GATOR_PERF_PMU_SUPPORT
|
||||
|
||||
#include <linux/io.h>
|
||||
#ifdef CONFIG_OF
|
||||
#include <linux/of_address.h>
|
||||
#endif
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
extern bool event_based_sampling;
|
||||
|
||||
// Maximum number of per-core counters - currently reserves enough space for two full hardware PMUs for big.LITTLE
|
||||
@@ -22,6 +27,9 @@ extern bool event_based_sampling;
|
||||
// + 1 for the cci-400 cycles counter
|
||||
#define UCCNT (CCI_400 + 1)
|
||||
|
||||
// Default to 0 if unable to probe the revision which was the previous behavior
|
||||
#define DEFAULT_CCI_REVISION 0
|
||||
|
||||
// A gator_attr is needed for every counter
|
||||
struct gator_attr {
|
||||
// Set once in gator_events_perf_pmu_*_init - the name of the event in the gatorfs
|
||||
@@ -404,17 +412,81 @@ static void __attr_init(struct gator_attr *const attr)
|
||||
attr->key = gator_events_get_key();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
||||
static const struct of_device_id arm_cci_matches[] = {
|
||||
{.compatible = "arm,cci-400" },
|
||||
{},
|
||||
};
|
||||
|
||||
static int probe_cci_revision(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct resource res;
|
||||
void __iomem *cci_ctrl_base;
|
||||
int rev;
|
||||
int ret = DEFAULT_CCI_REVISION;
|
||||
|
||||
np = of_find_matching_node(NULL, arm_cci_matches);
|
||||
if (!np) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (of_address_to_resource(np, 0, &res)) {
|
||||
goto node_put;
|
||||
}
|
||||
|
||||
cci_ctrl_base = ioremap(res.start, resource_size(&res));
|
||||
|
||||
rev = (readl_relaxed(cci_ctrl_base + 0xfe8) >> 4) & 0xf;
|
||||
|
||||
if (rev <= 4) {
|
||||
ret = 0;
|
||||
} else if (rev <= 6) {
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
iounmap(cci_ctrl_base);
|
||||
|
||||
node_put:
|
||||
of_node_put(np);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int probe_cci_revision(void)
|
||||
{
|
||||
return DEFAULT_CCI_REVISION;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void gator_events_perf_pmu_cci_init(const int type)
|
||||
{
|
||||
int cnt;
|
||||
const char *cci_name;
|
||||
|
||||
strncpy(uc_attrs[uc_attr_count].name, "cci-400_ccnt", sizeof(uc_attrs[uc_attr_count].name));
|
||||
switch (probe_cci_revision()) {
|
||||
case 0:
|
||||
cci_name = "cci-400";
|
||||
break;
|
||||
case 1:
|
||||
cci_name = "cci-400-r1";
|
||||
break;
|
||||
default:
|
||||
pr_debug("gator: unrecognized cci-400 revision\n");
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(uc_attrs[uc_attr_count].name, sizeof(uc_attrs[uc_attr_count].name), "%s_ccnt", cci_name);
|
||||
uc_attrs[uc_attr_count].type = type;
|
||||
++uc_attr_count;
|
||||
|
||||
for (cnt = 0; cnt < CCI_400; ++cnt, ++uc_attr_count) {
|
||||
struct gator_attr *const attr = &uc_attrs[uc_attr_count];
|
||||
snprintf(attr->name, sizeof(attr->name), "cci-400_cnt%d", cnt);
|
||||
snprintf(attr->name, sizeof(attr->name), "%s_cnt%d", cci_name, cnt);
|
||||
attr->type = type;
|
||||
}
|
||||
}
|
||||
@@ -477,7 +549,7 @@ int gator_events_perf_pmu_init(void)
|
||||
}
|
||||
|
||||
if (pe->pmu != NULL && type == pe->pmu->type) {
|
||||
if (strcmp("CCI", pe->pmu->name) == 0) {
|
||||
if (strcmp("CCI", pe->pmu->name) == 0 || strcmp("CCI_400", pe->pmu->name) == 0) {
|
||||
gator_events_perf_pmu_cci_init(type);
|
||||
} else if ((gator_cpu = gator_find_cpu_by_pmu_name(pe->pmu->name)) != NULL) {
|
||||
found_cpu = true;
|
||||
@@ -512,5 +584,4 @@ int gator_events_perf_pmu_init(void)
|
||||
return gator_events_install(&gator_events_perf_pmu_interface);
|
||||
}
|
||||
|
||||
gator_events_init(gator_events_perf_pmu_init);
|
||||
#endif
|
||||
|
||||
@@ -111,5 +111,3 @@ int gator_events_sched_init(void)
|
||||
|
||||
return gator_events_install(&gator_events_sched_interface);
|
||||
}
|
||||
|
||||
gator_events_init(gator_events_sched_init);
|
||||
|
||||
@@ -666,11 +666,4 @@ int gator_events_scorpion_init(void)
|
||||
return gator_events_install(&gator_events_scorpion_interface);
|
||||
}
|
||||
|
||||
gator_events_init(gator_events_scorpion_init);
|
||||
|
||||
#else
|
||||
int gator_events_scorpion_init(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
*/
|
||||
|
||||
// This version must match the gator daemon version
|
||||
static unsigned long gator_protocol_version = 16;
|
||||
#define PROTOCOL_VERSION 17
|
||||
static unsigned long gator_protocol_version = PROTOCOL_VERSION;
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/cpu.h>
|
||||
@@ -22,16 +23,20 @@ static unsigned long gator_protocol_version = 16;
|
||||
#include <linux/module.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <asm/stacktrace.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include "gator.h"
|
||||
#include "gator_events.h"
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
|
||||
#error kernels prior to 2.6.32 are not supported
|
||||
#endif
|
||||
|
||||
#if defined(MODULE) && !defined(CONFIG_MODULES)
|
||||
#error Cannot build a module against a kernel that does not support modules. To resolve, either rebuild the kernel to support modules or build gator as part of the kernel.
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_GENERIC_TRACER) && !defined(CONFIG_TRACING)
|
||||
#error gator requires the kernel to have CONFIG_GENERIC_TRACER or CONFIG_TRACING defined
|
||||
#endif
|
||||
@@ -44,7 +49,7 @@ static unsigned long gator_protocol_version = 16;
|
||||
#error gator requires the kernel to have CONFIG_HIGH_RES_TIMERS defined to support PC sampling
|
||||
#endif
|
||||
|
||||
#if defined(__arm__) && defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) && defined(__arm__) && defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS)
|
||||
#error gator requires the kernel to have CONFIG_LOCAL_TIMERS defined on SMP systems
|
||||
#endif
|
||||
|
||||
@@ -87,6 +92,7 @@ static unsigned long gator_protocol_version = 16;
|
||||
#define MESSAGE_COOKIE 1
|
||||
#define MESSAGE_THREAD_NAME 2
|
||||
#define HRTIMER_CORE_NAME 3
|
||||
#define MESSAGE_LINK 4
|
||||
|
||||
#define MESSAGE_GPU_START 1
|
||||
#define MESSAGE_GPU_STOP 2
|
||||
@@ -136,6 +142,7 @@ static u64 gator_live_rate;
|
||||
|
||||
static unsigned long gator_started;
|
||||
static u64 gator_monotonic_started;
|
||||
static u64 gator_hibernate_time;
|
||||
static unsigned long gator_buffer_opened;
|
||||
static unsigned long gator_timer_count;
|
||||
static unsigned long gator_response_type;
|
||||
@@ -147,6 +154,8 @@ bool event_based_sampling;
|
||||
static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait);
|
||||
static DECLARE_WAIT_QUEUE_HEAD(gator_annotate_wait);
|
||||
static struct timer_list gator_buffer_wake_up_timer;
|
||||
static bool gator_buffer_wake_stop;
|
||||
static struct task_struct *gator_buffer_wake_thread;
|
||||
static LIST_HEAD(gator_events);
|
||||
|
||||
static DEFINE_PER_CPU(u64, last_timestamp);
|
||||
@@ -189,6 +198,34 @@ static DEFINE_PER_CPU(char *[NUM_GATOR_BUFS], gator_buffer);
|
||||
// The time after which the buffer should be committed for live display
|
||||
static DEFINE_PER_CPU(u64, gator_buffer_commit_time);
|
||||
|
||||
// List of all gator events - new events must be added to this list
|
||||
#define GATOR_EVENTS_LIST \
|
||||
GATOR_EVENT(gator_events_armv6_init) \
|
||||
GATOR_EVENT(gator_events_armv7_init) \
|
||||
GATOR_EVENT(gator_events_block_init) \
|
||||
GATOR_EVENT(gator_events_ccn504_init) \
|
||||
GATOR_EVENT(gator_events_irq_init) \
|
||||
GATOR_EVENT(gator_events_l2c310_init) \
|
||||
GATOR_EVENT(gator_events_mali_init) \
|
||||
GATOR_EVENT(gator_events_mali_t6xx_hw_init) \
|
||||
GATOR_EVENT(gator_events_mali_t6xx_init) \
|
||||
GATOR_EVENT(gator_events_meminfo_init) \
|
||||
GATOR_EVENT(gator_events_mmapped_init) \
|
||||
GATOR_EVENT(gator_events_net_init) \
|
||||
GATOR_EVENT(gator_events_perf_pmu_init) \
|
||||
GATOR_EVENT(gator_events_sched_init) \
|
||||
GATOR_EVENT(gator_events_scorpion_init) \
|
||||
|
||||
#define GATOR_EVENT(EVENT_INIT) __weak int EVENT_INIT(void);
|
||||
GATOR_EVENTS_LIST
|
||||
#undef GATOR_EVENT
|
||||
|
||||
static int (*gator_events_list[])(void) = {
|
||||
#define GATOR_EVENT(EVENT_INIT) EVENT_INIT,
|
||||
GATOR_EVENTS_LIST
|
||||
#undef GATOR_EVENT
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Application Includes
|
||||
******************************************************************************/
|
||||
@@ -392,6 +429,21 @@ static void gator_buffer_wake_up(unsigned long data)
|
||||
wake_up(&gator_buffer_wait);
|
||||
}
|
||||
|
||||
static int gator_buffer_wake_func(void *data)
|
||||
{
|
||||
while (!gator_buffer_wake_stop) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule();
|
||||
if (gator_buffer_wake_stop) {
|
||||
break;
|
||||
}
|
||||
|
||||
gator_buffer_wake_up(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Commit interface
|
||||
******************************************************************************/
|
||||
@@ -517,7 +569,14 @@ static void gator_commit_buffer(int cpu, int buftype, u64 time)
|
||||
marshal_frame(cpu, buftype);
|
||||
|
||||
// had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
|
||||
mod_timer(&gator_buffer_wake_up_timer, jiffies + 1);
|
||||
if (per_cpu(in_scheduler_context, cpu)) {
|
||||
#ifndef CONFIG_PREEMPT_RT_FULL
|
||||
// mod_timer can not be used in interrupt context in RT-Preempt full
|
||||
mod_timer(&gator_buffer_wake_up_timer, jiffies + 1);
|
||||
#endif
|
||||
} else {
|
||||
wake_up_process(gator_buffer_wake_thread);
|
||||
}
|
||||
}
|
||||
|
||||
static void buffer_check(int cpu, int buftype, u64 time)
|
||||
@@ -590,8 +649,13 @@ void gator_backtrace_handler(struct pt_regs *const regs)
|
||||
|
||||
// Collect counters
|
||||
if (!per_cpu(collecting, cpu)) {
|
||||
collect_counters(time);
|
||||
collect_counters(time, NULL);
|
||||
}
|
||||
|
||||
// No buffer flushing occurs during sched switch for RT-Preempt full. The block counter frame will be flushed by collect_counters, but the sched buffer needs to be explicitly flushed
|
||||
#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
buffer_check(cpu, SCHED_TRACE_BUF, time);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int gator_running;
|
||||
@@ -815,6 +879,7 @@ static struct notifier_block __refdata gator_hotcpu_notifier = {
|
||||
static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy)
|
||||
{
|
||||
int cpu;
|
||||
struct timespec ts;
|
||||
|
||||
switch (event) {
|
||||
case PM_HIBERNATION_PREPARE:
|
||||
@@ -825,9 +890,20 @@ static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void
|
||||
for_each_online_cpu(cpu) {
|
||||
gator_timer_offline_dispatch(lcpu_to_pcpu(cpu), false);
|
||||
}
|
||||
|
||||
// Record the wallclock hibernate time
|
||||
getnstimeofday(&ts);
|
||||
gator_hibernate_time = timespec_to_ns(&ts) - gator_get_time();
|
||||
break;
|
||||
case PM_POST_HIBERNATION:
|
||||
case PM_POST_SUSPEND:
|
||||
// Adjust gator_monotonic_started for the time spent sleeping, as gator_get_time does not account for it
|
||||
if (gator_hibernate_time > 0) {
|
||||
getnstimeofday(&ts);
|
||||
gator_monotonic_started += gator_hibernate_time + gator_get_time() - timespec_to_ns(&ts);
|
||||
gator_hibernate_time = 0;
|
||||
}
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
gator_timer_online_dispatch(lcpu_to_pcpu(cpu), false);
|
||||
}
|
||||
@@ -902,8 +978,10 @@ int gator_events_install(struct gator_interface *interface)
|
||||
|
||||
int gator_events_get_key(void)
|
||||
{
|
||||
// key of zero is reserved as a timestamp
|
||||
static int key = 1;
|
||||
// key 0 is reserved as a timestamp
|
||||
// key 1 is reserved as the marker for thread specific counters
|
||||
// Odd keys are assigned by the driver, even keys by the daemon
|
||||
static int key = 3;
|
||||
|
||||
const int ret = key;
|
||||
key += 2;
|
||||
@@ -916,7 +994,7 @@ static int gator_init(void)
|
||||
|
||||
calc_first_cluster_size();
|
||||
|
||||
// events sources (gator_events.h, generated by gator_events.sh)
|
||||
// events sources
|
||||
for (i = 0; i < ARRAY_SIZE(gator_events_list); i++)
|
||||
if (gator_events_list[i])
|
||||
gator_events_list[i]();
|
||||
@@ -941,6 +1019,11 @@ static int gator_start(void)
|
||||
unsigned long cpu, i;
|
||||
struct gator_interface *gi;
|
||||
|
||||
gator_buffer_wake_stop = false;
|
||||
if (IS_ERR(gator_buffer_wake_thread = kthread_run(gator_buffer_wake_func, NULL, "gator_bwake"))) {
|
||||
goto bwake_failure;
|
||||
}
|
||||
|
||||
if (gator_migrate_start())
|
||||
goto migrate_failure;
|
||||
|
||||
@@ -1011,6 +1094,9 @@ cookies_failure:
|
||||
events_failure:
|
||||
gator_migrate_stop();
|
||||
migrate_failure:
|
||||
gator_buffer_wake_stop = true;
|
||||
wake_up_process(gator_buffer_wake_thread);
|
||||
bwake_failure:
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -1034,6 +1120,9 @@ static void gator_stop(void)
|
||||
gi->stop();
|
||||
|
||||
gator_migrate_stop();
|
||||
|
||||
gator_buffer_wake_stop = true;
|
||||
wake_up_process(gator_buffer_wake_thread);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@@ -1438,3 +1527,6 @@ module_exit(gator_module_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("ARM Ltd");
|
||||
MODULE_DESCRIPTION("Gator system profiler");
|
||||
#define STRIFY2(ARG) #ARG
|
||||
#define STRIFY(ARG) STRIFY2(ARG)
|
||||
MODULE_VERSION(STRIFY(PROTOCOL_VERSION));
|
||||
|
||||
@@ -89,6 +89,25 @@ static void marshal_thread_name(int pid, char *name)
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void marshal_link(int cookie, int tgid, int pid)
|
||||
{
|
||||
unsigned long cpu = get_physical_cpu(), flags;
|
||||
u64 time;
|
||||
|
||||
local_irq_save(flags);
|
||||
time = gator_get_time();
|
||||
if (buffer_check_space(cpu, NAME_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
|
||||
gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_LINK);
|
||||
gator_buffer_write_packed_int64(cpu, NAME_BUF, time);
|
||||
gator_buffer_write_packed_int(cpu, NAME_BUF, cookie);
|
||||
gator_buffer_write_packed_int(cpu, NAME_BUF, tgid);
|
||||
gator_buffer_write_packed_int(cpu, NAME_BUF, pid);
|
||||
}
|
||||
// Check and commit; commit is set to occur once buffer is 3/4 full
|
||||
buffer_check(cpu, NAME_BUF, time);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inKernel, u64 time)
|
||||
{
|
||||
int cpu = get_physical_cpu();
|
||||
|
||||
@@ -85,7 +85,7 @@ static void mali_gpu_stop(int unit, int core)
|
||||
int count;
|
||||
int last_tgid = 0;
|
||||
int last_pid = 0;
|
||||
int last_job_id = 0;
|
||||
//int last_job_id = 0;
|
||||
|
||||
spin_lock(&mali_gpu_jobs_lock);
|
||||
if (mali_gpu_jobs[unit][core].count == 0) {
|
||||
@@ -97,7 +97,7 @@ static void mali_gpu_stop(int unit, int core)
|
||||
if (count) {
|
||||
last_tgid = mali_gpu_jobs[unit][core].last_tgid;
|
||||
last_pid = mali_gpu_jobs[unit][core].last_pid;
|
||||
last_job_id = mali_gpu_jobs[unit][core].last_job_id;
|
||||
//last_job_id = mali_gpu_jobs[unit][core].last_job_id;
|
||||
}
|
||||
spin_unlock(&mali_gpu_jobs_lock);
|
||||
|
||||
@@ -242,7 +242,7 @@ int gator_trace_gpu_start(void)
|
||||
* Absence of gpu trace points is not an error
|
||||
*/
|
||||
|
||||
memset(&mali_gpu_jobs, sizeof(mali_gpu_jobs), 0);
|
||||
memset(&mali_gpu_jobs, 0, sizeof(mali_gpu_jobs));
|
||||
gpu_trace_registered = mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;
|
||||
|
||||
#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
|
||||
|
||||
@@ -22,6 +22,7 @@ enum {
|
||||
|
||||
static DEFINE_PER_CPU(uint64_t *, taskname_keys);
|
||||
static DEFINE_PER_CPU(int, collecting);
|
||||
static DEFINE_PER_CPU(bool, in_scheduler_context);
|
||||
|
||||
// this array is never read as the cpu wait charts are derived counters
|
||||
// the files are needed, nonetheless, to show that these counters are available
|
||||
@@ -89,7 +90,7 @@ void emit_pid_name(struct task_struct *task)
|
||||
}
|
||||
}
|
||||
|
||||
static void collect_counters(u64 time)
|
||||
static void collect_counters(u64 time, struct task_struct *task)
|
||||
{
|
||||
int *buffer, len, cpu = get_physical_cpu();
|
||||
long long *buffer64;
|
||||
@@ -104,17 +105,26 @@ static void collect_counters(u64 time)
|
||||
len = gi->read64(&buffer64);
|
||||
marshal_event64(len, buffer64);
|
||||
}
|
||||
if (gi->read_proc && task != NULL) {
|
||||
len = gi->read_proc(&buffer64, task);
|
||||
marshal_event64(len, buffer64);
|
||||
}
|
||||
}
|
||||
// Only check after writing all counters so that time and corresponding counters appear in the same frame
|
||||
buffer_check(cpu, BLOCK_COUNTER_BUF, time);
|
||||
|
||||
// Commit buffers on timeout
|
||||
if (gator_live_rate > 0 && time >= per_cpu(gator_buffer_commit_time, cpu)) {
|
||||
static const int buftypes[] = { COUNTER_BUF, BLOCK_COUNTER_BUF, SCHED_TRACE_BUF };
|
||||
static const int buftypes[] = { NAME_BUF, COUNTER_BUF, BLOCK_COUNTER_BUF, SCHED_TRACE_BUF };
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
local_irq_save(flags);
|
||||
for (i = 0; i < ARRAY_SIZE(buftypes); ++i) {
|
||||
gator_commit_buffer(cpu, buftypes[i], time);
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
|
||||
// Try to preemptively flush the annotate buffer to reduce the chance of the buffer being full
|
||||
if (on_primary_core() && spin_trylock(&annotate_lock)) {
|
||||
gator_commit_buffer(0, ANNOTATE_BUF, time);
|
||||
@@ -151,6 +161,8 @@ GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_
|
||||
int state;
|
||||
int cpu = get_physical_cpu();
|
||||
|
||||
per_cpu(in_scheduler_context, cpu) = true;
|
||||
|
||||
// do as much work as possible before disabling interrupts
|
||||
cookie = get_exec_cookie(cpu, next);
|
||||
emit_pid_name(next);
|
||||
@@ -163,10 +175,12 @@ GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_
|
||||
}
|
||||
|
||||
per_cpu(collecting, cpu) = 1;
|
||||
collect_counters(gator_get_time());
|
||||
collect_counters(gator_get_time(), prev);
|
||||
per_cpu(collecting, cpu) = 0;
|
||||
|
||||
marshal_sched_trace_switch(next->tgid, next->pid, cookie, state);
|
||||
|
||||
per_cpu(in_scheduler_context, cpu) = false;
|
||||
}
|
||||
|
||||
GATOR_DEFINE_PROBE(sched_process_free, TP_PROTO(struct task_struct *p))
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
/*
|
||||
* This confidential and proprietary software may be used only as
|
||||
* authorised by a licensing agreement from ARM Limited
|
||||
* (C) COPYRIGHT 2013 ARM Limited
|
||||
* ALL RIGHTS RESERVED
|
||||
* The entire notice above must be reproduced on all authorised
|
||||
* copies and copies may only be made to the extent permitted
|
||||
* by a licensing agreement from ARM Limited.
|
||||
/**
|
||||
* Copyright (C) ARM Limited 2013. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MALI_MJOLLNIR_PROFILING_GATOR_API_H__
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
/*
|
||||
* This confidential and proprietary software may be used only as
|
||||
* authorised by a licensing agreement from ARM Limited
|
||||
* (C) COPYRIGHT 2013 ARM Limited
|
||||
* ALL RIGHTS RESERVED
|
||||
* The entire notice above must be reproduced on all authorised
|
||||
* copies and copies may only be made to the extent permitted
|
||||
* by a licensing agreement from ARM Limited.
|
||||
/**
|
||||
* Copyright (C) ARM Limited 2013. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MALI_UTGARD_PROFILING_GATOR_API_H__
|
||||
|
||||
@@ -9,16 +9,17 @@ EXTRA_CFLAGS += -DMALI_USE_UMP=1 \
|
||||
-DMALI_BACKEND_KERNEL=1 \
|
||||
-DMALI_NO_MALI=0
|
||||
|
||||
KBASE_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase
|
||||
OSK_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase/osk
|
||||
UMP_DIR = $(DDK_DIR)/kernel/include/linux
|
||||
DDK_DIR ?= .
|
||||
KBASE_DIR = $(DDK_DIR)/drivers/gpu/arm/t6xx/kbase
|
||||
OSK_DIR = $(DDK_DIR)/drivers/gpu/arm/t6xx/kbase/osk
|
||||
UMP_DIR = $(DDK_DIR)/include/linux
|
||||
|
||||
# Include directories in the DDK
|
||||
EXTRA_CFLAGS += -I$(DDK_DIR) \
|
||||
EXTRA_CFLAGS += -I$(KBASE_DIR)/ \
|
||||
-I$(KBASE_DIR)/.. \
|
||||
-I$(OSK_DIR)/.. \
|
||||
-I$(UMP_DIR)/.. \
|
||||
-I$(DDK_DIR)/kernel/include \
|
||||
-I$(DDK_DIR)/include \
|
||||
-I$(KBASE_DIR)/osk/src/linux/include \
|
||||
-I$(KBASE_DIR)/platform_dummy \
|
||||
-I$(KBASE_DIR)/src
|
||||
|
||||
@@ -193,6 +193,17 @@ bool Buffer::eventHeader (const uint64_t curr_time) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool Buffer::eventTid (const int tid) {
|
||||
bool retval = false;
|
||||
if (checkSpace(2*MAXSIZE_PACK32)) {
|
||||
packInt(1); // key of 1 indicates a tid
|
||||
packInt(tid);
|
||||
retval = true;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void Buffer::event (const int32_t key, const int32_t value) {
|
||||
if (checkSpace(2 * MAXSIZE_PACK32)) {
|
||||
packInt(key);
|
||||
|
||||
@@ -32,6 +32,7 @@ public:
|
||||
void frame ();
|
||||
|
||||
bool eventHeader (uint64_t curr_time);
|
||||
bool eventTid (int tid);
|
||||
void event (int32_t key, int32_t value);
|
||||
void event64 (int64_t key, int64_t value);
|
||||
|
||||
@@ -56,6 +57,10 @@ private:
|
||||
char *const buf;
|
||||
uint64_t commitTime;
|
||||
sem_t *const readerSem;
|
||||
|
||||
// Intentionally unimplemented
|
||||
Buffer(const Buffer &);
|
||||
Buffer &operator=(const Buffer &);
|
||||
};
|
||||
|
||||
#endif // BUFFER_H
|
||||
|
||||
@@ -86,7 +86,7 @@ static void child_handler(int signum) {
|
||||
}
|
||||
}
|
||||
|
||||
static void* durationThread(void* pVoid) {
|
||||
static void *durationThread(void *) {
|
||||
prctl(PR_SET_NAME, (unsigned long)&"gatord-duration", 0, 0, 0);
|
||||
sem_wait(&startProfile);
|
||||
if (gSessionData->mSessionIsActive) {
|
||||
@@ -102,7 +102,7 @@ static void* durationThread(void* pVoid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void* stopThread(void* pVoid) {
|
||||
static void *stopThread(void *) {
|
||||
OlySocket* socket = child->socket;
|
||||
|
||||
prctl(PR_SET_NAME, (unsigned long)&"gatord-stopper", 0, 0, 0);
|
||||
@@ -139,7 +139,7 @@ static void* stopThread(void* pVoid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* countersThread(void* pVoid) {
|
||||
static void *countersThread(void *) {
|
||||
prctl(PR_SET_NAME, (unsigned long)&"gatord-counters", 0, 0, 0);
|
||||
|
||||
gSessionData->hwmon.start();
|
||||
@@ -192,7 +192,7 @@ void* countersThread(void* pVoid) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void* senderThread(void* pVoid) {
|
||||
static void *senderThread(void *) {
|
||||
int length = 1;
|
||||
char* data;
|
||||
char end_sequence[] = {RESPONSE_APC_DATA, 0, 0, 0, 0};
|
||||
@@ -340,7 +340,8 @@ void Child::run() {
|
||||
thread_creation_success = false;
|
||||
}
|
||||
|
||||
if (gSessionData->hwmon.countersEnabled()) {
|
||||
bool startcountersThread = gSessionData->hwmon.countersEnabled();
|
||||
if (startcountersThread) {
|
||||
if (pthread_create(&countersThreadID, NULL, countersThread, this)) {
|
||||
thread_creation_success = false;
|
||||
}
|
||||
@@ -378,7 +379,7 @@ void Child::run() {
|
||||
} while (bytesCollected > 0);
|
||||
logg->logMessage("Exit collect data loop");
|
||||
|
||||
if (gSessionData->hwmon.countersEnabled()) {
|
||||
if (startcountersThread) {
|
||||
pthread_join(countersThreadID, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,10 @@ private:
|
||||
int mNumConnections;
|
||||
|
||||
void initialization();
|
||||
|
||||
// Intentionally unimplemented
|
||||
Child(const Child &);
|
||||
Child &operator=(const Child &);
|
||||
};
|
||||
|
||||
#endif //__CHILD_H__
|
||||
|
||||
@@ -29,6 +29,10 @@ private:
|
||||
int parse(const char* xmlFile);
|
||||
int configurationsTag(mxml_node_t *node);
|
||||
void configurationTag(mxml_node_t *node);
|
||||
|
||||
// Intentionally unimplemented
|
||||
ConfigurationXML(const ConfigurationXML &);
|
||||
ConfigurationXML &operator=(const ConfigurationXML &);
|
||||
};
|
||||
|
||||
#endif // COUNTERS_H
|
||||
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
// Emits available counters
|
||||
virtual void writeCounters(mxml_node_t *root) const = 0;
|
||||
// Emits possible dynamically generated events/counters
|
||||
virtual void writeEvents(mxml_node_t *root) const {}
|
||||
virtual void writeEvents(mxml_node_t *) const {}
|
||||
|
||||
Driver *getNext() const { return next; }
|
||||
|
||||
@@ -39,6 +39,10 @@ protected:
|
||||
private:
|
||||
static Driver *head;
|
||||
Driver *next;
|
||||
|
||||
// Intentionally unimplemented
|
||||
Driver(const Driver &);
|
||||
Driver &operator=(const Driver &);
|
||||
};
|
||||
|
||||
#endif // DRIVER_H
|
||||
|
||||
@@ -39,6 +39,10 @@ private:
|
||||
sem_t* mReaderSem;
|
||||
char* mBuffer;
|
||||
bool mEnd;
|
||||
|
||||
// Intentionally unimplemented
|
||||
Fifo(const Fifo &);
|
||||
Fifo &operator=(const Fifo &);
|
||||
};
|
||||
|
||||
#endif //__FIFO_H__
|
||||
|
||||
@@ -63,6 +63,10 @@ private:
|
||||
double previous_value;
|
||||
|
||||
sensors_subfeature_type input;
|
||||
|
||||
// Intentionally unimplemented
|
||||
HwmonCounter(const HwmonCounter &);
|
||||
HwmonCounter &operator=(const HwmonCounter &);
|
||||
};
|
||||
|
||||
HwmonCounter::HwmonCounter(HwmonCounter *next, int key, const sensors_chip_name *chip, const sensors_feature *feature) : next(next), key(key), polled(false), readable(false), enabled(false), duplicate(false), chip(chip), feature(feature) {
|
||||
|
||||
@@ -34,6 +34,10 @@ private:
|
||||
HwmonCounter *findCounter(const Counter &counter) const;
|
||||
|
||||
HwmonCounter *counters;
|
||||
|
||||
// Intentionally unimplemented
|
||||
Hwmon(const Hwmon &);
|
||||
Hwmon &operator=(const Hwmon &);
|
||||
};
|
||||
|
||||
#endif // HWMON_H
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <stdio.h>
|
||||
#ifdef WIN32
|
||||
#include <Winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -126,11 +127,17 @@ void OlySocket::createSingleServerConnection(int port) {
|
||||
}
|
||||
|
||||
void OlySocket::createServerSocket(int port) {
|
||||
int family = AF_INET6;
|
||||
|
||||
// Create socket
|
||||
mFDServer = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
mFDServer = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (mFDServer < 0) {
|
||||
logg->logError(__FILE__, __LINE__, "Error creating server socket");
|
||||
handleException();
|
||||
family = AF_INET;
|
||||
mFDServer = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (mFDServer < 0) {
|
||||
logg->logError(__FILE__, __LINE__, "Error creating server socket");
|
||||
handleException();
|
||||
}
|
||||
}
|
||||
|
||||
// Enable address reuse, another solution would be to create the server socket once and only close it when the object exits
|
||||
@@ -141,11 +148,11 @@ void OlySocket::createServerSocket(int port) {
|
||||
}
|
||||
|
||||
// Create sockaddr_in structure, ensuring non-populated fields are zero
|
||||
struct sockaddr_in sockaddr;
|
||||
memset((void*)&sockaddr, 0, sizeof(struct sockaddr_in));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
sockaddr.sin_port = htons(port);
|
||||
sockaddr.sin_addr.s_addr = INADDR_ANY;
|
||||
struct sockaddr_in6 sockaddr;
|
||||
memset((void*)&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin6_family = family;
|
||||
sockaddr.sin6_port = htons(port);
|
||||
sockaddr.sin6_addr = in6addr_any;
|
||||
|
||||
// Bind the socket to an address
|
||||
if (bind(mFDServer, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) {
|
||||
|
||||
@@ -33,6 +33,10 @@ private:
|
||||
FILE* mDataFile;
|
||||
char* mDataFileName;
|
||||
pthread_mutex_t mSendMutex;
|
||||
|
||||
// Intentionally unimplemented
|
||||
Sender(const Sender &);
|
||||
Sender &operator=(const Sender &);
|
||||
};
|
||||
|
||||
#endif //__SENDER_H__
|
||||
|
||||
@@ -44,13 +44,13 @@ void SessionData::parseSessionXML(char* xmlString) {
|
||||
SessionXML session(xmlString);
|
||||
session.parse();
|
||||
|
||||
// Set session data values
|
||||
// Set session data values - use prime numbers just below the desired value to reduce the chance of events firing at the same time
|
||||
if (strcmp(session.parameters.sample_rate, "high") == 0) {
|
||||
mSampleRate = 10000;
|
||||
mSampleRate = 9973; // 10000
|
||||
} else if (strcmp(session.parameters.sample_rate, "normal") == 0) {
|
||||
mSampleRate = 1000;
|
||||
mSampleRate = 997; // 1000
|
||||
} else if (strcmp(session.parameters.sample_rate, "low") == 0) {
|
||||
mSampleRate = 100;
|
||||
mSampleRate = 97; // 100
|
||||
} else if (strcmp(session.parameters.sample_rate, "none") == 0) {
|
||||
mSampleRate = 0;
|
||||
} else {
|
||||
@@ -139,7 +139,9 @@ void SessionData::readCpuInfo() {
|
||||
}
|
||||
|
||||
int getEventKey() {
|
||||
// Start one after the gator.ko's value of 1
|
||||
// key 0 is reserved as a timestamp
|
||||
// key 1 is reserved as the marker for thread specific counters
|
||||
// Odd keys are assigned by the driver, even keys by the daemon
|
||||
static int key = 2;
|
||||
|
||||
const int ret = key;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#define MAX_PERFORMANCE_COUNTERS 50
|
||||
|
||||
#define PROTOCOL_VERSION 16
|
||||
#define PROTOCOL_VERSION 17
|
||||
#define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions
|
||||
|
||||
struct ImageLinkList {
|
||||
@@ -62,6 +62,10 @@ public:
|
||||
|
||||
private:
|
||||
void readCpuInfo();
|
||||
|
||||
// Intentionally unimplemented
|
||||
SessionData(const SessionData &);
|
||||
SessionData &operator=(const SessionData &);
|
||||
};
|
||||
|
||||
extern SessionData* gSessionData;
|
||||
|
||||
@@ -33,6 +33,10 @@ private:
|
||||
char* mPath;
|
||||
void sessionTag(mxml_node_t *tree, mxml_node_t *node);
|
||||
void sessionImage(mxml_node_t *node);
|
||||
|
||||
// Intentionally unimplemented
|
||||
SessionXML(const SessionXML &);
|
||||
SessionXML &operator=(const SessionXML &);
|
||||
};
|
||||
|
||||
#endif // SESSION_XML_H
|
||||
|
||||
@@ -38,6 +38,10 @@ private:
|
||||
void sendDefaults();
|
||||
void sendCounters();
|
||||
void writeConfiguration(char* xml);
|
||||
|
||||
// Intentionally unimplemented
|
||||
StreamlineSetup(const StreamlineSetup &);
|
||||
StreamlineSetup &operator=(const StreamlineSetup &);
|
||||
};
|
||||
|
||||
#endif //__STREAMLINE_SETUP_H__
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# -std=c++0x is the planned new c++ standard
|
||||
# -std=c++98 is the 1998 c++ standard
|
||||
CFLAGS += -O3 -Wall -fno-exceptions -pthread -MMD -DETCDIR=\"/etc\" -Ilibsensors
|
||||
CXXFLAGS += -fno-rtti
|
||||
CXXFLAGS += -fno-rtti -Wextra # -Weffc++
|
||||
ifeq ($(WERROR),1)
|
||||
CFLAGS += -Werror
|
||||
endif
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<event event="0x04" option_set="Slave" title="CCI-400" name="Read: cache" description="Read request handshake: cache maintenance operation, CleanInvalid, CleanShared, MakeInvalid"/>
|
||||
<event event="0x05" option_set="Slave" title="CCI-400" name="Read: memory barrier" description="Read request handshake: memory barrier"/>
|
||||
<event event="0x06" option_set="Slave" title="CCI-400" name="Read: sync barrier" description="Read request handshake: synchronization barrier"/>
|
||||
<event event="0x07" option_set="Slave" title="CCI-400" name="Read: DVM message, no sync" description="Read request handshake: DVM message, no synchronization"/>
|
||||
<event event="0x07" option_set="Slave" title="CCI-400" name="Read: DVM message, no sync" description="Read request handshake: DVM message, not synchronization"/>
|
||||
<event event="0x08" option_set="Slave" title="CCI-400" name="Read: DVM message, sync" description="Read request handshake: DVM message, synchronization"/>
|
||||
<event event="0x09" option_set="Slave" title="CCI-400" name="Read: stall" description="Read request stall cycle because the transaction tracker is full. Increase SIx_R_MAX to avoid this stall"/>
|
||||
<event event="0x0a" option_set="Slave" title="CCI-400" name="Read data last handshake" description="Read data last handshake: data returned from the snoop instead of from downstream"/>
|
||||
@@ -45,3 +45,63 @@
|
||||
<event event="0x19" option_set="Master" title="CCI-400" name="Write stall: barrier hazard" description="Write request stall cycle because of a barrier hazard"/>
|
||||
<event event="0x1a" option_set="Master" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase MIx_W_MAX to avoid this stall. See the CoreLink CCI-400 Cache Coherent Interconnect Integration Manual"/>
|
||||
</category>
|
||||
|
||||
<counter_set name="cci-400-r1_cnt" count="4"/>
|
||||
<category name="CCI-400" counter_set="cci-400-r1_cnt" per_cpu="no" supports_event_based_sampling="yes">
|
||||
<event counter="cci-400-r1_ccnt" event="0xff" title="CCI-400 Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
|
||||
|
||||
<option_set name="Slave">
|
||||
<option event_delta="0x00" name="S0" description="Slave interface 0"/>
|
||||
<option event_delta="0x20" name="S1" description="Slave interface 1"/>
|
||||
<option event_delta="0x40" name="S2" description="Slave interface 2"/>
|
||||
<option event_delta="0x60" name="S3" description="Slave interface 3"/>
|
||||
<option event_delta="0x80" name="S4" description="Slave interface 4"/>
|
||||
</option_set>
|
||||
|
||||
<event event="0x00" option_set="Slave" title="CCI-400" name="Read: any" description="Read request handshake: any"/>
|
||||
<event event="0x01" option_set="Slave" title="CCI-400" name="Read: transaction" description="Read request handshake: device transaction"/>
|
||||
<event event="0x02" option_set="Slave" title="CCI-400" name="Read: normal" description="Read request handshake: normal, non-shareable or system-shareable, but not barrier or cache maintenance operation"/>
|
||||
<event event="0x03" option_set="Slave" title="CCI-400" name="Read: shareable" description="Read request handshake: inner- or outer-shareable, but not barrier, DVM message or cache maintenance operation"/>
|
||||
<event event="0x04" option_set="Slave" title="CCI-400" name="Read: cache" description="Read request handshake: cache maintenance operation"/>
|
||||
<event event="0x05" option_set="Slave" title="CCI-400" name="Read: memory barrier" description="Read request handshake: memory barrier"/>
|
||||
<event event="0x06" option_set="Slave" title="CCI-400" name="Read: sync barrier" description="Read request handshake: synchronization barrier"/>
|
||||
<event event="0x07" option_set="Slave" title="CCI-400" name="Read: DVM message, no sync" description="Read request handshake: DVM message, not synchronization"/>
|
||||
<event event="0x08" option_set="Slave" title="CCI-400" name="Read: DVM message, sync" description="Read request handshake: DVM message, synchronization"/>
|
||||
<event event="0x09" option_set="Slave" title="CCI-400" name="Read: stall" description="Read request stall cycle because the transaction tracker is full. Increase SIx_R_MAX to avoid this stall"/>
|
||||
<event event="0x0a" option_set="Slave" title="CCI-400" name="Read data last handshake" description="Read data last handshake: data returned from the snoop instead of from downstream"/>
|
||||
<event event="0x0b" option_set="Slave" title="CCI-400" name="Read data stall cycle" description="Read data stall cycle: RVALIDS is HIGH, RREADYS is LOW"/>
|
||||
<event event="0x0c" option_set="Slave" title="CCI-400" name="Write: any" description="Write request handshake: any"/>
|
||||
<event event="0x0d" option_set="Slave" title="CCI-400" name="Write: transaction" description="Write request handshake: device transaction"/>
|
||||
<event event="0x0e" option_set="Slave" title="CCI-400" name="Write: normal" description="Write request handshake: normal, non-shareable, or system-shareable, but not barrier"/>
|
||||
<event event="0x0f" option_set="Slave" title="CCI-400" name="Write: shareable" description="Write request handshake: inner- or outer-shareable, WriteBack or WriteClean"/>
|
||||
<event event="0x10" option_set="Slave" title="CCI-400" name="Write: WriteUnique" description="Write request handshake: WriteUnique"/>
|
||||
<event event="0x11" option_set="Slave" title="CCI-400" name="Write: WriteLineUnique" description="Write request handshake: WriteLineUnique"/>
|
||||
<event event="0x12" option_set="Slave" title="CCI-400" name="Write: Evict" description="Write request handshake: Evict"/>
|
||||
<event event="0x13" option_set="Slave" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase SIx_W_MAX to avoid this stall"/>
|
||||
<event event="0x14" option_set="Slave" title="CCI-400" name="Read stall: slave hazard" description="Read request stall cycle because of a slave interface ID hazard"/>
|
||||
|
||||
<option_set name="Master">
|
||||
<option event_delta="0xa0" name="M0" description="Master interface 0"/>
|
||||
<option event_delta="0xc0" name="M1" description="Master interface 1"/>
|
||||
<option event_delta="0xe0" name="M2" description="Master interface 2"/>
|
||||
</option_set>
|
||||
|
||||
<event event="0x00" option_set="Master" title="CCI-400" name="Retry fetch" description="RETRY of speculative fetch transaction"/>
|
||||
<event event="0x01" option_set="Master" title="CCI-400" name="Read stall: address hazard" description="Stall cycle because of an address hazard. A read or write invalidation is stalled because of an outstanding transaction to an overlapping address"/>
|
||||
<event event="0x02" option_set="Master" title="CCI-400" name="Read stall: ID hazard" description="Read request stall cycle because of a master interface ID hazard"/>
|
||||
<event event="0x03" option_set="Master" title="CCI-400" name="Read stall: tracker full" description="A read request with a QoS value in the high priority group is stalled for a cycle because the read transaction queue is full. Increase MIx_R_MAX to avoid this stall"/>
|
||||
<event event="0x04" option_set="Master" title="CCI-400" name="Read stall: barrier hazard" description="Read request stall cycle because of a barrier hazard"/>
|
||||
<event event="0x05" option_set="Master" title="CCI-400" name="Write stall: barrier hazard" description="Write request stall cycle because of a barrier hazard"/>
|
||||
<event event="0x06" option_set="Master" title="CCI-400" name="Write stall: tracker full" description="A write request is stalled for a cycle because the write transaction tracker is full. Increase MIx_W_MAX to avoid this stall"/>
|
||||
<event event="0x07" option_set="Master" title="CCI-400" name="Read Stall: Low Priority" description="A read request with a QoS value in the low priority group is stalled for a cycle because there are no slots available in the read queue for the low priority group"/>
|
||||
<event event="0x08" option_set="Master" title="CCI-400" name="Read Stall: Medium Priority" description="A read request with a QoS value in the medium priority group is stalled for a cycle because there are no slots available in the read queue for the medium priority group"/>
|
||||
<event event="0x09" option_set="Master" title="CCI-400" name="Read Stall: VN0" description="A read request is stalled for a cycle while it was waiting for a QVN token on VN0"/>
|
||||
<event event="0x0a" option_set="Master" title="CCI-400" name="Read Stall: VN1" description="A read request is stalled for a cycle while it was waiting for a QVN token on VN1"/>
|
||||
<event event="0x0b" option_set="Master" title="CCI-400" name="Read Stall: VN2" description="A read request is stalled for a cycle while it was waiting for a QVN token on VN2"/>
|
||||
<event event="0x0c" option_set="Master" title="CCI-400" name="Read Stall: VN3" description="A read request is stalled for a cycle while it was waiting for a QVN token on VN3"/>
|
||||
<event event="0x0d" option_set="Master" title="CCI-400" name="Write Stall: VN0" description="A write request is stalled for a cycle while it was waiting for a QVN token on VN0"/>
|
||||
<event event="0x0e" option_set="Master" title="CCI-400" name="Write Stall: VN1" description="A write request is stalled for a cycle while it was waiting for a QVN token on VN1"/>
|
||||
<event event="0x0f" option_set="Master" title="CCI-400" name="Write Stall: VN2" description="A write request is stalled for a cycle while it was waiting for a QVN token on VN2"/>
|
||||
<event event="0x10" option_set="Master" title="CCI-400" name="Write Stall: VN" description="A write request is stalled for a cycle while it was waiting for a QVN token on VN"/>
|
||||
<event event="0x11" option_set="Master" title="CCI-400" name="WriteUnique or WriteLineUnique Stall" description="A WriteUnique or WriteLineUnique request is stalled for a cycle because of an address hazard"/>
|
||||
</category>
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
<event counter="Linux_net_rx" title="Network" name="Receive" units="B" description="Receive network traffic, including effect from Streamline"/>
|
||||
<event counter="Linux_net_tx" title="Network" name="Transmit" units="B" description="Transmit network traffic, including effect from Streamline"/>
|
||||
<event counter="Linux_sched_switch" title="Scheduler" name="Switch" per_cpu="yes" description="Context switch events"/>
|
||||
<event counter="Linux_meminfo_memused" title="Memory" name="Used" display="maximum" units="B" average_selection="yes" description="Total used memory size"/>
|
||||
<event counter="Linux_meminfo_memfree" title="Memory" name="Free" display="minimum" units="B" average_selection="yes" description="Available memory size"/>
|
||||
<event counter="Linux_meminfo_bufferram" title="Memory" name="Buffer" display="maximum" units="B" average_selection="yes" description="Memory used by OS disk buffers"/>
|
||||
<event counter="Linux_power_cpu_freq" title="Clock" name="Frequency" per_cpu="yes" display="maximum" units="Hz" series_composition="overlay" average_selection="yes" average_cores="yes" description="Frequency setting of the CPU"/>
|
||||
<event counter="Linux_power_cpu_idle" title="Idle" name="State" per_cpu="yes" display="maximum" average_selection="yes" description="CPU Idle State + 1, set the Sample Rate to None to prevent the hrtimer from interrupting the system"/>
|
||||
<event counter="Linux_meminfo_memused" title="Memory" name="Used" display="maximum" units="B" proc="yes" description="Total used memory size. Note: a process' used memory includes shared memory that may be counted more than once (equivalent to RES from top). Kernel threads are not filterable."/>
|
||||
<event counter="Linux_meminfo_memfree" title="Memory" name="Free" display="minimum" units="B" description="Available memory size"/>
|
||||
<event counter="Linux_meminfo_bufferram" title="Memory" name="Buffer" display="maximum" units="B" description="Memory used by OS disk buffers"/>
|
||||
<event counter="Linux_power_cpu_freq" title="Clock" name="Frequency" per_cpu="yes" display="maximum" units="Hz" series_composition="overlay" average_cores="yes" description="Frequency setting of the CPU"/>
|
||||
<event counter="Linux_power_cpu_idle" title="Idle" name="State" per_cpu="yes" display="maximum" description="CPU Idle State + 1, set the Sample Rate to None to prevent the hrtimer from interrupting the system"/>
|
||||
<event counter="Linux_cpu_wait_contention" title="CPU Contention" name="Wait" per_cpu="no" display="average" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" description="Thread waiting on contended resource"/>
|
||||
<event counter="Linux_cpu_wait_io" title="CPU I/O" name="Wait" per_cpu="no" display="average" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" description="Thread waiting on I/O resource"/>
|
||||
</category>
|
||||
|
||||
@@ -36,3 +36,13 @@
|
||||
<event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_2" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 2" description="Reports the number of newly allocated pages after a MMU page fault in address space 2."/>
|
||||
<event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_3" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 3" description="Reports the number of newly allocated pages after a MMU page fault in address space 3."/>
|
||||
</category>
|
||||
|
||||
<counter_set name="ARM_Mali-T6xx_Filmstrip_cnt" count="1"/>
|
||||
<category name="ARM Mali-T6xx Filmstrip" counter_set="ARM_Mali-T6xx_Filmstrip_cnt" per_cpu="no">
|
||||
<option_set name="fs">
|
||||
<option event_delta="0x3c" name="1:60" description="captures every 60th frame"/>
|
||||
<option event_delta="0x1e" name="1:30" description="captures every 30th frame"/>
|
||||
<option event_delta="0xa" name="1:10" description="captures every 10th frame"/>
|
||||
</option_set>
|
||||
<event event="0x0400" option_set="fs" title="ARM Mali-T6xx" name="Filmstrip" description="Scaled framebuffer"/>
|
||||
</category>
|
||||
|
||||
@@ -60,12 +60,15 @@
|
||||
|
||||
<event counter="ARM_Mali-T6xx_FRAG_THREADS" title="Mali Core Threads" name="Fragment threads" description="Number of fragment threads started"/>
|
||||
<event counter="ARM_Mali-T6xx_FRAG_DUMMY_THREADS" title="Mali Core Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
|
||||
<event counter="ARM_Mali-T6xx_COMPUTE_THREADS" title="Mali Core Threads" name="Compute threads" description="Number of vertex\compute threads started"/>
|
||||
<event counter="ARM_Mali-T6xx_FRAG_QUADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/>
|
||||
<event counter="ARM_Mali-T6xx_FRAG_QUADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/>
|
||||
<event counter="ARM_Mali-T6xx_FRAG_THREADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/>
|
||||
<event counter="ARM_Mali-T6xx_FRAG_THREADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/>
|
||||
|
||||
<event counter="ARM_Mali-T6xx_COMPUTE_TASKS" title="Mali Compute Threads" name="Compute tasks" description="Number of compute tasks"/>
|
||||
<event counter="ARM_Mali-T6xx_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads started" description="Number of compute threads started"/>
|
||||
<event counter="ARM_Mali-T6xx_COMPUTE_CYCLES_DESC" title="Mali Compute Threads" name="Compute cycles awaiting descriptors" description="Number of compute cycles spent waiting for descriptors"/>
|
||||
|
||||
<event counter="ARM_Mali-T6xx_FRAG_PRIMATIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
|
||||
<event counter="ARM_Mali-T6xx_FRAG_PRIMATIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
|
||||
<event counter="ARM_Mali-T6xx_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
|
||||
|
||||
@@ -93,7 +93,7 @@ static void handler(int signum) {
|
||||
}
|
||||
|
||||
// Child exit Signal Handler
|
||||
static void child_exit(int signum) {
|
||||
static void child_exit(int) {
|
||||
int status;
|
||||
int pid = wait(&status);
|
||||
if (pid != -1) {
|
||||
@@ -106,13 +106,18 @@ static void child_exit(int signum) {
|
||||
|
||||
static int udpPort(int port) {
|
||||
int s;
|
||||
struct sockaddr_in sockaddr;
|
||||
struct sockaddr_in6 sockaddr;
|
||||
int on;
|
||||
int family = AF_INET6;
|
||||
|
||||
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (s == -1) {
|
||||
logg->logError(__FILE__, __LINE__, "socket failed");
|
||||
handleException();
|
||||
family = AF_INET;
|
||||
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (s == -1) {
|
||||
logg->logError(__FILE__, __LINE__, "socket failed");
|
||||
handleException();
|
||||
}
|
||||
}
|
||||
|
||||
on = 1;
|
||||
@@ -122,9 +127,9 @@ static int udpPort(int port) {
|
||||
}
|
||||
|
||||
memset((void*)&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
sockaddr.sin_port = htons(port);
|
||||
sockaddr.sin_addr.s_addr = INADDR_ANY;
|
||||
sockaddr.sin6_family = family;
|
||||
sockaddr.sin6_port = htons(port);
|
||||
sockaddr.sin6_addr = in6addr_any;
|
||||
if (bind(s, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) {
|
||||
logg->logError(__FILE__, __LINE__, "socket failed");
|
||||
handleException();
|
||||
@@ -173,7 +178,7 @@ static void* answerThread(void* pVoid) {
|
||||
|
||||
for (;;) {
|
||||
char buf[128];
|
||||
struct sockaddr_in sockaddr;
|
||||
struct sockaddr_in6 sockaddr;
|
||||
socklen_t addrlen;
|
||||
int read;
|
||||
addrlen = sizeof(sockaddr);
|
||||
@@ -386,7 +391,7 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) {
|
||||
}
|
||||
|
||||
// Gator data flow: collector -> collector fifo -> sender
|
||||
int main(int argc, char** argv, char* envp[]) {
|
||||
int main(int argc, char** argv) {
|
||||
// Ensure proper signal handling by making gatord the process group leader
|
||||
// e.g. it may not be the group leader when launched as 'sudo gatord'
|
||||
setsid();
|
||||
|
||||
Reference in New Issue
Block a user