diff options
author | Pawel Moll | 2011-05-27 10:30:10 -0500 |
---|---|---|
committer | Pawel Moll | 2011-05-27 10:30:10 -0500 |
commit | c5e21c20e9c3b00a3057965e7ab0a55a5873594b (patch) | |
tree | 591738ea4836c9e5fec619a21cd84d02b0b1ade1 | |
parent | 438a1e1cbf4b99b4f6ff1ecf07f9b7cfcc20d517 (diff) | |
download | arm-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.c | 20 | ||||
-rw-r--r-- | gator_cookies.c | 204 | ||||
-rw-r--r-- | gator_events_net.c | 10 | ||||
-rw-r--r-- | gator_fs.c | 18 | ||||
-rw-r--r-- | gator_main.c | 33 |
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; | |||
23 | static int annotatePos; | 23 | static int annotatePos; |
24 | static int annotateSel; | 24 | static int annotateSel; |
25 | 25 | ||
26 | static 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 | |||
37 | static ssize_t annotate_write(struct file *file, char const __user *buf, size_t count, loff_t *offset) | 26 | static 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 | ||
102 | void gator_annotate_stop(void) | 93 | void 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 | ||
113 | int gator_annotate_read(int **buffer) | 105 | int 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 | ||
14 | static uint32_t *gator_crc32_table; | ||
15 | static uint32_t translate_buffer_mask; | ||
16 | |||
17 | static DEFINE_PER_CPU(char *, translate_text); | ||
13 | static DEFINE_PER_CPU(uint32_t, cookie_next_key); | 18 | static DEFINE_PER_CPU(uint32_t, cookie_next_key); |
14 | static DEFINE_PER_CPU(uint64_t *, cookie_keys); | 19 | static DEFINE_PER_CPU(uint64_t *, cookie_keys); |
15 | static DEFINE_PER_CPU(uint32_t *, cookie_values); | 20 | static DEFINE_PER_CPU(uint32_t *, cookie_values); |
21 | static DEFINE_PER_CPU(int, translate_buffer_read); | ||
22 | static DEFINE_PER_CPU(int, translate_buffer_write); | ||
23 | static DEFINE_PER_CPU(unsigned int *, translate_buffer); | ||
16 | 24 | ||
17 | static uint32_t *gator_crc32_table; | 25 | static inline uint32_t get_cookie(int cpu, struct task_struct *task, struct vm_area_struct *vma, struct module *mod); |
26 | static void wq_cookie_handler(struct work_struct *unused); | ||
27 | DECLARE_WORK(cookie_work, wq_cookie_handler); | ||
18 | 28 | ||
19 | static uint32_t cookiemap_code(uint32_t value) { | 29 | static 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 | */ |
47 | static uint32_t cookiemap_exists(uint64_t key) { | 58 | static 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 | ||
90 | static inline uint32_t get_cookie(int cpu, int tgid, struct vm_area_struct *vma) | 105 | static 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 | |||
111 | static 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 | |||
118 | static 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 | ||
134 | static 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 | |||
200 | outsem: | ||
201 | up_read(&mm->mmap_sem); | ||
202 | outmm: | ||
203 | mmput(mm); | ||
204 | out: | ||
205 | return retval; | ||
206 | } | ||
207 | |||
208 | static 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 | ||
121 | output: | 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 | ||
176 | static void cookies_initialize(void) | 308 | static 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 | |||
358 | cookie_setup_error: | ||
359 | return err; | ||
208 | } | 360 | } |
209 | 361 | ||
210 | static void cookies_release(void) | 362 | static 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) | |||
136 | static int gator_events_net_read(int **buffer) | 136 | static 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 | } |
@@ -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) | ||
249 | static int gatorfs_get_sb(struct file_system_type *fs_type, | 253 | static 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 | ||
259 | static 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 | ||
255 | static struct file_system_type gatorfs_type = { | 266 | static 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 | ||
10 | static unsigned long gator_protocol_version = 3; | 10 | static 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 | ||
281 | static void gator_add_sample(int cpu, struct pt_regs * const regs) | 290 | static 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; |