diff options
Diffstat (limited to 'drivers/gator/driver/gator_cookies.c')
-rw-r--r-- | drivers/gator/driver/gator_cookies.c | 403 |
1 files changed, 0 insertions, 403 deletions
diff --git a/drivers/gator/driver/gator_cookies.c b/drivers/gator/driver/gator_cookies.c deleted file mode 100644 index 1beb34f5170..00000000000 --- a/drivers/gator/driver/gator_cookies.c +++ /dev/null @@ -1,403 +0,0 @@ -/** - * Copyright (C) ARM Limited 2010-2012. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#define COOKIEMAP_ENTRIES 1024 /* must be power of 2 */ -#define TRANSLATE_SIZE 256 -#define MAX_COLLISIONS 2 - -static uint32_t *gator_crc32_table; -static uint32_t translate_buffer_mask; - -static DEFINE_PER_CPU(char *, translate_text); -static DEFINE_PER_CPU(uint32_t, cookie_next_key); -static DEFINE_PER_CPU(uint64_t *, cookie_keys); -static DEFINE_PER_CPU(uint32_t *, cookie_values); -static DEFINE_PER_CPU(int, translate_buffer_read); -static DEFINE_PER_CPU(int, translate_buffer_write); -static DEFINE_PER_CPU(unsigned int *, translate_buffer); - -static inline uint32_t get_cookie(int cpu, int buftype, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt); -static void wq_cookie_handler(struct work_struct *unused); -DECLARE_WORK(cookie_work, wq_cookie_handler); - -static uint32_t cookiemap_code(uint64_t value64) { - uint32_t value = (uint32_t)((value64 >> 32) + value64); - uint32_t cookiecode = (value >> 24) & 0xff; - cookiecode = cookiecode * 31 + ((value >> 16) & 0xff); - cookiecode = cookiecode * 31 + ((value >> 8) & 0xff); - cookiecode = cookiecode * 31 + ((value >> 0) & 0xff); - cookiecode &= (COOKIEMAP_ENTRIES-1); - return cookiecode * MAX_COLLISIONS; -} - -static uint32_t gator_chksum_crc32(char *data) -{ - register unsigned long crc; - unsigned char *block = data; - int i, length = strlen(data); - - crc = 0xFFFFFFFF; - for (i = 0; i < length; i++) { - crc = ((crc >> 8) & 0x00FFFFFF) ^ gator_crc32_table[(crc ^ *block++) & 0xFF]; - } - - return (crc ^ 0xFFFFFFFF); -} - -/* - * Exists - * Pre: [0][1][v][3]..[n-1] - * Post: [v][0][1][3]..[n-1] - */ -static uint32_t cookiemap_exists(uint64_t key) { - unsigned long x, flags, retval = 0; - int cpu = smp_processor_id(); - uint32_t cookiecode = cookiemap_code(key); - uint64_t *keys = &(per_cpu(cookie_keys, cpu)[cookiecode]); - uint32_t *values = &(per_cpu(cookie_values, cpu)[cookiecode]); - - // Can be called from interrupt handler or from work queue - local_irq_save(flags); - for (x = 0; x < MAX_COLLISIONS; x++) { - if (keys[x] == key) { - uint32_t value = values[x]; - for (; x > 0; x--) { - keys[x] = keys[x-1]; - values[x] = values[x-1]; - } - keys[0] = key; - values[0] = value; - retval = value; - break; - } - } - local_irq_restore(flags); - - return retval; -} - -/* - * Add - * Pre: [0][1][2][3]..[n-1] - * Post: [v][0][1][2]..[n-2] - */ -static void cookiemap_add(uint64_t key, uint32_t value) { - int cpu = smp_processor_id(); - int cookiecode = cookiemap_code(key); - uint64_t *keys = &(per_cpu(cookie_keys, cpu)[cookiecode]); - uint32_t *values = &(per_cpu(cookie_values, cpu)[cookiecode]); - int x; - - for (x = MAX_COLLISIONS-1; x > 0; x--) { - keys[x] = keys[x-1]; - values[x] = values[x-1]; - } - keys[0] = key; - values[0] = value; -} - -static void translate_buffer_write_int(int cpu, unsigned int x) -{ - per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_write, cpu)++] = x; - per_cpu(translate_buffer_write, cpu) &= translate_buffer_mask; -} - -static unsigned int translate_buffer_read_int(int cpu) -{ - unsigned int value = per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_read, cpu)++]; - per_cpu(translate_buffer_read, cpu) &= translate_buffer_mask; - return value; -} - -static void wq_cookie_handler(struct work_struct *unused) -{ - struct task_struct *task; - struct vm_area_struct *vma; - int cpu = smp_processor_id(); - unsigned int cookie, commit; - - mutex_lock(&start_mutex); - - if (gator_started != 0) { - commit = per_cpu(translate_buffer_write, cpu); - while (per_cpu(translate_buffer_read, cpu) != commit) { - task = (struct task_struct *)translate_buffer_read_int(cpu); - vma = (struct vm_area_struct *)translate_buffer_read_int(cpu); - cookie = get_cookie(cpu, TIMER_BUF, task, vma, NULL, false); - } - } - - mutex_unlock(&start_mutex); -} - -// Retrieve full name from proc/pid/cmdline for java processes on Android -static int translate_app_process(char** text, int cpu, struct task_struct * task, struct vm_area_struct *vma, bool in_interrupt) -{ - void *maddr; - unsigned int len; - unsigned long addr; - struct mm_struct *mm; - struct page *page = NULL; - struct vm_area_struct *page_vma; - int bytes, offset, retval = 0, ptr; - char * buf = per_cpu(translate_text, cpu); - - // Push work into a work queue if in atomic context as the kernel functions below might sleep - // Rely on the in_interrupt variable rather than in_irq() or in_interrupt() kernel functions, as the value of these functions seems - // inconsistent during a context switch between android/linux versions - if (in_interrupt) { - // Check if already in buffer - ptr = per_cpu(translate_buffer_read, cpu); - while (ptr != per_cpu(translate_buffer_write, cpu)) { - if (per_cpu(translate_buffer, cpu)[ptr] == (int)task) - goto out; - ptr = (ptr + 2) & translate_buffer_mask; - } - - translate_buffer_write_int(cpu, (unsigned int)task); - translate_buffer_write_int(cpu, (unsigned int)vma); - schedule_work(&cookie_work); - goto out; - } - - mm = get_task_mm(task); - if (!mm) - goto out; - if (!mm->arg_end) - goto outmm; - addr = mm->arg_start; - len = mm->arg_end - mm->arg_start; - - if (len > TRANSLATE_SIZE) - len = TRANSLATE_SIZE; - - down_read(&mm->mmap_sem); - while (len) { - if (get_user_pages(task, mm, addr, 1, 0, 1, &page, &page_vma) <= 0) - goto outsem; - - maddr = kmap(page); - offset = addr & (PAGE_SIZE-1); - bytes = len; - if (bytes > PAGE_SIZE - offset) - bytes = PAGE_SIZE - offset; - - copy_from_user_page(page_vma, page, addr, buf, maddr + offset, bytes); - - kunmap(page); // release page allocated by get_user_pages() - page_cache_release(page); - - len -= bytes; - buf += bytes; - addr += bytes; - - *text = per_cpu(translate_text, cpu); - retval = 1; - } - - // On app_process startup, /proc/pid/cmdline is initially "zygote" then "<pre-initialized>" but changes after an initial startup period - if (strcmp(*text, "zygote") == 0 || strcmp(*text, "<pre-initialized>") == 0) - retval = 0; - -outsem: - up_read(&mm->mmap_sem); -outmm: - mmput(mm); -out: - return retval; -} - -static inline uint32_t get_cookie(int cpu, int buftype, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt) -{ - unsigned long flags, cookie; - struct path *path; - uint64_t key; - char *text; - - if (mod) { - text = mod->name; - } else { - if (!vma || !vma->vm_file) { - return INVALID_COOKIE; - } - path = &vma->vm_file->f_path; - if (!path || !path->dentry) { - return INVALID_COOKIE; - } - - text = (char*)path->dentry->d_name.name; - } - - key = gator_chksum_crc32(text); - key = (key << 32) | (uint32_t)task->tgid; - - cookie = cookiemap_exists(key); - if (cookie) { - return cookie; - } - - if (strcmp(text, "app_process") == 0 && !mod) { - if (!translate_app_process(&text, cpu, task, vma, in_interrupt)) - return INVALID_COOKIE; - } - - // Can be called from interrupt handler or from work queue or from scheduler trace - local_irq_save(flags); - - cookie = INVALID_COOKIE; - if (buffer_check_space(cpu, buftype, strlen(text) + 2 * MAXSIZE_PACK32)) { - cookie = per_cpu(cookie_next_key, cpu) += nr_cpu_ids; - cookiemap_add(key, cookie); - - gator_buffer_write_packed_int(cpu, buftype, MESSAGE_COOKIE); - gator_buffer_write_packed_int(cpu, buftype, cookie); - gator_buffer_write_string(cpu, buftype, text); - } - - local_irq_restore(flags); - - return cookie; -} - -static int get_exec_cookie(int cpu, int buftype, struct task_struct *task) -{ - unsigned long cookie = NO_COOKIE; - struct mm_struct *mm = task->mm; - struct vm_area_struct *vma; - - if (!mm) - return cookie; - - for (vma = mm->mmap; vma; vma = vma->vm_next) { - if (!vma->vm_file) - continue; - if (!(vma->vm_flags & VM_EXECUTABLE)) - continue; - cookie = get_cookie(cpu, buftype, task, vma, NULL, true); - break; - } - - return cookie; -} - -static unsigned long get_address_cookie(int cpu, int buftype, struct task_struct *task, unsigned long addr, off_t *offset) -{ - unsigned long cookie = NO_COOKIE; - struct mm_struct *mm = task->mm; - struct vm_area_struct *vma; - - if (!mm) - return cookie; - - for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) { - if (addr < vma->vm_start || addr >= vma->vm_end) - continue; - - if (vma->vm_file) { - cookie = get_cookie(cpu, buftype, task, vma, NULL, true); - *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start; - } else { - /* must be an anonymous map */ - *offset = addr; - } - - break; - } - - if (!vma) - cookie = INVALID_COOKIE; - - return cookie; -} - -static int cookies_initialize(void) -{ - uint32_t crc, poly; - int i, j, cpu, size, err = 0; - - int translate_buffer_size = 512; // must be a power of 2 - translate_buffer_mask = translate_buffer_size / sizeof(per_cpu(translate_buffer, 0)[0]) - 1; - - for_each_present_cpu(cpu) { - per_cpu(cookie_next_key, cpu) = nr_cpu_ids + cpu; - - size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint64_t); - per_cpu(cookie_keys, cpu) = (uint64_t*)kmalloc(size, GFP_KERNEL); - if (!per_cpu(cookie_keys, cpu)) { - err = -ENOMEM; - goto cookie_setup_error; - } - memset(per_cpu(cookie_keys, cpu), 0, size); - - size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint32_t); - per_cpu(cookie_values, cpu) = (uint32_t*)kmalloc(size, GFP_KERNEL); - if (!per_cpu(cookie_values, cpu)) { - err = -ENOMEM; - goto cookie_setup_error; - } - memset(per_cpu(cookie_values, cpu), 0, size); - - per_cpu(translate_buffer, cpu) = (unsigned int *)kmalloc(translate_buffer_size, GFP_KERNEL); - if (!per_cpu(translate_buffer, cpu)) { - err = -ENOMEM; - goto cookie_setup_error; - } - - per_cpu(translate_buffer_write, cpu) = 0; - per_cpu(translate_buffer_read, cpu) = 0; - - per_cpu(translate_text, cpu) = (char *)kmalloc(TRANSLATE_SIZE, GFP_KERNEL); - if (!per_cpu(translate_text, cpu)) { - err = -ENOMEM; - goto cookie_setup_error; - } - } - - // build CRC32 table - poly = 0x04c11db7; - gator_crc32_table = (uint32_t*)kmalloc(256 * sizeof(uint32_t), GFP_KERNEL); - for (i = 0; i < 256; i++) { - crc = i; - for (j = 8; j > 0; j--) { - if (crc & 1) { - crc = (crc >> 1) ^ poly; - } else { - crc >>= 1; - } - } - gator_crc32_table[i] = crc; - } - -cookie_setup_error: - return err; -} - -static void cookies_release(void) -{ - int cpu; - - for_each_present_cpu(cpu) { - kfree(per_cpu(cookie_keys, cpu)); - per_cpu(cookie_keys, cpu) = NULL; - - kfree(per_cpu(cookie_values, cpu)); - per_cpu(cookie_values, cpu) = NULL; - - kfree(per_cpu(translate_buffer, cpu)); - per_cpu(translate_buffer, cpu) = NULL; - per_cpu(translate_buffer_read, cpu) = 0; - per_cpu(translate_buffer_write, cpu) = 0; - - kfree(per_cpu(translate_text, cpu)); - per_cpu(translate_text, cpu) = NULL; - } - - kfree(gator_crc32_table); - gator_crc32_table = NULL; -} |