$ ./sync_swap_to_kernel.sh <swap_dir> <kernel_dir>
```
+ * #### add options to config:
+ ```sh
+ #
+ # SWAP subsystem for Dynamic Analyzer
+ #
+ CONFIG_SWAP_DA=y
+ CONFIG_SWAP_KERNEL_IMMUTABLE=y
+ CONFIG_SWAP_HOOK_TASKDATA=y
+ CONFIG_SWAP_HOOK_USAUX=y
+ CONFIG_SWAP_HOOK_SYSCALL=y
+ CONFIG_SWAP_HOOK_SWITCH_TO=y
+ CONFIG_SWAP_HOOK_ENERGY=y
+ CONFIG_SWAP_HOOK_FILE_OPS=y
+ CONFIG_SWAP_HOOK_SIGNAL=y
+ ```
+
### 2. swap-modules changes synchronization to kernel, do the following step:
--- /dev/null
+/*
+ * 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, 2017
+ *
+ * 2017 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ */
+
+
+#ifndef _LINUX_SWAP_HOOK_ENERGY_H
+#define _LINUX_SWAP_HOOK_ENERGY_H
+
+
+#ifdef CONFIG_SWAP_HOOK_ENERGY
+
+#include <linux/compiler.h>
+
+struct socket;
+
+struct swap_hook_energy {
+ void (*bt_recvmsg)(struct socket *sock, int len);
+ void (*bt_sendmsg)(struct socket *sock, int len);
+ void (*wifi_recvmsg)(struct socket *sock, int len);
+ void (*wifi_sendmsg)(struct socket *sock, int len);
+};
+
+extern struct swap_hook_energy *swap_nrg_hook;
+
+int swap_hook_energy_set(struct swap_hook_energy *hook);
+void swap_hook_energy_unset(void);
+
+
+/* private interface */
+struct swap_hook_energy *swap_hook_energy_get(void);
+void swap_hook_energy_put(void);
+
+#define SWAP_ENERGY_HOOK_CALL(hook_name, ...) \
+ if (unlikely(swap_nrg_hook)) { \
+ struct swap_hook_energy *hook = swap_hook_energy_get();\
+ if (hook) { \
+ hook->hook_name(__VA_ARGS__); \
+ swap_hook_energy_put(); \
+ } \
+ }
+
+#else /* CONFIG_SWAP_HOOK_ENERGY */
+
+#define SWAP_ENERGY_HOOK_CALL(hook_name, ...)
+
+#endif /* CONFIG_SWAP_HOOK_ENERGY */
+
+static inline void swap_bt_recvmsg(struct socket *sock, int len)
+{
+ SWAP_ENERGY_HOOK_CALL(bt_recvmsg, sock, len);
+}
+
+static inline void swap_bt_sendmsg(struct socket *sock, int len)
+{
+ SWAP_ENERGY_HOOK_CALL(bt_sendmsg, sock, len);
+}
+
+static inline void swap_sock_recvmsg(struct socket *sock, int len)
+{
+ /* we interested only in wifi consumption
+ * wifi_recvmsg has checking for wifi interface
+ */
+ SWAP_ENERGY_HOOK_CALL(wifi_recvmsg, sock, len);
+}
+
+static inline void swap_sock_sendmsg(struct socket *sock, int len)
+{
+ /* we interested only in wifi consumption
+ * wifi_sendmsg has checking for wifi interface
+ */
+ SWAP_ENERGY_HOOK_CALL(wifi_sendmsg, sock, len);
+}
+
+#endif /* _LINUX_SWAP_HOOK_ENERGY_H */
--- /dev/null
+/*
+ * 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, 2017
+ *
+ * 2017 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ */
+
+
+#ifndef _LINUX_SWAP_FILE_OPS_H
+#define _LINUX_SWAP_FILE_OPS_H
+
+
+struct file;
+
+
+#ifdef CONFIG_SWAP_HOOK_FILE_OPS
+
+#include <linux/list.h>
+
+struct module;
+
+struct swap_hook_fops {
+ struct hlist_node node;
+ struct module *owner;
+ void (*filp_close)(struct file *filp);
+};
+
+int swap_hook_fops_reg(struct swap_hook_fops *hook);
+void swap_hook_fops_unreg(struct swap_hook_fops *hook);
+
+
+/* private interface */
+extern int swap_fops_counter;
+void call_fops_filp_close(struct file *filp);
+
+static inline void swap_fops_filp_close(struct file *filp)
+{
+ if (unlikely(swap_fops_counter))
+ call_fops_filp_close(filp);
+}
+
+#else /* CONFIG_SWAP_HOOK_FILE_OPS */
+
+static inline void swap_fops_filp_close(struct file *filp) {}
+
+#endif /* CONFIG_SWAP_HOOK_FILE_OPS */
+
+
+#endif /* _LINUX_SWAP_FILE_OPS_H */
--- /dev/null
+/*
+ * 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, 2017
+ *
+ * 2017 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ */
+
+
+#ifndef _LINUX_SWAP_HOOK_SIGNAL_H
+#define _LINUX_SWAP_HOOK_SIGNAL_H
+
+
+#ifdef CONFIG_SWAP_HOOK_SIGNAL
+
+#include <linux/list.h>
+#include <linux/compiler.h>
+
+struct module;
+struct ksignal;
+
+struct hook_signal {
+ struct hlist_node node;
+ struct module *owner;
+ void (*hook)(struct ksignal *ksig);
+};
+
+int hook_signal_reg(struct hook_signal *hook);
+void hook_signal_unreg(struct hook_signal *hook);
+
+
+/* private interface */
+extern int __hook_signal_counter;
+void __hook_signal(struct ksignal *ksig);
+
+static inline void swap_hook_signal(struct ksignal *ksig)
+{
+ if (unlikely(__hook_signal_counter))
+ __hook_signal(ksig);
+}
+
+#else /* CONFIG_SWAP_HOOK_SIGNAL */
+
+static inline void swap_hook_signal(struct ksignal *ksig) {}
+
+#endif /* CONFIG_SWAP_HOOK_SIGNAL */
+
+
+#endif /* _LINUX_SWAP_HOOK_SIGNAL_H */
--- /dev/null
+/*
+ * 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, 2017
+ *
+ * 2017 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ */
+
+
+#ifndef _LINUX_SWAP_HOOK_SWITCH_TO_H
+#define _LINUX_SWAP_HOOK_SWITCH_TO_H
+
+
+#ifdef CONFIG_SWAP_HOOK_SWITCH_TO
+
+#include <linux/compiler.h>
+
+
+struct swap_hook_ctx {
+ struct hlist_node node;
+ void (*hook)(struct task_struct *prev, struct task_struct *next);
+};
+
+
+extern int ctx_hook_nr;
+
+int swap_hook_ctx_reg(struct swap_hook_ctx *hook);
+void swap_hook_ctx_unreg(struct swap_hook_ctx *hook);
+
+
+/* private interface */
+void swap_hook_ctx_call(struct task_struct *prev, struct task_struct *next);
+
+static inline void swap_hook_switch_to(struct task_struct *prev,
+ struct task_struct *next)
+{
+ if (unlikely(ctx_hook_nr)) {
+ swap_hook_ctx_call(prev, next);
+ }
+}
+
+#else /* CONFIG_SWAP_HOOK_SWITCH_TO */
+
+static inline void swap_hook_switch_to(struct task_struct *prev,
+ struct task_struct *next)
+{
+}
+#endif /* CONFIG_SWAP_HOOK_SWITCH_TO */
+
+#endif /* _LINUX_SWAP_HOOK_SWITCH_TO_H */
--- /dev/null
+/*
+ * 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, 2017
+ *
+ * 2017 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ */
+
+
+#ifndef _SWAP_HOOK_SYSCALL_H
+#define _SWAP_HOOK_SYSCALL_H
+
+
+struct pt_regs;
+struct task_struct;
+
+
+#include <linux/list.h>
+#include <linux/errno.h>
+
+
+struct hook_syscall {
+ struct hlist_node node;
+ void (*entry)(struct hook_syscall *self, struct pt_regs *regs);
+ void (*exit)(struct hook_syscall *self, struct pt_regs *regs);
+};
+
+#ifdef CONFIG_SWAP_HOOK_SYSCALL
+
+int hook_syscall_reg(struct hook_syscall *hook, unsigned long nr_call);
+void hook_syscall_unreg(struct hook_syscall *hook);
+
+# ifdef CONFIG_COMPAT
+int hook_syscall_reg_compat(struct hook_syscall *hook, unsigned long nr_call);
+static inline void hook_syscall_unreg_compat(struct hook_syscall *hook)
+{
+ hook_syscall_unreg(hook);
+}
+# endif /* CONFIG_COMPAT */
+
+#else /* CONFIG_SWAP_HOOK_SYSCALL */
+
+static inline int hook_syscall_reg(struct hook_syscall *hook,
+ unsigned long nr_call)
+{
+ return -ENOSYS;
+}
+
+static inline void hook_syscall_unreg(struct hook_syscall *hook) {}
+
+# ifdef CONFIG_COMPAT
+static inline int hook_syscall_reg_compat(struct hook_syscall *hook,
+ unsigned long nr_call)
+{
+ return -ENOSYS;
+}
+
+static inline void hook_syscall_unreg_compat(struct hook_syscall *hook) {}
+# endif /* CONFIG_COMPAT */
+
+#endif /* CONFIG_SWAP_HOOK_SYSCALL */
+
+
+#endif /* _SWAP_HOOK_SYSCALL_H */
--- /dev/null
+/*
+ * 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, 2017
+ *
+ * 2017 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ */
+
+
+#ifndef _SWAP_HOOK_SYSCALL_PRIV_H
+#define _SWAP_HOOK_SYSCALL_PRIV_H
+
+
+struct pt_regs;
+struct task_struct;
+
+
+#ifdef CONFIG_SWAP_HOOK_SYSCALL
+
+#include <linux/sched.h>
+
+static inline void swap_hook_syscall_update(struct task_struct *p)
+{
+ if (test_thread_flag(TIF_SWAP_HOOK_SYSCALL))
+ set_tsk_thread_flag(p, TIF_SWAP_HOOK_SYSCALL);
+ else
+ clear_tsk_thread_flag(p, TIF_SWAP_HOOK_SYSCALL);
+}
+
+void swap_hook_syscall_entry(struct pt_regs *regs);
+void swap_hook_syscall_exit(struct pt_regs *regs);
+
+#else /* CONFIG_SWAP_HOOK_SYSCALL */
+
+static inline void swap_hook_syscall_update(struct task_struct *p) {}
+static inline void swap_hook_syscall_entry(struct pt_regs *regs) {}
+static inline void swap_hook_syscall_exit(struct pt_regs *regs) {}
+
+#endif /* CONFIG_SWAP_HOOK_SYSCALL */
+
+
+#endif /* _SWAP_HOOK_SYSCALL_PRIV_H */
--- /dev/null
+/*
+ * 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, 2017
+ *
+ * 2017 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ */
+
+
+#ifndef _LINUX_SWAP_HOOK_TASKDATA_H
+#define _LINUX_SWAP_HOOK_TASKDATA_H
+
+
+#ifdef CONFIG_SWAP_HOOK_TASKDATA
+
+#include <linux/list.h>
+#include <linux/compiler.h>
+
+struct module;
+struct task_struct;
+
+struct hook_taskdata {
+ struct hlist_node node;
+ struct module *owner;
+ void (*put_task)(struct task_struct *task);
+};
+
+int hook_taskdata_reg(struct hook_taskdata *hook);
+void hook_taskdata_unreg(struct hook_taskdata *hook);
+
+/* private interface */
+extern int hook_taskdata_counter;
+void hook_taskdata_put_task(struct task_struct *task);
+
+static inline void swap_taskdata_put_task(struct task_struct *task)
+{
+ if (unlikely(hook_taskdata_counter))
+ hook_taskdata_put_task(task);
+}
+
+#else /* CONFIG_SWAP_HOOK_TASKDATA */
+
+static inline void swap_taskdata_put_task(struct task_struct *task) {}
+
+#endif /* CONFIG_SWAP_HOOK_TASKDATA */
+
+
+#endif /* _LINUX_SWAP_HOOK_TASKDATA_H */
--- /dev/null
+/*
+ * 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, 2017
+ *
+ * 2017 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ */
+
+
+#ifndef _LINUX_SWAP_HOOK_USAUX_H
+#define _LINUX_SWAP_HOOK_USAUX_H
+
+
+#ifdef CONFIG_SWAP_HOOK_USAUX
+
+#include <linux/compiler.h>
+
+struct file;
+struct module;
+struct task_struct;
+
+struct hook_usaux {
+ struct module *owner;
+ void (*page_fault)(unsigned long addr);
+ void (*copy_process_pre)(void);
+ void (*copy_process_post)(struct task_struct *task);
+ void (*mm_release)(struct task_struct *task);
+ void (*munmap)(unsigned long start, unsigned long end);
+ void (*mmap)(struct file *file, unsigned long addr);
+ void (*set_comm)(struct task_struct *task);
+ void (*change_leader)(struct task_struct *p, struct task_struct *n);
+};
+
+
+extern struct hook_usaux *hook_usaux_user;
+
+int hook_usaux_set(struct hook_usaux *hook);
+void hook_usaux_reset(void);
+
+
+/* private interface */
+struct hook_usaux *swap_hook_usaux_get(void);
+void swap_hook_usaux_put(struct hook_usaux *hook);
+
+
+#define SWAP_HOOK_USAUX_CALL(hook_name, ...) \
+ if (unlikely(hook_usaux_user)) { \
+ struct hook_usaux *hook = swap_hook_usaux_get(); \
+ if (hook) { \
+ hook->hook_name(__VA_ARGS__); \
+ swap_hook_usaux_put(hook); \
+ } \
+ }
+
+#else /* CONFIG_SWAP_HOOK_USAUX */
+
+#define SWAP_HOOK_USAUX_CALL(hook_name, ...)
+
+#endif /* CONFIG_SWAP_HOOK_USAUX */
+
+
+static inline void swap_usaux_page_fault(unsigned long addr)
+{
+ SWAP_HOOK_USAUX_CALL(page_fault, addr);
+}
+
+static inline void swap_usaux_copy_process_pre(void)
+{
+ SWAP_HOOK_USAUX_CALL(copy_process_pre);
+}
+
+static inline void swap_usaux_copy_process_post(struct task_struct *task)
+{
+ SWAP_HOOK_USAUX_CALL(copy_process_post, task);
+}
+
+static inline void swap_usaux_mm_release(struct task_struct *task)
+{
+ SWAP_HOOK_USAUX_CALL(mm_release, task);
+}
+
+static inline void swap_usaux_munmap(unsigned long start, unsigned long end)
+{
+ SWAP_HOOK_USAUX_CALL(munmap, start, end);
+}
+
+static inline void swap_usaux_mmap(struct file *file, unsigned long addr)
+{
+ SWAP_HOOK_USAUX_CALL(mmap, file, addr);
+}
+
+static inline void swap_usaux_set_comm(struct task_struct *task)
+{
+ SWAP_HOOK_USAUX_CALL(set_comm, task);
+}
+
+static inline void swap_usaux_change_leader(struct task_struct *prev,
+ struct task_struct *next)
+{
+ SWAP_HOOK_USAUX_CALL(change_leader, prev, next);
+}
+
+#endif /* _LINUX_SWAP_HOOK_USAUX_H */
--- /dev/null
+#
+# General SWAP options
+#
+
+menuconfig SWAP_DA
+ bool "System Wide Analysis of Performance"
+ select KALLSYMS
+ select DEBUG_FS
+ help
+ SWAP is a profiling tool.
+
+ If unsure, say Y.
+
+if SWAP_DA
+
+config SWAP_KERNEL_IMMUTABLE
+ bool "SWAP cannot modify kernel"
+
+config SWAP_HOOK_TASKDATA
+ bool "SWAP TD hooks"
+
+config SWAP_HOOK_USAUX
+ bool "SWAP US hooks"
+ depends on ARM64
+ select SWAP_HOOK_TASKDATA
+
+config SWAP_HOOK_SYSCALL
+ bool "SWAP syscall hooks"
+ depends on ARM64
+
+config SWAP_HOOK_SWITCH_TO
+ bool "SWAP context hooks"
+
+config SWAP_HOOK_ENERGY
+ bool "SWAP energy estimation hooks"
+
+config SWAP_HOOK_FILE_OPS
+ bool "SWAP file operations hooks"
+
+config SWAP_HOOK_SIGNAL
+ bool "SWAP signal hooks"
+
+endif # SWAP_DA
--- /dev/null
+#
+# Makefile for the SWAP
+#
+
+obj-y += hooks/
+obj-y += modules/
--- /dev/null
+#
+# Makefile for hooks
+#
+
+obj-$(CONFIG_SWAP_HOOK_TASKDATA) += taskdata.o
+obj-$(CONFIG_SWAP_HOOK_USAUX) += userspace_aux.o
+obj-$(CONFIG_SWAP_HOOK_SYSCALL) += syscall.o
+obj-$(CONFIG_SWAP_HOOK_SWITCH_TO) += switch_to.o
+obj-$(CONFIG_SWAP_HOOK_ENERGY) += energy.o
+obj-$(CONFIG_SWAP_HOOK_FILE_OPS) += file_ops.o
+obj-$(CONFIG_SWAP_HOOK_SIGNAL) += signal.o
--- /dev/null
+/*
+ * 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, 2017
+ *
+ * 2017 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ */
+
+
+#include <linux/rwsem.h>
+#include <linux/module.h>
+#include <swap/hook_energy.h>
+#include <linux/list.h>
+
+
+struct swap_hook_energy *swap_nrg_hook;
+static DECLARE_RWSEM(energy_hook_sem);
+
+struct swap_hook_energy *swap_hook_energy_get(void)
+{
+ struct swap_hook_energy *hook = NULL;
+ down_read(&energy_hook_sem);
+ if (swap_nrg_hook)
+ hook = swap_nrg_hook;
+ else
+ up_read(&energy_hook_sem);
+
+ return hook;
+}
+void swap_hook_energy_put(void)
+{
+ up_read(&energy_hook_sem);
+}
+
+int swap_hook_energy_set(struct swap_hook_energy *hook)
+{
+ int ret = 0;
+
+ down_write(&energy_hook_sem);
+ if (swap_nrg_hook) {
+ ret = -EBUSY;
+ goto unlock;
+ }
+
+ swap_nrg_hook = hook;
+
+unlock:
+ up_write(&energy_hook_sem);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(swap_hook_energy_set);
+
+void swap_hook_energy_unset(void)
+{
+ down_write(&energy_hook_sem);
+ swap_nrg_hook = NULL;
+ up_write(&energy_hook_sem);
+}
+EXPORT_SYMBOL_GPL(swap_hook_energy_unset);
--- /dev/null
+/*
+ * 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, 2017
+ *
+ * 2017 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ */
+
+
+#include <linux/rwsem.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <swap/hook_file_ops.h>
+
+
+static HLIST_HEAD(fops_head);
+static DECLARE_RWSEM(fops_sem);
+
+int swap_fops_counter;
+
+int swap_hook_fops_reg(struct swap_hook_fops *hook)
+{
+ if (!try_module_get(hook->owner))
+ return -ENODEV;
+
+ INIT_HLIST_NODE(&hook->node);
+
+ down_write(&fops_sem);
+ hlist_add_head(&hook->node, &fops_head);
+ ++swap_fops_counter;
+ up_write(&fops_sem);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(swap_hook_fops_reg);
+
+void swap_hook_fops_unreg(struct swap_hook_fops *hook)
+{
+ down_write(&fops_sem);
+ --swap_fops_counter;
+ hlist_del(&hook->node);
+ up_write(&fops_sem);
+
+ module_put(hook->owner);
+}
+EXPORT_SYMBOL_GPL(swap_hook_fops_unreg);
+
+void call_fops_filp_close(struct file *filp)
+{
+ down_read(&fops_sem);
+ if (swap_fops_counter) {
+ struct swap_hook_fops *hook;
+
+ hlist_for_each_entry(hook, &fops_head, node)
+ hook->filp_close(filp);
+ }
+ up_read(&fops_sem);
+}
--- /dev/null
+/*
+ * 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, 2017
+ *
+ * 2017 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ */
+
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/rwsem.h>
+#include <swap/hook_signal.h>
+
+
+static HLIST_HEAD(hook_head);
+static DECLARE_RWSEM(hook_sem);
+int __hook_signal_counter;
+
+int hook_signal_reg(struct hook_signal *hook)
+{
+ if (!try_module_get(hook->owner))
+ return -ENODEV;
+
+ INIT_HLIST_NODE(&hook->node);
+
+ down_write(&hook_sem);
+ hlist_add_head(&hook->node, &hook_head);
+ ++__hook_signal_counter;
+ up_write(&hook_sem);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(hook_signal_reg);
+
+void hook_signal_unreg(struct hook_signal *hook)
+{
+ down_write(&hook_sem);
+ --__hook_signal_counter;
+ hlist_del(&hook->node);
+ up_write(&hook_sem);
+
+ module_put(hook->owner);
+}
+EXPORT_SYMBOL_GPL(hook_signal_unreg);
+
+void __hook_signal(struct ksignal *ksig)
+{
+ down_read(&hook_sem);
+ if (__hook_signal_counter) {
+ struct hook_signal *hook;
+
+ hlist_for_each_entry(hook, &hook_head, node)
+ hook->hook(ksig);
+ }
+ up_read(&hook_sem);
+}
--- /dev/null
+/*
+ * 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, 2017
+ *
+ * 2017 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ */
+
+
+#include <linux/rwsem.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <swap/hook_switch_to.h>
+
+
+static HLIST_HEAD(ctx_hook_head);
+static DEFINE_SPINLOCK(ctx_hook_lock);
+int ctx_hook_nr = 0;
+
+static inline void hook_context_get(void)
+{
+ spin_lock(&ctx_hook_lock);
+}
+static inline void hook_context_put(void)
+{
+ spin_unlock(&ctx_hook_lock);
+}
+
+void swap_hook_ctx_call(struct task_struct *prev, struct task_struct *next)
+{
+ struct swap_hook_ctx *tmp;
+
+ hook_context_get();
+ hlist_for_each_entry(tmp, &ctx_hook_head, node) {
+ tmp->hook(prev, next);
+ }
+ hook_context_put();
+}
+
+
+int swap_hook_ctx_reg(struct swap_hook_ctx *hook)
+{
+ int ret = 0;
+
+ INIT_HLIST_NODE(&hook->node);
+ hook_context_get();
+
+ hlist_add_head(&hook->node, &ctx_hook_head);
+ ctx_hook_nr++;
+
+ hook_context_put();
+ return ret;
+}
+EXPORT_SYMBOL_GPL(swap_hook_ctx_reg);
+
+void swap_hook_ctx_unreg(struct swap_hook_ctx *hook)
+{
+ hook_context_get();
+ ctx_hook_nr--;
+ if (ctx_hook_nr < 0) {
+ pr_err("ERROR: [%s:%d]: ctx_hook_nr < 0\n", __FILE__, __LINE__);
+ ctx_hook_nr = 0;
+ }
+ hlist_del(&hook->node);
+ hook_context_put();
+}
+EXPORT_SYMBOL_GPL(swap_hook_ctx_unreg);
--- /dev/null
+/*
+ * 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, 2017
+ *
+ * 2017 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ */
+
+
+#include <linux/rwsem.h>
+#include <linux/module.h>
+#include <swap/hook_syscall.h>
+#include <asm/syscall.h>
+
+
+static DECLARE_RWSEM(syscall_hook_sem);
+static struct hlist_head syscall_hook[__NR_syscalls] = {
+ [0 ... __NR_syscalls - 1] = HLIST_HEAD_INIT,
+};
+
+
+static void syshook_set(void)
+{
+ struct task_struct *p, *t;
+
+ read_lock(&tasklist_lock);
+ for_each_process_thread(p, t) {
+ set_tsk_thread_flag(t, TIF_SWAP_HOOK_SYSCALL);
+ }
+ read_unlock(&tasklist_lock);
+}
+
+static void syshook_unset(void)
+{
+ struct task_struct *p, *t;
+
+ read_lock(&tasklist_lock);
+ for_each_process_thread(p, t) {
+ clear_tsk_thread_flag(t, TIF_SWAP_HOOK_SYSCALL);
+ }
+ read_unlock(&tasklist_lock);
+}
+
+static int syshook_cnt;
+
+static int do_syshook_reg(struct hook_syscall *hook, unsigned long nr_call,
+ unsigned long nr_max, struct hlist_head *hook_table)
+{
+ if (nr_call >= nr_max) {
+ pr_err("ERROR: nr_call=%lu is very big\n", nr_call);
+ return -EINVAL;
+ }
+
+ INIT_HLIST_NODE(&hook->node);
+
+ down_write(&syscall_hook_sem);
+ hlist_add_head(&hook->node, &hook_table[nr_call]);
+
+ if (syshook_cnt == 0)
+ syshook_set();
+
+ ++syshook_cnt;
+ up_write(&syscall_hook_sem);
+
+ return 0;
+}
+
+int hook_syscall_reg(struct hook_syscall *hook, unsigned long nr_call)
+{
+ return do_syshook_reg(hook, nr_call, __NR_syscalls, syscall_hook);
+}
+EXPORT_SYMBOL_GPL(hook_syscall_reg);
+
+void hook_syscall_unreg(struct hook_syscall *hook)
+{
+ down_write(&syscall_hook_sem);
+ --syshook_cnt;
+ if (syshook_cnt == 0)
+ syshook_unset();
+
+ hlist_del(&hook->node);
+ up_write(&syscall_hook_sem);
+}
+EXPORT_SYMBOL_GPL(hook_syscall_unreg);
+
+#ifdef CONFIG_COMPAT
+static struct hlist_head compat_syscall_hook[__NR_compat_syscalls] = {
+ [0 ... __NR_compat_syscalls - 1] = HLIST_HEAD_INIT,
+};
+
+int hook_syscall_reg_compat(struct hook_syscall *hook, unsigned long nr_call)
+{
+ return do_syshook_reg(hook, nr_call, __NR_compat_syscalls,
+ compat_syscall_hook);
+}
+EXPORT_SYMBOL_GPL(hook_syscall_reg_compat);
+
+static unsigned long nr_syscalls(struct pt_regs *regs)
+{
+ return compat_user_mode(regs) ? __NR_compat_syscalls : __NR_syscalls;
+}
+
+static struct hlist_head *sys_head(struct pt_regs *regs, unsigned long nr_call)
+{
+ return compat_user_mode(regs) ?
+ &compat_syscall_hook[nr_call] :
+ &syscall_hook[nr_call];
+}
+#else /* CONFIG_COMPAT */
+# define nr_syscalls(regs) __NR_syscalls
+# define sys_head(regs, nr_call) (&syscall_hook[nr_call])
+#endif /* CONFIG_COMPAT */
+
+/* private */
+void swap_hook_syscall_entry(struct pt_regs *regs)
+{
+ struct hook_syscall *hook;
+ unsigned long nr_call = syscall_get_nr(current, regs);
+ struct hlist_head *head;
+
+ if (nr_call >= nr_syscalls(regs))
+ return;
+
+ head = sys_head(regs, nr_call);
+
+ down_read(&syscall_hook_sem);
+ hlist_for_each_entry(hook, head, node) {
+ if (hook->entry)
+ hook->entry(hook, regs);
+ }
+ up_read(&syscall_hook_sem);
+}
+
+void swap_hook_syscall_exit(struct pt_regs *regs)
+{
+ struct hook_syscall *hook;
+ unsigned long nr_call = syscall_get_nr(current, regs);
+ struct hlist_head *head;
+
+ if (nr_call >= nr_syscalls(regs))
+ return;
+
+ head = sys_head(regs, nr_call);
+
+ down_read(&syscall_hook_sem);
+ hlist_for_each_entry(hook, head, node) {
+ if (hook->exit)
+ hook->exit(hook, regs);
+ }
+ up_read(&syscall_hook_sem);
+}
--- /dev/null
+/*
+ * 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, 2017
+ *
+ * 2017 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ */
+
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <swap/hook_taskdata.h>
+
+
+static HLIST_HEAD(td_head);
+static DEFINE_SPINLOCK(td_lock);
+int hook_taskdata_counter;
+
+int hook_taskdata_reg(struct hook_taskdata *hook)
+{
+ if (!try_module_get(hook->owner))
+ return -ENODEV;
+
+ INIT_HLIST_NODE(&hook->node);
+
+ spin_lock(&td_lock);
+ hlist_add_head(&hook->node, &td_head);
+ ++hook_taskdata_counter;
+ spin_unlock(&td_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(hook_taskdata_reg);
+
+void hook_taskdata_unreg(struct hook_taskdata *hook)
+{
+ spin_lock(&td_lock);
+ --hook_taskdata_counter;
+ hlist_del(&hook->node);
+ spin_unlock(&td_lock);
+
+ module_put(hook->owner);
+}
+EXPORT_SYMBOL_GPL(hook_taskdata_unreg);
+
+void hook_taskdata_put_task(struct task_struct *task)
+{
+ spin_lock(&td_lock);
+ if (hook_taskdata_counter) {
+ struct hook_taskdata *hook;
+
+ hlist_for_each_entry(hook, &td_head, node)
+ hook->put_task(task);
+ }
+ spin_unlock(&td_lock);
+}
--- /dev/null
+/*
+ * 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, 2017
+ *
+ * 2017 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ */
+
+
+#include <linux/rwsem.h>
+#include <linux/module.h>
+#include <swap/hook_usaux.h>
+
+
+struct hook_usaux *hook_usaux_user;
+static DECLARE_RWSEM(hook_sem);
+
+struct hook_usaux *swap_hook_usaux_get(void)
+{
+ struct hook_usaux *hook = NULL;
+
+ down_read(&hook_sem);
+ if (hook_usaux_user) {
+ hook = hook_usaux_user;
+ __module_get(hook->owner);
+ } else {
+ up_read(&hook_sem);
+ }
+
+ return hook;
+}
+void swap_hook_usaux_put(struct hook_usaux *hook)
+{
+ module_put(hook->owner);
+ up_read(&hook_sem);
+}
+
+int hook_usaux_set(struct hook_usaux *hook)
+{
+ int ret = 0;
+
+ down_write(&hook_sem);
+ if (hook_usaux_user) {
+ ret = -EBUSY;
+ goto unlock;
+ }
+
+ if (!try_module_get(hook->owner)) {
+ ret = -ENODEV;
+ goto unlock;
+ }
+
+ hook_usaux_user = hook;
+
+unlock:
+ up_write(&hook_sem);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(hook_usaux_set);
+
+void hook_usaux_reset(void)
+{
+ down_write(&hook_sem);
+ if (hook_usaux_user)
+ module_put(hook_usaux_user->owner);
+ hook_usaux_user = NULL;
+ up_write(&hook_sem);
+}
+EXPORT_SYMBOL_GPL(hook_usaux_reset);