summaryrefslogtreecommitdiffstats
path: root/driver
diff options
context:
space:
mode:
authorJon Medhurst2012-10-26 11:05:14 -0500
committerJon Medhurst2012-10-26 11:05:14 -0500
commite17241f3e69b79e9470797e0dcc2a34094b542c7 (patch)
treeab36ba48e1bc766b691b26de3983b5c725bce72a /driver
parent1963aa53d43ccd827335b28ba2c7e25300065e6c (diff)
downloadarm-ds5-gator-e17241f3e69b79e9470797e0dcc2a34094b542c7.tar.gz
arm-ds5-gator-e17241f3e69b79e9470797e0dcc2a34094b542c7.tar.xz
arm-ds5-gator-e17241f3e69b79e9470797e0dcc2a34094b542c7.zip
gator: Version 5.12
Signed-off-by: Jon Medhurst <tixy@linaro.org>
Diffstat (limited to 'driver')
-rw-r--r--driver/Makefile4
-rw-r--r--driver/gator.h25
-rw-r--r--driver/gator_annotate.c39
-rw-r--r--driver/gator_annotate_kernel.c89
-rw-r--r--driver/gator_backtrace.c15
-rw-r--r--driver/gator_cookies.c52
-rw-r--r--driver/gator_ebs.c156
-rw-r--r--driver/gator_events_block.c70
-rw-r--r--driver/gator_events_mali_400.c10
-rw-r--r--driver/gator_events_mali_400.h15
-rw-r--r--driver/gator_events_mali_common.c15
-rw-r--r--driver/gator_events_mali_common.h19
-rw-r--r--driver/gator_events_mali_t6xx.c15
-rw-r--r--driver/gator_events_mali_t6xx_hw.c216
-rw-r--r--driver/gator_events_mali_t6xx_hw_test.c57
-rw-r--r--driver/gator_events_mmaped.c8
-rw-r--r--driver/gator_events_net.c4
-rw-r--r--driver/gator_events_perf_pmu.c55
-rw-r--r--driver/gator_main.c258
-rw-r--r--driver/gator_marshaling.c152
-rw-r--r--driver/gator_pack.c25
-rw-r--r--driver/gator_trace_gpu.c37
-rw-r--r--driver/gator_trace_power.c26
-rw-r--r--driver/gator_trace_sched.c17
-rw-r--r--driver/mali_t6xx.mk3
25 files changed, 821 insertions, 561 deletions
diff --git a/driver/Makefile b/driver/Makefile
index 025dd9e..6cafecf 100644
--- a/driver/Makefile
+++ b/driver/Makefile
@@ -27,6 +27,10 @@ gator-y += gator_events_mali_common.o
27EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT) 27EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT)
28endif 28endif
29 29
30# GATOR_TEST controls whether to include (=1) or exclude (=0) test code.
31GATOR_TEST ?= 0
32EXTRA_CFLAGS += -DGATOR_TEST=$(GATOR_TEST)
33
30gator-$(CONFIG_ARM) += gator_events_armv6.o \ 34gator-$(CONFIG_ARM) += gator_events_armv6.o \
31 gator_events_armv7.o \ 35 gator_events_armv7.o \
32 gator_events_l2c-310.o \ 36 gator_events_l2c-310.o \
diff --git a/driver/gator.h b/driver/gator.h
index 6b96109..5a40e17 100644
--- a/driver/gator.h
+++ b/driver/gator.h
@@ -20,19 +20,20 @@
20#define GATOR_CPU_FREQ_SUPPORT (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) && defined(CONFIG_CPU_FREQ) 20#define GATOR_CPU_FREQ_SUPPORT (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) && defined(CONFIG_CPU_FREQ)
21 21
22// cpu ids 22// cpu ids
23#define ARM1136 0xb36 23#define ARM1136 0xb36
24#define ARM1156 0xb56 24#define ARM1156 0xb56
25#define ARM1176 0xb76 25#define ARM1176 0xb76
26#define ARM11MPCORE 0xb02 26#define ARM11MPCORE 0xb02
27#define CORTEX_A5 0xc05 27#define CORTEX_A5 0xc05
28#define CORTEX_A7 0xc07 28#define CORTEX_A7 0xc07
29#define CORTEX_A8 0xc08 29#define CORTEX_A8 0xc08
30#define CORTEX_A9 0xc09 30#define CORTEX_A9 0xc09
31#define CORTEX_A15 0xc0f 31#define CORTEX_A15 0xc0f
32#define SCORPION 0x00f 32#define SCORPION 0x00f
33#define SCORPIONMP 0x02d 33#define SCORPIONMP 0x02d
34#define KRAITSIM 0x049 34#define KRAITSIM 0x049
35#define KRAIT 0x04d 35#define KRAIT 0x04d
36#define AARCH64 0xd0f
36 37
37/****************************************************************************** 38/******************************************************************************
38 * Filesystem 39 * Filesystem
@@ -97,4 +98,6 @@ int gator_events_install(struct gator_interface *interface);
97int gator_events_get_key(void); 98int gator_events_get_key(void);
98extern u32 gator_cpuid(void); 99extern u32 gator_cpuid(void);
99 100
101void gator_backtrace_handler(struct pt_regs * const regs);
102
100#endif // GATOR_H_ 103#endif // GATOR_H_
diff --git a/driver/gator_annotate.c b/driver/gator_annotate.c
index b444789..928e252 100644
--- a/driver/gator_annotate.c
+++ b/driver/gator_annotate.c
@@ -38,26 +38,34 @@ static int annotate_copy(struct file *file, char const __user *buf, size_t count
38 38
39static ssize_t annotate_write(struct file *file, char const __user *buf, size_t count_orig, loff_t *offset) 39static ssize_t annotate_write(struct file *file, char const __user *buf, size_t count_orig, loff_t *offset)
40{ 40{
41 int tid, cpu, header_size, available, contiguous, length1, length2, size, count = count_orig & 0x7fffffff; 41 int pid, cpu, header_size, available, contiguous, length1, length2, size, count = count_orig & 0x7fffffff;
42 42
43 if (*offset) 43 if (*offset) {
44 return -EINVAL; 44 return -EINVAL;
45 }
46
47 // Annotation is not supported in interrupt context
48 if (in_interrupt()) {
49 return -EINVAL;
50 }
45 51
46 if (!collect_annotations) 52 // synchronize between cores and with collect_annotations
53 spin_lock(&annotate_lock);
54
55 if (!collect_annotations) {
47 // Not collecting annotations, tell the caller everything was written 56 // Not collecting annotations, tell the caller everything was written
48 return count_orig; 57 size = count_orig;
58 goto annotate_write_out;
59 }
49 60
50 cpu = 0; // Annotation only uses a single per-cpu buffer as the data must be in order to the engine 61 cpu = 0; // Annotation only uses a single per-cpu buffer as the data must be in order to the engine
51 62
52 if (file == NULL) { 63 if (current == NULL) {
53 tid = -1; // set the thread id to the kernel thread 64 pid = 0;
54 } else { 65 } else {
55 tid = current->pid; 66 pid = current->pid;
56 } 67 }
57 68
58 // synchronize between cores
59 spin_lock(&annotate_lock);
60
61 // determine total size of the payload 69 // determine total size of the payload
62 header_size = MAXSIZE_PACK32 * 3 + MAXSIZE_PACK64; 70 header_size = MAXSIZE_PACK32 * 3 + MAXSIZE_PACK64;
63 available = buffer_bytes_available(cpu, ANNOTATE_BUF) - header_size; 71 available = buffer_bytes_available(cpu, ANNOTATE_BUF) - header_size;
@@ -71,9 +79,9 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t
71 } 79 }
72 80
73 // synchronize shared variables annotateBuf and annotatePos 81 // synchronize shared variables annotateBuf and annotatePos
74 if (collect_annotations && per_cpu(gator_buffer, cpu)[ANNOTATE_BUF]) { 82 if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF]) {
75 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, smp_processor_id()); 83 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, smp_processor_id());
76 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, tid); 84 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid);
77 gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, gator_get_time()); 85 gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, gator_get_time());
78 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, size); 86 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, size);
79 87
@@ -118,9 +126,9 @@ static int annotate_release(struct inode *inode, struct file *file)
118 spin_lock(&annotate_lock); 126 spin_lock(&annotate_lock);
119 127
120 if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF] && buffer_check_space(cpu, ANNOTATE_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) { 128 if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF] && buffer_check_space(cpu, ANNOTATE_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) {
121 uint32_t tid = current->pid; 129 uint32_t pid = current->pid;
122 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, smp_processor_id()); 130 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, smp_processor_id());
123 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, tid); 131 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid);
124 gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0); // time 132 gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0); // time
125 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0); // size 133 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0); // size
126 } 134 }
@@ -148,5 +156,8 @@ static int gator_annotate_start(void)
148 156
149static void gator_annotate_stop(void) 157static void gator_annotate_stop(void)
150{ 158{
159 // the spinlock here will ensure that when this function exits, we are not in the middle of an annotation
160 spin_lock(&annotate_lock);
151 collect_annotations = false; 161 collect_annotations = false;
162 spin_unlock(&annotate_lock);
152} 163}
diff --git a/driver/gator_annotate_kernel.c b/driver/gator_annotate_kernel.c
index ffab087..bc68fa8 100644
--- a/driver/gator_annotate_kernel.c
+++ b/driver/gator_annotate_kernel.c
@@ -7,50 +7,83 @@
7 * 7 *
8 */ 8 */
9 9
10static void kannotate_write(char* ptr, unsigned int size) 10#define ESCAPE_CODE 0x1c
11#define STRING_ANNOTATION 0x03
12#define VISUAL_ANNOTATION 0x04
13#define MARKER_ANNOTATION 0x05
14
15static void kannotate_write(const char* ptr, unsigned int size)
11{ 16{
12 int retval; 17 int retval;
13 int pos = 0; 18 int pos = 0;
14 loff_t offset = 0; 19 loff_t offset = 0;
15 while (pos < size) { 20 while (pos < size) {
16 retval = annotate_write(NULL, &ptr[pos], size - pos, &offset); 21 retval = annotate_write(NULL, &ptr[pos], size - pos, &offset);
17 if (retval < 0) { 22 if (retval < 0) {
18 printk(KERN_WARNING "gator: kannotate_write failed with return value %d\n", retval); 23 printk(KERN_WARNING "gator: kannotate_write failed with return value %d\n", retval);
19 return; 24 return;
20 } 25 }
21 pos += retval; 26 pos += retval;
22 } 27 }
23} 28}
24 29
30static void gator_annotate_code(char code)
31{
32 int header = ESCAPE_CODE | (code << 8);
33 kannotate_write((char*)&header, sizeof(header));
34}
35
36static void gator_annotate_code_str(char code, const char* string)
37{
38 int str_size = strlen(string) & 0xffff;
39 int header = ESCAPE_CODE | (code << 8) | (str_size << 16);
40 kannotate_write((char*)&header, sizeof(header));
41 kannotate_write(string, str_size);
42}
43
44static void gator_annotate_code_color(char code, int color)
45{
46 long long header = (ESCAPE_CODE | (code << 8) | 0x00040000 | ((long long)color << 32));
47 kannotate_write((char*)&header, sizeof(header));
48}
49
50static void gator_annotate_code_color_str(char code, int color, const char* string)
51{
52 int str_size = (strlen(string) + 4) & 0xffff;
53 long long header = ESCAPE_CODE | (code << 8) | (str_size << 16) | ((long long)color << 32);
54 kannotate_write((char*)&header, sizeof(header));
55 kannotate_write(string, str_size - 4);
56}
57
25// String annotation 58// String annotation
26void gator_annotate(char* string) 59void gator_annotate(const char* string)
27{ 60{
28 kannotate_write(string, strlen(string) + 1); 61 gator_annotate_code_str(STRING_ANNOTATION, string);
29} 62}
30EXPORT_SYMBOL(gator_annotate); 63EXPORT_SYMBOL(gator_annotate);
31 64
32// String annotation with color 65// String annotation with color
33void gator_annotate_color(int color, char* string) 66void gator_annotate_color(int color, const char* string)
34{ 67{
35 kannotate_write((char*)&color, sizeof(color)); 68 gator_annotate_code_color_str(STRING_ANNOTATION, color, string);
36 kannotate_write(string, strlen(string) + 1);
37} 69}
38EXPORT_SYMBOL(gator_annotate_color); 70EXPORT_SYMBOL(gator_annotate_color);
39 71
40// Terminate an annotation 72// Terminate an annotation
41void gator_annotate_end(void) 73void gator_annotate_end(void)
42{ 74{
43 char nul = 0; 75 gator_annotate_code(STRING_ANNOTATION);
44 kannotate_write(&nul, sizeof(nul));
45} 76}
46EXPORT_SYMBOL(gator_annotate_end); 77EXPORT_SYMBOL(gator_annotate_end);
47 78
48// Image annotation with optional string 79// Image annotation with optional string
49void gator_annotate_visual(char* data, unsigned int length, char* string) 80void gator_annotate_visual(const char* data, unsigned int length, const char* string)
50{ 81{
51 long long visual_annotation = 0x011c | (strlen(string) << 16) | ((long long)length << 32); 82 int str_size = strlen(string) & 0xffff;
52 kannotate_write((char*)&visual_annotation, 8); 83 int visual_annotation = ESCAPE_CODE | (VISUAL_ANNOTATION << 8) | (str_size << 16);
53 kannotate_write(string, strlen(string)); 84 kannotate_write((char*)&visual_annotation, sizeof(visual_annotation));
85 kannotate_write(string, str_size);
86 kannotate_write((char*)&length, sizeof(length));
54 kannotate_write(data, length); 87 kannotate_write(data, length);
55} 88}
56EXPORT_SYMBOL(gator_annotate_visual); 89EXPORT_SYMBOL(gator_annotate_visual);
@@ -58,33 +91,27 @@ EXPORT_SYMBOL(gator_annotate_visual);
58// Marker annotation 91// Marker annotation
59void gator_annotate_marker(void) 92void gator_annotate_marker(void)
60{ 93{
61 int marker_annotation = 0x00021c; 94 gator_annotate_code(MARKER_ANNOTATION);
62 kannotate_write((char*)&marker_annotation, 3);
63} 95}
64EXPORT_SYMBOL(gator_annotate_marker); 96EXPORT_SYMBOL(gator_annotate_marker);
65 97
66// Marker annotation with a string 98// Marker annotation with a string
67void gator_annotate_marker_str(char* string) 99void gator_annotate_marker_str(const char* string)
68{ 100{
69 int marker_annotation = 0x021c; 101 gator_annotate_code_str(MARKER_ANNOTATION, string);
70 kannotate_write((char*)&marker_annotation, 2);
71 kannotate_write(string, strlen(string) + 1);
72} 102}
73EXPORT_SYMBOL(gator_annotate_marker_str); 103EXPORT_SYMBOL(gator_annotate_marker_str);
74 104
75// Marker annotation with a color 105// Marker annotation with a color
76void gator_annotate_marker_color(int color) 106void gator_annotate_marker_color(int color)
77{ 107{
78 long long marker_annotation = (0x021c | ((long long)color << 16)) & 0x0000ffffffffffffLL; 108 gator_annotate_code_color(MARKER_ANNOTATION, color);
79 kannotate_write((char*)&marker_annotation, 7);
80} 109}
81EXPORT_SYMBOL(gator_annotate_marker_color); 110EXPORT_SYMBOL(gator_annotate_marker_color);
82 111
83// Marker annotationw ith a string and color 112// Marker annotation with a string and color
84void gator_annotate_marker_color_str(int color, char* string) 113void gator_annotate_marker_color_str(int color, const char* string)
85{ 114{
86 long long marker_annotation = 0x021c | ((long long)color << 16); 115 gator_annotate_code_color_str(MARKER_ANNOTATION, color, string);
87 kannotate_write((char*)&marker_annotation, 6);
88 kannotate_write(string, strlen(string) + 1);
89} 116}
90EXPORT_SYMBOL(gator_annotate_marker_color_str); 117EXPORT_SYMBOL(gator_annotate_marker_color_str);
diff --git a/driver/gator_backtrace.c b/driver/gator_backtrace.c
index 50783d6..2173d8a 100644
--- a/driver/gator_backtrace.c
+++ b/driver/gator_backtrace.c
@@ -15,7 +15,7 @@ struct frame_tail_eabi {
15 unsigned long lr; 15 unsigned long lr;
16}; 16};
17 17
18static void arm_backtrace_eabi(int cpu, int buftype, struct pt_regs * const regs, unsigned int depth) 18static void arm_backtrace_eabi(int cpu, struct pt_regs * const regs, unsigned int depth)
19{ 19{
20#if defined(__arm__) 20#if defined(__arm__)
21 struct frame_tail_eabi *tail; 21 struct frame_tail_eabi *tail;
@@ -32,7 +32,7 @@ static void arm_backtrace_eabi(int cpu, int buftype, struct pt_regs * const regs
32 } 32 }
33 33
34 /* entry preamble may not have executed */ 34 /* entry preamble may not have executed */
35 gator_add_trace(cpu, buftype, lr); 35 gator_add_trace(cpu, lr);
36 36
37 /* check tail is valid */ 37 /* check tail is valid */
38 if (fp == 0 || fp < sp) { 38 if (fp == 0 || fp < sp) {
@@ -50,7 +50,7 @@ static void arm_backtrace_eabi(int cpu, int buftype, struct pt_regs * const regs
50 ptrtail = &buftail; 50 ptrtail = &buftail;
51 51
52 lr = ptrtail[0].lr; 52 lr = ptrtail[0].lr;
53 gator_add_trace(cpu, buftype, lr); 53 gator_add_trace(cpu, lr);
54 54
55 /* frame pointers should progress back up the stack, towards higher addresses */ 55 /* frame pointers should progress back up the stack, towards higher addresses */
56 next = (struct frame_tail_eabi *)(lr - 4); 56 next = (struct frame_tail_eabi *)(lr - 4);
@@ -69,16 +69,16 @@ static void arm_backtrace_eabi(int cpu, int buftype, struct pt_regs * const regs
69} 69}
70 70
71#if defined(__arm__) 71#if defined(__arm__)
72static DEFINE_PER_CPU(int, backtrace_buffer);
73static int report_trace(struct stackframe *frame, void *d) 72static int report_trace(struct stackframe *frame, void *d)
74{ 73{
75 struct module *mod; 74 struct module *mod;
76 unsigned int *depth = d, addr = frame->pc, cookie = NO_COOKIE, cpu = smp_processor_id(); 75 unsigned int *depth = d, cookie = NO_COOKIE, cpu = smp_processor_id();
76 unsigned long addr = frame->pc;
77 77
78 if (*depth) { 78 if (*depth) {
79 mod = __module_address(addr); 79 mod = __module_address(addr);
80 if (mod) { 80 if (mod) {
81 cookie = get_cookie(cpu, per_cpu(backtrace_buffer, cpu), current, NULL, mod, true); 81 cookie = get_cookie(cpu, current, NULL, mod, true);
82 addr = addr - (unsigned long)mod->module_core; 82 addr = addr - (unsigned long)mod->module_core;
83 } 83 }
84 marshal_backtrace(addr & ~1, cookie); 84 marshal_backtrace(addr & ~1, cookie);
@@ -91,7 +91,7 @@ static int report_trace(struct stackframe *frame, void *d)
91 91
92// Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile 92// Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile
93// #define GATOR_KERNEL_STACK_UNWINDING 93// #define GATOR_KERNEL_STACK_UNWINDING
94static void kernel_backtrace(int cpu, int buftype, struct pt_regs * const regs) 94static void kernel_backtrace(int cpu, struct pt_regs * const regs)
95{ 95{
96#if defined(__arm__) 96#if defined(__arm__)
97#ifdef GATOR_KERNEL_STACK_UNWINDING 97#ifdef GATOR_KERNEL_STACK_UNWINDING
@@ -106,7 +106,6 @@ static void kernel_backtrace(int cpu, int buftype, struct pt_regs * const regs)
106 frame.sp = regs->ARM_sp; 106 frame.sp = regs->ARM_sp;
107 frame.lr = regs->ARM_lr; 107 frame.lr = regs->ARM_lr;
108 frame.pc = regs->ARM_pc; 108 frame.pc = regs->ARM_pc;
109 per_cpu(backtrace_buffer, cpu) = buftype;
110 walk_stackframe(&frame, report_trace, &depth); 109 walk_stackframe(&frame, report_trace, &depth);
111#else 110#else
112 marshal_backtrace(PC_REG & ~1, NO_COOKIE); 111 marshal_backtrace(PC_REG & ~1, NO_COOKIE);
diff --git a/driver/gator_cookies.c b/driver/gator_cookies.c
index d7d8e84..b2ed686 100644
--- a/driver/gator_cookies.c
+++ b/driver/gator_cookies.c
@@ -12,7 +12,7 @@
12#define MAX_COLLISIONS 2 12#define MAX_COLLISIONS 2
13 13
14static uint32_t *gator_crc32_table; 14static uint32_t *gator_crc32_table;
15static uint32_t translate_buffer_mask; 15static unsigned int translate_buffer_mask;
16 16
17static DEFINE_PER_CPU(char *, translate_text); 17static DEFINE_PER_CPU(char *, translate_text);
18static DEFINE_PER_CPU(uint32_t, cookie_next_key); 18static DEFINE_PER_CPU(uint32_t, cookie_next_key);
@@ -20,9 +20,9 @@ static DEFINE_PER_CPU(uint64_t *, cookie_keys);
20static DEFINE_PER_CPU(uint32_t *, cookie_values); 20static DEFINE_PER_CPU(uint32_t *, cookie_values);
21static DEFINE_PER_CPU(int, translate_buffer_read); 21static DEFINE_PER_CPU(int, translate_buffer_read);
22static DEFINE_PER_CPU(int, translate_buffer_write); 22static DEFINE_PER_CPU(int, translate_buffer_write);
23static DEFINE_PER_CPU(unsigned int *, translate_buffer); 23static DEFINE_PER_CPU(void * *, translate_buffer);
24 24
25static inline uint32_t get_cookie(int cpu, int buftype, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt); 25static inline uint32_t get_cookie(int cpu, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt);
26static void wq_cookie_handler(struct work_struct *unused); 26static void wq_cookie_handler(struct work_struct *unused);
27DECLARE_WORK(cookie_work, wq_cookie_handler); 27DECLARE_WORK(cookie_work, wq_cookie_handler);
28static struct timer_list app_process_wake_up_timer; 28static struct timer_list app_process_wake_up_timer;
@@ -40,16 +40,16 @@ static uint32_t cookiemap_code(uint64_t value64) {
40 40
41static uint32_t gator_chksum_crc32(char *data) 41static uint32_t gator_chksum_crc32(char *data)
42{ 42{
43 register unsigned long crc; 43 register unsigned long crc;
44 unsigned char *block = data; 44 unsigned char *block = data;
45 int i, length = strlen(data); 45 int i, length = strlen(data);
46 46
47 crc = 0xFFFFFFFF; 47 crc = 0xFFFFFFFF;
48 for (i = 0; i < length; i++) { 48 for (i = 0; i < length; i++) {
49 crc = ((crc >> 8) & 0x00FFFFFF) ^ gator_crc32_table[(crc ^ *block++) & 0xFF]; 49 crc = ((crc >> 8) & 0x00FFFFFF) ^ gator_crc32_table[(crc ^ *block++) & 0xFF];
50 } 50 }
51 51
52 return (crc ^ 0xFFFFFFFF); 52 return (crc ^ 0xFFFFFFFF);
53} 53}
54 54
55/* 55/*
@@ -104,15 +104,15 @@ static void cookiemap_add(uint64_t key, uint32_t value) {
104 values[0] = value; 104 values[0] = value;
105} 105}
106 106
107static void translate_buffer_write_int(int cpu, unsigned int x) 107static void translate_buffer_write_ptr(int cpu, void * x)
108{ 108{
109 per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_write, cpu)++] = x; 109 per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_write, cpu)++] = x;
110 per_cpu(translate_buffer_write, cpu) &= translate_buffer_mask; 110 per_cpu(translate_buffer_write, cpu) &= translate_buffer_mask;
111} 111}
112 112
113static unsigned int translate_buffer_read_int(int cpu) 113static void * translate_buffer_read_ptr(int cpu)
114{ 114{
115 unsigned int value = per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_read, cpu)++]; 115 void * value = per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_read, cpu)++];
116 per_cpu(translate_buffer_read, cpu) &= translate_buffer_mask; 116 per_cpu(translate_buffer_read, cpu) &= translate_buffer_mask;
117 return value; 117 return value;
118} 118}
@@ -129,9 +129,9 @@ static void wq_cookie_handler(struct work_struct *unused)
129 if (gator_started != 0) { 129 if (gator_started != 0) {
130 commit = per_cpu(translate_buffer_write, cpu); 130 commit = per_cpu(translate_buffer_write, cpu);
131 while (per_cpu(translate_buffer_read, cpu) != commit) { 131 while (per_cpu(translate_buffer_read, cpu) != commit) {
132 task = (struct task_struct *)translate_buffer_read_int(cpu); 132 task = (struct task_struct *)translate_buffer_read_ptr(cpu);
133 vma = (struct vm_area_struct *)translate_buffer_read_int(cpu); 133 vma = (struct vm_area_struct *)translate_buffer_read_ptr(cpu);
134 cookie = get_cookie(cpu, BACKTRACE_BUF, task, vma, NULL, false); 134 cookie = get_cookie(cpu, task, vma, NULL, false);
135 } 135 }
136 } 136 }
137 137
@@ -163,13 +163,13 @@ static int translate_app_process(char** text, int cpu, struct task_struct * task
163 // Check if already in buffer 163 // Check if already in buffer
164 ptr = per_cpu(translate_buffer_read, cpu); 164 ptr = per_cpu(translate_buffer_read, cpu);
165 while (ptr != per_cpu(translate_buffer_write, cpu)) { 165 while (ptr != per_cpu(translate_buffer_write, cpu)) {
166 if (per_cpu(translate_buffer, cpu)[ptr] == (int)task) 166 if (per_cpu(translate_buffer, cpu)[ptr] == (void *)task)
167 goto out; 167 goto out;
168 ptr = (ptr + 2) & translate_buffer_mask; 168 ptr = (ptr + 2) & translate_buffer_mask;
169 } 169 }
170 170
171 translate_buffer_write_int(cpu, (unsigned int)task); 171 translate_buffer_write_ptr(cpu, (void *)task);
172 translate_buffer_write_int(cpu, (unsigned int)vma); 172 translate_buffer_write_ptr(cpu, (void *)vma);
173 173
174 mod_timer(&app_process_wake_up_timer, jiffies + 1); 174 mod_timer(&app_process_wake_up_timer, jiffies + 1);
175 goto out; 175 goto out;
@@ -222,7 +222,7 @@ out:
222 return retval; 222 return retval;
223} 223}
224 224
225static inline uint32_t get_cookie(int cpu, int buftype, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt) 225static inline uint32_t get_cookie(int cpu, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt)
226{ 226{
227 unsigned long flags, cookie; 227 unsigned long flags, cookie;
228 struct path *path; 228 struct path *path;
@@ -271,7 +271,7 @@ static inline uint32_t get_cookie(int cpu, int buftype, struct task_struct *task
271 return cookie; 271 return cookie;
272} 272}
273 273
274static int get_exec_cookie(int cpu, int buftype, struct task_struct *task) 274static int get_exec_cookie(int cpu, struct task_struct *task)
275{ 275{
276 unsigned long cookie = NO_COOKIE; 276 unsigned long cookie = NO_COOKIE;
277 struct mm_struct *mm = task->mm; 277 struct mm_struct *mm = task->mm;
@@ -286,14 +286,14 @@ static int get_exec_cookie(int cpu, int buftype, struct task_struct *task)
286 continue; 286 continue;
287 if (!(vma->vm_flags & VM_EXECUTABLE)) 287 if (!(vma->vm_flags & VM_EXECUTABLE))
288 continue; 288 continue;
289 cookie = get_cookie(cpu, buftype, task, vma, NULL, true); 289 cookie = get_cookie(cpu, task, vma, NULL, true);
290 break; 290 break;
291 } 291 }
292 292
293 return cookie; 293 return cookie;
294} 294}
295 295
296static unsigned long get_address_cookie(int cpu, int buftype, struct task_struct *task, unsigned long addr, off_t *offset) 296static unsigned long get_address_cookie(int cpu, struct task_struct *task, unsigned long addr, off_t *offset)
297{ 297{
298 unsigned long cookie = NO_COOKIE; 298 unsigned long cookie = NO_COOKIE;
299 struct mm_struct *mm = task->mm; 299 struct mm_struct *mm = task->mm;
@@ -307,7 +307,7 @@ static unsigned long get_address_cookie(int cpu, int buftype, struct task_struct
307 continue; 307 continue;
308 308
309 if (vma->vm_file) { 309 if (vma->vm_file) {
310 cookie = get_cookie(cpu, buftype, task, vma, NULL, true); 310 cookie = get_cookie(cpu, task, vma, NULL, true);
311 *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start; 311 *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start;
312 } else { 312 } else {
313 /* must be an anonymous map */ 313 /* must be an anonymous map */
@@ -350,7 +350,7 @@ static int cookies_initialize(void)
350 } 350 }
351 memset(per_cpu(cookie_values, cpu), 0, size); 351 memset(per_cpu(cookie_values, cpu), 0, size);
352 352
353 per_cpu(translate_buffer, cpu) = (unsigned int *)kmalloc(translate_buffer_size, GFP_KERNEL); 353 per_cpu(translate_buffer, cpu) = (void * *)kmalloc(translate_buffer_size, GFP_KERNEL);
354 if (!per_cpu(translate_buffer, cpu)) { 354 if (!per_cpu(translate_buffer, cpu)) {
355 err = -ENOMEM; 355 err = -ENOMEM;
356 goto cookie_setup_error; 356 goto cookie_setup_error;
diff --git a/driver/gator_ebs.c b/driver/gator_ebs.c
deleted file mode 100644
index 6abdfa4..0000000
--- a/driver/gator_ebs.c
+++ /dev/null
@@ -1,156 +0,0 @@
1/**
2 * Copyright (C) ARM Limited 2012. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 */
9
10#if defined(__arm__) && (GATOR_PERF_PMU_SUPPORT)
11#include <linux/platform_device.h>
12#include <linux/interrupt.h>
13#include <linux/irq.h>
14
15#include <asm/pmu.h>
16
17static DEFINE_MUTEX(perf_mutex);
18
19extern int pmnc_counters;
20extern int ccnt;
21extern unsigned long pmnc_enabled[];
22extern unsigned long pmnc_event[];
23extern unsigned long pmnc_count[];
24extern unsigned long pmnc_key[];
25
26static DEFINE_PER_CPU(struct perf_event_attr *, pevent_attr);
27static DEFINE_PER_CPU(int, key);
28
29#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
30static void ebs_overflow_handler(struct perf_event *event, int unused, struct perf_sample_data *data, struct pt_regs *regs)
31#else
32static void ebs_overflow_handler(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs)
33#endif
34{
35 int cpu = smp_processor_id();
36
37 if (event != per_cpu(pevent_ebs, cpu))
38 return;
39
40 // Output backtrace
41 gator_add_sample(cpu, BACKTRACE_BUF, regs);
42
43 // Collect counters
44 collect_counters();
45}
46
47static void gator_event_sampling_online_dispatch(int cpu)
48{
49 struct perf_event * ev;
50
51 if (!event_based_sampling)
52 return;
53
54#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
55 ev = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu), cpu, 0, ebs_overflow_handler);
56#else
57 ev = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu), cpu, 0, ebs_overflow_handler, 0);
58#endif
59
60 if (IS_ERR(ev)) {
61 pr_err("gator: unable to start event-based-sampling");
62 return;
63 }
64
65 if (ev->state != PERF_EVENT_STATE_ACTIVE) {
66 pr_err("gator: unable to start event-based-sampling");
67 perf_event_release_kernel(ev);
68 return;
69 }
70
71 ev->pmu->read(ev);
72 per_cpu(pevent_ebs, cpu) = ev;
73}
74
75static void gator_event_sampling_offline_dispatch(int cpu)
76{
77 struct perf_event * pe = NULL;
78
79 mutex_lock(&perf_mutex);
80 if (per_cpu(pevent_ebs, cpu)) {
81 pe = per_cpu(pevent_ebs, cpu);
82 per_cpu(pevent_ebs, cpu) = NULL;
83 }
84 mutex_unlock(&perf_mutex);
85
86 if (pe) {
87 perf_event_release_kernel(pe);
88 }
89}
90
91static int gator_event_sampling_start(void)
92{
93 int cnt, event = 0, count = 0, ebs_key = 0, cpu;
94
95 for_each_present_cpu(cpu) {
96 per_cpu(pevent_ebs, cpu) = NULL;
97 per_cpu(pevent_attr, cpu) = NULL;
98 }
99
100 event_based_sampling = false;
101 for (cnt = 0; cnt < pmnc_counters; cnt++) {
102 if (pmnc_count[cnt] > 0) {
103 event_based_sampling = true;
104 event = pmnc_event[cnt];
105 count = pmnc_count[cnt];
106 ebs_key = pmnc_key[cnt];
107 break;
108 }
109 }
110
111 if (!event_based_sampling)
112 return 0;
113
114 for_each_present_cpu(cpu) {
115 u32 size = sizeof(struct perf_event_attr);
116 per_cpu(pevent_attr, cpu) = kmalloc(size, GFP_KERNEL);
117 if (!per_cpu(pevent_attr, cpu))
118 return -1;
119
120 memset(per_cpu(pevent_attr, cpu), 0, size);
121 per_cpu(pevent_attr, cpu)->type = PERF_TYPE_RAW;
122 per_cpu(pevent_attr, cpu)->size = size;
123 per_cpu(pevent_attr, cpu)->config = event;
124 per_cpu(pevent_attr, cpu)->sample_period = count;
125 per_cpu(pevent_attr, cpu)->pinned = 1;
126
127 // handle special case for ccnt
128 if (cnt == ccnt) {
129 per_cpu(pevent_attr, cpu)->type = PERF_TYPE_HARDWARE;
130 per_cpu(pevent_attr, cpu)->config = PERF_COUNT_HW_CPU_CYCLES;
131 }
132
133 per_cpu(key, cpu) = ebs_key;
134 }
135
136 return 0;
137}
138
139static void gator_event_sampling_stop(void)
140{
141 int cpu;
142
143 for_each_present_cpu(cpu) {
144 if (per_cpu(pevent_attr, cpu)) {
145 kfree(per_cpu(pevent_attr, cpu));
146 per_cpu(pevent_attr, cpu) = NULL;
147 }
148 }
149}
150
151#else
152static void gator_event_sampling_online_dispatch(int cpu) {}
153static void gator_event_sampling_offline_dispatch(int cpu) {}
154static int gator_event_sampling_start(void) {return 0;}
155static void gator_event_sampling_stop(void) {}
156#endif
diff --git a/driver/gator_events_block.c b/driver/gator_events_block.c
index a8b8114..b18c3ca 100644
--- a/driver/gator_events_block.c
+++ b/driver/gator_events_block.c
@@ -25,15 +25,13 @@ static ulong block_rq_wr_enabled;
25static ulong block_rq_rd_enabled; 25static ulong block_rq_rd_enabled;
26static ulong block_rq_wr_key; 26static ulong block_rq_wr_key;
27static ulong block_rq_rd_key; 27static ulong block_rq_rd_key;
28static DEFINE_PER_CPU(int[BLOCK_TOTAL], blockCnt); 28static atomic_t blockCnt[BLOCK_TOTAL];
29static DEFINE_PER_CPU(int[BLOCK_TOTAL * 4], blockGet); 29static int blockGet[BLOCK_TOTAL * 4];
30static DEFINE_PER_CPU(bool, new_data_avail);
31 30
32GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct request *rq)) 31GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct request *rq))
33{ 32{
34 unsigned long flags; 33 unsigned long flags;
35 int write, size; 34 int write, size;
36 int cpu = smp_processor_id();
37 35
38 if (!rq) 36 if (!rq)
39 return; 37 return;
@@ -47,13 +45,16 @@ GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct r
47 // disable interrupts to synchronize with gator_events_block_read() 45 // disable interrupts to synchronize with gator_events_block_read()
48 // spinlocks not needed since percpu buffers are used 46 // spinlocks not needed since percpu buffers are used
49 local_irq_save(flags); 47 local_irq_save(flags);
50 if (write) 48 if (write) {
51 per_cpu(blockCnt, cpu)[BLOCK_RQ_WR] += size; 49 if (block_rq_wr_enabled) {
52 else 50 atomic_add(size, &blockCnt[BLOCK_RQ_WR]);
53 per_cpu(blockCnt, cpu)[BLOCK_RQ_RD] += size; 51 }
52 } else {
53 if (block_rq_rd_enabled) {
54 atomic_add(size, &blockCnt[BLOCK_RQ_RD]);
55 }
56 }
54 local_irq_restore(flags); 57 local_irq_restore(flags);
55
56 per_cpu(new_data_avail, cpu) = true;
57} 58}
58 59
59static int gator_events_block_create_files(struct super_block *sb, struct dentry *root) 60static int gator_events_block_create_files(struct super_block *sb, struct dentry *root)
@@ -81,11 +82,6 @@ static int gator_events_block_create_files(struct super_block *sb, struct dentry
81 82
82static int gator_events_block_start(void) 83static int gator_events_block_start(void)
83{ 84{
84 int cpu;
85
86 for_each_present_cpu(cpu)
87 per_cpu(new_data_avail, cpu) = true;
88
89 // register tracepoints 85 // register tracepoints
90 if (block_rq_wr_enabled || block_rq_rd_enabled) 86 if (block_rq_wr_enabled || block_rq_rd_enabled)
91 if (GATOR_REGISTER_TRACE(block_rq_complete)) 87 if (GATOR_REGISTER_TRACE(block_rq_complete))
@@ -113,44 +109,32 @@ static void gator_events_block_stop(void)
113 109
114static int gator_events_block_read(int **buffer) 110static int gator_events_block_read(int **buffer)
115{ 111{
116 unsigned long flags; 112 int len, value, data = 0;
117 int len, value, cpu, data = 0;
118 cpu = smp_processor_id();
119 113
120 if (per_cpu(new_data_avail, cpu) == false) 114 if (smp_processor_id() != 0) {
121 return 0; 115 return 0;
122 116 }
123 per_cpu(new_data_avail, cpu) = false;
124 117
125 len = 0; 118 len = 0;
126 if (block_rq_wr_enabled) { 119 if (block_rq_wr_enabled && (value = atomic_read(&blockCnt[BLOCK_RQ_WR])) > 0) {
127 local_irq_save(flags); 120 atomic_sub(value, &blockCnt[BLOCK_RQ_WR]);
128 value = per_cpu(blockCnt, cpu)[BLOCK_RQ_WR]; 121 blockGet[len++] = block_rq_wr_key;
129 per_cpu(blockCnt, cpu)[BLOCK_RQ_WR] = 0; 122 blockGet[len++] = 0; // indicates to Streamline that value bytes were written now, not since the last message
130 local_irq_restore(flags); 123 blockGet[len++] = block_rq_wr_key;
131 per_cpu(blockGet, cpu)[len++] = block_rq_wr_key; 124 blockGet[len++] = value;
132 per_cpu(blockGet, cpu)[len++] = 0; // indicates to Streamline that value bytes were written now, not since the last message
133 per_cpu(blockGet, cpu)[len++] = block_rq_wr_key;
134 per_cpu(blockGet, cpu)[len++] = value;
135 data += value; 125 data += value;
136 } 126 }
137 if (block_rq_rd_enabled) { 127 if (block_rq_rd_enabled && (value = atomic_read(&blockCnt[BLOCK_RQ_RD])) > 0) {
138 local_irq_save(flags); 128 atomic_sub(value, &blockCnt[BLOCK_RQ_RD]);
139 value = per_cpu(blockCnt, cpu)[BLOCK_RQ_RD]; 129 blockGet[len++] = block_rq_rd_key;
140 per_cpu(blockCnt, cpu)[BLOCK_RQ_RD] = 0; 130 blockGet[len++] = 0; // indicates to Streamline that value bytes were read now, not since the last message
141 local_irq_restore(flags); 131 blockGet[len++] = block_rq_rd_key;
142 per_cpu(blockGet, cpu)[len++] = block_rq_rd_key; 132 blockGet[len++] = value;
143 per_cpu(blockGet, cpu)[len++] = 0; // indicates to Streamline that value bytes were read now, not since the last message
144 per_cpu(blockGet, cpu)[len++] = block_rq_rd_key;
145 per_cpu(blockGet, cpu)[len++] = value;
146 data += value; 133 data += value;
147 } 134 }
148 135
149 if (data != 0)
150 per_cpu(new_data_avail, cpu) = true;
151
152 if (buffer) 136 if (buffer)
153 *buffer = per_cpu(blockGet, cpu); 137 *buffer = blockGet;
154 138
155 return len; 139 return len;
156} 140}
diff --git a/driver/gator_events_mali_400.c b/driver/gator_events_mali_400.c
index 38d5b3d..65eeb4f 100644
--- a/driver/gator_events_mali_400.c
+++ b/driver/gator_events_mali_400.c
@@ -17,14 +17,6 @@
17#include "gator_events_mali_common.h" 17#include "gator_events_mali_common.h"
18#include "gator_events_mali_400.h" 18#include "gator_events_mali_400.h"
19 19
20#if !defined(GATOR_MALI_INTERFACE_STYLE)
21/*
22 * At the moment, we only have users with the old style interface, so
23 * make our life easier by making it the default...
24 */
25#define GATOR_MALI_INTERFACE_STYLE (2)
26#endif
27
28/* 20/*
29 * There are (currently) three different variants of the comms between gator and Mali: 21 * There are (currently) three different variants of the comms between gator and Mali:
30 * 1 (deprecated): No software counter support 22 * 1 (deprecated): No software counter support
@@ -393,7 +385,7 @@ static int create_files(struct super_block *sb, struct dentry *root) {
393 385
394 switch(event) { 386 switch(event) {
395 case COUNTER_FILMSTRIP: 387 case COUNTER_FILMSTRIP:
396 snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip", mali_name); 388 snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip_cnt0", mali_name);
397 break; 389 break;
398 390
399 case COUNTER_FREQUENCY: 391 case COUNTER_FREQUENCY:
diff --git a/driver/gator_events_mali_400.h b/driver/gator_events_mali_400.h
index b784ae9..a09757e 100644
--- a/driver/gator_events_mali_400.h
+++ b/driver/gator_events_mali_400.h
@@ -1,11 +1,10 @@
1/* 1/**
2 * This confidential and proprietary software may be used only as 2 * Copyright (C) ARM Limited 2011-2012. All rights reserved.
3 * authorised by a licensing agreement from ARM Limited 3 *
4 * (C) COPYRIGHT 2011-2012 ARM Limited 4 * This program is free software; you can redistribute it and/or modify
5 * ALL RIGHTS RESERVED 5 * it under the terms of the GNU General Public License version 2 as
6 * The entire notice above must be reproduced on all authorised 6 * published by the Free Software Foundation.
7 * copies and copies may only be made to the extent permitted 7 *
8 * by a licensing agreement from ARM Limited.
9 */ 8 */
10 9
11/* 10/*
diff --git a/driver/gator_events_mali_common.c b/driver/gator_events_mali_common.c
index 2dd9ad6..62e441c 100644
--- a/driver/gator_events_mali_common.c
+++ b/driver/gator_events_mali_common.c
@@ -1,11 +1,10 @@
1/* 1/**
2 * This confidential and proprietary software may be used only as 2 * Copyright (C) ARM Limited 2012. All rights reserved.
3 * authorised by a licensing agreement from ARM Limited 3 *
4 * (C) COPYRIGHT 2011-2012 ARM Limited 4 * This program is free software; you can redistribute it and/or modify
5 * ALL RIGHTS RESERVED 5 * it under the terms of the GNU General Public License version 2 as
6 * The entire notice above must be reproduced on all authorised 6 * published by the Free Software Foundation.
7 * copies and copies may only be made to the extent permitted 7 *
8 * by a licensing agreement from ARM Limited.
9 */ 8 */
10#include "gator_events_mali_common.h" 9#include "gator_events_mali_common.h"
11 10
diff --git a/driver/gator_events_mali_common.h b/driver/gator_events_mali_common.h
index cb851d5..2c9457f 100644
--- a/driver/gator_events_mali_common.h
+++ b/driver/gator_events_mali_common.h
@@ -1,12 +1,12 @@
1/* 1/**
2 * This confidential and proprietary software may be used only as 2 * Copyright (C) ARM Limited 2012. All rights reserved.
3 * authorised by a licensing agreement from ARM Limited 3 *
4 * (C) COPYRIGHT 2011-2012 ARM Limited 4 * This program is free software; you can redistribute it and/or modify
5 * ALL RIGHTS RESERVED 5 * it under the terms of the GNU General Public License version 2 as
6 * The entire notice above must be reproduced on all authorised 6 * published by the Free Software Foundation.
7 * copies and copies may only be made to the extent permitted 7 *
8 * by a licensing agreement from ARM Limited.
9 */ 8 */
9
10#if !defined(GATOR_EVENTS_MALI_COMMON_H) 10#if !defined(GATOR_EVENTS_MALI_COMMON_H)
11#define GATOR_EVENTS_MALI_COMMON_H 11#define GATOR_EVENTS_MALI_COMMON_H
12 12
@@ -39,6 +39,9 @@ typedef struct {
39 unsigned long enabled; /* counter enable state */ 39 unsigned long enabled; /* counter enable state */
40} mali_counter; 40} mali_counter;
41 41
42/*
43 * Mali-400
44 */
42typedef void mali_profiling_set_event_type(unsigned int, unsigned int); 45typedef void mali_profiling_set_event_type(unsigned int, unsigned int);
43typedef void mali_osk_fb_control_set_type(unsigned int, unsigned int); 46typedef void mali_osk_fb_control_set_type(unsigned int, unsigned int);
44typedef void mali_profiling_control_type(unsigned int, unsigned int); 47typedef void mali_profiling_control_type(unsigned int, unsigned int);
diff --git a/driver/gator_events_mali_t6xx.c b/driver/gator_events_mali_t6xx.c
index 79af764..f8f868e 100644
--- a/driver/gator_events_mali_t6xx.c
+++ b/driver/gator_events_mali_t6xx.c
@@ -1,11 +1,10 @@
1/* 1/**
2 * This confidential and proprietary software may be used only as 2 * Copyright (C) ARM Limited 2011-2012. All rights reserved.
3 * authorised by a licensing agreement from ARM Limited 3 *
4 * (C) COPYRIGHT 2011 ARM Limited 4 * This program is free software; you can redistribute it and/or modify
5 * ALL RIGHTS RESERVED 5 * it under the terms of the GNU General Public License version 2 as
6 * The entire notice above must be reproduced on all authorised 6 * published by the Free Software Foundation.
7 * copies and copies may only be made to the extent permitted 7 *
8 * by a licensing agreement from ARM Limited.
9 */ 8 */
10 9
11#include "gator.h" 10#include "gator.h"
diff --git a/driver/gator_events_mali_t6xx_hw.c b/driver/gator_events_mali_t6xx_hw.c
index 12ffebc..854d02d 100644
--- a/driver/gator_events_mali_t6xx_hw.c
+++ b/driver/gator_events_mali_t6xx_hw.c
@@ -1,11 +1,10 @@
1/* 1/**
2 * This confidential and proprietary software may be used only as 2 * Copyright (C) ARM Limited 2012. All rights reserved.
3 * authorised by a licensing agreement from ARM Limited 3 *
4 * (C) COPYRIGHT 2011-2012 ARM Limited 4 * This program is free software; you can redistribute it and/or modify
5 * ALL RIGHTS RESERVED 5 * it under the terms of the GNU General Public License version 2 as
6 * The entire notice above must be reproduced on all authorised 6 * published by the Free Software Foundation.
7 * copies and copies may only be made to the extent permitted 7 *
8 * by a licensing agreement from ARM Limited.
9 */ 8 */
10 9
11#include "gator.h" 10#include "gator.h"
@@ -23,6 +22,39 @@
23 22
24#include "gator_events_mali_common.h" 23#include "gator_events_mali_common.h"
25 24
25/*
26 * Mali-T6xx
27 */
28typedef struct kbase_device *kbase_find_device_type(int);
29typedef kbase_context *kbase_create_context_type(kbase_device*);
30typedef void kbase_destroy_context_type(kbase_context *);
31typedef void *kbase_va_alloc_type(kbase_context *, u32);
32typedef void kbase_va_free_type(kbase_context *, void *);
33typedef mali_error kbase_instr_hwcnt_enable_type(kbase_context *, kbase_uk_hwcnt_setup *);
34typedef mali_error kbase_instr_hwcnt_disable_type(kbase_context *);
35typedef mali_error kbase_instr_hwcnt_clear_type(kbase_context *);
36typedef mali_error kbase_instr_hwcnt_dump_irq_type(kbase_context *);
37typedef mali_bool kbase_instr_hwcnt_dump_complete_type(kbase_context *, mali_bool *);
38
39static kbase_find_device_type * kbase_find_device_symbol;
40static kbase_create_context_type * kbase_create_context_symbol;
41static kbase_va_alloc_type * kbase_va_alloc_symbol;
42static kbase_instr_hwcnt_enable_type * kbase_instr_hwcnt_enable_symbol;
43static kbase_instr_hwcnt_clear_type * kbase_instr_hwcnt_clear_symbol;
44static kbase_instr_hwcnt_dump_irq_type * kbase_instr_hwcnt_dump_irq_symbol;
45static kbase_instr_hwcnt_dump_complete_type * kbase_instr_hwcnt_dump_complete_symbol;
46static kbase_instr_hwcnt_disable_type * kbase_instr_hwcnt_disable_symbol;
47static kbase_va_free_type * kbase_va_free_symbol;
48static kbase_destroy_context_type * kbase_destroy_context_symbol;
49
50/** The interval between reads, in ns. */
51static const int READ_INTERVAL_NSEC = 1000000;
52
53
54#if GATOR_TEST
55#include "gator_events_mali_t6xx_hw_test.c"
56#endif
57
26/* Blocks for HW counters */ 58/* Blocks for HW counters */
27enum 59enum
28{ 60{
@@ -322,7 +354,12 @@ static void *kernel_dump_buffer;
322static kbase_context *kbcontext = NULL; 354static kbase_context *kbcontext = NULL;
323static struct kbase_device *kbdevice = NULL; 355static struct kbase_device *kbdevice = NULL;
324 356
325extern struct kbase_device *kbase_find_device(int minor); 357/*
358 * The following function has no external prototype in older DDK revisions. When the DDK
359 * is updated then this should be removed.
360 */
361struct kbase_device *kbase_find_device(int minor);
362
326static volatile bool kbase_device_busy = false; 363static volatile bool kbase_device_busy = false;
327static unsigned int num_hardware_counters_enabled; 364static unsigned int num_hardware_counters_enabled;
328 365
@@ -336,6 +373,96 @@ static mali_counter counters[NUMBER_OF_HARDWARE_COUNTERS];
336 */ 373 */
337static unsigned long counter_dump[NUMBER_OF_HARDWARE_COUNTERS * 2]; 374static unsigned long counter_dump[NUMBER_OF_HARDWARE_COUNTERS * 2];
338 375
376#define SYMBOL_GET(FUNCTION, ERROR_COUNT) \
377 if(FUNCTION ## _symbol) \
378 { \
379 printk("gator: mali " #FUNCTION " symbol was already registered\n"); \
380 (ERROR_COUNT)++; \
381 } \
382 else \
383 { \
384 FUNCTION ## _symbol = symbol_get(FUNCTION); \
385 if(! FUNCTION ## _symbol) \
386 { \
387 printk("gator: mali online " #FUNCTION " symbol not found\n"); \
388 (ERROR_COUNT)++; \
389 } \
390 }
391
392#define SYMBOL_CLEANUP(FUNCTION) \
393 if(FUNCTION ## _symbol) \
394 { \
395 symbol_put(FUNCTION); \
396 FUNCTION ## _symbol = NULL; \
397 }
398
399/**
400 * Execute symbol_get for all the Mali symbols and check for success.
401 * @return the number of symbols not loaded.
402 */
403static int init_symbols(void)
404{
405 int error_count = 0;
406 SYMBOL_GET(kbase_find_device, error_count);
407 SYMBOL_GET(kbase_create_context, error_count);
408 SYMBOL_GET(kbase_va_alloc, error_count);
409 SYMBOL_GET(kbase_instr_hwcnt_enable, error_count);
410 SYMBOL_GET(kbase_instr_hwcnt_clear, error_count);
411 SYMBOL_GET(kbase_instr_hwcnt_dump_irq, error_count);
412 SYMBOL_GET(kbase_instr_hwcnt_dump_complete, error_count);
413 SYMBOL_GET(kbase_instr_hwcnt_disable, error_count);
414 SYMBOL_GET(kbase_va_free, error_count);
415 SYMBOL_GET(kbase_destroy_context, error_count);
416
417 return error_count;
418}
419
420/**
421 * Execute symbol_put for all the registered Mali symbols.
422 */
423static void clean_symbols(void)
424{
425 SYMBOL_CLEANUP(kbase_find_device);
426 SYMBOL_CLEANUP(kbase_create_context);
427 SYMBOL_CLEANUP(kbase_va_alloc);
428 SYMBOL_CLEANUP(kbase_instr_hwcnt_enable);
429 SYMBOL_CLEANUP(kbase_instr_hwcnt_clear);
430 SYMBOL_CLEANUP(kbase_instr_hwcnt_dump_irq);
431 SYMBOL_CLEANUP(kbase_instr_hwcnt_dump_complete);
432 SYMBOL_CLEANUP(kbase_instr_hwcnt_disable);
433 SYMBOL_CLEANUP(kbase_va_free);
434 SYMBOL_CLEANUP(kbase_destroy_context);
435}
436
437/**
438 * Determines whether a read should take place
439 * @param current_time The current time, obtained from getnstimeofday()
440 * @param prev_time_s The number of seconds at the previous read attempt.
441 * @param next_read_time_ns The time (in ns) when the next read should be allowed.
442 *
443 * Note that this function has been separated out here to allow it to be tested.
444 */
445static int is_read_scheduled(const struct timespec *current_time, u32* prev_time_s, s32* next_read_time_ns)
446{
447 /* If the current ns count rolls over a second, roll the next read time too. */
448 if(current_time->tv_sec != *prev_time_s)
449 {
450 *next_read_time_ns = *next_read_time_ns - NSEC_PER_SEC;
451 }
452
453 /* Abort the read if the next read time has not arrived. */
454 if(current_time->tv_nsec < *next_read_time_ns)
455 {
456 return 0;
457 }
458
459 /* Set the next read some fixed time after this one, and update the read timestamp. */
460 *next_read_time_ns = current_time->tv_nsec + READ_INTERVAL_NSEC;
461
462 *prev_time_s = current_time->tv_sec;
463 return 1;
464}
465
339static int start(void) 466static int start(void)
340{ 467{
341 kbase_uk_hwcnt_setup setup; 468 kbase_uk_hwcnt_setup setup;
@@ -368,12 +495,23 @@ static int start(void)
368 /* Create a kbase context for HW counters */ 495 /* Create a kbase context for HW counters */
369 if (num_hardware_counters_enabled > 0) 496 if (num_hardware_counters_enabled > 0)
370 { 497 {
371 kbdevice = kbase_find_device(-1); 498 if(init_symbols() > 0)
372 499 {
373 if (kbcontext) 500 clean_symbols();
374 return -1; 501 /* No Mali driver code entrypoints found - not a fault. */
375 502 return 0;
376 kbcontext = kbase_create_context(kbdevice); 503 }
504
505 kbdevice = kbase_find_device_symbol(-1);
506
507 /* If we already got a context, fail */
508 if (kbcontext) {
509 pr_debug("gator: Mali-T6xx: error context already present\n");
510 goto out;
511 }
512
513 /* kbcontext will only be valid after all the Mali symbols are loaded successfully */
514 kbcontext = kbase_create_context_symbol(kbdevice);
377 if (!kbcontext) 515 if (!kbcontext)
378 { 516 {
379 pr_debug("gator: Mali-T6xx: error creating kbase context\n"); 517 pr_debug("gator: Mali-T6xx: error creating kbase context\n");
@@ -388,7 +526,7 @@ static int start(void)
388 * * number of bytes per counter (always 4 in midgard) 526 * * number of bytes per counter (always 4 in midgard)
389 * For a Mali-T6xx with a single core group = 1 * 8 * 64 * 4 527 * For a Mali-T6xx with a single core group = 1 * 8 * 64 * 4
390 */ 528 */
391 kernel_dump_buffer = kbase_va_alloc(kbcontext, 2048); 529 kernel_dump_buffer = kbase_va_alloc_symbol(kbcontext, 2048);
392 if (!kernel_dump_buffer) 530 if (!kernel_dump_buffer)
393 { 531 {
394 pr_debug("gator: Mali-T6xx: error trying to allocate va\n"); 532 pr_debug("gator: Mali-T6xx: error trying to allocate va\n");
@@ -404,14 +542,14 @@ static int start(void)
404 setup.l3_cache_bm = 0; 542 setup.l3_cache_bm = 0;
405 543
406 /* Use kbase API to enable hardware counters and provide dump buffer */ 544 /* Use kbase API to enable hardware counters and provide dump buffer */
407 err = kbase_instr_hwcnt_enable(kbcontext, &setup); 545 err = kbase_instr_hwcnt_enable_symbol(kbcontext, &setup);
408 if (err != MALI_ERROR_NONE) 546 if (err != MALI_ERROR_NONE)
409 { 547 {
410 pr_debug("gator: Mali-T6xx: can't setup hardware counters\n"); 548 pr_debug("gator: Mali-T6xx: can't setup hardware counters\n");
411 goto free_buffer; 549 goto free_buffer;
412 } 550 }
413 pr_debug("gator: Mali-T6xx: hardware counters enabled\n"); 551 pr_debug("gator: Mali-T6xx: hardware counters enabled\n");
414 kbase_instr_hwcnt_clear(kbcontext); 552 kbase_instr_hwcnt_clear_symbol(kbcontext);
415 pr_debug("gator: Mali-T6xx: hardware counters cleared \n"); 553 pr_debug("gator: Mali-T6xx: hardware counters cleared \n");
416 554
417 kbase_device_busy = false; 555 kbase_device_busy = false;
@@ -420,10 +558,13 @@ static int start(void)
420 return 0; 558 return 0;
421 559
422 free_buffer: 560 free_buffer:
423 kbase_va_free(kbcontext, kernel_dump_buffer); 561 kbase_va_free_symbol(kbcontext, kernel_dump_buffer);
562
424 destroy_context: 563 destroy_context:
425 kbase_destroy_context(kbcontext); 564 kbase_destroy_context_symbol(kbcontext);
565
426 out: 566 out:
567 clean_symbols();
427 return -1; 568 return -1;
428} 569}
429 570
@@ -448,10 +589,13 @@ static void stop(void) {
448 temp_kbcontext = kbcontext; 589 temp_kbcontext = kbcontext;
449 kbcontext = NULL; 590 kbcontext = NULL;
450 591
451 kbase_instr_hwcnt_disable(temp_kbcontext); 592 kbase_instr_hwcnt_disable_symbol(temp_kbcontext);
452 kbase_va_free(temp_kbcontext, kernel_dump_buffer); 593 kbase_va_free_symbol(temp_kbcontext, kernel_dump_buffer);
453 kbase_destroy_context(temp_kbcontext); 594 kbase_destroy_context_symbol(temp_kbcontext);
595
454 pr_debug("gator: Mali-T6xx: hardware counters stopped\n"); 596 pr_debug("gator: Mali-T6xx: hardware counters stopped\n");
597
598 clean_symbols();
455 } 599 }
456} 600}
457 601
@@ -461,11 +605,26 @@ static int read(int **buffer) {
461 u32 value = 0; 605 u32 value = 0;
462 mali_bool success; 606 mali_bool success;
463 607
608 struct timespec current_time;
609 static u32 prev_time_s = 0;
610 static s32 next_read_time_ns = 0;
611
464 if (smp_processor_id()!=0) 612 if (smp_processor_id()!=0)
465 { 613 {
466 return 0; 614 return 0;
467 } 615 }
468 616
617 getnstimeofday(&current_time);
618
619 /*
620 * Discard reads unless a respectable time has passed. This reduces the load on the GPU without sacrificing
621 * accuracy on the Streamline display.
622 */
623 if(!is_read_scheduled(&current_time, &prev_time_s, &next_read_time_ns))
624 {
625 return 0;
626 }
627
469 /* 628 /*
470 * Report the HW counters 629 * Report the HW counters
471 * Only process hardware counters if at least one of the hardware counters is enabled. 630 * Only process hardware counters if at least one of the hardware counters is enabled.
@@ -484,8 +643,8 @@ static int read(int **buffer) {
484 return -1; 643 return -1;
485 } 644 }
486 645
487 // TODO: SYMBOL_GET (all kbase functions) 646 /* Mali symbols can be called safely since a kbcontext is valid */
488 if (kbase_instr_hwcnt_dump_complete(kbcontext, &success) == MALI_TRUE) 647 if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success) == MALI_TRUE)
489 { 648 {
490 kbase_device_busy = false; 649 kbase_device_busy = false;
491 650
@@ -520,7 +679,7 @@ static int read(int **buffer) {
520 if (! kbase_device_busy) 679 if (! kbase_device_busy)
521 { 680 {
522 kbase_device_busy = true; 681 kbase_device_busy = true;
523 kbase_instr_hwcnt_dump_irq(kbcontext); 682 kbase_instr_hwcnt_dump_irq_symbol(kbcontext);
524 } 683 }
525 } 684 }
526 685
@@ -551,7 +710,6 @@ static int create_files(struct super_block *sb, struct dentry *root)
551 return 0; 710 return 0;
552} 711}
553 712
554
555static struct gator_interface gator_events_mali_t6xx_interface = { 713static struct gator_interface gator_events_mali_t6xx_interface = {
556 .create_files = create_files, 714 .create_files = create_files,
557 .start = start, 715 .start = start,
@@ -563,6 +721,10 @@ int gator_events_mali_t6xx_hw_init(void)
563{ 721{
564 pr_debug("gator: Mali-T6xx: sw_counters init\n"); 722 pr_debug("gator: Mali-T6xx: sw_counters init\n");
565 723
724#if GATOR_TEST
725 test_all_is_read_scheduled();
726#endif
727
566 gator_mali_initialise_counters(counters, NUMBER_OF_HARDWARE_COUNTERS); 728 gator_mali_initialise_counters(counters, NUMBER_OF_HARDWARE_COUNTERS);
567 729
568 return gator_events_install(&gator_events_mali_t6xx_interface); 730 return gator_events_install(&gator_events_mali_t6xx_interface);
diff --git a/driver/gator_events_mali_t6xx_hw_test.c b/driver/gator_events_mali_t6xx_hw_test.c
new file mode 100644
index 0000000..2a35e77
--- /dev/null
+++ b/driver/gator_events_mali_t6xx_hw_test.c
@@ -0,0 +1,57 @@
1/**
2 * Copyright (C) ARM Limited 2012. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 */
9
10/**
11 * Test functions for mali_t600_hw code.
12 */
13
14static int is_read_scheduled(const struct timespec *current_time, u32* prev_time_s, s32* next_read_time_ns);
15
16static int test_is_read_scheduled(u32 s, u32 ns, u32 prev_s, s32 next_ns, int expected_result, s32 expected_next_ns)
17{
18 struct timespec current_time;
19 u32 prev_time_s = prev_s;
20 s32 next_read_time_ns = next_ns;
21
22 current_time.tv_sec = s;
23 current_time.tv_nsec = ns;
24
25 if(is_read_scheduled(&current_time, &prev_time_s, &next_read_time_ns) != expected_result)
26 {
27 printk("Failed do_read(%u, %u, %u, %d): expected %d\n", s, ns, prev_s, next_ns, expected_result);
28 return 0;
29 }
30
31 if(next_read_time_ns != expected_next_ns)
32 {
33 printk("Failed: next_read_ns expected=%d, actual=%d\n", expected_next_ns, next_read_time_ns);
34 return 0;
35 }
36
37 return 1;
38}
39
40static void test_all_is_read_scheduled(void)
41{
42 const int HIGHEST_NS = 999999999;
43 int n_tests_passed = 0;
44
45 printk("gator: running tests on %s\n", __FILE__);
46
47 n_tests_passed += test_is_read_scheduled(0,0,0,0, 1, READ_INTERVAL_NSEC); /* Null time */
48 n_tests_passed += test_is_read_scheduled(100,1000,0,0, 1, READ_INTERVAL_NSEC + 1000); /* Initial values */
49
50 n_tests_passed += test_is_read_scheduled(100, HIGHEST_NS, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500);
51 n_tests_passed += test_is_read_scheduled(101, 0001, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500 - NSEC_PER_SEC);
52 n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500 - NSEC_PER_SEC, 1, 600 + READ_INTERVAL_NSEC);
53
54 n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500, 1, 600 + READ_INTERVAL_NSEC);
55
56 printk("gator: %d tests passed\n", n_tests_passed);
57}
diff --git a/driver/gator_events_mmaped.c b/driver/gator_events_mmaped.c
index f81c402..1be6e66 100644
--- a/driver/gator_events_mmaped.c
+++ b/driver/gator_events_mmaped.c
@@ -11,12 +11,8 @@
11 * To add them to the events.xml, create an events-mmap.xml with the 11 * To add them to the events.xml, create an events-mmap.xml with the
12 * following contents and rebuild gatord: 12 * following contents and rebuild gatord:
13 * 13 *
14 * <counter_set name="mmaped_cntX"> 14 * <counter_set name="mmaped_cnt" count="3"/>
15 * <counter name="mmaped_cnt0"/> 15 * <category name="mmaped" counter_set="mmaped_cnt" per_cpu="no">
16 * <counter name="mmaped_cnt1"/>
17 * <counter name="mmaped_cnt2"/>
18 * </counter_set>
19 * <category name="mmaped" counter_set="mmaped_cntX" per_cpu="no">
20 * <event event="0x0" title="Simulated" name="Sine" display="maximum" average_selection="yes" description="Sort-of-sine"/> 16 * <event event="0x0" title="Simulated" name="Sine" display="maximum" average_selection="yes" description="Sort-of-sine"/>
21 * <event event="0x1" title="Simulated" name="Triangle" display="maximum" average_selection="yes" description="Triangular wave"/> 17 * <event event="0x1" title="Simulated" name="Triangle" display="maximum" average_selection="yes" description="Triangular wave"/>
22 * <event event="0x2" title="Simulated" name="PWM" display="maximum" average_selection="yes" description="PWM Signal"/> 18 * <event event="0x2" title="Simulated" name="PWM" display="maximum" average_selection="yes" description="PWM Signal"/>
diff --git a/driver/gator_events_net.c b/driver/gator_events_net.c
index 11282b5..31cc3ef 100644
--- a/driver/gator_events_net.c
+++ b/driver/gator_events_net.c
@@ -95,7 +95,11 @@ static int gator_events_net_start(void)
95 get_network_stats(0); 95 get_network_stats(0);
96 netPrev[NETRX] = rx_total; 96 netPrev[NETRX] = rx_total;
97 netPrev[NETTX] = tx_total; 97 netPrev[NETTX] = tx_total;
98#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
98 setup_timer(&net_wake_up_timer, net_wake_up_handler, 0); 99 setup_timer(&net_wake_up_timer, net_wake_up_handler, 0);
100#else
101 setup_deferrable_timer_on_stack(&net_wake_up_timer, net_wake_up_handler, 0);
102#endif
99 return 0; 103 return 0;
100} 104}
101 105
diff --git a/driver/gator_events_perf_pmu.c b/driver/gator_events_perf_pmu.c
index 9d78b46..e025155 100644
--- a/driver/gator_events_perf_pmu.c
+++ b/driver/gator_events_perf_pmu.c
@@ -32,7 +32,6 @@ static DEFINE_PER_CPU(int[CNTMAX], perfPrevDelta);
32static DEFINE_PER_CPU(int[CNTMAX * 2], perfCnt); 32static DEFINE_PER_CPU(int[CNTMAX * 2], perfCnt);
33static DEFINE_PER_CPU(struct perf_event *[CNTMAX], pevent); 33static DEFINE_PER_CPU(struct perf_event *[CNTMAX], pevent);
34static DEFINE_PER_CPU(struct perf_event_attr *[CNTMAX], pevent_attr); 34static DEFINE_PER_CPU(struct perf_event_attr *[CNTMAX], pevent_attr);
35extern DEFINE_PER_CPU(struct perf_event *, pevent_ebs);
36 35
37static void gator_events_perf_pmu_stop(void); 36static void gator_events_perf_pmu_stop(void);
38 37
@@ -64,6 +63,15 @@ static int gator_events_perf_pmu_create_files(struct super_block *sb, struct den
64} 63}
65 64
66#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) 65#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
66static void ebs_overflow_handler(struct perf_event *event, int unused, struct perf_sample_data *data, struct pt_regs *regs)
67#else
68static void ebs_overflow_handler(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs)
69#endif
70{
71 gator_backtrace_handler(regs);
72}
73
74#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
67static void dummy_handler(struct perf_event *event, int unused, struct perf_sample_data *data, struct pt_regs *regs) 75static void dummy_handler(struct perf_event *event, int unused, struct perf_sample_data *data, struct pt_regs *regs)
68#else 76#else
69static void dummy_handler(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs) 77static void dummy_handler(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs)
@@ -75,15 +83,10 @@ static void dummy_handler(struct perf_event *event, struct perf_sample_data *dat
75static int gator_events_perf_pmu_online(int** buffer) 83static int gator_events_perf_pmu_online(int** buffer)
76{ 84{
77 int cnt, len = 0, cpu = smp_processor_id(); 85 int cnt, len = 0, cpu = smp_processor_id();
78 struct perf_event * ev;
79 86
80 // read the counters and toss the invalid data, return zero instead 87 // read the counters and toss the invalid data, return zero instead
81 for (cnt = 0; cnt < pmnc_counters; cnt++) { 88 for (cnt = 0; cnt < pmnc_counters; cnt++) {
82 if (pmnc_count[cnt] > 0) { 89 struct perf_event * ev = per_cpu(pevent, cpu)[cnt];
83 ev = per_cpu(pevent_ebs, cpu); // special case for EBS
84 } else {
85 ev = per_cpu(pevent, cpu)[cnt];
86 }
87 if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) { 90 if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) {
88 ev->pmu->read(ev); 91 ev->pmu->read(ev);
89 per_cpu(perfPrev, cpu)[cnt] = per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count); 92 per_cpu(perfPrev, cpu)[cnt] = per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count);
@@ -102,18 +105,22 @@ static int gator_events_perf_pmu_online(int** buffer)
102static void gator_events_perf_pmu_online_dispatch(int cpu) 105static void gator_events_perf_pmu_online_dispatch(int cpu)
103{ 106{
104 int cnt; 107 int cnt;
108 perf_overflow_handler_t handler;
105 109
106 for (cnt = 0; cnt < pmnc_counters; cnt++) { 110 for (cnt = 0; cnt < pmnc_counters; cnt++) {
107 if (per_cpu(pevent, cpu)[cnt] != NULL || per_cpu(pevent_attr, cpu)[cnt] == 0) 111 if (per_cpu(pevent, cpu)[cnt] != NULL || per_cpu(pevent_attr, cpu)[cnt] == 0)
108 continue; 112 continue;
109 113
110 if (pmnc_count[cnt] > 0) 114 if (pmnc_count[cnt] > 0) {
111 continue; // skip the EBS counter 115 handler = ebs_overflow_handler;
116 } else {
117 handler = dummy_handler;
118 }
112 119
113#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) 120#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
114 per_cpu(pevent, cpu)[cnt] = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu)[cnt], cpu, 0, dummy_handler); 121 per_cpu(pevent, cpu)[cnt] = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu)[cnt], cpu, 0, handler);
115#else 122#else
116 per_cpu(pevent, cpu)[cnt] = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu)[cnt], cpu, 0, dummy_handler, 0); 123 per_cpu(pevent, cpu)[cnt] = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu)[cnt], cpu, 0, handler, 0);
117#endif 124#endif
118 if (IS_ERR(per_cpu(pevent, cpu)[cnt])) { 125 if (IS_ERR(per_cpu(pevent, cpu)[cnt])) {
119 pr_debug("gator: unable to online a counter on cpu %d\n", cpu); 126 pr_debug("gator: unable to online a counter on cpu %d\n", cpu);
@@ -154,6 +161,18 @@ static int gator_events_perf_pmu_start(void)
154{ 161{
155 int cnt, cpu; 162 int cnt, cpu;
156 u32 size = sizeof(struct perf_event_attr); 163 u32 size = sizeof(struct perf_event_attr);
164 int found_ebs = false;
165
166 for (cnt = 0; cnt < pmnc_counters; cnt++) {
167 if (pmnc_count[cnt] > 0) {
168 if (!found_ebs) {
169 found_ebs = true;
170 } else {
171 // Only one ebs counter is allowed
172 return -1;
173 }
174 }
175 }
157 176
158 for_each_present_cpu(cpu) { 177 for_each_present_cpu(cpu) {
159 for (cnt = 0; cnt < pmnc_counters; cnt++) { 178 for (cnt = 0; cnt < pmnc_counters; cnt++) {
@@ -174,7 +193,7 @@ static int gator_events_perf_pmu_start(void)
174 per_cpu(pevent_attr, cpu)[cnt]->type = PERF_TYPE_RAW; 193 per_cpu(pevent_attr, cpu)[cnt]->type = PERF_TYPE_RAW;
175 per_cpu(pevent_attr, cpu)[cnt]->size = size; 194 per_cpu(pevent_attr, cpu)[cnt]->size = size;
176 per_cpu(pevent_attr, cpu)[cnt]->config = pmnc_event[cnt]; 195 per_cpu(pevent_attr, cpu)[cnt]->config = pmnc_event[cnt];
177 per_cpu(pevent_attr, cpu)[cnt]->sample_period = 0; 196 per_cpu(pevent_attr, cpu)[cnt]->sample_period = pmnc_count[cnt];
178 per_cpu(pevent_attr, cpu)[cnt]->pinned = 1; 197 per_cpu(pevent_attr, cpu)[cnt]->pinned = 1;
179 198
180 // handle special case for ccnt 199 // handle special case for ccnt
@@ -212,14 +231,9 @@ static int gator_events_perf_pmu_read(int **buffer)
212{ 231{
213 int cnt, delta, len = 0; 232 int cnt, delta, len = 0;
214 int cpu = smp_processor_id(); 233 int cpu = smp_processor_id();
215 struct perf_event * ev;
216 234
217 for (cnt = 0; cnt < pmnc_counters; cnt++) { 235 for (cnt = 0; cnt < pmnc_counters; cnt++) {
218 if (pmnc_count[cnt] > 0) { 236 struct perf_event * ev = per_cpu(pevent, cpu)[cnt];
219 ev = per_cpu(pevent_ebs, cpu); // special case for EBS
220 } else {
221 ev = per_cpu(pevent, cpu)[cnt];
222 }
223 if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) { 237 if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) {
224 ev->pmu->read(ev); 238 ev->pmu->read(ev);
225 per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count); 239 per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count);
@@ -300,6 +314,11 @@ int gator_events_perf_pmu_init(void)
300 pmnc_name = "Krait"; 314 pmnc_name = "Krait";
301 pmnc_counters = 4; 315 pmnc_counters = 4;
302 break; 316 break;
317 case AARCH64:
318 pmnc_name = "ARM_AArch64";
319 // Copied from A15, get the correct number
320 pmnc_counters = 6;
321 break;
303 default: 322 default:
304 return -1; 323 return -1;
305 } 324 }
diff --git a/driver/gator_main.c b/driver/gator_main.c
index f6c1135..309c6c2 100644
--- a/driver/gator_main.c
+++ b/driver/gator_main.c
@@ -7,7 +7,7 @@
7 * 7 *
8 */ 8 */
9 9
10static unsigned long gator_protocol_version = 10; 10static unsigned long gator_protocol_version = 11;
11 11
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/cpu.h> 13#include <linux/cpu.h>
@@ -48,50 +48,74 @@ static unsigned long gator_protocol_version = 10;
48 48
49#if (GATOR_PERF_SUPPORT) && (!(GATOR_PERF_PMU_SUPPORT)) 49#if (GATOR_PERF_SUPPORT) && (!(GATOR_PERF_PMU_SUPPORT))
50#ifndef CONFIG_PERF_EVENTS 50#ifndef CONFIG_PERF_EVENTS
51#warning gator requires the kernel to have CONFIG_PERF_EVENTS defined to support pmu hardware counters 51#error gator requires the kernel to have CONFIG_PERF_EVENTS defined to support pmu hardware counters
52#elif !defined CONFIG_HW_PERF_EVENTS 52#elif !defined CONFIG_HW_PERF_EVENTS
53#warning gator requires the kernel to have CONFIG_HW_PERF_EVENTS defined to support pmu hardware counters 53#error gator requires the kernel to have CONFIG_HW_PERF_EVENTS defined to support pmu hardware counters
54#endif 54#endif
55#endif 55#endif
56 56
57/****************************************************************************** 57/******************************************************************************
58 * DEFINES 58 * DEFINES
59 ******************************************************************************/ 59 ******************************************************************************/
60#define BACKTRACE_BUFFER_SIZE (128*1024) 60#define SUMMARY_BUFFER_SIZE (1*1024)
61#define COUNTER_BUFFER_SIZE (128*1024) 61#define BACKTRACE_BUFFER_SIZE (128*1024)
62#define ANNOTATE_BUFFER_SIZE (64*1024) // annotate counters have the core as part of the data and the core value in the frame header may be discarded 62#define NAME_BUFFER_SIZE (64*1024)
63#define SCHED_TRACE_BUFFER_SIZE (128*1024) 63#define COUNTER_BUFFER_SIZE (64*1024) // counters have the core as part of the data and the core value in the frame header may be discarded
64#define GPU_TRACE_BUFFER_SIZE (64*1024) 64#define BLOCK_COUNTER_BUFFER_SIZE (128*1024)
65#define COUNTER2_BUFFER_SIZE (64*1024) // counters2 counters have the core as part of the data and the core value in the frame header may be discarded 65#define ANNOTATE_BUFFER_SIZE (64*1024) // annotate counters have the core as part of the data and the core value in the frame header may be discarded
66#define WFI_BUFFER_SIZE (32*1024) // wfi counters have the core as part of the data and the core value in the frame header may be discarded 66#define SCHED_TRACE_BUFFER_SIZE (128*1024)
67 67#define GPU_TRACE_BUFFER_SIZE (64*1024) // gpu trace counters have the core as part of the data and the core value in the frame header may be discarded
68#define NO_COOKIE 0UL 68#define IDLE_BUFFER_SIZE (32*1024) // idle counters have the core as part of the data and the core value in the frame header may be discarded
69#define INVALID_COOKIE ~0UL 69
70 70#define NO_COOKIE 0U
71#define FRAME_BACKTRACE 1 71#define INVALID_COOKIE ~0U
72#define FRAME_COUNTER 2 72
73#define FRAME_ANNOTATE 3 73#define FRAME_SUMMARY 1
74#define FRAME_SCHED_TRACE 4 74#define FRAME_BACKTRACE 2
75#define FRAME_GPU_TRACE 5 75#define FRAME_NAME 3
76#define FRAME_COUNTER2 6 76#define FRAME_COUNTER 4
77#define FRAME_WFI 7 77#define FRAME_BLOCK_COUNTER 5
78 78#define FRAME_ANNOTATE 6
79#define MESSAGE_COOKIE 1 79#define FRAME_SCHED_TRACE 7
80#define MESSAGE_START_BACKTRACE 5 80#define FRAME_GPU_TRACE 8
81#define MESSAGE_END_BACKTRACE 7 81#define FRAME_IDLE 9
82#define MESSAGE_SUMMARY 9 82
83#define MESSAGE_PID_NAME 11 83#define MESSAGE_END_BACKTRACE 1
84 84
85#define MAXSIZE_PACK32 5 85#define MESSAGE_COOKIE 1
86#define MAXSIZE_PACK64 9 86#define MESSAGE_THREAD_NAME 2
87#define HRTIMER_CORE_NAME 3
88
89#define MESSAGE_GPU_START 1
90#define MESSAGE_GPU_STOP 2
91
92#define MESSAGE_SCHED_SWITCH 1
93#define MESSAGE_SCHED_EXIT 2
94
95#define MAXSIZE_PACK32 5
96#define MAXSIZE_PACK64 10
97#define MAXSIZE_CORE_NAME 32
87 98
88#if defined(__arm__) 99#if defined(__arm__)
89#define PC_REG regs->ARM_pc 100#define PC_REG regs->ARM_pc
101#elif defined(__aarch64__)
102#define PC_REG regs->pc
90#else 103#else
91#define PC_REG regs->ip 104#define PC_REG regs->ip
92#endif 105#endif
93 106
94enum {BACKTRACE_BUF, COUNTER_BUF, SCHED_TRACE_BUF, GPU_TRACE_BUF, ANNOTATE_BUF, COUNTER2_BUF, WFI_BUF, NUM_GATOR_BUFS}; 107enum {
108 SUMMARY_BUF,
109 BACKTRACE_BUF,
110 NAME_BUF,
111 COUNTER_BUF,
112 BLOCK_COUNTER_BUF,
113 ANNOTATE_BUF,
114 SCHED_TRACE_BUF,
115 GPU_TRACE_BUF,
116 IDLE_BUF,
117 NUM_GATOR_BUFS
118};
95 119
96/****************************************************************************** 120/******************************************************************************
97 * Globals 121 * Globals
@@ -101,17 +125,13 @@ static unsigned long userspace_buffer_size;
101static unsigned long gator_backtrace_depth; 125static unsigned long gator_backtrace_depth;
102 126
103static unsigned long gator_started; 127static unsigned long gator_started;
128static uint64_t monotonic_started;
104static unsigned long gator_buffer_opened; 129static unsigned long gator_buffer_opened;
105static unsigned long gator_timer_count; 130static unsigned long gator_timer_count;
106static unsigned long gator_response_type; 131static unsigned long gator_response_type;
107static DEFINE_MUTEX(start_mutex); 132static DEFINE_MUTEX(start_mutex);
108static DEFINE_MUTEX(gator_buffer_mutex); 133static DEFINE_MUTEX(gator_buffer_mutex);
109 134
110bool event_based_sampling;
111#if defined(__arm__) && (GATOR_PERF_PMU_SUPPORT)
112DEFINE_PER_CPU(struct perf_event *, pevent_ebs);
113#endif
114
115static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait); 135static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait);
116static struct timer_list gator_buffer_wake_up_timer; 136static struct timer_list gator_buffer_wake_up_timer;
117static LIST_HEAD(gator_events); 137static LIST_HEAD(gator_events);
@@ -125,10 +145,10 @@ static bool buffer_check_space(int cpu, int buftype, int bytes);
125static int contiguous_space_available(int cpu, int bufytpe); 145static int contiguous_space_available(int cpu, int bufytpe);
126static void gator_buffer_write_packed_int(int cpu, int buftype, unsigned int x); 146static void gator_buffer_write_packed_int(int cpu, int buftype, unsigned int x);
127static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long long x); 147static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long long x);
128static void gator_buffer_write_bytes(int cpu, int buftype, char *x, int len); 148static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int len);
129static void gator_buffer_write_string(int cpu, int buftype, char *x); 149static void gator_buffer_write_string(int cpu, int buftype, const char *x);
130static void gator_add_trace(int cpu, int buftype, unsigned int address); 150static void gator_add_trace(int cpu, unsigned long address);
131static void gator_add_sample(int cpu, int buftype, struct pt_regs * const regs); 151static void gator_add_sample(int cpu, struct pt_regs * const regs);
132static uint64_t gator_get_time(void); 152static uint64_t gator_get_time(void);
133 153
134static uint32_t gator_buffer_size[NUM_GATOR_BUFS]; 154static uint32_t gator_buffer_size[NUM_GATOR_BUFS];
@@ -152,17 +172,20 @@ static DEFINE_PER_CPU(char *[NUM_GATOR_BUFS], gator_buffer);
152#include "gator_backtrace.c" 172#include "gator_backtrace.c"
153#include "gator_annotate.c" 173#include "gator_annotate.c"
154#include "gator_fs.c" 174#include "gator_fs.c"
155#include "gator_ebs.c"
156#include "gator_pack.c" 175#include "gator_pack.c"
157 176
158/****************************************************************************** 177/******************************************************************************
159 * Misc 178 * Misc
160 ******************************************************************************/ 179 ******************************************************************************/
161#if defined(__arm__) 180#if defined(__arm__) || defined(__aarch64__)
162u32 gator_cpuid(void) 181u32 gator_cpuid(void)
163{ 182{
164 u32 val; 183 u32 val;
184#if !defined(__aarch64__)
165 asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r" (val)); 185 asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r" (val));
186#else
187 asm volatile("mrs %0, midr_el1" : "=r" (val));
188#endif
166 return (val >> 4) & 0xfff; 189 return (val >> 4) & 0xfff;
167} 190}
168#endif 191#endif
@@ -237,7 +260,7 @@ static bool buffer_check_space(int cpu, int buftype, int bytes)
237 return per_cpu(buffer_space_available, cpu)[buftype]; 260 return per_cpu(buffer_space_available, cpu)[buftype];
238} 261}
239 262
240static void gator_buffer_write_bytes(int cpu, int buftype, char *x, int len) 263static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int len)
241{ 264{
242 int i; 265 int i;
243 u32 write = per_cpu(gator_buffer_write, cpu)[buftype]; 266 u32 write = per_cpu(gator_buffer_write, cpu)[buftype];
@@ -252,7 +275,7 @@ static void gator_buffer_write_bytes(int cpu, int buftype, char *x, int len)
252 per_cpu(gator_buffer_write, cpu)[buftype] = write; 275 per_cpu(gator_buffer_write, cpu)[buftype] = write;
253} 276}
254 277
255static void gator_buffer_write_string(int cpu, int buftype, char *x) 278static void gator_buffer_write_string(int cpu, int buftype, const char *x)
256{ 279{
257 int len = strlen(x); 280 int len = strlen(x);
258 gator_buffer_write_packed_int(cpu, buftype, len); 281 gator_buffer_write_packed_int(cpu, buftype, len);
@@ -263,22 +286,38 @@ static void gator_buffer_header(int cpu, int buftype)
263{ 286{
264 int frame; 287 int frame;
265 288
266 if (buftype == BACKTRACE_BUF) 289 switch (buftype) {
290 case SUMMARY_BUF:
291 frame = FRAME_SUMMARY;
292 break;
293 case BACKTRACE_BUF:
267 frame = FRAME_BACKTRACE; 294 frame = FRAME_BACKTRACE;
268 else if (buftype == COUNTER_BUF) 295 break;
296 case NAME_BUF:
297 frame = FRAME_NAME;
298 break;
299 case COUNTER_BUF:
269 frame = FRAME_COUNTER; 300 frame = FRAME_COUNTER;
270 else if (buftype == ANNOTATE_BUF) 301 break;
302 case BLOCK_COUNTER_BUF:
303 frame = FRAME_BLOCK_COUNTER;
304 break;
305 case ANNOTATE_BUF:
271 frame = FRAME_ANNOTATE; 306 frame = FRAME_ANNOTATE;
272 else if (buftype == SCHED_TRACE_BUF) 307 break;
308 case SCHED_TRACE_BUF:
273 frame = FRAME_SCHED_TRACE; 309 frame = FRAME_SCHED_TRACE;
274 else if (buftype == GPU_TRACE_BUF) 310 break;
311 case GPU_TRACE_BUF:
275 frame = FRAME_GPU_TRACE; 312 frame = FRAME_GPU_TRACE;
276 else if (buftype == COUNTER2_BUF) 313 break;
277 frame = FRAME_COUNTER2; 314 case IDLE_BUF:
278 else if (buftype == WFI_BUF) 315 frame = FRAME_IDLE;
279 frame = FRAME_WFI; 316 break;
280 else 317 default:
281 frame = -1; 318 frame = -1;
319 break;
320 }
282 321
283 if (per_cpu(gator_buffer, cpu)[buftype]) { 322 if (per_cpu(gator_buffer, cpu)[buftype]) {
284 marshal_frame(cpu, buftype, frame); 323 marshal_frame(cpu, buftype, frame);
@@ -308,10 +347,10 @@ static void buffer_check(int cpu, int buftype)
308 } 347 }
309} 348}
310 349
311static void gator_add_trace(int cpu, int buftype, unsigned int address) 350static void gator_add_trace(int cpu, unsigned long address)
312{ 351{
313 off_t offset = 0; 352 off_t offset = 0;
314 unsigned long cookie = get_address_cookie(cpu, buftype, current, address & ~1, &offset); 353 unsigned long cookie = get_address_cookie(cpu, current, address & ~1, &offset);
315 354
316 if (cookie == NO_COOKIE || cookie == INVALID_COOKIE) { 355 if (cookie == NO_COOKIE || cookie == INVALID_COOKIE) {
317 offset = address; 356 offset = address;
@@ -320,26 +359,29 @@ static void gator_add_trace(int cpu, int buftype, unsigned int address)
320 marshal_backtrace(offset & ~1, cookie); 359 marshal_backtrace(offset & ~1, cookie);
321} 360}
322 361
323static void gator_add_sample(int cpu, int buftype, struct pt_regs * const regs) 362static void gator_add_sample(int cpu, struct pt_regs * const regs)
324{ 363{
325 int inKernel = regs ? !user_mode(regs) : 1; 364 bool inKernel;
326 unsigned long exec_cookie = inKernel ? NO_COOKIE : get_exec_cookie(cpu, buftype, current); 365 unsigned long exec_cookie;
327 366
328 if (!regs) 367 if (!regs)
329 return; 368 return;
330 369
370 inKernel = !user_mode(regs);
371 exec_cookie = get_exec_cookie(cpu, current);
372
331 if (!marshal_backtrace_header(exec_cookie, current->tgid, current->pid, inKernel)) 373 if (!marshal_backtrace_header(exec_cookie, current->tgid, current->pid, inKernel))
332 return; 374 return;
333 375
334 if (inKernel) { 376 if (inKernel) {
335 kernel_backtrace(cpu, buftype, regs); 377 kernel_backtrace(cpu, regs);
336 } else { 378 } else {
337 // Cookie+PC 379 // Cookie+PC
338 gator_add_trace(cpu, buftype, PC_REG); 380 gator_add_trace(cpu, PC_REG);
339 381
340 // Backtrace 382 // Backtrace
341 if (gator_backtrace_depth) 383 if (gator_backtrace_depth)
342 arm_backtrace_eabi(cpu, buftype, regs, gator_backtrace_depth); 384 arm_backtrace_eabi(cpu, regs, gator_backtrace_depth);
343 } 385 }
344 386
345 marshal_backtrace_footer(); 387 marshal_backtrace_footer();
@@ -351,13 +393,20 @@ static void gator_add_sample(int cpu, int buftype, struct pt_regs * const regs)
351static void gator_timer_interrupt(void) 393static void gator_timer_interrupt(void)
352{ 394{
353 struct pt_regs * const regs = get_irq_regs(); 395 struct pt_regs * const regs = get_irq_regs();
396 gator_backtrace_handler(regs);
397}
398
399void gator_backtrace_handler(struct pt_regs * const regs)
400{
354 int cpu = smp_processor_id(); 401 int cpu = smp_processor_id();
355 402
356 // Output backtrace 403 // Output backtrace
357 gator_add_sample(cpu, BACKTRACE_BUF, regs); 404 gator_add_sample(cpu, regs);
358 405
359 // Collect counters 406 // Collect counters
360 collect_counters(); 407 if (!per_cpu(collecting, cpu)) {
408 collect_counters();
409 }
361} 410}
362 411
363static int gator_running; 412static int gator_running;
@@ -397,8 +446,6 @@ static void gator_timer_offline_dispatch(int cpu)
397 list_for_each_entry(gi, &gator_events, list) 446 list_for_each_entry(gi, &gator_events, list)
398 if (gi->offline_dispatch) 447 if (gi->offline_dispatch)
399 gi->offline_dispatch(cpu); 448 gi->offline_dispatch(cpu);
400
401 gator_event_sampling_offline_dispatch(cpu);
402} 449}
403 450
404static void gator_timer_stop(void) 451static void gator_timer_stop(void)
@@ -436,6 +483,32 @@ static void gator_timer_online(void* unused)
436 } 483 }
437 484
438 gator_hrtimer_online(cpu); 485 gator_hrtimer_online(cpu);
486#if defined(__arm__) || defined(__aarch64__)
487 {
488 const char * core_name = NULL;
489
490 // String lengths must be less than MAXSIZE_CORE_NAME
491 switch (gator_cpuid()) {
492 case ARM1136: core_name = "ARM1136"; break;
493 case ARM1156: core_name = "ARM1156"; break;
494 case ARM1176: core_name = "ARM1176"; break;
495 case ARM11MPCORE: core_name = "ARM11MPCore"; break;
496 case CORTEX_A5: core_name = "Cortex-A5"; break;
497 case CORTEX_A7: core_name = "Cortex-A7"; break;
498 case CORTEX_A8: core_name = "Cortex-A8"; break;
499 case CORTEX_A9: core_name = "Cortex-A9"; break;
500 case CORTEX_A15: core_name = "Cortex-A15"; break;
501 case SCORPION: core_name = "Scorpion"; break;
502 case SCORPIONMP: core_name = "ScorpionMP"; break;
503 case KRAITSIM: core_name = "KraitSIM"; break;
504 case KRAIT: core_name = "Krait"; break;
505 case AARCH64: core_name = "AArch64"; break;
506 default: core_name = "Unknown"; break;
507 }
508
509 marshal_core_name(core_name);
510 }
511#endif
439} 512}
440 513
441// This function runs in interrupt context and may be running on a core other than core 'cpu' 514// This function runs in interrupt context and may be running on a core other than core 'cpu'
@@ -446,8 +519,6 @@ static void gator_timer_online_dispatch(int cpu)
446 list_for_each_entry(gi, &gator_events, list) 519 list_for_each_entry(gi, &gator_events, list)
447 if (gi->online_dispatch) 520 if (gi->online_dispatch)
448 gi->online_dispatch(cpu); 521 gi->online_dispatch(cpu);
449
450 gator_event_sampling_online_dispatch(cpu);
451} 522}
452 523
453int gator_timer_start(unsigned long sample_rate) 524int gator_timer_start(unsigned long sample_rate)
@@ -461,10 +532,6 @@ int gator_timer_start(unsigned long sample_rate)
461 532
462 gator_running = 1; 533 gator_running = 1;
463 534
464 // event based sampling trumps hr timer based sampling
465 if (event_based_sampling)
466 sample_rate = 0;
467
468 if (gator_hrtimer_init(sample_rate, gator_timer_interrupt) == -1) 535 if (gator_hrtimer_init(sample_rate, gator_timer_interrupt) == -1)
469 return -1; 536 return -1;
470 537
@@ -481,8 +548,9 @@ static uint64_t gator_get_time(void)
481 struct timespec ts; 548 struct timespec ts;
482 uint64_t timestamp; 549 uint64_t timestamp;
483 550
484 getnstimeofday(&ts); 551 //getnstimeofday(&ts);
485 timestamp = timespec_to_ns(&ts); 552 do_posix_clock_monotonic_gettime(&ts);
553 timestamp = timespec_to_ns(&ts) - monotonic_started;
486 554
487 return timestamp; 555 return timestamp;
488} 556}
@@ -568,20 +636,15 @@ static void gator_notifier_stop(void)
568 ******************************************************************************/ 636 ******************************************************************************/
569static void gator_summary(void) 637static void gator_summary(void)
570{ 638{
571 uint64_t timestamp, uptime = 0; 639 uint64_t timestamp;
572 struct timespec uptime_ts; 640 struct timespec uptime_ts;
573 void (*m2b)(struct timespec *ts);
574 641
575 timestamp = gator_get_time(); 642 timestamp = gator_get_time();
576 643
577 do_posix_clock_monotonic_gettime(&uptime_ts); 644 do_posix_clock_monotonic_gettime(&uptime_ts);
578 m2b = symbol_get(monotonic_to_bootbased); 645 monotonic_started = timespec_to_ns(&uptime_ts);
579 if (m2b) {
580 m2b(&uptime_ts);
581 uptime = (long long)uptime_ts.tv_sec * 1000000000 + uptime_ts.tv_nsec;
582 }
583 646
584 marshal_summary(timestamp, uptime); 647 marshal_summary(timestamp, monotonic_started);
585} 648}
586 649
587int gator_events_install(struct gator_interface *interface) 650int gator_events_install(struct gator_interface *interface)
@@ -656,8 +719,6 @@ static int gator_start(void)
656 goto power_failure; 719 goto power_failure;
657 if (gator_trace_gpu_start()) 720 if (gator_trace_gpu_start())
658 goto gpu_failure; 721 goto gpu_failure;
659 if (gator_event_sampling_start())
660 goto event_sampling_failure;
661 if (gator_timer_start(gator_timer_count)) 722 if (gator_timer_start(gator_timer_count))
662 goto timer_failure; 723 goto timer_failure;
663 if (gator_notifier_start()) 724 if (gator_notifier_start())
@@ -668,8 +729,6 @@ static int gator_start(void)
668notifier_failure: 729notifier_failure:
669 gator_timer_stop(); 730 gator_timer_stop();
670timer_failure: 731timer_failure:
671 gator_event_sampling_stop();
672event_sampling_failure:
673 gator_trace_gpu_stop(); 732 gator_trace_gpu_stop();
674gpu_failure: 733gpu_failure:
675 gator_trace_power_stop(); 734 gator_trace_power_stop();
@@ -697,7 +756,6 @@ static void gator_stop(void)
697 gator_trace_sched_stop(); 756 gator_trace_sched_stop();
698 gator_trace_power_stop(); 757 gator_trace_power_stop();
699 gator_trace_gpu_stop(); 758 gator_trace_gpu_stop();
700 gator_event_sampling_stop();
701 759
702 // stop all interrupt callback reads before tearing down other interfaces 760 // stop all interrupt callback reads before tearing down other interfaces
703 gator_notifier_stop(); // should be called before gator_timer_stop to avoid re-enabling the hrtimer after it has been offlined 761 gator_notifier_stop(); // should be called before gator_timer_stop to avoid re-enabling the hrtimer after it has been offlined
@@ -720,26 +778,32 @@ static int gator_op_setup(void)
720 778
721 mutex_lock(&start_mutex); 779 mutex_lock(&start_mutex);
722 780
781 gator_buffer_size[SUMMARY_BUF] = SUMMARY_BUFFER_SIZE;
782 gator_buffer_mask[SUMMARY_BUF] = SUMMARY_BUFFER_SIZE - 1;
783
723 gator_buffer_size[BACKTRACE_BUF] = BACKTRACE_BUFFER_SIZE; 784 gator_buffer_size[BACKTRACE_BUF] = BACKTRACE_BUFFER_SIZE;
724 gator_buffer_mask[BACKTRACE_BUF] = BACKTRACE_BUFFER_SIZE - 1; 785 gator_buffer_mask[BACKTRACE_BUF] = BACKTRACE_BUFFER_SIZE - 1;
725 786
787 gator_buffer_size[NAME_BUF] = NAME_BUFFER_SIZE;
788 gator_buffer_mask[NAME_BUF] = NAME_BUFFER_SIZE - 1;
789
726 gator_buffer_size[COUNTER_BUF] = COUNTER_BUFFER_SIZE; 790 gator_buffer_size[COUNTER_BUF] = COUNTER_BUFFER_SIZE;
727 gator_buffer_mask[COUNTER_BUF] = COUNTER_BUFFER_SIZE - 1; 791 gator_buffer_mask[COUNTER_BUF] = COUNTER_BUFFER_SIZE - 1;
728 792
793 gator_buffer_size[BLOCK_COUNTER_BUF] = BLOCK_COUNTER_BUFFER_SIZE;
794 gator_buffer_mask[BLOCK_COUNTER_BUF] = BLOCK_COUNTER_BUFFER_SIZE - 1;
795
796 gator_buffer_size[ANNOTATE_BUF] = ANNOTATE_BUFFER_SIZE;
797 gator_buffer_mask[ANNOTATE_BUF] = ANNOTATE_BUFFER_SIZE - 1;
798
729 gator_buffer_size[SCHED_TRACE_BUF] = SCHED_TRACE_BUFFER_SIZE; 799 gator_buffer_size[SCHED_TRACE_BUF] = SCHED_TRACE_BUFFER_SIZE;
730 gator_buffer_mask[SCHED_TRACE_BUF] = SCHED_TRACE_BUFFER_SIZE - 1; 800 gator_buffer_mask[SCHED_TRACE_BUF] = SCHED_TRACE_BUFFER_SIZE - 1;
731 801
732 gator_buffer_size[GPU_TRACE_BUF] = GPU_TRACE_BUFFER_SIZE; 802 gator_buffer_size[GPU_TRACE_BUF] = GPU_TRACE_BUFFER_SIZE;
733 gator_buffer_mask[GPU_TRACE_BUF] = GPU_TRACE_BUFFER_SIZE - 1; 803 gator_buffer_mask[GPU_TRACE_BUF] = GPU_TRACE_BUFFER_SIZE - 1;
734 804
735 gator_buffer_size[ANNOTATE_BUF] = ANNOTATE_BUFFER_SIZE; 805 gator_buffer_size[IDLE_BUF] = IDLE_BUFFER_SIZE;
736 gator_buffer_mask[ANNOTATE_BUF] = ANNOTATE_BUFFER_SIZE - 1; 806 gator_buffer_mask[IDLE_BUF] = IDLE_BUFFER_SIZE - 1;
737
738 gator_buffer_size[COUNTER2_BUF] = COUNTER2_BUFFER_SIZE;
739 gator_buffer_mask[COUNTER2_BUF] = COUNTER2_BUFFER_SIZE - 1;
740
741 gator_buffer_size[WFI_BUF] = WFI_BUFFER_SIZE;
742 gator_buffer_mask[WFI_BUF] = WFI_BUFFER_SIZE - 1;
743 807
744 // Initialize percpu per buffer variables 808 // Initialize percpu per buffer variables
745 for (i = 0; i < NUM_GATOR_BUFS; i++) { 809 for (i = 0; i < NUM_GATOR_BUFS; i++) {
@@ -1047,8 +1111,8 @@ void gator_op_create_files(struct super_block *sb, struct dentry *root)
1047 gatorfs_create_file(sb, root, "enable", &enable_fops); 1111 gatorfs_create_file(sb, root, "enable", &enable_fops);
1048 gatorfs_create_file(sb, root, "buffer", &gator_event_buffer_fops); 1112 gatorfs_create_file(sb, root, "buffer", &gator_event_buffer_fops);
1049 gatorfs_create_file(sb, root, "backtrace_depth", &depth_fops); 1113 gatorfs_create_file(sb, root, "backtrace_depth", &depth_fops);
1050 gatorfs_create_ulong(sb, root, "cpu_cores", &gator_cpu_cores); 1114 gatorfs_create_ro_ulong(sb, root, "cpu_cores", &gator_cpu_cores);
1051 gatorfs_create_ulong(sb, root, "buffer_size", &userspace_buffer_size); 1115 gatorfs_create_ro_ulong(sb, root, "buffer_size", &userspace_buffer_size);
1052 gatorfs_create_ulong(sb, root, "tick", &gator_timer_count); 1116 gatorfs_create_ulong(sb, root, "tick", &gator_timer_count);
1053 gatorfs_create_ulong(sb, root, "response_type", &gator_response_type); 1117 gatorfs_create_ulong(sb, root, "response_type", &gator_response_type);
1054 gatorfs_create_ro_ulong(sb, root, "version", &gator_protocol_version); 1118 gatorfs_create_ro_ulong(sb, root, "version", &gator_protocol_version);
diff --git a/driver/gator_marshaling.c b/driver/gator_marshaling.c
index 630d142..a84b280 100644
--- a/driver/gator_marshaling.c
+++ b/driver/gator_marshaling.c
@@ -9,40 +9,44 @@
9 9
10static void marshal_summary(long long timestamp, long long uptime) { 10static void marshal_summary(long long timestamp, long long uptime) {
11 int cpu = 0; 11 int cpu = 0;
12 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_SUMMARY); 12 gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, timestamp);
13 gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, timestamp); 13 gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, uptime);
14 gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, uptime); 14 buffer_check(cpu, SUMMARY_BUF);
15} 15}
16 16
17static bool marshal_cookie_header(char* text) { 17static bool marshal_cookie_header(char* text) {
18 int cpu = smp_processor_id(); 18 int cpu = smp_processor_id();
19 return buffer_check_space(cpu, BACKTRACE_BUF, strlen(text) + 2 * MAXSIZE_PACK32); 19 return buffer_check_space(cpu, NAME_BUF, strlen(text) + 2*MAXSIZE_PACK32);
20} 20}
21 21
22static void marshal_cookie(int cookie, char* text) { 22static void marshal_cookie(int cookie, char* text) {
23 int cpu = smp_processor_id(); 23 int cpu = smp_processor_id();
24 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_COOKIE); 24 // TODO(dreric01) How long can the string be?
25 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, cookie); 25 if (buffer_check_space(cpu, NAME_BUF, 2*MAXSIZE_PACK32)) {
26 gator_buffer_write_string(cpu, BACKTRACE_BUF, text); 26 gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_COOKIE);
27 gator_buffer_write_packed_int(cpu, NAME_BUF, cookie);
28 gator_buffer_write_string(cpu, NAME_BUF, text);
29 }
30 buffer_check(cpu, NAME_BUF);
27} 31}
28 32
29static void marshal_pid_name(int pid, char* name) { 33static void marshal_thread_name(int pid, char* name) {
30 unsigned long flags, cpu; 34 unsigned long flags, cpu;
31 local_irq_save(flags); 35 local_irq_save(flags);
32 cpu = smp_processor_id(); 36 cpu = smp_processor_id();
33 if (buffer_check_space(cpu, BACKTRACE_BUF, TASK_COMM_LEN + 2 * MAXSIZE_PACK32 + MAXSIZE_PACK64)) { 37 if (buffer_check_space(cpu, NAME_BUF, TASK_COMM_LEN + 2*MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
34 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_PID_NAME); 38 gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_THREAD_NAME);
35 gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, gator_get_time()); 39 gator_buffer_write_packed_int64(cpu, NAME_BUF, gator_get_time());
36 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, pid); 40 gator_buffer_write_packed_int(cpu, NAME_BUF, pid);
37 gator_buffer_write_string(cpu, BACKTRACE_BUF, name); 41 gator_buffer_write_string(cpu, NAME_BUF, name);
38 } 42 }
39 local_irq_restore(flags); 43 local_irq_restore(flags);
44 buffer_check(cpu, NAME_BUF);
40} 45}
41 46
42static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inKernel) { 47static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inKernel) {
43 int cpu = smp_processor_id(); 48 int cpu = smp_processor_id();
44 if (buffer_check_space(cpu, BACKTRACE_BUF, gator_backtrace_depth * 2 * MAXSIZE_PACK32)) { 49 if (buffer_check_space(cpu, BACKTRACE_BUF, gator_backtrace_depth*2*MAXSIZE_PACK32)) {
45 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_START_BACKTRACE);
46 gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, gator_get_time()); 50 gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, gator_get_time());
47 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, exec_cookie); 51 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, exec_cookie);
48 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, tgid); 52 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, tgid);
@@ -57,9 +61,9 @@ static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inK
57 return false; 61 return false;
58} 62}
59 63
60static void marshal_backtrace(int address, int cookie) { 64static void marshal_backtrace(unsigned long address, int cookie) {
61 int cpu = smp_processor_id(); 65 int cpu = smp_processor_id();
62 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, address); 66 gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, address);
63 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, cookie); 67 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, cookie);
64} 68}
65 69
@@ -76,15 +80,15 @@ static bool marshal_event_header(void) {
76 bool retval = false; 80 bool retval = false;
77 81
78 local_irq_save(flags); 82 local_irq_save(flags);
79 if (buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK32 + MAXSIZE_PACK64)) { 83 if (buffer_check_space(cpu, BLOCK_COUNTER_BUF, MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
80 gator_buffer_write_packed_int(cpu, COUNTER_BUF, 0); // key of zero indicates a timestamp 84 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, 0); // key of zero indicates a timestamp
81 gator_buffer_write_packed_int64(cpu, COUNTER_BUF, gator_get_time()); 85 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, gator_get_time());
82 retval = true; 86 retval = true;
83 } 87 }
84 local_irq_restore(flags); 88 local_irq_restore(flags);
85 89
86 // Check and commit; commit is set to occur once buffer is 3/4 full 90 // Check and commit; commit is set to occur once buffer is 3/4 full
87 buffer_check(cpu, COUNTER_BUF); 91 buffer_check(cpu, BLOCK_COUNTER_BUF);
88 92
89 return retval; 93 return retval;
90} 94}
@@ -104,17 +108,17 @@ static void marshal_event(int len, int* buffer) {
104 // events must be written in key,value pairs 108 // events must be written in key,value pairs
105 for (i = 0; i < len; i += 2) { 109 for (i = 0; i < len; i += 2) {
106 local_irq_save(flags); 110 local_irq_save(flags);
107 if (!buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK32 * 2)) { 111 if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2*MAXSIZE_PACK32)) {
108 local_irq_restore(flags); 112 local_irq_restore(flags);
109 break; 113 break;
110 } 114 }
111 gator_buffer_write_packed_int(cpu, COUNTER_BUF, buffer[i]); 115 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i]);
112 gator_buffer_write_packed_int(cpu, COUNTER_BUF, buffer[i + 1]); 116 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i + 1]);
113 local_irq_restore(flags); 117 local_irq_restore(flags);
114 } 118 }
115 119
116 // Check and commit; commit is set to occur once buffer is 3/4 full 120 // Check and commit; commit is set to occur once buffer is 3/4 full
117 buffer_check(cpu, COUNTER_BUF); 121 buffer_check(cpu, BLOCK_COUNTER_BUF);
118} 122}
119 123
120static void marshal_event64(int len, long long* buffer64) { 124static void marshal_event64(int len, long long* buffer64) {
@@ -132,17 +136,17 @@ static void marshal_event64(int len, long long* buffer64) {
132 // events must be written in key,value pairs 136 // events must be written in key,value pairs
133 for (i = 0; i < len; i += 2) { 137 for (i = 0; i < len; i += 2) {
134 local_irq_save(flags); 138 local_irq_save(flags);
135 if (!buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK64 * 2)) { 139 if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2*MAXSIZE_PACK64)) {
136 local_irq_restore(flags); 140 local_irq_restore(flags);
137 break; 141 break;
138 } 142 }
139 gator_buffer_write_packed_int64(cpu, COUNTER_BUF, buffer64[i]); 143 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i]);
140 gator_buffer_write_packed_int64(cpu, COUNTER_BUF, buffer64[i + 1]); 144 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i + 1]);
141 local_irq_restore(flags); 145 local_irq_restore(flags);
142 } 146 }
143 147
144 // Check and commit; commit is set to occur once buffer is 3/4 full 148 // Check and commit; commit is set to occur once buffer is 3/4 full
145 buffer_check(cpu, COUNTER_BUF); 149 buffer_check(cpu, BLOCK_COUNTER_BUF);
146} 150}
147 151
148#if GATOR_CPU_FREQ_SUPPORT 152#if GATOR_CPU_FREQ_SUPPORT
@@ -151,28 +155,28 @@ static void marshal_event_single(int core, int key, int value) {
151 155
152 local_irq_save(flags); 156 local_irq_save(flags);
153 cpu = smp_processor_id(); 157 cpu = smp_processor_id();
154 if (buffer_check_space(cpu, COUNTER2_BUF, MAXSIZE_PACK64 + MAXSIZE_PACK32 * 3)) { 158 if (buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK64 + 3*MAXSIZE_PACK32)) {
155 gator_buffer_write_packed_int64(cpu, COUNTER2_BUF, gator_get_time()); 159 gator_buffer_write_packed_int64(cpu, COUNTER_BUF, gator_get_time());
156 gator_buffer_write_packed_int(cpu, COUNTER2_BUF, core); 160 gator_buffer_write_packed_int(cpu, COUNTER_BUF, core);
157 gator_buffer_write_packed_int(cpu, COUNTER2_BUF, key); 161 gator_buffer_write_packed_int(cpu, COUNTER_BUF, key);
158 gator_buffer_write_packed_int(cpu, COUNTER2_BUF, value); 162 gator_buffer_write_packed_int(cpu, COUNTER_BUF, value);
159 } 163 }
160 local_irq_restore(flags); 164 local_irq_restore(flags);
161 165
162 // Check and commit; commit is set to occur once buffer is 3/4 full 166 // Check and commit; commit is set to occur once buffer is 3/4 full
163 buffer_check(cpu, COUNTER2_BUF); 167 buffer_check(cpu, COUNTER_BUF);
164} 168}
165#endif 169#endif
166 170
167static void marshal_sched_gpu(int type, int unit, int core, int tgid, int pid) { 171static void marshal_sched_gpu_start(int unit, int core, int tgid, int pid) {
168 unsigned long cpu = smp_processor_id(), flags; 172 unsigned long cpu = smp_processor_id(), flags;
169 173
170 if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF]) 174 if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF])
171 return; 175 return;
172 176
173 local_irq_save(flags); 177 local_irq_save(flags);
174 if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) { 178 if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 5*MAXSIZE_PACK32)) {
175 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, type); 179 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_START);
176 gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, gator_get_time()); 180 gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, gator_get_time());
177 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit); 181 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit);
178 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core); 182 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core);
@@ -185,18 +189,37 @@ static void marshal_sched_gpu(int type, int unit, int core, int tgid, int pid) {
185 buffer_check(cpu, GPU_TRACE_BUF); 189 buffer_check(cpu, GPU_TRACE_BUF);
186} 190}
187 191
188static void marshal_sched_trace(int type, int pid, int tgid, int cookie, int state) { 192static void marshal_sched_gpu_stop(int unit, int core) {
193 unsigned long cpu = smp_processor_id(), flags;
194
195 if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF])
196 return;
197
198 local_irq_save(flags);
199 if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 3*MAXSIZE_PACK32)) {
200 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_STOP);
201 gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, gator_get_time());
202 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit);
203 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core);
204 }
205 local_irq_restore(flags);
206
207 // Check and commit; commit is set to occur once buffer is 3/4 full
208 buffer_check(cpu, GPU_TRACE_BUF);
209}
210
211static void marshal_sched_trace_switch(int tgid, int pid, int cookie, int state) {
189 unsigned long cpu = smp_processor_id(), flags; 212 unsigned long cpu = smp_processor_id(), flags;
190 213
191 if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF]) 214 if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
192 return; 215 return;
193 216
194 local_irq_save(flags); 217 local_irq_save(flags);
195 if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) { 218 if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5*MAXSIZE_PACK32)) {
196 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, type); 219 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_SWITCH);
197 gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, gator_get_time()); 220 gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, gator_get_time());
198 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
199 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, tgid); 221 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, tgid);
222 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
200 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, cookie); 223 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, cookie);
201 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, state); 224 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, state);
202 } 225 }
@@ -206,21 +229,39 @@ static void marshal_sched_trace(int type, int pid, int tgid, int cookie, int sta
206 buffer_check(cpu, SCHED_TRACE_BUF); 229 buffer_check(cpu, SCHED_TRACE_BUF);
207} 230}
208 231
232static void marshal_sched_trace_exit(int tgid, int pid) {
233 unsigned long cpu = smp_processor_id(), flags;
234
235 if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
236 return;
237
238 local_irq_save(flags);
239 if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 2*MAXSIZE_PACK32)) {
240 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_EXIT);
241 gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, gator_get_time());
242 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
243 }
244 local_irq_restore(flags);
245
246 // Check and commit; commit is set to occur once buffer is 3/4 full
247 buffer_check(cpu, SCHED_TRACE_BUF);
248}
249
209#if GATOR_CPU_FREQ_SUPPORT 250#if GATOR_CPU_FREQ_SUPPORT
210static void marshal_wfi(int core, int state) { 251static void marshal_idle(int core, int state) {
211 unsigned long flags, cpu; 252 unsigned long flags, cpu;
212 253
213 local_irq_save(flags); 254 local_irq_save(flags);
214 cpu = smp_processor_id(); 255 cpu = smp_processor_id();
215 if (buffer_check_space(cpu, WFI_BUF, MAXSIZE_PACK64 + MAXSIZE_PACK32 * 2)) { 256 if (buffer_check_space(cpu, IDLE_BUF, MAXSIZE_PACK64 + 2*MAXSIZE_PACK32)) {
216 gator_buffer_write_packed_int64(cpu, WFI_BUF, gator_get_time()); 257 gator_buffer_write_packed_int(cpu, IDLE_BUF, state);
217 gator_buffer_write_packed_int(cpu, WFI_BUF, core); 258 gator_buffer_write_packed_int64(cpu, IDLE_BUF, gator_get_time());
218 gator_buffer_write_packed_int(cpu, WFI_BUF, state); 259 gator_buffer_write_packed_int(cpu, IDLE_BUF, core);
219 } 260 }
220 local_irq_restore(flags); 261 local_irq_restore(flags);
221 262
222 // Check and commit; commit is set to occur once buffer is 3/4 full 263 // Check and commit; commit is set to occur once buffer is 3/4 full
223 buffer_check(cpu, WFI_BUF); 264 buffer_check(cpu, IDLE_BUF);
224} 265}
225#endif 266#endif
226 267
@@ -237,3 +278,18 @@ static void marshal_frame(int cpu, int buftype, int frame) {
237 gator_buffer_write_packed_int(cpu, buftype, frame); 278 gator_buffer_write_packed_int(cpu, buftype, frame);
238 gator_buffer_write_packed_int(cpu, buftype, cpu); 279 gator_buffer_write_packed_int(cpu, buftype, cpu);
239} 280}
281
282#if defined(__arm__) || defined(__aarch64__)
283static void marshal_core_name(const char* name) {
284 int cpu = smp_processor_id();
285 unsigned long flags;
286 local_irq_save(flags);
287 if (buffer_check_space(cpu, NAME_BUF, MAXSIZE_PACK32 + MAXSIZE_CORE_NAME)) {
288 gator_buffer_write_packed_int(cpu, NAME_BUF, HRTIMER_CORE_NAME);
289 gator_buffer_write_string(cpu, NAME_BUF, name);
290 }
291 local_irq_restore(flags);
292
293 buffer_check(cpu, NAME_BUF);
294}
295#endif
diff --git a/driver/gator_pack.c b/driver/gator_pack.c
index 925469a..5ad53db 100644
--- a/driver/gator_pack.c
+++ b/driver/gator_pack.c
@@ -141,7 +141,7 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long
141 buffer[write6] = (x>>42) | 0x80; 141 buffer[write6] = (x>>42) | 0x80;
142 buffer[write7] = (x>>49) & 0x7f; 142 buffer[write7] = (x>>49) & 0x7f;
143 per_cpu(gator_buffer_write, cpu)[buftype] = write8; 143 per_cpu(gator_buffer_write, cpu)[buftype] = write8;
144 } else { 144 } else if ((x & 0x8000000000000000LL) == 0) {
145 int write2 = (write + 2) & mask; 145 int write2 = (write + 2) & mask;
146 int write3 = (write + 3) & mask; 146 int write3 = (write + 3) & mask;
147 int write4 = (write + 4) & mask; 147 int write4 = (write + 4) & mask;
@@ -158,7 +158,28 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long
158 buffer[write5] = (x>>35) | 0x80; 158 buffer[write5] = (x>>35) | 0x80;
159 buffer[write6] = (x>>42) | 0x80; 159 buffer[write6] = (x>>42) | 0x80;
160 buffer[write7] = (x>>49) | 0x80; 160 buffer[write7] = (x>>49) | 0x80;
161 buffer[write8] = (x>>56) & 0xff; 161 buffer[write8] = (x>>56) & 0x7f;
162 per_cpu(gator_buffer_write, cpu)[buftype] = write9; 162 per_cpu(gator_buffer_write, cpu)[buftype] = write9;
163 } else {
164 int write2 = (write + 2) & mask;
165 int write3 = (write + 3) & mask;
166 int write4 = (write + 4) & mask;
167 int write5 = (write + 5) & mask;
168 int write6 = (write + 6) & mask;
169 int write7 = (write + 7) & mask;
170 int write8 = (write + 8) & mask;
171 int write9 = (write + 9) & mask;
172 int write10 = (write + 10) & mask;
173 buffer[write0] = x | 0x80;
174 buffer[write1] = (x>>7) | 0x80;
175 buffer[write2] = (x>>14) | 0x80;
176 buffer[write3] = (x>>21) | 0x80;
177 buffer[write4] = (x>>28) | 0x80;
178 buffer[write5] = (x>>35) | 0x80;
179 buffer[write6] = (x>>42) | 0x80;
180 buffer[write7] = (x>>49) | 0x80;
181 buffer[write8] = (x>>56) | 0x80;
182 buffer[write9] = (x>>63) & 0x7f;
183 per_cpu(gator_buffer_write, cpu)[buftype] = write10;
163 } 184 }
164} 185}
diff --git a/driver/gator_trace_gpu.c b/driver/gator_trace_gpu.c
index d053987..0511d71 100644
--- a/driver/gator_trace_gpu.c
+++ b/driver/gator_trace_gpu.c
@@ -33,9 +33,7 @@ static int mali_timeline_trace_registered;
33static int mali_job_slots_trace_registered; 33static int mali_job_slots_trace_registered;
34static int gpu_trace_registered; 34static int gpu_trace_registered;
35 35
36#define GPU_START 1 36#define GPU_UNIT_NONE 0
37#define GPU_STOP 2
38
39#define GPU_UNIT_VP 1 37#define GPU_UNIT_VP 1
40#define GPU_UNIT_FP 2 38#define GPU_UNIT_FP 2
41#define GPU_UNIT_CL 3 39#define GPU_UNIT_CL 3
@@ -84,18 +82,18 @@ GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned
84 case EVENT_TYPE_START: 82 case EVENT_TYPE_START:
85 if (component == EVENT_CHANNEL_VP0) { 83 if (component == EVENT_CHANNEL_VP0) {
86 /* tgid = d0; pid = d1; */ 84 /* tgid = d0; pid = d1; */
87 marshal_sched_gpu(GPU_START, GPU_UNIT_VP, 0, d0, d1); 85 marshal_sched_gpu_start(GPU_UNIT_VP, 0, d0, d1);
88 } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) { 86 } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
89 /* tgid = d0; pid = d1; */ 87 /* tgid = d0; pid = d1; */
90 marshal_sched_gpu(GPU_START, GPU_UNIT_FP, component - EVENT_CHANNEL_FP0, d0, d1); 88 marshal_sched_gpu_start(GPU_UNIT_FP, component - EVENT_CHANNEL_FP0, d0, d1);
91 } 89 }
92 break; 90 break;
93 91
94 case EVENT_TYPE_STOP: 92 case EVENT_TYPE_STOP:
95 if (component == EVENT_CHANNEL_VP0) { 93 if (component == EVENT_CHANNEL_VP0) {
96 marshal_sched_gpu(GPU_STOP, GPU_UNIT_VP, 0, 0, 0); 94 marshal_sched_gpu_stop(GPU_UNIT_VP, 0);
97 } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) { 95 } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
98 marshal_sched_gpu(GPU_STOP, GPU_UNIT_FP, component - EVENT_CHANNEL_FP0, 0, 0); 96 marshal_sched_gpu_stop(GPU_UNIT_FP, component - EVENT_CHANNEL_FP0);
99 } 97 }
100 break; 98 break;
101 99
@@ -118,11 +116,10 @@ GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned
118#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx) 116#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
119GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid)) 117GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid))
120{ 118{
121 unsigned int component, state, type, unit = 0; 119 unsigned int component, state, unit;
122 120
123 component = (event_id >> 16) & 0xFF; // component is an 8-bit field 121 component = (event_id >> 16) & 0xFF; // component is an 8-bit field
124 state = (event_id >> 24) & 0xF; // state is a 4-bit field 122 state = (event_id >> 24) & 0xF; // state is a 4-bit field
125 type = (state == EVENT_TYPE_START) ? GPU_START : GPU_STOP;
126 123
127 switch (component) 124 switch (component)
128 { 125 {
@@ -135,23 +132,37 @@ GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigne
135 case 2: 132 case 2:
136 unit = GPU_UNIT_CL; 133 unit = GPU_UNIT_CL;
137 break; 134 break;
135 default:
136 unit = GPU_UNIT_NONE;
138 } 137 }
139 138
140 if (unit != 0) 139 if (unit != GPU_UNIT_NONE)
141 { 140 {
142 marshal_sched_gpu(type, unit, 0, tgid, (pid != 0 ? pid : tgid)); 141 switch(state) {
142 case EVENT_TYPE_START:
143 marshal_sched_gpu_start(unit, 0, tgid, (pid != 0 ? pid : tgid));
144 break;
145 case EVENT_TYPE_STOP:
146 marshal_sched_gpu_stop(unit, 0);
147 break;
148 default:
149 /*
150 * Some jobs can be soft-stopped, so ensure that this terminates the activity trace.
151 */
152 marshal_sched_gpu_stop(unit, 0);
153 }
143 } 154 }
144} 155}
145#endif 156#endif
146 157
147GATOR_DEFINE_PROBE(gpu_activity_start, TP_PROTO(int gpu_unit, int gpu_core, struct task_struct *p)) 158GATOR_DEFINE_PROBE(gpu_activity_start, TP_PROTO(int gpu_unit, int gpu_core, struct task_struct *p))
148{ 159{
149 marshal_sched_gpu(GPU_START, gpu_unit, gpu_core, (int)p->tgid, (int)p->pid); 160 marshal_sched_gpu_start(gpu_unit, gpu_core, (int)p->tgid, (int)p->pid);
150} 161}
151 162
152GATOR_DEFINE_PROBE(gpu_activity_stop, TP_PROTO(int gpu_unit, int gpu_core)) 163GATOR_DEFINE_PROBE(gpu_activity_stop, TP_PROTO(int gpu_unit, int gpu_core))
153{ 164{
154 marshal_sched_gpu(GPU_STOP, gpu_unit, gpu_core, 0, 0); 165 marshal_sched_gpu_stop(gpu_unit, gpu_core);
155} 166}
156 167
157int gator_trace_gpu_start(void) 168int gator_trace_gpu_start(void)
diff --git a/driver/gator_trace_power.c b/driver/gator_trace_power.c
index ca89b19..b1687e1 100644
--- a/driver/gator_trace_power.c
+++ b/driver/gator_trace_power.c
@@ -9,6 +9,7 @@
9 9
10#include <linux/cpufreq.h> 10#include <linux/cpufreq.h>
11#include <trace/events/power.h> 11#include <trace/events/power.h>
12#include <asm/mach-types.h>
12 13
13// cpu_frequency and cpu_idle trace points were introduced in Linux kernel v2.6.38 14// cpu_frequency and cpu_idle trace points were introduced in Linux kernel v2.6.38
14// the now deprecated power_frequency trace point was available prior to 2.6.38, but only for x86 15// the now deprecated power_frequency trace point was available prior to 2.6.38, but only for x86
@@ -52,32 +53,29 @@ GATOR_DEFINE_PROBE(cpu_frequency, TP_PROTO(unsigned int frequency, unsigned int
52 marshal_event_single(cpu, power_cpu_key[POWER_CPU_FREQ], frequency * 1000); 53 marshal_event_single(cpu, power_cpu_key[POWER_CPU_FREQ], frequency * 1000);
53} 54}
54 55
55#define WFI_ACTIVE_THRESHOLD 2 // may vary on platform/OS 56#define WFI_EXIT 2
56#define WFI_EXIT 0
57#define WFI_ENTER 1 57#define WFI_ENTER 1
58GATOR_DEFINE_PROBE(cpu_idle, TP_PROTO(unsigned int state, unsigned int cpu)) 58GATOR_DEFINE_PROBE(cpu_idle, TP_PROTO(unsigned int state, unsigned int cpu))
59{ 59{
60 // the streamline engine treats all counter values as unsigned
61 if (state & 0x80000000) {
62 state = 0;
63 }
64
65 if (state == per_cpu(idle_prev_state, cpu)) { 60 if (state == per_cpu(idle_prev_state, cpu)) {
66 return; 61 return;
67 } 62 }
68 63
69 if (state < WFI_ACTIVE_THRESHOLD && per_cpu(idle_prev_state, cpu) >= WFI_ACTIVE_THRESHOLD) { 64 if (!machine_is_omap3_beagle()) {
70 // transition from wfi to non-wfi 65 if (state == PWR_EVENT_EXIT) {
71 marshal_wfi(cpu, WFI_EXIT); 66 // transition from wfi to non-wfi
72 } else if (state >= WFI_ACTIVE_THRESHOLD && per_cpu(idle_prev_state, cpu) < WFI_ACTIVE_THRESHOLD) { 67 marshal_idle(cpu, WFI_EXIT);
73 // transition from non-wfi to wfi 68 } else {
74 marshal_wfi(cpu, WFI_ENTER); 69 // transition from non-wfi to wfi
70 marshal_idle(cpu, WFI_ENTER);
71 }
75 } 72 }
76 73
77 per_cpu(idle_prev_state, cpu) = state; 74 per_cpu(idle_prev_state, cpu) = state;
78 75
79 if (power_cpu_enabled[POWER_CPU_IDLE]) { 76 if (power_cpu_enabled[POWER_CPU_IDLE]) {
80 marshal_event_single(cpu, power_cpu_key[POWER_CPU_IDLE], state); 77 // Increment state so that no negative numbers are sent
78 marshal_event_single(cpu, power_cpu_key[POWER_CPU_IDLE], state + 1);
81 } 79 }
82} 80}
83 81
diff --git a/driver/gator_trace_sched.c b/driver/gator_trace_sched.c
index 08b0270..9ddb822 100644
--- a/driver/gator_trace_sched.c
+++ b/driver/gator_trace_sched.c
@@ -17,6 +17,7 @@
17#define TASK_MAX_COLLISIONS 2 17#define TASK_MAX_COLLISIONS 2
18 18
19static DEFINE_PER_CPU(uint64_t *, taskname_keys); 19static DEFINE_PER_CPU(uint64_t *, taskname_keys);
20static DEFINE_PER_CPU(int, collecting);
20 21
21enum { 22enum {
22 STATE_WAIT_ON_OTHER = 0, 23 STATE_WAIT_ON_OTHER = 0,
@@ -59,7 +60,7 @@ void emit_pid_name(struct task_struct* task)
59 strcat(taskcomm, "..."); 60 strcat(taskcomm, "...");
60 } 61 }
61 62
62 marshal_pid_name(task->pid, taskcomm); 63 marshal_thread_name(task->pid, taskcomm);
63 } 64 }
64} 65}
65 66
@@ -87,12 +88,12 @@ static void probe_sched_write(int type, struct task_struct* task, struct task_st
87{ 88{
88 int cookie = 0, state = 0; 89 int cookie = 0, state = 0;
89 int cpu = smp_processor_id(); 90 int cpu = smp_processor_id();
90 int pid = task->pid;
91 int tgid = task->tgid; 91 int tgid = task->tgid;
92 int pid = task->pid;
92 93
93 if (type == SCHED_SWITCH) { 94 if (type == SCHED_SWITCH) {
94 // do as much work as possible before disabling interrupts 95 // do as much work as possible before disabling interrupts
95 cookie = get_exec_cookie(cpu, BACKTRACE_BUF, task); 96 cookie = get_exec_cookie(cpu, task);
96 emit_pid_name(task); 97 emit_pid_name(task);
97 if (old_task->state == TASK_RUNNING) { 98 if (old_task->state == TASK_RUNNING) {
98 state = STATE_CONTENTION; 99 state = STATE_CONTENTION;
@@ -106,18 +107,24 @@ static void probe_sched_write(int type, struct task_struct* task, struct task_st
106 state = STATE_WAIT_ON_OTHER; 107 state = STATE_WAIT_ON_OTHER;
107 } 108 }
108 109
110 per_cpu(collecting, cpu) = 1;
109 collect_counters(); 111 collect_counters();
112 per_cpu(collecting, cpu) = 0;
110 } 113 }
111 114
112 // marshal_sched_trace() disables interrupts as the free may trigger while switch is writing to the buffer; disabling preemption is not sufficient 115 // marshal_sched_trace() disables interrupts as the free may trigger while switch is writing to the buffer; disabling preemption is not sufficient
113 // is disable interrupts necessary now that exit is used instead of free? 116 // is disable interrupts necessary now that exit is used instead of free?
114 marshal_sched_trace(type, pid, tgid, cookie, state); 117 if (type == SCHED_SWITCH) {
118 marshal_sched_trace_switch(tgid, pid, cookie, state);
119 } else {
120 marshal_sched_trace_exit(tgid, pid);
121 }
115} 122}
116 123
117// special case used during a suspend of the system 124// special case used during a suspend of the system
118static void trace_sched_insert_idle(void) 125static void trace_sched_insert_idle(void)
119{ 126{
120 marshal_sched_trace(SCHED_SWITCH, 0, 0, 0, 0); 127 marshal_sched_trace_switch(0, 0, 0, 0);
121} 128}
122 129
123#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) 130#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
diff --git a/driver/mali_t6xx.mk b/driver/mali_t6xx.mk
index 2e51670..2cc6411 100644
--- a/driver/mali_t6xx.mk
+++ b/driver/mali_t6xx.mk
@@ -11,13 +11,14 @@ EXTRA_CFLAGS += -DMALI_USE_UMP=1 \
11 11
12KBASE_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase 12KBASE_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase
13OSK_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase/osk 13OSK_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase/osk
14UMP_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/ump 14UMP_DIR = $(DDK_DIR)/kernel/include/linux
15 15
16# Include directories in the DDK 16# Include directories in the DDK
17EXTRA_CFLAGS += -I$(DDK_DIR) \ 17EXTRA_CFLAGS += -I$(DDK_DIR) \
18 -I$(KBASE_DIR)/.. \ 18 -I$(KBASE_DIR)/.. \
19 -I$(OSK_DIR)/.. \ 19 -I$(OSK_DIR)/.. \
20 -I$(UMP_DIR)/.. \ 20 -I$(UMP_DIR)/.. \
21 -I$(DDK_DIR)/kernel/include \
21 -I$(KBASE_DIR)/osk/src/linux/include \ 22 -I$(KBASE_DIR)/osk/src/linux/include \
22 -I$(KBASE_DIR)/platform_dummy \ 23 -I$(KBASE_DIR)/platform_dummy \
23 -I$(KBASE_DIR)/src 24 -I$(KBASE_DIR)/src