summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPawel Moll2011-05-27 10:30:10 -0500
committerPawel Moll2011-05-27 10:30:10 -0500
commitc5e21c20e9c3b00a3057965e7ab0a55a5873594b (patch)
tree591738ea4836c9e5fec619a21cd84d02b0b1ade1
parent438a1e1cbf4b99b4f6ff1ecf07f9b7cfcc20d517 (diff)
downloadarm-ds5-gator-c5e21c20e9c3b00a3057965e7ab0a55a5873594b.tar.gz
arm-ds5-gator-c5e21c20e9c3b00a3057965e7ab0a55a5873594b.tar.xz
arm-ds5-gator-c5e21c20e9c3b00a3057965e7ab0a55a5873594b.zip
gator: ARM DS-5.5 Streamline gator driver
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
-rw-r--r--gator_annotate.c20
-rw-r--r--gator_cookies.c204
-rw-r--r--gator_events_net.c10
-rw-r--r--gator_fs.c18
-rw-r--r--gator_main.c33
5 files changed, 236 insertions, 49 deletions
diff --git a/gator_annotate.c b/gator_annotate.c
index 56656f0..f261f73 100644
--- a/gator_annotate.c
+++ b/gator_annotate.c
@@ -23,17 +23,6 @@ static char *annotateBuf1;
23static int annotatePos; 23static int annotatePos;
24static int annotateSel; 24static int annotateSel;
25 25
26static int gatorfs_copy_from_user(char* localbuf, char const __user *buf, size_t count)
27{
28 if (count == 0)
29 return 0;
30
31 if (copy_from_user(localbuf, buf, count))
32 return -EFAULT;
33
34 return 0;
35}
36
37static ssize_t annotate_write(struct file *file, char const __user *buf, size_t count, loff_t *offset) 26static ssize_t annotate_write(struct file *file, char const __user *buf, size_t count, loff_t *offset)
38{ 27{
39 char tempBuffer[32]; 28 char tempBuffer[32];
@@ -51,7 +40,7 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t
51 return 0; 40 return 0;
52 41
53 // copy from user space 42 // copy from user space
54 retval = gatorfs_copy_from_user(tempBuffer, buf, size); 43 retval = copy_from_user(tempBuffer, buf, size);
55 if (retval == 0) { 44 if (retval == 0) {
56 // synchronize shared variables annotateBuf and annotatePos 45 // synchronize shared variables annotateBuf and annotatePos
57 spin_lock_irqsave(&annotate_lock, flags); 46 spin_lock_irqsave(&annotate_lock, flags);
@@ -68,6 +57,8 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t
68 57
69 // return the number of bytes written 58 // return the number of bytes written
70 retval = size; 59 retval = size;
60 } else {
61 retval = -EINVAL;
71 } 62 }
72 63
73 return retval; 64 return retval;
@@ -101,13 +92,14 @@ int gator_annotate_start(void)
101 92
102void gator_annotate_stop(void) 93void gator_annotate_stop(void)
103{ 94{
104 spin_lock(&annotate_lock); 95 unsigned long flags;
96 spin_lock_irqsave(&annotate_lock, flags);
105 97
106 kfree(annotateBuf0); 98 kfree(annotateBuf0);
107 kfree(annotateBuf1); 99 kfree(annotateBuf1);
108 annotateBuf = annotateBuf0 = annotateBuf1 = NULL; 100 annotateBuf = annotateBuf0 = annotateBuf1 = NULL;
109 101
110 spin_unlock(&annotate_lock); 102 spin_unlock_irqrestore(&annotate_lock, flags);
111} 103}
112 104
113int gator_annotate_read(int **buffer) 105int gator_annotate_read(int **buffer)
diff --git a/gator_cookies.c b/gator_cookies.c
index 4e39667..70fece0 100644
--- a/gator_cookies.c
+++ b/gator_cookies.c
@@ -8,15 +8,26 @@
8 */ 8 */
9 9
10#define COOKIEMAP_ENTRIES 1024 /* must be power of 2 */ 10#define COOKIEMAP_ENTRIES 1024 /* must be power of 2 */
11#define TRANSLATE_SIZE 256
11#define MAX_COLLISIONS 2 12#define MAX_COLLISIONS 2
12 13
14static uint32_t *gator_crc32_table;
15static uint32_t translate_buffer_mask;
16
17static DEFINE_PER_CPU(char *, translate_text);
13static DEFINE_PER_CPU(uint32_t, cookie_next_key); 18static DEFINE_PER_CPU(uint32_t, cookie_next_key);
14static DEFINE_PER_CPU(uint64_t *, cookie_keys); 19static DEFINE_PER_CPU(uint64_t *, cookie_keys);
15static DEFINE_PER_CPU(uint32_t *, cookie_values); 20static DEFINE_PER_CPU(uint32_t *, cookie_values);
21static DEFINE_PER_CPU(int, translate_buffer_read);
22static DEFINE_PER_CPU(int, translate_buffer_write);
23static DEFINE_PER_CPU(unsigned int *, translate_buffer);
16 24
17static uint32_t *gator_crc32_table; 25static inline uint32_t get_cookie(int cpu, struct task_struct *task, struct vm_area_struct *vma, struct module *mod);
26static void wq_cookie_handler(struct work_struct *unused);
27DECLARE_WORK(cookie_work, wq_cookie_handler);
18 28
19static uint32_t cookiemap_code(uint32_t value) { 29static uint32_t cookiemap_code(uint64_t value64) {
30 uint32_t value = (uint32_t)((value64 >> 32) + value64);
20 uint32_t cookiecode = (value >> 24) & 0xff; 31 uint32_t cookiecode = (value >> 24) & 0xff;
21 cookiecode = cookiecode * 31 + ((value >> 16) & 0xff); 32 cookiecode = cookiecode * 31 + ((value >> 16) & 0xff);
22 cookiecode = cookiecode * 31 + ((value >> 8) & 0xff); 33 cookiecode = cookiecode * 31 + ((value >> 8) & 0xff);
@@ -45,12 +56,14 @@ static uint32_t gator_chksum_crc32(char *data)
45 * Post: [v][0][1][3]..[n-1] 56 * Post: [v][0][1][3]..[n-1]
46 */ 57 */
47static uint32_t cookiemap_exists(uint64_t key) { 58static uint32_t cookiemap_exists(uint64_t key) {
59 unsigned long x, flags, retval = 0;
48 int cpu = raw_smp_processor_id(); 60 int cpu = raw_smp_processor_id();
49 uint32_t cookiecode = cookiemap_code(key); 61 uint32_t cookiecode = cookiemap_code(key);
50 uint64_t *keys = &(per_cpu(cookie_keys, cpu)[cookiecode]); 62 uint64_t *keys = &(per_cpu(cookie_keys, cpu)[cookiecode]);
51 uint32_t *values = &(per_cpu(cookie_values, cpu)[cookiecode]); 63 uint32_t *values = &(per_cpu(cookie_values, cpu)[cookiecode]);
52 int x;
53 64
65 // Can be called from interrupt handler or from work queue
66 local_irq_save(flags);
54 for (x = 0; x < MAX_COLLISIONS; x++) { 67 for (x = 0; x < MAX_COLLISIONS; x++) {
55 if (keys[x] == key) { 68 if (keys[x] == key) {
56 uint32_t value = values[x]; 69 uint32_t value = values[x];
@@ -60,11 +73,13 @@ static uint32_t cookiemap_exists(uint64_t key) {
60 } 73 }
61 keys[0] = key; 74 keys[0] = key;
62 values[0] = value; 75 values[0] = value;
63 return value; 76 retval = value;
77 break;
64 } 78 }
65 } 79 }
80 local_irq_restore(flags);
66 81
67 return 0; 82 return retval;
68} 83}
69 84
70/* 85/*
@@ -87,30 +102,146 @@ static void cookiemap_add(uint64_t key, uint32_t value) {
87 values[0] = value; 102 values[0] = value;
88} 103}
89 104
90static inline uint32_t get_cookie(int cpu, int tgid, struct vm_area_struct *vma) 105static void translate_buffer_write_int(int cpu, unsigned int x)
106{
107 per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_write, cpu)++] = x;
108 per_cpu(translate_buffer_write, cpu) &= translate_buffer_mask;
109}
110
111static unsigned int translate_buffer_read_int(int cpu)
112{
113 unsigned int value = per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_read, cpu)++];
114 per_cpu(translate_buffer_read, cpu) &= translate_buffer_mask;
115 return value;
116}
117
118static void wq_cookie_handler(struct work_struct *unused)
119{
120 struct task_struct *task;
121 struct vm_area_struct *vma;
122 int cpu = smp_processor_id();
123 unsigned int cookie, commit;
124
125 commit = per_cpu(translate_buffer_write, cpu);
126 while (per_cpu(translate_buffer_read, cpu) != commit) {
127 task = (struct task_struct *)translate_buffer_read_int(cpu);
128 vma = (struct vm_area_struct *)translate_buffer_read_int(cpu);
129 cookie = get_cookie(cpu, task, vma, NULL);
130 }
131}
132
133// Retrieve full name from proc/pid/cmdline for java processes on Android
134static int translate_app_process(char** text, int cpu, struct task_struct * task, struct vm_area_struct *vma)
91{ 135{
136 void *maddr;
137 unsigned int len;
138 unsigned long addr;
139 struct mm_struct *mm;
140 struct page *page = NULL;
141 struct vm_area_struct *page_vma;
142 int bytes, offset, retval = 0, ptr;
143 char * buf = per_cpu(translate_text, cpu);
144
145 // Push work into a work queue if in atomic context as the kernel functions below might sleep
146 if (in_irq()) {
147 // Check if already in buffer
148 ptr = per_cpu(translate_buffer_read, cpu);
149 while (ptr != per_cpu(translate_buffer_write, cpu)) {
150 if (per_cpu(translate_buffer, cpu)[ptr] == (int)task)
151 goto out;
152 ptr = (ptr + 2) & translate_buffer_mask;
153 }
154
155 translate_buffer_write_int(cpu, (unsigned int)task);
156 translate_buffer_write_int(cpu, (unsigned int)vma);
157 schedule_work(&cookie_work);
158 goto out;
159 }
160
161 mm = get_task_mm(task);
162 if (!mm)
163 goto out;
164 if (!mm->arg_end)
165 goto outmm;
166 addr = mm->arg_start;
167 len = mm->arg_end - mm->arg_start;
168
169 if (len > TRANSLATE_SIZE)
170 len = TRANSLATE_SIZE;
171
172 down_read(&mm->mmap_sem);
173 while (len) {
174 if (get_user_pages(task, mm, addr, 1, 0, 1, &page, &page_vma) <= 0)
175 goto outsem;
176
177 maddr = kmap(page);
178 offset = addr & (PAGE_SIZE-1);
179 bytes = len;
180 if (bytes > PAGE_SIZE - offset)
181 bytes = PAGE_SIZE - offset;
182
183 copy_from_user_page(page_vma, page, addr, buf, maddr + offset, bytes);
184
185 kunmap(page); // release page allocated by get_user_pages()
186 page_cache_release(page);
187
188 len -= bytes;
189 buf += bytes;
190 addr += bytes;
191
192 *text = per_cpu(translate_text, cpu);
193 retval = 1;
194 }
195
196 // On app_process startup, /proc/pid/cmdline is initially "zygote" then "<pre-initialized>" but changes after an initial startup period
197 if (strcmp(*text, "zygote") == 0 || strcmp(*text, "<pre-initialized>") == 0)
198 retval = 0;
199
200outsem:
201 up_read(&mm->mmap_sem);
202outmm:
203 mmput(mm);
204out:
205 return retval;
206}
207
208static inline uint32_t get_cookie(int cpu, struct task_struct *task, struct vm_area_struct *vma, struct module *mod)
209{
210 unsigned long flags, cookie;
92 struct path *path; 211 struct path *path;
93 uint64_t key; 212 uint64_t key;
94 int cookie;
95 char *text; 213 char *text;
96 214
97 if (!vma || !vma->vm_file) { 215 if (mod) {
98 return INVALID_COOKIE; 216 text = mod->name;
99 } 217 } else {
100 path = &vma->vm_file->f_path; 218 if (!vma || !vma->vm_file) {
101 if (!path || !path->dentry) { 219 return INVALID_COOKIE;
102 return INVALID_COOKIE; 220 }
221 path = &vma->vm_file->f_path;
222 if (!path || !path->dentry) {
223 return INVALID_COOKIE;
224 }
225
226 text = (char*)path->dentry->d_name.name;
103 } 227 }
104 228
105 text = (char*)path->dentry->d_name.name;
106 key = gator_chksum_crc32(text); 229 key = gator_chksum_crc32(text);
107 key = (key << 32) | (uint32_t)text; 230 key = (key << 32) | (uint32_t)task->tgid;
108 231
109 cookie = cookiemap_exists(key); 232 cookie = cookiemap_exists(key);
110 if (cookie) { 233 if (cookie) {
111 goto output; 234 return cookie;
112 } 235 }
113 236
237 if (strcmp(text, "app_process") == 0 && !mod) {
238 if (!translate_app_process(&text, cpu, task, vma))
239 return INVALID_COOKIE;
240 }
241
242 // Can be called from interrupt handler or from work queue
243 local_irq_save(flags);
244
114 cookie = per_cpu(cookie_next_key, cpu)+=nr_cpu_ids; 245 cookie = per_cpu(cookie_next_key, cpu)+=nr_cpu_ids;
115 cookiemap_add(key, cookie); 246 cookiemap_add(key, cookie);
116 247
@@ -118,7 +249,8 @@ static inline uint32_t get_cookie(int cpu, int tgid, struct vm_area_struct *vma)
118 gator_buffer_write_packed_int(cpu, cookie); 249 gator_buffer_write_packed_int(cpu, cookie);
119 gator_buffer_write_string(cpu, text); 250 gator_buffer_write_string(cpu, text);
120 251
121output: 252 local_irq_restore(flags);
253
122 return cookie; 254 return cookie;
123} 255}
124 256
@@ -136,7 +268,7 @@ static int get_exec_cookie(int cpu, struct task_struct *task)
136 continue; 268 continue;
137 if (!(vma->vm_flags & VM_EXECUTABLE)) 269 if (!(vma->vm_flags & VM_EXECUTABLE))
138 continue; 270 continue;
139 cookie = get_cookie(cpu, task->tgid, vma); 271 cookie = get_cookie(cpu, task, vma, NULL);
140 break; 272 break;
141 } 273 }
142 274
@@ -157,7 +289,7 @@ static unsigned long get_address_cookie(int cpu, struct task_struct *task, unsig
157 continue; 289 continue;
158 290
159 if (vma->vm_file) { 291 if (vma->vm_file) {
160 cookie = get_cookie(cpu, task->tgid, vma); 292 cookie = get_cookie(cpu, task, vma, NULL);
161 *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start; 293 *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start;
162 } else { 294 } else {
163 /* must be an anonymous map */ 295 /* must be an anonymous map */
@@ -173,11 +305,13 @@ static unsigned long get_address_cookie(int cpu, struct task_struct *task, unsig
173 return cookie; 305 return cookie;
174} 306}
175 307
176static void cookies_initialize(void) 308static int cookies_initialize(void)
177{ 309{
178 uint32_t crc, poly; 310 uint32_t crc, poly;
179 int cpu, size; 311 int i, j, cpu, size, err = 0;
180 int i, j; 312
313 int translate_buffer_size = 512; // must be a power of 2
314 translate_buffer_mask = translate_buffer_size / sizeof(per_cpu(translate_buffer, 0)[0]) - 1;
181 315
182 for_each_present_cpu(cpu) { 316 for_each_present_cpu(cpu) {
183 per_cpu(cookie_next_key, cpu) = nr_cpu_ids + cpu; 317 per_cpu(cookie_next_key, cpu) = nr_cpu_ids + cpu;
@@ -189,6 +323,21 @@ static void cookies_initialize(void)
189 size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint32_t); 323 size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint32_t);
190 per_cpu(cookie_values, cpu) = (uint32_t*)kmalloc(size, GFP_KERNEL); 324 per_cpu(cookie_values, cpu) = (uint32_t*)kmalloc(size, GFP_KERNEL);
191 memset(per_cpu(cookie_values, cpu), 0, size); 325 memset(per_cpu(cookie_values, cpu), 0, size);
326
327 per_cpu(translate_buffer, cpu) = (unsigned int *)kmalloc(translate_buffer_size, GFP_KERNEL);
328 if (!per_cpu(translate_buffer, cpu)) {
329 err = -ENOMEM;
330 goto cookie_setup_error;
331 }
332
333 per_cpu(translate_buffer_write, cpu) = 0;
334 per_cpu(translate_buffer_read, cpu) = 0;
335
336 per_cpu(translate_text, cpu) = (char *)kmalloc(TRANSLATE_SIZE, GFP_KERNEL);
337 if (!per_cpu(translate_text, cpu)) {
338 err = -ENOMEM;
339 goto cookie_setup_error;
340 }
192 } 341 }
193 342
194 // build CRC32 table 343 // build CRC32 table
@@ -205,6 +354,9 @@ static void cookies_initialize(void)
205 } 354 }
206 gator_crc32_table[i] = crc; 355 gator_crc32_table[i] = crc;
207 } 356 }
357
358cookie_setup_error:
359 return err;
208} 360}
209 361
210static void cookies_release(void) 362static void cookies_release(void)
@@ -217,6 +369,14 @@ static void cookies_release(void)
217 369
218 kfree(per_cpu(cookie_values, cpu)); 370 kfree(per_cpu(cookie_values, cpu));
219 per_cpu(cookie_values, cpu) = NULL; 371 per_cpu(cookie_values, cpu) = NULL;
372
373 kfree(per_cpu(translate_buffer, cpu));
374 per_cpu(translate_buffer, cpu) = NULL;
375 per_cpu(translate_buffer_read, cpu) = 0;
376 per_cpu(translate_buffer_write, cpu) = 0;
377
378 kfree(per_cpu(translate_text, cpu));
379 per_cpu(translate_text, cpu) = NULL;
220 } 380 }
221 381
222 kfree(gator_crc32_table); 382 kfree(gator_crc32_table);
diff --git a/gator_events_net.c b/gator_events_net.c
index 3ca5911..15a395e 100644
--- a/gator_events_net.c
+++ b/gator_events_net.c
@@ -136,6 +136,7 @@ static void gator_events_net_stop(void)
136static int gator_events_net_read(int **buffer) 136static int gator_events_net_read(int **buffer)
137{ 137{
138 int len, drv_delta, rx_delta, tx_delta; 138 int len, drv_delta, rx_delta, tx_delta;
139 static int last_drv_delta = 0, last_rx_delta = 0, last_tx_delta = 0;
139 140
140 if (raw_smp_processor_id() != 0) 141 if (raw_smp_processor_id() != 0)
141 return 0; 142 return 0;
@@ -144,17 +145,20 @@ static int gator_events_net_read(int **buffer)
144 calculate_delta(&drv_delta, &rx_delta, &tx_delta); 145 calculate_delta(&drv_delta, &rx_delta, &tx_delta);
145 146
146 len = 0; 147 len = 0;
147 if (netdrv_enabled) { 148 if (netdrv_enabled && last_drv_delta != drv_delta) {
149 last_drv_delta = drv_delta;
148 netGet[len++] = netdrv_key; 150 netGet[len++] = netdrv_key;
149 netGet[len++] = drv_delta; 151 netGet[len++] = drv_delta;
150 } 152 }
151 153
152 if (netrx_enabled) { 154 if (netrx_enabled && last_rx_delta != rx_delta) {
155 last_rx_delta = rx_delta;
153 netGet[len++] = netrx_key; 156 netGet[len++] = netrx_key;
154 netGet[len++] = rx_delta; 157 netGet[len++] = rx_delta;
155 } 158 }
156 159
157 if (nettx_enabled) { 160 if (nettx_enabled && last_tx_delta != tx_delta) {
161 last_tx_delta = tx_delta;
158 netGet[len++] = nettx_key; 162 netGet[len++] = nettx_key;
159 netGet[len++] = tx_delta; 163 netGet[len++] = tx_delta;
160 } 164 }
diff --git a/gator_fs.c b/gator_fs.c
index 5f8983f..f7cbff2 100644
--- a/gator_fs.c
+++ b/gator_fs.c
@@ -27,6 +27,9 @@ static struct inode *gatorfs_get_inode(struct super_block *sb, int mode)
27 struct inode *inode = new_inode(sb); 27 struct inode *inode = new_inode(sb);
28 28
29 if (inode) { 29 if (inode) {
30#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
31 inode->i_ino = get_next_ino();
32#endif
30 inode->i_mode = mode; 33 inode->i_mode = mode;
31 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 34 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
32 } 35 }
@@ -246,16 +249,29 @@ static int gatorfs_fill_super(struct super_block *sb, void *data, int silent)
246 return 0; 249 return 0;
247} 250}
248 251
252#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
249static int gatorfs_get_sb(struct file_system_type *fs_type, 253static int gatorfs_get_sb(struct file_system_type *fs_type,
250 int flags, const char *dev_name, void *data, struct vfsmount *mnt) 254 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
251{ 255{
252 return get_sb_single(fs_type, flags, data, gatorfs_fill_super, mnt); 256 return get_sb_single(fs_type, flags, data, gatorfs_fill_super, mnt);
253} 257}
258#else
259static struct dentry *gatorfs_mount(struct file_system_type *fs_type,
260 int flags, const char *dev_name, void *data)
261{
262 return mount_nodev(fs_type, flags, data, gatorfs_fill_super);
263}
264#endif
254 265
255static struct file_system_type gatorfs_type = { 266static struct file_system_type gatorfs_type = {
256 .owner = THIS_MODULE, 267 .owner = THIS_MODULE,
257 .name = "gatorfs", 268 .name = "gatorfs",
258 .get_sb = gatorfs_get_sb, 269#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
270 .get_sb = gatorfs_get_sb,
271#else
272 .mount = gatorfs_mount,
273#endif
274
259 .kill_sb = kill_litter_super, 275 .kill_sb = kill_litter_super,
260}; 276};
261 277
diff --git a/gator_main.c b/gator_main.c
index 60b09cb..a1ab776 100644
--- a/gator_main.c
+++ b/gator_main.c
@@ -7,7 +7,7 @@
7 * 7 *
8 */ 8 */
9 9
10static unsigned long gator_protocol_version = 3; 10static unsigned long gator_protocol_version = 4;
11 11
12#include "gator.h" 12#include "gator.h"
13#include <linux/slab.h> 13#include <linux/slab.h>
@@ -15,6 +15,9 @@ static unsigned long gator_protocol_version = 3;
15#include <linux/sched.h> 15#include <linux/sched.h>
16#include <linux/irq.h> 16#include <linux/irq.h>
17#include <linux/vmalloc.h> 17#include <linux/vmalloc.h>
18#include <linux/hardirq.h>
19#include <linux/highmem.h>
20#include <linux/pagemap.h>
18#include <asm/uaccess.h> 21#include <asm/uaccess.h>
19 22
20#ifndef CONFIG_GENERIC_TRACER 23#ifndef CONFIG_GENERIC_TRACER
@@ -31,6 +34,12 @@ static unsigned long gator_protocol_version = 3;
31#warning gator requires the kernel to have CONFIG_HIGH_RES_TIMERS defined 34#warning gator requires the kernel to have CONFIG_HIGH_RES_TIMERS defined
32#endif 35#endif
33 36
37#ifdef CONFIG_SMP
38#ifndef CONFIG_LOCAL_TIMERS
39#warning gator requires the kernel to have CONFIG_LOCAL_TIMERS defined on SMP systems
40#endif
41#endif
42
34#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32) 43#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
35#error kernels prior to 2.6.32 are not supported 44#error kernels prior to 2.6.32 are not supported
36#endif 45#endif
@@ -38,7 +47,7 @@ static unsigned long gator_protocol_version = 3;
38/****************************************************************************** 47/******************************************************************************
39 * DEFINES 48 * DEFINES
40 ******************************************************************************/ 49 ******************************************************************************/
41#define BUFFER_SIZE_DEFAULT 262144 50#define BUFFER_SIZE_DEFAULT (256*1024)
42#define SYNC_FREQ_DEFAULT 1000 51#define SYNC_FREQ_DEFAULT 1000
43 52
44#define NO_COOKIE 0UL 53#define NO_COOKIE 0UL
@@ -280,13 +289,15 @@ static void gator_add_trace(int cpu, unsigned int address)
280 289
281static void gator_add_sample(int cpu, struct pt_regs * const regs) 290static void gator_add_sample(int cpu, struct pt_regs * const regs)
282{ 291{
292 struct module *mod;
293 unsigned int addr, cookie = 0;
283 int inKernel = regs ? !user_mode(regs) : 1; 294 int inKernel = regs ? !user_mode(regs) : 1;
284 unsigned long cookie = !inKernel ? get_exec_cookie(cpu, current) : NO_COOKIE; 295 unsigned long exec_cookie = !inKernel ? get_exec_cookie(cpu, current) : NO_COOKIE;
285 296
286 gator_buffer_write_packed_int(cpu, PROTOCOL_START_BACKTRACE); 297 gator_buffer_write_packed_int(cpu, PROTOCOL_START_BACKTRACE);
287 298
288 // TGID::PID::inKernel 299 // TGID::PID::inKernel
289 gator_buffer_write_packed_int(cpu, cookie); 300 gator_buffer_write_packed_int(cpu, exec_cookie);
290 gator_buffer_write_packed_int(cpu, (unsigned int)current->tgid); 301 gator_buffer_write_packed_int(cpu, (unsigned int)current->tgid);
291 gator_buffer_write_packed_int(cpu, (unsigned int)current->pid); 302 gator_buffer_write_packed_int(cpu, (unsigned int)current->pid);
292 gator_buffer_write_packed_int(cpu, inKernel); 303 gator_buffer_write_packed_int(cpu, inKernel);
@@ -294,8 +305,14 @@ static void gator_add_sample(int cpu, struct pt_regs * const regs)
294 // get_irq_regs() will return NULL outside of IRQ context (e.g. nested IRQ) 305 // get_irq_regs() will return NULL outside of IRQ context (e.g. nested IRQ)
295 if (regs) { 306 if (regs) {
296 if (inKernel) { 307 if (inKernel) {
297 gator_buffer_write_packed_int(cpu, PC_REG & ~1); 308 addr = PC_REG;
298 gator_buffer_write_packed_int(cpu, 0); // cookie 309 mod = __module_address(addr);
310 if (mod) {
311 cookie = get_cookie(cpu, current, NULL, mod);
312 addr = addr - (unsigned long)mod->module_core;
313 }
314 gator_buffer_write_packed_int(cpu, addr & ~1);
315 gator_buffer_write_packed_int(cpu, cookie);
299 } else { 316 } else {
300 // Cookie+PC 317 // Cookie+PC
301 gator_add_trace(cpu, PC_REG); 318 gator_add_trace(cpu, PC_REG);
@@ -739,13 +756,11 @@ static int gator_op_start(void)
739 756
740 mutex_lock(&start_mutex); 757 mutex_lock(&start_mutex);
741 758
742 if (gator_started || gator_start()) 759 if (gator_started || gator_start() || cookies_initialize())
743 err = -EINVAL; 760 err = -EINVAL;
744 else 761 else
745 gator_started = 1; 762 gator_started = 1;
746 763
747 cookies_initialize();
748
749 mutex_unlock(&start_mutex); 764 mutex_unlock(&start_mutex);
750 765
751 return err; 766 return err;