gator: ARM DS-5.3 Streamline gator driver
[android-sdk/arm-ds5-gator.git] / gator_cookies.c
1 /**
2  * Copyright (C) ARM Limited 2010. 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  */
10 #define COOKIEMAP_ENTRIES       1024            /* must be power of 2 */
11 #define MAX_COLLISIONS          2
13 static DEFINE_PER_CPU(uint32_t, cookie_next_key);
14 static DEFINE_PER_CPU(uint32_t, cookie_prev_text);
15 static DEFINE_PER_CPU(uint32_t, cookie_prev_value);
16 static DEFINE_PER_CPU(uint64_t *, cookie_keys);
17 static DEFINE_PER_CPU(uint32_t *, cookie_values);
19 static uint32_t *gator_crc32_table;
21 static uint32_t cookiemap_code(uint32_t value) {
22         uint32_t cookiecode = (value >> 24) & 0xff;
23         cookiecode = cookiecode * 31 + ((value >> 16) & 0xff);
24         cookiecode = cookiecode * 31 + ((value >> 8) & 0xff);
25         cookiecode = cookiecode * 31 + ((value >> 0) & 0xff);
26         cookiecode &= (COOKIEMAP_ENTRIES-1);
27         return cookiecode * MAX_COLLISIONS;
28 }
30 static uint32_t gator_chksum_crc32(char *data)
31 {
32    register unsigned long crc;
33    unsigned char *block = data;
34    int i, length = strlen(data);
36    crc = 0xFFFFFFFF;
37    for (i = 0; i < length; i++) {
38       crc = ((crc >> 8) & 0x00FFFFFF) ^ gator_crc32_table[(crc ^ *block++) & 0xFF];
39    }
41    return (crc ^ 0xFFFFFFFF);
42 }
44 /*
45  * Exists
46  *  Pre:  [0][1][v][3]..[n-1]
47  *  Post: [v][0][1][3]..[n-1]
48  */
49 static uint32_t cookiemap_exists(uint64_t key) {
50         int cpu = raw_smp_processor_id();
51         uint32_t cookiecode = cookiemap_code(key);
52         uint64_t *keys = &(per_cpu(cookie_keys, cpu)[cookiecode]);
53         uint32_t *values = &(per_cpu(cookie_values, cpu)[cookiecode]);
54         int x;
56         for (x = 0; x < MAX_COLLISIONS; x++) {
57                 if (keys[x] == key) {
58                         uint32_t value = values[x];
59                         for (; x > 0; x--) {
60                                 keys[x] = keys[x-1];
61                                 values[x] = values[x-1];
62                         }
63                         keys[0] = key;
64                         values[0] = value;
65                         return value;
66                 }
67         }
69         return 0;
70 }
72 /*
73  * Add
74  *  Pre:  [0][1][2][3]..[n-1]
75  *  Post: [v][0][1][2]..[n-2]
76  */
77 static void cookiemap_add(uint64_t key, uint32_t value) {
78         int cpu = raw_smp_processor_id();
79         int cookiecode = cookiemap_code(key);
80         uint64_t *keys = &(per_cpu(cookie_keys, cpu)[cookiecode]);
81         uint32_t *values = &(per_cpu(cookie_values, cpu)[cookiecode]);
82         int x;
84         for (x = MAX_COLLISIONS-1; x > 0; x--) {
85                 keys[x] = keys[x-1];
86                 values[x] = keys[x-1];
87         }
88         keys[0] = key;
89         values[0] = value;
90 }
92 static inline uint32_t get_cookie(int cpu, int tgid, struct vm_area_struct *vma)
93 {
94         struct path *path;
95         uint64_t key;
96         int cookie;
97         char *text;
99         if (!vma || !vma->vm_file) {
100                 return INVALID_COOKIE;
101         }
102         path = &vma->vm_file->f_path;
103         if (!path || !path->dentry) {
104                 return INVALID_COOKIE;
105         }
107         text = (char*)path->dentry->d_name.name;
108         if (per_cpu     (cookie_prev_text, cpu) == (uint32_t)text) {
109                 return per_cpu(cookie_prev_value, cpu);
110         }
112         key = gator_chksum_crc32(text);
113         key = (key << 32) | (uint32_t)text;
115         cookie = cookiemap_exists(key);
116         if (cookie) {
117                 goto output;
118         }
120         cookie = per_cpu(cookie_next_key, cpu)+=nr_cpu_ids;
121         cookiemap_add(key, cookie);
123         gator_buffer_write_packed_int(cpu, PROTOCOL_COOKIE);
124         gator_buffer_write_packed_int(cpu, cookie);
125         gator_buffer_write_string(cpu, text);
127 output:
128         per_cpu(cookie_prev_text, cpu) = (uint32_t)text;
129         per_cpu(cookie_prev_value, cpu) = cookie;
130         return cookie;
133 static int get_exec_cookie(int cpu, struct task_struct *task)
135         unsigned long cookie = NO_COOKIE;
136         struct mm_struct *mm = task->mm;
137         struct vm_area_struct *vma;
139         if (!mm)
140                 return cookie;
142         for (vma = mm->mmap; vma; vma = vma->vm_next) {
143                 if (!vma->vm_file)
144                         continue;
145                 if (!(vma->vm_flags & VM_EXECUTABLE))
146                         continue;
147                 cookie = get_cookie(cpu, task->tgid, vma);
148                 break;
149         }
151         return cookie;
154 static unsigned long get_address_cookie(int cpu, struct task_struct *task, unsigned long addr, off_t *offset)
156         unsigned long cookie = NO_COOKIE;
157         struct mm_struct *mm = task->mm;
158         struct vm_area_struct *vma;
160         if (!mm)
161                 return cookie;
163         for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) {
164                 if (addr < vma->vm_start || addr >= vma->vm_end)
165                         continue;
167                 if (vma->vm_file) {
168                         cookie = get_cookie(cpu, task->tgid, vma);
169                         *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start;
170                 } else {
171                         /* must be an anonymous map */
172                         *offset = addr;
173                 }
175                 break;
176         }
178         if (!vma)
179                 cookie = INVALID_COOKIE;
181         return cookie;
184 static void cookies_initialize(void)
186         uint32_t crc, poly;
187         int cpu, size;
188         int i, j;
190         for_each_possible_cpu(cpu) {
191                 per_cpu(cookie_next_key, cpu) = nr_cpu_ids + cpu;
192                 per_cpu(cookie_prev_text, cpu) = 0;
193                 per_cpu(cookie_prev_value, cpu) = 0;
195                 size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint64_t);
196                 per_cpu(cookie_keys, cpu) = (uint64_t*)kmalloc(size, GFP_KERNEL);
197                 memset(per_cpu(cookie_keys, cpu), 0, size);
199                 size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint32_t);
200                 per_cpu(cookie_values, cpu) = (uint32_t*)kmalloc(size, GFP_KERNEL);
201                 memset(per_cpu(cookie_values, cpu), 0, size);
202         }
204         // build CRC32 table
205         poly = 0x04c11db7;
206         gator_crc32_table = (uint32_t*)kmalloc(256 * sizeof(uint32_t), GFP_KERNEL);
207         for (i = 0; i < 256; i++) {
208                 crc = i;
209                 for (j = 8; j > 0; j--) {
210                         if (crc & 1) {
211                                 crc = (crc >> 1) ^ poly;
212                         } else {
213                                 crc >>= 1;
214                         }
215                 }
216                 gator_crc32_table[i] = crc;
217         }
220 static void cookies_release(void)
222         int cpu;
224         for_each_possible_cpu(cpu) {
225                 kfree(per_cpu(cookie_keys, cpu));
226                 per_cpu(cookie_keys, cpu) = NULL;
228                 kfree(per_cpu(cookie_values, cpu));
229                 per_cpu(cookie_values, cpu) = NULL;
230         }
232         kfree(gator_crc32_table);
233         gator_crc32_table = NULL;