[FEATURE] swap_td_raw implement 87/49987/3
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Thu, 8 Oct 2015 13:38:44 +0000 (16:38 +0300)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Thu, 22 Oct 2015 10:05:09 +0000 (13:05 +0300)
Change-Id: I96939a7710d3ddac969b26c50b0fd507f5b54b47
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
kprobe/Kbuild
kprobe/swap_kprobes.c
kprobe/swap_td_raw.c [new file with mode: 0644]
kprobe/swap_td_raw.h [new file with mode: 0644]

index 640899f..c952322 100644 (file)
@@ -3,7 +3,8 @@ EXTRA_CFLAGS := $(extra_cflags)
 obj-m := swap_kprobe.o
 swap_kprobe-y := swap_kprobes.o \
                  swap_kprobes_deps.o \
-                 swap_slots.o
+                 swap_slots.o \
+                 swap_td_raw.o
 
 ### ARM
 swap_kprobe-$(CONFIG_ARM) += arch/arm/swap-asm/swap_kprobes.o \
index 7f11152..20a2e35 100644 (file)
@@ -47,6 +47,7 @@
 #include <swap-asm/swap_kprobes.h>
 
 #include "swap_slots.h"
+#include "swap_td_raw.h"
 #include "swap_kdebug.h"
 #include "swap_kprobes.h"
 #include "swap_kprobes_deps.h"
@@ -1240,23 +1241,32 @@ static int init_kprobes(void)
        init_sm();
        atomic_set(&kprobe_count, 0);
 
-       ret = swap_arch_init_kprobes();
+       ret = swap_td_raw_init();
        if (ret)
                return ret;
 
+       ret = swap_arch_init_kprobes();
+       if (ret)
+               goto td_raw_uninit;
+
        ret = swap_register_kprobe(&put_task_kp);
-       if (ret) {
-               swap_arch_exit_kprobes();
-               return ret;
-       }
+       if (ret)
+               goto arch_kp_exit;
 
        return 0;
+
+arch_kp_exit:
+       swap_arch_exit_kprobes();
+td_raw_uninit:
+       swap_td_raw_uninit();
+       return ret;
 }
 
 static void exit_kprobes(void)
 {
        swap_unregister_kprobe(&put_task_kp);
        swap_arch_exit_kprobes();
+       swap_td_raw_uninit();
        exit_sm();
 }
 
diff --git a/kprobe/swap_td_raw.c b/kprobe/swap_td_raw.c
new file mode 100644 (file)
index 0000000..9985d06
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Samsung Electronics, 2015
+ *
+ * 2014         Vasiliy Ulyanov <v.ulyanov@samsung.com>
+ * 2015         Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+
+#include <linux/sched.h>
+#include <linux/module.h>
+#include "swap_td_raw.h"
+
+
+#define TD_OFFSET              1  /* skip STACK_END_MAGIC */
+#define TD_PREFIX              "[SWAP_TD_RAW] "
+#define TD_STACK_USAGE_MAX     0x200
+#define TD_CHUNK_MIN           sizeof(long)
+
+
+static DEFINE_MUTEX(mutex_stack_usage);
+static unsigned long stack_usage = 0;
+static LIST_HEAD(td_raw_list);
+
+
+/*
+ * take small area from stack
+ *
+ * 0x00 +--------------------------+
+ *      |      STACK_END_MAGIC     |
+ *      +--------------------------+  <-- bottom of stack;
+ *      |                          |
+ *      |           stack          |
+ *      |                          |
+ * 0xff
+ *
+ */
+
+static void *bottom_of_stack(struct task_struct *task)
+{
+       return (void *)(end_of_stack(task) + TD_OFFSET);
+}
+
+int swap_td_raw_reg(struct td_raw *raw, unsigned long size)
+{
+       int ret = 0;
+
+       size = (size / TD_CHUNK_MIN + !!(size % TD_CHUNK_MIN)) * TD_CHUNK_MIN;
+
+       mutex_lock(&mutex_stack_usage);
+       if (stack_usage + size > TD_STACK_USAGE_MAX) {
+               pr_warn(TD_PREFIX "free stack ended: usage=%ld size=%ld\n",
+                       stack_usage, size);
+               ret = -ENOMEM;
+               goto unlock;
+       }
+
+       raw->offset = stack_usage;
+
+       INIT_LIST_HEAD(&raw->list);
+       list_add(&raw->list, &td_raw_list);
+
+       stack_usage += size;
+
+unlock:
+       mutex_unlock(&mutex_stack_usage);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(swap_td_raw_reg);
+
+void swap_td_raw_unreg(struct td_raw *raw)
+{
+       mutex_lock(&mutex_stack_usage);
+
+       list_del(&raw->list);
+       if (list_empty(&td_raw_list))
+               stack_usage = 0;
+
+       mutex_unlock(&mutex_stack_usage);
+}
+EXPORT_SYMBOL_GPL(swap_td_raw_unreg);
+
+void *swap_td_raw(struct td_raw *raw, struct task_struct *task)
+{
+       return bottom_of_stack(task) + raw->offset;
+}
+EXPORT_SYMBOL_GPL(swap_td_raw);
+
+int swap_td_raw_init(void)
+{
+       WARN_ON(stack_usage);
+
+       stack_usage = 0;
+
+       return 0;
+}
+
+void swap_td_raw_uninit(void)
+{
+       WARN_ON(!list_empty(&td_raw_list));
+       WARN_ON(stack_usage);
+}
diff --git a/kprobe/swap_td_raw.h b/kprobe/swap_td_raw.h
new file mode 100644 (file)
index 0000000..079b153
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Samsung Electronics, 2015
+ *
+ * 2014         Vasiliy Ulyanov <v.ulyanov@samsung.com>
+ * 2015         Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+
+#ifndef _SWAP_TD_RAW_H
+#define _SWAP_TD_RAW_H
+
+
+#include <linux/list.h>
+
+
+struct td_raw {
+       struct list_head list;
+       unsigned long offset;
+};
+
+
+int swap_td_raw_reg(struct td_raw *raw, unsigned long size);
+void swap_td_raw_unreg(struct td_raw *raw);
+
+void *swap_td_raw(struct td_raw *raw, struct task_struct *task);
+
+int swap_td_raw_init(void);
+void swap_td_raw_uninit(void);
+
+
+#endif /* _SWAP_TD_RAW_H */