2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * Copyright (C) Samsung Electronics, 2015
18 * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
23 #include <linux/list.h>
24 #include <linux/slab.h>
25 #include <linux/spinlock.h>
26 #include <writer/swap_msg.h>
27 #include <kprobe/swap_kprobes.h>
28 #include <ksyms/ksyms.h>
29 #include "nsp_tdata.h"
30 #include "nsp_print.h"
33 /* ============================================================================
35 * ============================================================================
38 struct list_head list;
39 struct task_struct *task;
45 static LIST_HEAD(task_list);
46 static DEFINE_SPINLOCK(task_list_lock);
49 /* called with task_list_lock held */
50 static struct priv_tdata *priv_tdata_create(struct task_struct *task)
52 struct priv_tdata *p_tdata;
54 p_tdata = kmalloc(sizeof(*p_tdata), GFP_ATOMIC);
56 INIT_LIST_HEAD(&p_tdata->list);
60 list_add(&p_tdata->list, &task_list);
66 /* called with task_list_lock held */
67 static void priv_tdata_destroy(struct priv_tdata *p_tdata)
69 /* delete from list */
70 list_del(&p_tdata->list);
75 /* called with task_list_lock held */
76 static void __priv_tdata_destroy(struct tdata *tdata)
78 struct priv_tdata *p_tdata;
80 p_tdata = container_of(tdata, struct priv_tdata, tdata);
81 priv_tdata_destroy(p_tdata);
84 /* called with task_list_lock held */
85 static void priv_tdata_destroy_all(void)
87 struct priv_tdata *p_tdata, *n;
89 list_for_each_entry_safe(p_tdata, n, &task_list, list)
90 priv_tdata_destroy(p_tdata);
97 /* ============================================================================
99 * ============================================================================
101 struct tdata *tdata_create(struct task_struct *task)
103 struct priv_tdata *p_tdata;
105 spin_lock(&task_list_lock);
106 p_tdata = priv_tdata_create(task);
108 return &p_tdata->tdata;
109 spin_unlock(&task_list_lock);
115 void tdata_destroy(struct tdata *tdata)
117 __priv_tdata_destroy(tdata);
118 spin_unlock(&task_list_lock);
121 struct tdata *tdata_find(struct task_struct *task)
123 struct priv_tdata *p_tdata;
125 list_for_each_entry(p_tdata, &task_list, list) {
126 if (p_tdata->task == task)
127 return &p_tdata->tdata;
133 struct tdata *tdata_get(struct task_struct *task)
137 spin_lock(&task_list_lock);
138 tdata = tdata_find(task);
141 spin_unlock(&task_list_lock);
146 void tdata_put(struct tdata *tdata)
148 spin_unlock(&task_list_lock);
155 /* ============================================================================
157 * ============================================================================
159 static int do_exit_handler(struct kprobe *p, struct pt_regs *regs)
163 tdata = tdata_get(current);
165 tdata_destroy(tdata);
170 struct kprobe do_exit_kp = {
171 .pre_handler = do_exit_handler,
174 int tdata_enable(void)
178 ret = swap_register_kprobe(&do_exit_kp);
185 void tdata_disable(void)
187 swap_unregister_kprobe(&do_exit_kp);
189 spin_lock(&task_list_lock);
190 priv_tdata_destroy_all();
191 spin_unlock(&task_list_lock);
199 do_exit_kp.addr = (void *)swap_ksyms(sym);
200 if (do_exit_kp.addr == NULL)
206 nsp_print("ERROR: symbol '%s' not found\n", sym);