Merge "[IMPROVE] Gbs: add spec file" into prod_rel
[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         for (vma = mm->mmap; vma; vma = vma->vm_next) {
264                 if (vma->vm_file && (vma->vm_flags & VM_EXEC) &&
265                    (vma->vm_file->f_dentry == dentry))
266                         goto out;
267         }
268
269         vma = NULL;
270 out:
271
272         return vma;
273 }
274
275 static char *pack_shared_kmem(char *lib_obj, struct mm_struct *mm,
276                               u32 *lib_cnt_p)
277 {
278         struct lib_obj *so = (struct lib_obj *)lib_obj;
279         char *so_obj;
280         unsigned long start = 0, end = 0;
281
282         const char *kmem_name = get_shared_kmem(mm, &start, &end);
283         size_t name_len;
284
285         if (kmem_name == NULL)
286                 return lib_obj;
287
288         name_len = strlen(kmem_name) + 1;
289         so->low_addr = (u64)start;
290         so->high_addr = (u64)end;
291         memcpy(so->lib_path, kmem_name, name_len);
292         (*lib_cnt_p)++;
293         so_obj = so->lib_path + name_len;
294
295         return so_obj;
296 }
297
298 static char *pack_libs(char *lib_obj, struct mm_struct *mm, u32 *lib_cnt_p)
299 {
300         struct vm_area_struct *vma;
301
302         for (vma = mm->mmap; vma; vma = vma->vm_next) {
303                 if (check_vma(vma)) {
304                         lib_obj = pack_lib_obj(lib_obj, vma);
305                         ++(*lib_cnt_p);
306                 }
307         }
308
309         return lib_obj;
310 }
311
312 static char *pack_proc_info_part(char *end_path, struct mm_struct *mm)
313 {
314         struct proc_info_part *pip;
315         char *lib_obj;
316         u32 *lib_cnt_p;
317
318         pip = (struct proc_info_part *)end_path;
319         pip->lib_cnt = 0;
320         lib_obj = pip->libs;
321         lib_cnt_p = &pip->lib_cnt;
322
323         lib_obj = pack_libs(lib_obj, mm, lib_cnt_p);
324         lib_obj = pack_shared_kmem(lib_obj, mm, lib_cnt_p);
325
326         return lib_obj;
327 }
328
329 static char *pack_proc_info(char *payload, struct task_struct *task,
330                             struct dentry *dentry)
331 {
332         struct proc_info *pi = (struct proc_info *)payload;
333         struct vm_area_struct *vma = find_vma_exe_by_dentry(task->mm, dentry);
334         struct timespec boot_time;
335         struct timespec start_time;
336         char *end_path = NULL;
337
338         getboottime(&boot_time);
339         start_time = timespec_add(boot_time, task->real_start_time);
340
341         pi->pid = task->tgid;
342         pi->ppid = task->real_parent->tgid;
343         pi->start_sec = (u32)start_time.tv_sec;
344         pi->start_nsec = (u32)start_time.tv_nsec;
345
346         if (vma) {
347                 pi->low_addr = vma->vm_start;
348                 pi->high_addr = vma->vm_end;
349                 end_path = pack_path(pi->bin_path, vma->vm_file);
350         } else {
351                 pi->low_addr = 0;
352                 pi->high_addr = 0;
353                 end_path = pack_path(pi->bin_path, NULL);
354         }
355         return pack_proc_info_part(end_path, task->mm);
356 }
357
358 /* called with down\up\_read(&task->mm->mmap_sem) */
359 int proc_info_msg(struct task_struct *task, struct dentry *dentry)
360 {
361         char *buf, *payload, *buf_end;
362         int ret;
363
364         buf = get_current_buf();
365         payload = pack_basic_msg_fmt(buf, MSG_PROC_INFO);
366         buf_end = pack_proc_info(payload, task, dentry);
367
368         set_len_msg(buf, buf_end);
369
370         ret = write_to_buffer(buf);
371         put_current_buf();
372
373         return ret;
374 }
375 EXPORT_SYMBOL_GPL(proc_info_msg);
376
377
378
379
380
381 /* ============================================================================
382  * =                           PROCESS TERMINATE                              =
383  * ============================================================================
384  */
385
386 struct proc_terminate {
387         u32 pid;
388 } __attribute__((packed));
389
390 static char *pack_proc_terminate(char *payload, struct task_struct *task)
391 {
392         struct proc_terminate *pt = (struct proc_terminate *)payload;
393
394         pt->pid = task->pid;
395         return payload + sizeof(*pt);
396 }
397
398 void terminate_msg(struct task_struct *task)
399 {
400         char *buf, *payload, *buf_end;
401
402         buf = get_current_buf();
403         payload = pack_basic_msg_fmt(buf, MSG_TERMINATE);
404         buf_end = pack_proc_terminate(payload, task);
405
406         set_len_msg(buf, buf_end);
407
408         write_to_buffer(buf);
409         put_current_buf();
410 }
411 EXPORT_SYMBOL_GPL(terminate_msg);
412
413
414
415
416
417 /* ============================================================================
418  * =                             PROCESS MAP                                  =
419  * ============================================================================
420  */
421 struct proc_map {
422         u32 pid;
423         u64 low_addr;
424         u64 high_addr;
425         char bin_path[0];
426 } __attribute__((packed));
427
428 static char *pack_proc_map(char *payload, struct vm_area_struct *vma)
429 {
430         struct proc_map *pm = (struct proc_map *)payload;
431
432         pm->pid = current->tgid;
433         pm->low_addr = vma->vm_start;
434         pm->high_addr = vma->vm_end;
435
436         return pack_path(pm->bin_path, vma->vm_file);
437 }
438
439 void pcoc_map_msg(struct vm_area_struct *vma)
440 {
441         char *buf, *payload, *buf_end;
442
443         buf = get_current_buf();
444         payload = pack_basic_msg_fmt(buf, MSG_PROC_MAP);
445         buf_end = pack_proc_map(payload, vma);
446
447         set_len_msg(buf, buf_end);
448
449         write_to_buffer(buf);
450         put_current_buf();
451 }
452 EXPORT_SYMBOL_GPL(pcoc_map_msg);
453
454
455
456
457
458 /* ============================================================================
459  * =                            PROCESS UNMAP                                 =
460  * ============================================================================
461  */
462 struct proc_unmap {
463         u32 pid;
464         u64 low_addr;
465         u64 high_addr;
466 } __attribute__((packed));
467
468 static char *pack_proc_unmap(char *payload, unsigned long start,
469                              unsigned long end)
470 {
471         struct proc_unmap *pum = (struct proc_unmap *)payload;
472
473         pum->pid = current->tgid;
474         pum->low_addr = start;
475         pum->high_addr = end;
476
477         return payload + sizeof(*pum);
478 }
479
480 void proc_unmap_msg(unsigned long start, unsigned long end)
481 {
482         char *buf, *payload, *buf_end;
483
484         buf = get_current_buf();
485         payload = pack_basic_msg_fmt(buf, MSG_PROC_UNMAP);
486         buf_end = pack_proc_unmap(payload, start, end);
487
488         set_len_msg(buf, buf_end);
489
490         write_to_buffer(buf);
491         put_current_buf();
492 }
493 EXPORT_SYMBOL_GPL(proc_unmap_msg);
494
495
496
497
498
499 /* ============================================================================
500  * =                                 SAMPLE                                   =
501  * ============================================================================
502  */
503
504 struct sample {
505         u32 pid;
506         u64 pc_addr;
507         u32 tid;
508         u32 cpu_num;
509 } __attribute__((packed));
510
511 static char *pack_sample(char *payload, struct pt_regs *regs)
512 {
513         struct sample *s = (struct sample *)payload;
514         struct task_struct *task = current;
515
516         s->pid = task->tgid;
517         s->pc_addr = get_regs_ip(regs);
518         s->tid = task->pid;
519         s->cpu_num = smp_processor_id();
520
521         return payload + sizeof(*s);
522 }
523
524 int sample_msg(struct pt_regs *regs)
525 {
526         char *buf, *payload, *buf_end;
527         int ret;
528
529         if (!check_event(current))
530                 return 0;
531
532         buf = get_current_buf();
533         payload = pack_basic_msg_fmt(buf, MSG_SAMPLE);
534         buf_end = pack_sample(payload, regs);
535
536         set_len_msg(buf, buf_end);
537
538         ret = write_to_buffer(buf);
539         put_current_buf();
540
541         return ret;
542 }
543 EXPORT_SYMBOL_GPL(sample_msg);
544
545
546
547
548 /* ============================================================================
549  * =                                 ENTRY                                    =
550  * ============================================================================
551  */
552
553 struct msg_func_entry {
554         u64 pc_addr;
555         u64 caller_pc_addr;
556         u16 probe_type;
557         u16 probe_sub_type;
558         u32 pid;
559         u32 tid;
560         u32 cpu_num;
561         u32 cnt_args;
562         char args[0];
563 } __attribute__((packed));
564
565 static char *pack_msg_func_entry(char *payload, const char *fmt,
566                                  unsigned long func_addr, struct pt_regs *regs,
567                                  enum PROBE_TYPE pt, int sub_type)
568 {
569         struct msg_func_entry *mfe = (struct msg_func_entry *)payload;
570         struct task_struct *task = current;
571
572         mfe->pid = task->tgid;
573         mfe->tid = task->pid;
574         mfe->cpu_num = smp_processor_id();
575         mfe->pc_addr = func_addr;
576         mfe->caller_pc_addr = get_regs_ret_func(regs);
577         mfe->probe_type = pt;
578         mfe->probe_sub_type = sub_type;
579         mfe->cnt_args = strlen(fmt);
580
581         return payload + sizeof(*mfe);
582 }
583
584 static unsigned long get_arg(struct pt_regs *regs, unsigned long n)
585 {
586         return user_mode(regs) ?
587                         swap_get_uarg(regs, n) :        /* US argument */
588                         swap_get_sarg(regs, n);         /* sys_call argument */
589 }
590
591 static int pack_args(char *buf, int len, const char *fmt, struct pt_regs *regs)
592 {
593         char *buf_old = buf;
594         u32 *tmp_u32;
595         u64 *tmp_u64;
596         int i,          /* the index of the argument */
597             fmt_i,      /* format index */
598             fmt_len;    /* the number of parameters, in format */
599
600         fmt_len = strlen(fmt);
601
602         for (i = 0, fmt_i = 0; fmt_i < fmt_len; ++i, ++fmt_i) {
603                 if (len < 2)
604                         return -ENOMEM;
605
606                 *buf = fmt[fmt_i];
607                 buf += 1;
608                 len -= 1;
609
610                 switch (fmt[fmt_i]) {
611                 case 'b': /* 1 byte(bool) */
612                         *buf = (char)!!get_arg(regs, i);
613                         buf += 1;
614                         len -= 1;
615                         break;
616                 case 'c': /* 1 byte(char) */
617                         *buf = (char)get_arg(regs, i);
618                         buf += 1;
619                         len -= 1;
620                         break;
621                 case 'f': /* 4 byte(float) */
622                 case 'd': /* 4 byte(int) */
623                         if (len < 4)
624                                 return -ENOMEM;
625                         tmp_u32 = (u32 *)buf;
626                         *tmp_u32 = (u32)get_arg(regs, i);
627                         buf += 4;
628                         len -= 4;
629                         break;
630                 case 'x': /* 8 byte(long) */
631                 case 'p': /* 8 byte(pointer) */
632                         if (len < 8)
633                                 return -ENOMEM;
634                         tmp_u64 = (u64 *)buf;
635                         *tmp_u64 = (u64)get_arg(regs, i);
636                         buf += 8;
637                         len -= 8;
638                         break;
639                 case 'w': /* 8 byte(double) */
640                         if (len < 8)
641                                 return -ENOMEM;
642                         tmp_u64 = (u64 *)buf;
643                         *tmp_u64 = get_arg(regs, i);
644                         ++i;
645                         *tmp_u64 |= (u64)get_arg(regs, i) << 32;
646                         buf += 8;
647                         len -= 8;
648                         break;
649                 case 's': /* string end with '\0' */
650                 {
651                         enum { max_str_len = 512 };
652                         const char __user *user_s;
653                         int len_s, ret;
654
655                         user_s = (const char __user *)get_arg(regs, i);
656                         len_s = strnlen_user(user_s, max_str_len);
657                         if (len < len_s)
658                                 return -ENOMEM;
659
660                         ret = strncpy_from_user(buf, user_s, len_s);
661                         if (ret < 0)
662                                 return -EFAULT;
663
664                         buf[ret] = '\0';
665
666                         buf += ret + 1;
667                         len -= ret + 1;
668                 }
669                         break;
670                 default:
671                         return -EINVAL;
672                 }
673         }
674
675         return buf - buf_old;
676 }
677
678 int entry_event(const char *fmt, unsigned long func_addr, struct pt_regs *regs,
679                 enum PROBE_TYPE pt, int sub_type)
680 {
681         char *buf, *payload, *args, *buf_end;
682         int ret;
683
684         if (pt == PT_KS && !check_event(current))
685                 return 0;
686
687         buf = get_current_buf();
688         payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_ENTRY);
689         args = pack_msg_func_entry(payload, fmt, func_addr,
690                                    regs, pt, sub_type);
691
692         /* FIXME: len = 1024 */
693         ret = pack_args(args, 1024, fmt, regs);
694         if (ret < 0) {
695                 printk("ERROR: !!!!!\n");
696                 return ret;
697         }
698
699         buf_end = args + ret;
700
701         set_len_msg(buf, buf_end);
702
703         ret = write_to_buffer(buf);
704         put_current_buf();
705
706         return ret;
707 }
708 EXPORT_SYMBOL_GPL(entry_event);
709
710
711
712
713
714 /* ============================================================================
715  * =                                 EXIT                                     =
716  * ============================================================================
717  */
718
719 struct msg_func_exit {
720         u32 pid;
721         u32 tid;
722         u64 pc_addr;
723         u64 caller_pc_addr;
724         u32 cpu_num;
725         char ret_val[0];
726 } __attribute__((packed));
727
728 static int pack_msg_ret_val(char *buf, int len, char ret_type,
729                               struct pt_regs *regs)
730 {
731         const char *buf_old = buf;
732         u32 *tmp_u32;
733         u64 *tmp_u64;
734
735         *buf = ret_type;
736         ++buf;
737
738         switch (ret_type) {
739         case 'b': /* 1 byte(bool) */
740                 if (len < 1)
741                         return -ENOMEM;
742                 *buf = (char)!!get_regs_ret_val(regs);
743                 ++buf;
744                 break;
745         case 'c': /* 1 byte(char) */
746                 if (len < 1)
747                         return -ENOMEM;
748                 *buf = (char)get_regs_ret_val(regs);
749                 ++buf;
750                 break;
751         case 'd': /* 4 byte(int) */
752                 if (len < 4)
753                         return -ENOMEM;
754                 tmp_u32 = (u32 *)buf;
755                 *tmp_u32 = get_regs_ret_val(regs);
756                 buf += 4;
757                 break;
758         case 'x': /* 8 byte(long) */
759         case 'p': /* 8 byte(pointer) */
760                 if (len < 8)
761                         return -ENOMEM;
762                 tmp_u64 = (u64 *)buf;
763                 *tmp_u64 = (u64)get_regs_ret_val(regs);
764                 buf += 8;
765                 break;
766         case 's': /* string end with '\0' */
767         {
768                 enum { max_str_len = 512 };
769                 const char __user *user_s;
770                 int len_s, ret;
771
772                 user_s = (const char __user *)get_regs_ret_val(regs);
773                 len_s = strnlen_user(user_s, max_str_len);
774                 if (len < len_s)
775                         return -ENOMEM;
776
777                 ret = strncpy_from_user(buf, user_s, len_s);
778                 if (ret < 0)
779                         return -EFAULT;
780
781                 buf[ret] = '\0';
782                 buf += ret + 1;
783         }
784                 break;
785         case 'n':
786         case 'v':
787                 break;
788         case 'f': /* 4 byte(float) */
789                 if (len < 4)
790                         return -ENOMEM;
791                 tmp_u32 = (u32 *)buf;
792                 *tmp_u32 = swap_get_urp_float(regs);
793                 buf += 4;
794                 break;
795         case 'w': /* 8 byte(double) */
796                 if (len < 8)
797                         return -ENOMEM;
798                 tmp_u64 = (u64 *)buf;
799                 *tmp_u64 = swap_get_urp_double(regs);
800                 buf += 8;
801                 break;
802         default:
803                 return -EINVAL;
804         }
805
806         return buf - buf_old;
807 }
808
809
810 static int pack_msg_func_exit(char *buf, int len, char ret_type,
811                               struct pt_regs *regs, unsigned long func_addr,
812                               unsigned long ret_addr)
813 {
814         struct msg_func_exit *mfe = (struct msg_func_exit *)buf;
815         struct task_struct *task = current;
816         int ret;
817
818         mfe->pid = task->tgid;
819         mfe->tid = task->pid;
820         mfe->cpu_num = smp_processor_id();
821         mfe->pc_addr = func_addr;
822         mfe->caller_pc_addr = ret_addr;
823
824         ret = pack_msg_ret_val(mfe->ret_val, len, ret_type, regs);
825         if (ret < 0) {
826                 printk("ERROR: packing MSG_FUNCTION_EXIT (ret=%d)\n", ret);
827                 return ret;
828         }
829
830         return sizeof(*mfe) + ret;
831 }
832
833 int exit_event(char ret_type, struct pt_regs *regs, unsigned long func_addr,
834                unsigned long ret_addr)
835 {
836         char *buf, *payload, *buf_end;
837         int ret;
838
839         if (!check_event(current))
840                 return 0;
841
842         buf = get_current_buf();
843         payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_EXIT);
844         /* FIXME: len=1024 */
845         ret = pack_msg_func_exit(payload, 1024, ret_type, regs,
846                                  func_addr, ret_addr);
847         if (ret < 0)
848                 return ret;
849
850         buf_end = payload + ret;
851         set_len_msg(buf, buf_end);
852
853         ret = write_to_buffer(buf);
854         put_current_buf();
855
856         return ret;
857 }
858 EXPORT_SYMBOL_GPL(exit_event);
859
860
861
862
863
864 /* ============================================================================
865  * =                            CONTEXT SWITCH                                =
866  * ============================================================================
867  */
868
869 struct msg_context_switch {
870         u64 pc_addr;
871         u32 pid;
872         u32 tid;
873         u32 cpu_num;
874 } __attribute__((packed));
875
876 static char *pack_msg_context_switch(char *payload, struct pt_regs *regs)
877 {
878         struct msg_context_switch *mcs = (struct msg_context_switch *)payload;
879         struct task_struct *task = current;
880
881         mcs->pc_addr = 0;
882         mcs->pid = task->tgid;
883         mcs->tid = task->pid;
884         mcs->cpu_num = smp_processor_id();
885
886         return payload + sizeof(*mcs);
887 }
888
889 static int context_switch(struct pt_regs *regs, enum MSG_ID id)
890 {
891         char *buf, *payload, *buf_end;
892         int ret;
893
894         buf = get_current_buf();
895         payload = pack_basic_msg_fmt(buf, id);
896         buf_end = pack_msg_context_switch(payload, regs);
897         set_len_msg(buf, buf_end);
898
899         ret = write_to_buffer(buf);
900         put_current_buf();
901
902         return ret;
903 }
904
905 int switch_entry(struct pt_regs *regs)
906 {
907         if (!check_event(current))
908                 return 0;
909
910         return context_switch(regs, MSG_CONTEXT_SWITCH_ENTRY);
911 }
912 EXPORT_SYMBOL_GPL(switch_entry);
913
914 int switch_exit(struct pt_regs *regs)
915 {
916         if (!check_event(current))
917                 return 0;
918
919         return context_switch(regs, MSG_CONTEXT_SWITCH_EXIT);
920 }
921 EXPORT_SYMBOL_GPL(switch_exit);
922
923
924
925
926 /* ============================================================================
927  * =                                 ERROR                                    =
928  * ============================================================================
929  */
930
931 struct msg_err {
932         char msg[0];
933 } __attribute__((packed));
934
935 static char *pack_msg_err(char *payload, const char *fmt, va_list args)
936 {
937         struct msg_err *me = (struct msg_err *)payload;
938         int ret;
939
940         ret = vsprintf(me->msg, fmt, args);
941         if (ret < 0)
942                 return payload;
943
944         return payload + sizeof(*me) + ret + 1;
945 }
946
947 int error_msg(const char *fmt, ...)
948 {
949         char *buf, *payload, *buf_end;
950         va_list args;
951         int ret;
952
953         buf = get_current_buf();
954         payload = pack_basic_msg_fmt(buf, MSG_ERROR);
955
956         va_start(args, fmt);
957         buf_end = pack_msg_err(payload, fmt, args);
958         va_end(args);
959
960         set_len_msg(buf, buf_end);
961
962         ret = write_to_buffer(buf);
963         put_current_buf();
964
965         return ret;
966 }
967 EXPORT_SYMBOL_GPL(error_msg);
968
969
970
971
972
973 /* ============================================================================
974  * =                         MESSAGES FROM USER SPACE                         =
975  * ============================================================================
976  */
977
978 int raw_msg(char *buf, size_t len)
979 {
980         struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)buf;
981
982         if (sizeof(*bmf) > len)
983                 return -EINVAL;
984
985         if (bmf->len + sizeof(*bmf) != len)
986                 return -EINVAL;
987
988         set_seq_num(bmf);
989         write_to_buffer(buf);
990
991         return len;
992 }
993
994 static int __init swap_writer_module_init(void)
995 {
996         int ret;
997
998         ret = event_filter_init();
999         if (ret)
1000                 return ret;
1001
1002         ret = init_debugfs_writer();
1003         if (ret)
1004                 event_filter_exit();
1005
1006         return ret;
1007 }
1008
1009 static void __exit swap_writer_module_exit(void)
1010 {
1011         exit_debugfs_writer();
1012         event_filter_exit();
1013 }
1014
1015 module_init(swap_writer_module_init);
1016 module_exit(swap_writer_module_exit);
1017
1018 MODULE_LICENSE("GPL");
1019 MODULE_DESCRIPTION("SWAP Writer module");
1020 MODULE_AUTHOR("Cherkashin V., Aksenov A.S.");