rework UIHV init/deinit
[kernel/swap-modules.git] / uihv / uihv_module.c
1 #include <linux/namei.h>
2 #include <us_manager/us_manager_common.h>
3 #include <us_manager/pf/pf_group.h>
4 #include <us_manager/sspt/sspt_page.h>
5 #include <us_manager/sspt/sspt_file.h>
6 #include <us_manager/sspt/sspt_proc.h>
7 #include <us_manager/sspt/sspt_ip.h>
8 #include <us_manager/callbacks.h>
9 #include <us_manager/probes/probe_info_new.h>
10 #include <writer/kernel_operations.h>
11 #include <master/swap_initializer.h>
12 #include <writer/swap_msg.h>
13 #include <loader/loader.h>
14 #include "uihv.h"
15 #include "uihv_module.h"
16 #include "uihv_debugfs.h"
17
18 #define page_to_proc(page) ((page)->file->proc)
19 #define ip_to_proc(ip) page_to_proc((ip)->page)
20 #define urp_to_ip(rp) container_of(rp, struct sspt_ip, retprobe)
21
22 static DEFINE_MUTEX(mutex_enable);
23
24 static struct dentry *uihv_dentry = NULL;
25
26 static inline struct pd_t *__get_process_data(struct uretprobe *rp)
27 {
28         struct sspt_ip *ip = urp_to_ip(rp);
29         struct sspt_proc *proc = ip_to_proc(ip);
30
31         return lpd_get(proc);
32 }
33
34
35 /* ============================================================================
36  * =                               ui_viewer                                  =
37  * ============================================================================
38  */
39
40 /* main handler for ui viewer */
41 static int uihv_main_eh(struct uretprobe_instance *ri, struct pt_regs *regs);
42 static int uihv_main_rh(struct uretprobe_instance *ri, struct pt_regs *regs);
43 static struct probe_desc pin_main = MAKE_URPROBE(uihv_main_eh,
44                                                      uihv_main_rh, 0);
45
46 struct ui_viewer_data {
47         struct dentry *app_dentry;
48         struct probe_new p_main;
49         struct pf_group *pfg;
50         bool enable;
51 };
52
53 static struct ui_viewer_data __ui_data;
54
55 static int uihv_data_inst(void)
56 {
57         struct pf_group *pfg;
58
59         pfg = get_pf_group_by_dentry(__ui_data.app_dentry,
60                                      (void *)__ui_data.app_dentry);
61         if (!pfg)
62                 return -ENOMEM;
63
64         __ui_data.pfg = pfg;
65
66         return 0;
67 }
68
69 struct dentry *get_dentry(const char *filepath)
70 {
71         struct path path;
72         struct dentry *dentry = NULL;
73
74         if (kern_path(filepath, LOOKUP_FOLLOW, &path) == 0) {
75                 dentry = dget(path.dentry);
76                 path_put(&path);
77         }
78
79         return dentry;
80 }
81
82 void put_dentry(struct dentry *dentry)
83 {
84         dput(dentry);
85 }
86
87 int uihv_data_set(const char *app_path, unsigned long main_addr)
88 {
89         struct dentry *dentry;
90
91         if (__ui_data.enable) {
92                 pr_err("UIHV already enabled, can't set data\n");
93                 return -EBUSY;
94         }
95
96         dentry = dentry_by_path(app_path);
97         if (dentry == NULL)
98                 return -ENOENT;
99
100         __ui_data.app_dentry = dentry;
101         __ui_data.p_main.desc = &pin_main;
102         __ui_data.p_main.offset = main_addr;
103
104         return uihv_data_inst();
105 }
106
107 int uihv_set_handler(char *path)
108 {
109         struct dentry *dentry;
110         int ret;
111
112         if (uihv_dentry != NULL)
113                 put_dentry(uihv_dentry);
114
115         dentry = get_dentry(path);
116         if (dentry == NULL) {
117                 printk(KERN_WARNING UIHV_PREFIX "Error! Cannot get handler %s\n",
118                            path);
119                 return -EINVAL;
120         }
121
122         ret = loader_add_handler(path);
123         if (ret != 0)
124                 return ret;
125
126         uihv_dentry = dentry;
127
128         return 0;
129 }
130
131
132
133 /* ============================================================================
134  * =                          ui viewer handlers                              =
135  * ============================================================================
136  */
137 static int uihv_main_eh(struct uretprobe_instance *ri, struct pt_regs *regs)
138 {
139         struct pd_t *pd = __get_process_data(ri->rp);
140         struct hd_t *hd;
141         unsigned long old_pc = swap_get_instr_ptr(regs);
142         unsigned long vaddr = 0;
143
144         if (uihv_dentry == NULL)
145                 return 0;
146
147         hd = lpd_get_hd(pd, uihv_dentry);
148         if (hd == NULL)
149                 return 0;
150
151         if (lpd_get_state(hd) == NOT_LOADED)
152                 vaddr = loader_not_loaded_entry(ri, regs, pd, hd);
153
154         loader_set_priv_origin(ri, vaddr);
155
156         /* PC change check */
157         return old_pc != swap_get_instr_ptr(regs);
158 }
159
160 static int uihv_main_rh(struct uretprobe_instance *ri, struct pt_regs *regs)
161 {
162         struct pd_t *pd = __get_process_data(ri->rp);
163         struct hd_t *hd;
164
165         if (uihv_dentry == NULL)
166                 return 0;
167
168         hd = lpd_get_hd(pd, uihv_dentry);
169         if (hd == NULL)
170                 return 0;
171
172         if (lpd_get_state(hd) == LOADING)
173                 loader_loading_ret(ri, regs, pd, hd);
174
175         return 0;
176 }
177
178 int uihv_enable(void)
179 {
180         int ret = 0;
181
182         mutex_lock(&mutex_enable);
183         if (__ui_data.enable) {
184                 pr_err("UIHV already enabled\n");
185                 ret = -EBUSY;
186                 goto out;
187         }
188
189         ret = pin_register(&__ui_data.p_main, __ui_data.pfg,
190                            __ui_data.app_dentry);
191         if (ret)
192                 goto out;
193
194         __ui_data.enable = true;
195
196 out:
197         mutex_unlock(&mutex_enable);
198         return ret;
199 }
200
201 int uihv_disable(void)
202 {
203         int ret = 0;
204
205         mutex_lock(&mutex_enable);
206         if (!__ui_data.enable) {
207                 pr_err("UIHV already disabled\n");
208                 ret = -EBUSY;
209                 goto out;
210         }
211
212         ret = pin_unregister(&__ui_data.p_main, __ui_data.pfg,
213                              __ui_data.app_dentry);
214         if (ret)
215                 goto out;
216
217         put_pf_group(__ui_data.pfg);
218         __ui_data.pfg = NULL;
219         __ui_data.enable = false;
220
221 out:
222         mutex_unlock(&mutex_enable);
223         return ret;
224 }
225
226 static int uihv_init(void)
227 {
228         int ret;
229
230         ret = uihv_dfs_init();
231
232         return ret;
233 }
234
235 static void uihv_exit(void)
236 {
237         if (uihv_dentry != NULL)
238                 put_dentry(uihv_dentry);
239
240         uihv_dfs_exit();
241 }
242
243 SWAP_LIGHT_INIT_MODULE(NULL, uihv_init, uihv_exit, NULL, NULL);
244 MODULE_LICENSE("GPL");
245 MODULE_DESCRIPTION("SWAP UI Hierarchy Viewer");
246 MODULE_AUTHOR("Alexander Aksenov <a.aksenov@samsung.com>, Anastasia Lypa");