[REFACTOR] us_manager: install helper probes
[kernel/swap-modules.git] / writer / swap_writer_module.c
1 /*
2  *  SWAP Writer
3  *  modules/writer/swap_writer_module.c
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  *
19  * Copyright (C) Samsung Electronics, 2013
20  *
21  * 2013  Alexander Aksenov <a.aksenov@samsung.com>, Vyacheslav Cherkashin: 
22  *                  SWAP Writer module implement
23  *
24  */
25
26 #include <linux/types.h>
27 #include <linux/errno.h>
28 #include <linux/sched.h>
29 #include <linux/dcache.h>
30 #include <linux/mm.h>
31 #include <linux/mm_types.h>
32 #include <linux/fs.h>
33 #include <linux/err.h>
34 #include <linux/module.h>
35 #include <linux/slab.h>
36 #include <asm/uaccess.h>
37 #include <kprobe/arch/asm/dbi_kprobes.h>
38 #include <uprobe/arch/asm/swap_uprobes.h>
39
40 #include <buffer/swap_buffer_module.h>
41 #include <buffer/swap_buffer_errors.h>
42
43 #include "swap_writer_module.h"
44 #include "swap_writer_errors.h"
45 #include "kernel_operations.h"
46 #include "debugfs_writer.h"
47 #include "event_filter.h"
48
49
50 enum MSG_ID {
51         MSG_PROC_INFO                   = 0x0001,
52         MSG_TERMINATE                   = 0x0002,
53         MSG_ERROR                       = 0x0003,
54         MSG_SAMPLE                      = 0x0004,
55         MSG_FUNCTION_ENTRY              = 0x0008,
56         MSG_FUNCTION_EXIT               = 0x0009,
57         MSG_CONTEXT_SWITCH_ENTRY        = 0x0010,
58         MSG_CONTEXT_SWITCH_EXIT         = 0x0011,
59         MSG_PROC_MAP                    = 0x0012,
60         MSG_PROC_UNMAP                  = 0x0013
61 };
62
63 static char *cpu_buf[NR_CPUS];
64 static u32 seq_num = 0;
65 static unsigned int discarded = 0;
66
67 int init_msg(size_t buf_size)
68 {
69         int i;
70
71         for (i = 0; i < NR_CPUS; ++i)
72                 cpu_buf[i] = kmalloc(buf_size, GFP_KERNEL);
73
74         return E_SW_SUCCESS;
75 }
76 EXPORT_SYMBOL_GPL(init_msg);
77
78 void uninit_msg(void)
79 {
80         int i;
81
82         for (i = 0; i < NR_CPUS; ++i)
83                 kfree(cpu_buf[i]);
84 }
85 EXPORT_SYMBOL_GPL(uninit_msg);
86
87 void reset_discarded(void)
88 {
89         discarded = 0;
90 }
91 EXPORT_SYMBOL_GPL(reset_discarded);
92
93 void reset_seq_num(void)
94 {
95         seq_num = 0;
96 }
97 EXPORT_SYMBOL_GPL(reset_seq_num);
98
99 unsigned int get_discarded_count(void)
100 {
101         return discarded;
102 }
103 EXPORT_SYMBOL_GPL(get_discarded_count);
104
105 static inline char *get_current_buf(void)
106 {
107         return cpu_buf[get_cpu()];
108 }
109
110 static inline void put_current_buf(void)
111 {
112         put_cpu();
113 }
114
115 static inline u64 timespec2time(struct timespec *ts)
116 {
117         return ((u64)ts->tv_nsec) << 32 | ts->tv_sec;
118 }
119
120 /* ============================================================================
121  * =                         BASIC MESSAGE FORMAT                             =
122  * ============================================================================
123  */
124
125 struct basic_msg_fmt {
126         u32 msg_id;
127         u32 seq_number;
128         u64 time;
129         u32 len;
130         char payload[0];
131 } __attribute__((packed));
132
133 #if 0 /* debug */
134 static void print_hex(char *ptr, int len)
135 {
136         int i;
137
138         printk("print_hex:\n");
139         for (i = 0; i < len; ++i) {
140                 printk("[%x]  [%3d]=%2x\n", &ptr[i], i, ptr[i]);
141         }
142 }
143 #endif
144
145 static int write_to_buffer(void *data)
146 {
147         int result;
148         struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)data;
149
150         result = swap_buffer_write(bmf, bmf->len + sizeof(*bmf));
151         if (result < 0) {
152                 discarded++;
153         }
154
155         return result;
156 }
157
158 static void set_len_msg(char *buf, char *end)
159 {
160         struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)buf;
161         bmf->len = end - buf - sizeof(*bmf);
162 }
163
164 static inline void set_seq_num(struct basic_msg_fmt *bmf)
165 {
166         bmf->seq_number = seq_num;
167         seq_num++;
168 }
169
170 static inline void set_time(struct basic_msg_fmt *bmf)
171 {
172         struct timespec ts;
173
174         getnstimeofday(&ts);
175         bmf->time = timespec2time(&ts);
176 }
177
178 static char* pack_basic_msg_fmt(char *buf, enum MSG_ID id)
179 {
180         struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)buf;
181
182         set_time(bmf);
183         set_seq_num(bmf);
184         bmf->msg_id = id;
185
186         return bmf->payload;
187 }
188
189
190
191
192
193 /* ============================================================================
194  * =                             PROCESS INFO                                 =
195  * ============================================================================
196  */
197
198 struct proc_info {
199         u32 pid;
200         u32 ppid;
201         u32 start_sec;
202         u32 start_nsec;
203         u64 low_addr;
204         u64 high_addr;
205         char bin_path[0];
206 } __attribute__((packed));
207
208 struct proc_info_part {
209         u32 lib_cnt;
210         char libs[0];
211 } __attribute__((packed));
212
213 struct lib_obj {
214         u64 low_addr;
215         u64 high_addr;
216         char lib_path[0];
217 } __attribute__((packed));
218
219 static char *pack_path(char *buf, struct file *file)
220 {
221         enum { TMP_BUF_LEN = 512 };
222         char tmp_buf[TMP_BUF_LEN];
223         char NA[] = "N/A";
224         char *filename;
225         size_t len;
226
227         if (file == NULL)
228                 return strcpy(buf, NA) + sizeof(NA);
229
230         filename = d_path(&file->f_path, tmp_buf, TMP_BUF_LEN);
231         if (IS_ERR_OR_NULL(filename))
232                 return strcpy(buf, NA) + sizeof(NA);
233
234         len = strlen(filename) + 1;
235         memcpy(buf, filename, len);
236
237         return buf + len;
238 }
239
240 static char *pack_lib_obj(char *lib_obj, struct vm_area_struct *vma)
241 {
242         struct lib_obj *lo = (struct lib_obj *)lib_obj;
243
244         lo->low_addr = vma->vm_start;
245         lo->high_addr = vma->vm_end;
246
247         return pack_path(lo->lib_path, vma->vm_file);
248 }
249
250 /* FIXME: check_vma()*/
251 static int check_vma(struct vm_area_struct *vma)
252 {
253         return vma->vm_file &&
254                !(vma->vm_pgoff != 0 ||
255                  !(vma->vm_flags & VM_EXEC) ||
256                  !(vma->vm_flags & (VM_READ | VM_MAYREAD)));
257 }
258
259 static struct vm_area_struct *find_vma_exe_by_dentry(struct mm_struct *mm, struct dentry *dentry)
260 {
261         struct vm_area_struct *vma;
262
263         down_read(&mm->mmap_sem);
264         for (vma = mm->mmap; vma; vma = vma->vm_next) {
265                 if (vma->vm_file && (vma->vm_flags & VM_EXEC) &&
266                    (vma->vm_file->f_dentry == dentry))
267                         goto out;
268         }
269
270         vma = NULL;
271 out:
272         up_read(&mm->mmap_sem);
273
274         return vma;
275 }
276
277 static char *pack_shared_kmem(char *lib_obj, struct mm_struct *mm,
278                               u32 *lib_cnt_p)
279 {
280         struct lib_obj *so = (struct lib_obj *)lib_obj;
281         char *so_obj;
282         unsigned long start = 0, end = 0;
283
284         const char *kmem_name = get_shared_kmem(mm, &start, &end);
285         size_t name_len;
286
287         if (kmem_name == NULL)
288                 return lib_obj;
289
290         name_len = strlen(kmem_name) + 1;
291         so->low_addr = (u64)start;
292         so->high_addr = (u64)end;
293         memcpy(so->lib_path, kmem_name, name_len);
294         (*lib_cnt_p)++;
295         so_obj = so->lib_path + name_len;
296
297         return so_obj;
298 }
299
300 static char *pack_libs(char *lib_obj, struct mm_struct *mm, u32 *lib_cnt_p)
301 {
302         struct vm_area_struct *vma;
303
304         down_read(&mm->mmap_sem);
305         for (vma = mm->mmap; vma; vma = vma->vm_next) {
306                 if (check_vma(vma)) {
307                         lib_obj = pack_lib_obj(lib_obj, vma);
308                         ++(*lib_cnt_p);
309                 }
310         }
311         up_read(&mm->mmap_sem);
312
313         return lib_obj;
314 }
315
316 static char *pack_proc_info_part(char *end_path, struct mm_struct *mm)
317 {
318         struct proc_info_part *pip;
319         char *lib_obj;
320         u32 *lib_cnt_p;
321
322         pip = (struct proc_info_part *)end_path;
323         pip->lib_cnt = 0;
324         lib_obj = pip->libs;
325         lib_cnt_p = &pip->lib_cnt;
326
327         lib_obj = pack_libs(lib_obj, mm, lib_cnt_p);
328         lib_obj = pack_shared_kmem(lib_obj, mm, lib_cnt_p);
329
330         return lib_obj;
331 }
332
333 static char *pack_proc_info(char *payload, struct task_struct *task,
334                             struct dentry *dentry)
335 {
336         struct proc_info *pi = (struct proc_info *)payload;
337         struct vm_area_struct *vma = find_vma_exe_by_dentry(task->mm, dentry);
338         struct timespec boot_time;
339         struct timespec start_time;
340         char *end_path = NULL;
341
342         getboottime(&boot_time);
343         start_time = timespec_add(boot_time, task->real_start_time);
344
345         pi->pid = task->tgid;
346         pi->ppid = task->real_parent->tgid;
347         pi->start_sec = (u32)start_time.tv_sec;
348         pi->start_nsec = (u32)start_time.tv_nsec;
349
350         if (vma) {
351                 pi->low_addr = vma->vm_start;
352                 pi->high_addr = vma->vm_end;
353                 end_path = pack_path(pi->bin_path, vma->vm_file);
354         } else {
355                 pi->low_addr = 0;
356                 pi->high_addr = 0;
357                 end_path = pack_path(pi->bin_path, NULL);
358         }
359         return pack_proc_info_part(end_path, task->mm);
360 }
361
362 int proc_info_msg(struct task_struct *task, struct dentry *dentry)
363 {
364         char *buf, *payload, *buf_end;
365         int ret;
366
367         buf = get_current_buf();
368         payload = pack_basic_msg_fmt(buf, MSG_PROC_INFO);
369         buf_end = pack_proc_info(payload, task, dentry);
370
371         set_len_msg(buf, buf_end);
372
373         ret = write_to_buffer(buf);
374         put_current_buf();
375
376         return ret;
377 }
378 EXPORT_SYMBOL_GPL(proc_info_msg);
379
380
381
382
383
384 /* ============================================================================
385  * =                           PROCESS TERMINATE                              =
386  * ============================================================================
387  */
388
389 struct proc_terminate {
390         u32 pid;
391 } __attribute__((packed));
392
393 static char *pack_proc_terminate(char *payload, struct task_struct *task)
394 {
395         struct proc_terminate *pt = (struct proc_terminate *)payload;
396
397         pt->pid = task->pid;
398         return payload + sizeof(*pt);
399 }
400
401 void terminate_msg(struct task_struct *task)
402 {
403         char *buf, *payload, *buf_end;
404
405         buf = get_current_buf();
406         payload = pack_basic_msg_fmt(buf, MSG_TERMINATE);
407         buf_end = pack_proc_terminate(payload, task);
408
409         set_len_msg(buf, buf_end);
410
411         write_to_buffer(buf);
412         put_current_buf();
413 }
414 EXPORT_SYMBOL_GPL(terminate_msg);
415
416
417
418
419
420 /* ============================================================================
421  * =                             PROCESS MAP                                  =
422  * ============================================================================
423  */
424 struct proc_map {
425         u32 pid;
426         u64 low_addr;
427         u64 high_addr;
428         char bin_path[0];
429 } __attribute__((packed));
430
431 static char *pack_proc_map(char *payload, struct vm_area_struct *vma)
432 {
433         struct proc_map *pm = (struct proc_map *)payload;
434
435         pm->pid = current->tgid;
436         pm->low_addr = vma->vm_start;
437         pm->high_addr = vma->vm_end;
438
439         return pack_path(pm->bin_path, vma->vm_file);
440 }
441
442 void pcoc_map_msg(struct vm_area_struct *vma)
443 {
444         char *buf, *payload, *buf_end;
445
446         buf = get_current_buf();
447         payload = pack_basic_msg_fmt(buf, MSG_PROC_MAP);
448         buf_end = pack_proc_map(payload, vma);
449
450         set_len_msg(buf, buf_end);
451
452         write_to_buffer(buf);
453         put_current_buf();
454 }
455 EXPORT_SYMBOL_GPL(pcoc_map_msg);
456
457
458
459
460
461 /* ============================================================================
462  * =                            PROCESS UNMAP                                 =
463  * ============================================================================
464  */
465 struct proc_unmap {
466         u32 pid;
467         u64 low_addr;
468         u64 high_addr;
469 } __attribute__((packed));
470
471 static char *pack_proc_unmap(char *payload, unsigned long start,
472                              unsigned long end)
473 {
474         struct proc_unmap *pum = (struct proc_unmap *)payload;
475
476         pum->pid = current->tgid;
477         pum->low_addr = start;
478         pum->high_addr = end;
479
480         return payload + sizeof(*pum);
481 }
482
483 void proc_unmap_msg(unsigned long start, unsigned long end)
484 {
485         char *buf, *payload, *buf_end;
486
487         buf = get_current_buf();
488         payload = pack_basic_msg_fmt(buf, MSG_PROC_UNMAP);
489         buf_end = pack_proc_unmap(payload, start, end);
490
491         set_len_msg(buf, buf_end);
492
493         write_to_buffer(buf);
494         put_current_buf();
495 }
496 EXPORT_SYMBOL_GPL(proc_unmap_msg);
497
498
499
500
501
502 /* ============================================================================
503  * =                                 SAMPLE                                   =
504  * ============================================================================
505  */
506
507 struct sample {
508         u32 pid;
509         u64 pc_addr;
510         u32 tid;
511         u32 cpu_num;
512 } __attribute__((packed));
513
514 static char *pack_sample(char *payload, struct pt_regs *regs)
515 {
516         struct sample *s = (struct sample *)payload;
517         struct task_struct *task = current;
518
519         s->pid = task->tgid;
520         s->pc_addr = get_regs_ip(regs);
521         s->tid = task->pid;
522         s->cpu_num = smp_processor_id();
523
524         return payload + sizeof(*s);
525 }
526
527 int sample_msg(struct pt_regs *regs)
528 {
529         char *buf, *payload, *buf_end;
530         int ret;
531
532         if (!check_event(current))
533                 return 0;
534
535         buf = get_current_buf();
536         payload = pack_basic_msg_fmt(buf, MSG_SAMPLE);
537         buf_end = pack_sample(payload, regs);
538
539         set_len_msg(buf, buf_end);
540
541         ret = write_to_buffer(buf);
542         put_current_buf();
543
544         return ret;
545 }
546 EXPORT_SYMBOL_GPL(sample_msg);
547
548
549
550
551 /* ============================================================================
552  * =                                 ENTRY                                    =
553  * ============================================================================
554  */
555
556 struct msg_func_entry {
557         u64 pc_addr;
558         u64 caller_pc_addr;
559         u16 probe_type;
560         u16 probe_sub_type;
561         u32 pid;
562         u32 tid;
563         u32 cpu_num;
564         u32 cnt_args;
565         char args[0];
566 } __attribute__((packed));
567
568 static char *pack_msg_func_entry(char *payload, const char *fmt,
569                                  unsigned long func_addr, struct pt_regs *regs,
570                                  enum PROBE_TYPE pt, int sub_type)
571 {
572         struct msg_func_entry *mfe = (struct msg_func_entry *)payload;
573         struct task_struct *task = current;
574
575         mfe->pid = task->tgid;
576         mfe->tid = task->pid;
577         mfe->cpu_num = smp_processor_id();
578         mfe->pc_addr = func_addr;
579         mfe->caller_pc_addr = get_regs_ret_func(regs);
580         mfe->probe_type = pt;
581         mfe->probe_sub_type = sub_type;
582         mfe->cnt_args = strlen(fmt);
583
584         return payload + sizeof(*mfe);
585 }
586
587 static unsigned long get_arg(struct pt_regs *regs, unsigned long n)
588 {
589         return user_mode(regs) ?
590                         swap_get_uarg(regs, n) :        /* US argument */
591                         swap_get_sarg(regs, n);         /* sys_call argument */
592 }
593
594 static int pack_args(char *buf, int len, const char *fmt, struct pt_regs *regs)
595 {
596         char *buf_old = buf;
597         u32 *tmp_u32;
598         u64 *tmp_u64;
599         int i,          /* the index of the argument */
600             fmt_i,      /* format index */
601             fmt_len;    /* the number of parameters, in format */
602
603         fmt_len = strlen(fmt);
604
605         for (i = 0, fmt_i = 0; fmt_i < fmt_len; ++i, ++fmt_i) {
606                 if (len < 2)
607                         return -ENOMEM;
608
609                 *buf = fmt[fmt_i];
610                 buf += 1;
611                 len -= 1;
612
613                 switch (fmt[fmt_i]) {
614                 case 'b': /* 1 byte(bool) */
615                         *buf = (char)!!get_arg(regs, i);
616                         buf += 1;
617                         len -= 1;
618                         break;
619                 case 'c': /* 1 byte(char) */
620                         *buf = (char)get_arg(regs, i);
621                         buf += 1;
622                         len -= 1;
623                         break;
624                 case 'f': /* 4 byte(float) */
625                 case 'd': /* 4 byte(int) */
626                         if (len < 4)
627                                 return -ENOMEM;
628                         tmp_u32 = (u32 *)buf;
629                         *tmp_u32 = (u32)get_arg(regs, i);
630                         buf += 4;
631                         len -= 4;
632                         break;
633                 case 'x': /* 8 byte(long) */
634                 case 'p': /* 8 byte(pointer) */
635                         if (len < 8)
636                                 return -ENOMEM;
637                         tmp_u64 = (u64 *)buf;
638                         *tmp_u64 = (u64)get_arg(regs, i);
639                         buf += 8;
640                         len -= 8;
641                         break;
642                 case 'w': /* 8 byte(double) */
643                         if (len < 8)
644                                 return -ENOMEM;
645                         tmp_u64 = (u64 *)buf;
646                         *tmp_u64 = get_arg(regs, i);
647                         ++i;
648                         *tmp_u64 |= (u64)get_arg(regs, i) << 32;
649                         buf += 8;
650                         len -= 8;
651                         break;
652                 case 's': /* string end with '\0' */
653                 {
654                         enum { max_str_len = 512 };
655                         const char __user *user_s;
656                         int len_s, ret;
657
658                         user_s = (const char __user *)get_arg(regs, i);
659                         len_s = strnlen_user(user_s, max_str_len);
660                         if (len < len_s)
661                                 return -ENOMEM;
662
663                         ret = strncpy_from_user(buf, user_s, len_s);
664                         if (ret < 0)
665                                 return -EFAULT;
666
667                         buf[ret] = '\0';
668
669                         buf += ret + 1;
670                         len -= ret + 1;
671                 }
672                         break;
673                 default:
674                         return -EINVAL;
675                 }
676         }
677
678         return buf - buf_old;
679 }
680
681 int entry_event(const char *fmt, unsigned long func_addr, struct pt_regs *regs,
682                 enum PROBE_TYPE pt, int sub_type)
683 {
684         char *buf, *payload, *args, *buf_end;
685         int ret;
686
687         if (pt == PT_KS && !check_event(current))
688                 return 0;
689
690         buf = get_current_buf();
691         payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_ENTRY);
692         args = pack_msg_func_entry(payload, fmt, func_addr,
693                                    regs, pt, sub_type);
694
695         /* FIXME: len = 1024 */
696         ret = pack_args(args, 1024, fmt, regs);
697         if (ret < 0) {
698                 printk("ERROR: !!!!!\n");
699                 return ret;
700         }
701
702         buf_end = args + ret;
703
704         set_len_msg(buf, buf_end);
705
706         ret = write_to_buffer(buf);
707         put_current_buf();
708
709         return ret;
710 }
711 EXPORT_SYMBOL_GPL(entry_event);
712
713
714
715
716
717 /* ============================================================================
718  * =                                 EXIT                                     =
719  * ============================================================================
720  */
721
722 struct msg_func_exit {
723         u32 pid;
724         u32 tid;
725         u64 pc_addr;
726         u64 caller_pc_addr;
727         u32 cpu_num;
728         char ret_val[0];
729 } __attribute__((packed));
730
731 static int pack_msg_ret_val(char *buf, int len, char ret_type,
732                               struct pt_regs *regs)
733 {
734         const char *buf_old = buf;
735         u32 *tmp_u32;
736         u64 *tmp_u64;
737
738         *buf = ret_type;
739         ++buf;
740
741         switch (ret_type) {
742         case 'b': /* 1 byte(bool) */
743                 if (len < 1)
744                         return -ENOMEM;
745                 *buf = (char)!!get_regs_ret_val(regs);
746                 ++buf;
747                 break;
748         case 'c': /* 1 byte(char) */
749                 if (len < 1)
750                         return -ENOMEM;
751                 *buf = (char)get_regs_ret_val(regs);
752                 ++buf;
753                 break;
754         case 'd': /* 4 byte(int) */
755                 if (len < 4)
756                         return -ENOMEM;
757                 tmp_u32 = (u32 *)buf;
758                 *tmp_u32 = get_regs_ret_val(regs);
759                 buf += 4;
760                 break;
761         case 'x': /* 8 byte(long) */
762         case 'p': /* 8 byte(pointer) */
763                 if (len < 8)
764                         return -ENOMEM;
765                 tmp_u64 = (u64 *)buf;
766                 *tmp_u64 = (u64)get_regs_ret_val(regs);
767                 buf += 8;
768                 break;
769         case 's': /* string end with '\0' */
770         {
771                 enum { max_str_len = 512 };
772                 const char __user *user_s;
773                 int len_s, ret;
774
775                 user_s = (const char __user *)get_regs_ret_val(regs);
776                 len_s = strnlen_user(user_s, max_str_len);
777                 if (len < len_s)
778                         return -ENOMEM;
779
780                 ret = strncpy_from_user(buf, user_s, len_s);
781                 if (ret < 0)
782                         return -EFAULT;
783
784                 buf[ret] = '\0';
785                 buf += ret + 1;
786         }
787                 break;
788         case 'n':
789         case 'v':
790                 break;
791         case 'f': /* 4 byte(float) */
792                 if (len < 4)
793                         return -ENOMEM;
794                 tmp_u32 = (u32 *)buf;
795                 *tmp_u32 = swap_get_urp_float(regs);
796                 buf += 4;
797                 break;
798         case 'w': /* 8 byte(double) */
799                 if (len < 8)
800                         return -ENOMEM;
801                 tmp_u64 = (u64 *)buf;
802                 *tmp_u64 = swap_get_urp_double(regs);
803                 buf += 8;
804                 break;
805         default:
806                 return -EINVAL;
807         }
808
809         return buf - buf_old;
810 }
811
812
813 static int pack_msg_func_exit(char *buf, int len, char ret_type,
814                               struct pt_regs *regs, unsigned long func_addr,
815                               unsigned long ret_addr)
816 {
817         struct msg_func_exit *mfe = (struct msg_func_exit *)buf;
818         struct task_struct *task = current;
819         int ret;
820
821         mfe->pid = task->tgid;
822         mfe->tid = task->pid;
823         mfe->cpu_num = smp_processor_id();
824         mfe->pc_addr = func_addr;
825         mfe->caller_pc_addr = ret_addr;
826
827         ret = pack_msg_ret_val(mfe->ret_val, len, ret_type, regs);
828         if (ret < 0) {
829                 printk("ERROR: packing MSG_FUNCTION_EXIT (ret=%d)\n", ret);
830                 return ret;
831         }
832
833         return sizeof(*mfe) + ret;
834 }
835
836 int exit_event(char ret_type, struct pt_regs *regs, unsigned long func_addr,
837                unsigned long ret_addr)
838 {
839         char *buf, *payload, *buf_end;
840         int ret;
841
842         if (!check_event(current))
843                 return 0;
844
845         buf = get_current_buf();
846         payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_EXIT);
847         /* FIXME: len=1024 */
848         ret = pack_msg_func_exit(payload, 1024, ret_type, regs,
849                                  func_addr, ret_addr);
850         if (ret < 0)
851                 return ret;
852
853         buf_end = payload + ret;
854         set_len_msg(buf, buf_end);
855
856         ret = write_to_buffer(buf);
857         put_current_buf();
858
859         return ret;
860 }
861 EXPORT_SYMBOL_GPL(exit_event);
862
863
864
865
866
867 /* ============================================================================
868  * =                            CONTEXT SWITCH                                =
869  * ============================================================================
870  */
871
872 struct msg_context_switch {
873         u64 pc_addr;
874         u32 pid;
875         u32 tid;
876         u32 cpu_num;
877 } __attribute__((packed));
878
879 static char *pack_msg_context_switch(char *payload, struct pt_regs *regs)
880 {
881         struct msg_context_switch *mcs = (struct msg_context_switch *)payload;
882         struct task_struct *task = current;
883
884         mcs->pc_addr = 0;
885         mcs->pid = task->tgid;
886         mcs->tid = task->pid;
887         mcs->cpu_num = smp_processor_id();
888
889         return payload + sizeof(*mcs);
890 }
891
892 static int context_switch(struct pt_regs *regs, enum MSG_ID id)
893 {
894         char *buf, *payload, *buf_end;
895         int ret;
896
897         buf = get_current_buf();
898         payload = pack_basic_msg_fmt(buf, id);
899         buf_end = pack_msg_context_switch(payload, regs);
900         set_len_msg(buf, buf_end);
901
902         ret = write_to_buffer(buf);
903         put_current_buf();
904
905         return ret;
906 }
907
908 int switch_entry(struct pt_regs *regs)
909 {
910         if (!check_event(current))
911                 return 0;
912
913         return context_switch(regs, MSG_CONTEXT_SWITCH_ENTRY);
914 }
915 EXPORT_SYMBOL_GPL(switch_entry);
916
917 int switch_exit(struct pt_regs *regs)
918 {
919         if (!check_event(current))
920                 return 0;
921
922         return context_switch(regs, MSG_CONTEXT_SWITCH_EXIT);
923 }
924 EXPORT_SYMBOL_GPL(switch_exit);
925
926
927
928
929 /* ============================================================================
930  * =                                 ERROR                                    =
931  * ============================================================================
932  */
933
934 struct msg_err {
935         char msg[0];
936 } __attribute__((packed));
937
938 static char *pack_msg_err(char *payload, const char *fmt, va_list args)
939 {
940         struct msg_err *me = (struct msg_err *)payload;
941         int ret;
942
943         ret = vsprintf(me->msg, fmt, args);
944         if (ret < 0)
945                 return payload;
946
947         return payload + sizeof(*me) + ret + 1;
948 }
949
950 int error_msg(const char *fmt, ...)
951 {
952         char *buf, *payload, *buf_end;
953         va_list args;
954         int ret;
955
956         buf = get_current_buf();
957         payload = pack_basic_msg_fmt(buf, MSG_ERROR);
958
959         va_start(args, fmt);
960         buf_end = pack_msg_err(payload, fmt, args);
961         va_end(args);
962
963         set_len_msg(buf, buf_end);
964
965         ret = write_to_buffer(buf);
966         put_current_buf();
967
968         return ret;
969 }
970 EXPORT_SYMBOL_GPL(error_msg);
971
972
973
974
975
976 /* ============================================================================
977  * =                         MESSAGES FROM USER SPACE                         =
978  * ============================================================================
979  */
980
981 int raw_msg(char *buf, size_t len)
982 {
983         struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)buf;
984
985         if (sizeof(*bmf) > len)
986                 return -EINVAL;
987
988         if (bmf->len + sizeof(*bmf) != len)
989                 return -EINVAL;
990
991         set_seq_num(bmf);
992         write_to_buffer(buf);
993
994         return len;
995 }
996
997 static int __init swap_writer_module_init(void)
998 {
999         int ret;
1000
1001         ret = event_filter_init();
1002         if (ret)
1003                 return ret;
1004
1005         ret = init_debugfs_writer();
1006         if (ret)
1007                 event_filter_exit();
1008
1009         return ret;
1010 }
1011
1012 static void __exit swap_writer_module_exit(void)
1013 {
1014         exit_debugfs_writer();
1015         event_filter_exit();
1016 }
1017
1018 module_init(swap_writer_module_init);
1019 module_exit(swap_writer_module_exit);
1020
1021 MODULE_LICENSE("GPL");
1022 MODULE_DESCRIPTION("SWAP Writer module");
1023 MODULE_AUTHOR("Cherkashin V., Aksenov A.S.");