df9c0069c9b10ba5fb1162dab97c4a9640a6ce3b
[platform/kernel/swap-modules.git] / writer / swap_writer_module.c
1 /**
2  * writer/swap_writer_module.c
3  * @author Alexander Aksenov <a.aksenov@samsung.com>
4  * @author Vyacheslav Cherkashin
5  *
6  * @section LICENSE
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  *
22  * @section COPYRIGHT
23  *
24  * Copyright (C) Samsung Electronics, 2013
25  *
26  * @section DESCRIPTION
27  *
28  * Packing and writing data.
29  */
30
31 #include <linux/types.h>
32 #include <linux/ctype.h>
33 #include <linux/errno.h>
34 #include <linux/sched.h>
35 #include <linux/dcache.h>
36 #include <linux/mm.h>
37 #include <linux/mm_types.h>
38 #include <linux/fs.h>
39 #include <linux/err.h>
40 #include <linux/module.h>
41 #include <linux/slab.h>
42
43 #include <asm/uaccess.h>
44
45 #include <master/swap_initializer.h>
46 #include <buffer/swap_buffer_module.h>
47 #include <buffer/swap_buffer_errors.h>
48
49 #include <swap-asm/swap_kprobes.h>
50 #include <swap-asm/swap_uprobes.h>
51
52 #include "swap_writer_module.h"
53 #include "swap_writer_errors.h"
54 #include "kernel_operations.h"
55 #include "debugfs_writer.h"
56 #include "event_filter.h"
57
58
59 /**
60  * @enum MSG_ID
61  * @brief Supported message IDs.
62  */
63 enum MSG_ID {
64         MSG_PROC_INFO                   = 0x0001,       /**< Process info */
65         MSG_TERMINATE                   = 0x0002,       /**< Terminate */
66         MSG_ERROR                       = 0x0003,           /**< Error */
67         MSG_SAMPLE                      = 0x0004,           /**< Sampler event */
68         MSG_FUNCTION_ENTRY              = 0x0008,       /**< Function entry */
69         MSG_FUNCTION_EXIT               = 0x0009,       /**< Function return */
70         MSG_CONTEXT_SWITCH_ENTRY        = 0x0010,   /**< Context switch entry */
71         MSG_CONTEXT_SWITCH_EXIT         = 0x0011,   /**< Context switch exit */
72         MSG_PROC_MAP                    = 0x0012,       /**< Process map */
73         MSG_PROC_UNMAP                  = 0x0013,       /**< Process unmap */
74         MSG_PROC_COMM                   = 0x0014        /**< Process comm */
75 };
76
77 static char *cpu_buf[NR_CPUS];
78 static u32 seq_num;
79 static unsigned int discarded;
80
81 /**
82  * @brief Initializes new message.
83  *
84  * @param buf_size Message buffer size.
85  * @return Success.
86  */
87 int init_msg(size_t buf_size)
88 {
89         int i;
90
91         for (i = 0; i < NR_CPUS; ++i)
92                 cpu_buf[i] = kmalloc(buf_size, GFP_KERNEL);
93
94         return E_SW_SUCCESS;
95 }
96 EXPORT_SYMBOL_GPL(init_msg);
97
98 /**
99  * @brief Uninitializes message.
100  *
101  * @return Void.
102  */
103 void uninit_msg(void)
104 {
105         int i;
106
107         for (i = 0; i < NR_CPUS; ++i)
108                 kfree(cpu_buf[i]);
109 }
110 EXPORT_SYMBOL_GPL(uninit_msg);
111
112 /**
113  * @brief Sets discarded events count to 0.
114  *
115  * @return Void.
116  */
117 void reset_discarded(void)
118 {
119         discarded = 0;
120 }
121 EXPORT_SYMBOL_GPL(reset_discarded);
122
123 /**
124  * @brief Sets events sequence number to 0.
125  *
126  * @return Void.
127  */
128 void reset_seq_num(void)
129 {
130         seq_num = 0;
131 }
132 EXPORT_SYMBOL_GPL(reset_seq_num);
133
134 /**
135  * @brief Gets discarded events count.
136  *
137  * @return Discarded events count.
138  */
139 unsigned int get_discarded_count(void)
140 {
141         return discarded;
142 }
143 EXPORT_SYMBOL_GPL(get_discarded_count);
144
145 static inline char *get_current_buf(void)
146 {
147         return cpu_buf[get_cpu()];
148 }
149
150 static inline void put_current_buf(void)
151 {
152         put_cpu();
153 }
154
155 static inline u64 timespec2time(struct timespec *ts)
156 {
157         return ((u64)ts->tv_nsec) << 32 | ts->tv_sec;
158 }
159
160 /* ============================================================================
161  * =                         BASIC MESSAGE FORMAT                             =
162  * ============================================================================
163  */
164
165 /**
166  * @struct basic_msg_fmt
167  * @brief Basic message.
168  */
169 struct basic_msg_fmt {
170         u32 msg_id;             /**< Message ID */
171         u32 seq_number;         /**< Sequence number */
172         u64 time;               /**< Message time */
173         u32 len;                /**< Message length */
174         char payload[0];        /**< Message itself */
175 } __packed;
176
177 #if 0 /* debug */
178 static void print_hex(char *ptr, int len)
179 {
180         int i;
181
182         printk(KERN_INFO "print_hex:\n");
183         for (i = 0; i < len; ++i)
184                 printk(KERN_INFO "[%x]  [%3d]=%2x\n", &ptr[i], i, ptr[i]);
185 }
186 #endif
187
188 static int write_to_buffer(void *data)
189 {
190         int result;
191         struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)data;
192
193         result = swap_buffer_write(bmf, bmf->len + sizeof(*bmf));
194         if (result < 0)
195                 discarded++;
196
197         return result;
198 }
199
200 static void set_len_msg(char *buf, char *end)
201 {
202         struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)buf;
203         bmf->len = end - buf - sizeof(*bmf);
204 }
205
206 static inline void set_seq_num(struct basic_msg_fmt *bmf)
207 {
208         bmf->seq_number = seq_num;
209         seq_num++;
210 }
211
212 static inline void set_time(struct basic_msg_fmt *bmf)
213 {
214         struct timespec ts;
215
216         getnstimeofday(&ts);
217         bmf->time = timespec2time(&ts);
218 }
219
220 static char *pack_basic_msg_fmt(char *buf, enum MSG_ID id)
221 {
222         struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)buf;
223
224         set_time(bmf);
225         set_seq_num(bmf);
226         bmf->msg_id = id;
227
228         return bmf->payload;
229 }
230
231
232
233
234
235 /* ============================================================================
236  * =                             PROCESS INFO                                 =
237  * ============================================================================
238  */
239
240 /**
241  * @struct proc_info_top
242  * @brief Top proc info part.
243  */
244 struct proc_info_top {
245         u32 pid;                    /**< Process PID */
246         char comm[0];               /**< Message */
247 } __packed;
248
249 /**
250  * @struct proc_info_bottom
251  * @brief Bottom proc info part.
252  */
253 struct proc_info_bottom {
254         u32 ppid;                   /**< Parent PID */
255         u32 start_sec;              /**< Start time sec */
256         u32 start_nsec;             /**< Start time nsec */
257         u64 low_addr;               /**< Low address */
258         u64 high_addr;              /**< High address */
259         char bin_path[0];           /**< Binary path */
260 } __packed;
261
262 /**
263  * @struct proc_info_part
264  * @brief Process info part.
265  */
266 struct proc_info_part {
267         u32 lib_cnt;                /**< Library count */
268         char libs[0];               /**< Libraries */
269 } __packed;
270
271 /**
272  * @struct lib_obj
273  * @brief Library object.
274  */
275 struct lib_obj {
276         u64 low_addr;               /**< Low library address */
277         u64 high_addr;              /**< High library address */
278         char lib_path[0];           /**< Library path */
279 } __packed;
280
281 static char *pack_path(char *buf, struct file *file)
282 {
283         enum { TMP_BUF_LEN = 512 };
284         char tmp_buf[TMP_BUF_LEN];
285         char NA[] = "N/A";
286         char *filename;
287         size_t len;
288
289         if (file == NULL)
290                 return strcpy(buf, NA) + sizeof(NA);
291
292         filename = d_path(&file->f_path, tmp_buf, TMP_BUF_LEN);
293         if (IS_ERR_OR_NULL(filename))
294                 return strcpy(buf, NA) + sizeof(NA);
295
296         len = strlen(filename) + 1;
297         memcpy(buf, filename, len);
298
299         return buf + len;
300 }
301
302 static char *pack_lib_obj(char *lib_obj, struct vm_area_struct *vma)
303 {
304         struct lib_obj *lo = (struct lib_obj *)lib_obj;
305
306         lo->low_addr = vma->vm_start;
307         lo->high_addr = vma->vm_end;
308
309         return pack_path(lo->lib_path, vma->vm_file);
310 }
311
312 /* FIXME: check_vma()*/
313 static int check_vma(struct vm_area_struct *vma)
314 {
315         return vma->vm_file &&
316                !(vma->vm_pgoff != 0 ||
317                  !(vma->vm_flags & VM_EXEC) ||
318                  !(vma->vm_flags & (VM_READ | VM_MAYREAD)));
319 }
320
321 static struct vm_area_struct *find_vma_exe_by_dentry(struct mm_struct *mm,
322                                                      struct dentry *dentry)
323 {
324         struct vm_area_struct *vma;
325
326         for (vma = mm->mmap; vma; vma = vma->vm_next) {
327                 if (vma->vm_file && (vma->vm_flags & VM_EXEC) &&
328                    (vma->vm_file->f_dentry == dentry))
329                         goto out;
330         }
331
332         vma = NULL;
333 out:
334
335         return vma;
336 }
337
338 static char *pack_shared_kmem(char *lib_obj,
339                               struct mm_struct *mm,
340                               u32 *lib_cnt_p)
341 {
342         struct lib_obj *so = (struct lib_obj *)lib_obj;
343         char *so_obj;
344         unsigned long start = 0, end = 0;
345
346         const char *kmem_name = get_shared_kmem(mm, &start, &end);
347         size_t name_len;
348
349         if (kmem_name == NULL)
350                 return lib_obj;
351
352         name_len = strlen(kmem_name) + 1;
353         so->low_addr = (u64)start;
354         so->high_addr = (u64)end;
355         memcpy(so->lib_path, kmem_name, name_len);
356         (*lib_cnt_p)++;
357         so_obj = so->lib_path + name_len;
358
359         return so_obj;
360 }
361
362 static char *pack_libs(char *lib_obj, struct mm_struct *mm, u32 *lib_cnt_p)
363 {
364         struct vm_area_struct *vma;
365
366         for (vma = mm->mmap; vma; vma = vma->vm_next) {
367                 if (check_vma(vma)) {
368                         lib_obj = pack_lib_obj(lib_obj, vma);
369                         ++(*lib_cnt_p);
370                 }
371         }
372
373         return lib_obj;
374 }
375
376 static char *pack_proc_info_part(char *end_path, struct mm_struct *mm)
377 {
378         struct proc_info_part *pip;
379         char *lib_obj;
380         u32 *lib_cnt_p;
381
382         pip = (struct proc_info_part *)end_path;
383         pip->lib_cnt = 0;
384         lib_obj = pip->libs;
385         lib_cnt_p = &pip->lib_cnt;
386
387         lib_obj = pack_libs(lib_obj, mm, lib_cnt_p);
388         lib_obj = pack_shared_kmem(lib_obj, mm, lib_cnt_p);
389
390         return lib_obj;
391 }
392
393 static char *pack_comm(char *buf, struct task_struct *task)
394 {
395         get_task_comm(buf, task);
396
397         return buf + strlen(buf) + 1;
398 }
399
400 static char *pack_proc_info_top(char *data, struct task_struct *task)
401 {
402         struct proc_info_top *pit = (struct proc_info_top *)data;
403
404         pit->pid = task->tgid;
405
406         return pack_comm(pit->comm, task);
407 }
408
409 static char *pack_proc_info_bottom(char *data, struct task_struct *task,
410                                    struct dentry *dentry)
411 {
412         struct proc_info_bottom *pib = (struct proc_info_bottom *)data;
413         struct vm_area_struct *vma = find_vma_exe_by_dentry(task->mm, dentry);
414         struct timespec boot_time;
415         struct timespec start_time;
416         char *end_path = NULL;
417
418         getboottime(&boot_time);
419         start_time = timespec_add(boot_time, task->real_start_time);
420
421         pib->ppid = task->real_parent->tgid;
422         pib->start_sec = (u32)start_time.tv_sec;
423         pib->start_nsec = (u32)start_time.tv_nsec;
424
425         if (vma) {
426                 pib->low_addr = vma->vm_start;
427                 pib->high_addr = vma->vm_end;
428                 end_path = pack_path(pib->bin_path, vma->vm_file);
429         } else {
430                 pib->low_addr = 0;
431                 pib->high_addr = 0;
432                 end_path = pack_path(pib->bin_path, NULL);
433         }
434         return pack_proc_info_part(end_path, task->mm);
435 }
436
437 static char *pack_proc_info(char *payload, struct task_struct *task,
438                             struct dentry *dentry)
439 {
440         payload = pack_proc_info_top(payload, task);
441         return pack_proc_info_bottom(payload, task, dentry);
442 }
443
444 /**
445  * @brief Packs and writes process info message. Called with
446  * down\up\_read(&task->mm->mmap_sem).
447  *
448  * @param task Pointer to the target task_struct.
449  * @param dentry Pointer to the task dentry.
450  * @return Written data size on success, negative error code on error.
451  */
452 int proc_info_msg(struct task_struct *task, struct dentry *dentry)
453 {
454         char *buf, *payload, *buf_end;
455         int ret;
456
457         buf = get_current_buf();
458         payload = pack_basic_msg_fmt(buf, MSG_PROC_INFO);
459         buf_end = pack_proc_info(payload, task, dentry);
460
461         set_len_msg(buf, buf_end);
462
463         ret = write_to_buffer(buf);
464         put_current_buf();
465
466         return ret;
467 }
468 EXPORT_SYMBOL_GPL(proc_info_msg);
469
470
471
472
473
474 /* ============================================================================
475  * =                           PROCESS TERMINATE                              =
476  * ============================================================================
477  */
478
479 /**
480  * @struct proc_terminate
481  * @brief Terminate message struct.
482  */
483 struct proc_terminate {
484         u32 pid;                /**< Process ID */
485 } __packed;
486
487 static char *pack_proc_terminate(char *payload, struct task_struct *task)
488 {
489         struct proc_terminate *pt = (struct proc_terminate *)payload;
490
491         pt->pid = task->pid;
492         return payload + sizeof(*pt);
493 }
494
495 /**
496  * @brief Packs and writes terminate message.
497  *
498  * @param task Target task_struct.
499  * @return Void.
500  */
501 void terminate_msg(struct task_struct *task)
502 {
503         char *buf, *payload, *buf_end;
504
505         buf = get_current_buf();
506         payload = pack_basic_msg_fmt(buf, MSG_TERMINATE);
507         buf_end = pack_proc_terminate(payload, task);
508
509         set_len_msg(buf, buf_end);
510
511         write_to_buffer(buf);
512         put_current_buf();
513 }
514 EXPORT_SYMBOL_GPL(terminate_msg);
515
516
517
518
519
520 /* ============================================================================
521  * =                             PROCESS MAP                                  =
522  * ============================================================================
523  */
524
525 /**
526  * @struct proc_map
527  * @brief Process mapping info.
528  */
529 struct proc_map {
530         u32 pid;                    /**< Process ID */
531         u64 low_addr;               /**< Low address */
532         u64 high_addr;              /**< High address */
533         char bin_path[0];           /**< Binary path */
534 } __packed;
535
536 static char *pack_proc_map(char *payload, struct vm_area_struct *vma)
537 {
538         struct proc_map *pm = (struct proc_map *)payload;
539
540         pm->pid = current->tgid;
541         pm->low_addr = vma->vm_start;
542         pm->high_addr = vma->vm_end;
543
544         return pack_path(pm->bin_path, vma->vm_file);
545 }
546
547 /**
548  * @brief Packs and writes process map message.
549  *
550  * @param vma Target memory area.
551  * @return Void.
552  */
553 void pcoc_map_msg(struct vm_area_struct *vma)
554 {
555         char *buf, *payload, *buf_end;
556
557         buf = get_current_buf();
558         payload = pack_basic_msg_fmt(buf, MSG_PROC_MAP);
559         buf_end = pack_proc_map(payload, vma);
560
561         set_len_msg(buf, buf_end);
562
563         write_to_buffer(buf);
564         put_current_buf();
565 }
566 EXPORT_SYMBOL_GPL(pcoc_map_msg);
567
568
569
570
571
572 /* ============================================================================
573  * =                            PROCESS UNMAP                                 =
574  * ============================================================================
575  */
576
577 /**
578  * @struct proc_unmap
579  * @brief Process mapping info.
580  */
581 struct proc_unmap {
582         u32 pid;                /**< Process ID */
583         u64 low_addr;           /**< Low address */
584         u64 high_addr;          /**< High address */
585 } __packed;
586
587 static char *pack_proc_unmap(char *payload, unsigned long start,
588                              unsigned long end)
589 {
590         struct proc_unmap *pum = (struct proc_unmap *)payload;
591
592         pum->pid = current->tgid;
593         pum->low_addr = start;
594         pum->high_addr = end;
595
596         return payload + sizeof(*pum);
597 }
598
599 /**
600  * @brief Packs and writes process unmap message.
601  *
602  * @param start Unmapping area low address.
603  * @param end Unmapping area high address.
604  * @return Void.
605  */
606 void proc_unmap_msg(unsigned long start, unsigned long end)
607 {
608         char *buf, *payload, *buf_end;
609
610         buf = get_current_buf();
611         payload = pack_basic_msg_fmt(buf, MSG_PROC_UNMAP);
612         buf_end = pack_proc_unmap(payload, start, end);
613
614         set_len_msg(buf, buf_end);
615
616         write_to_buffer(buf);
617         put_current_buf();
618 }
619 EXPORT_SYMBOL_GPL(proc_unmap_msg);
620
621
622
623
624
625 /* ============================================================================
626  * =                              PROCESS COMM                                =
627  * ============================================================================
628  */
629
630 /**
631  * @struct proc_comm
632  * @brief Comm message info.
633  */
634 struct proc_comm {
635         u32 pid;                /**< Process ID */
636         char comm[0];           /**< Comm */
637 } __packed;
638
639 static char *pack_proc_comm(char *data, struct task_struct *task)
640 {
641         struct proc_comm *pcomm = (struct proc_comm *)data;
642
643         pcomm->pid = task->tgid;
644
645         return pack_comm(pcomm->comm, task);
646 }
647
648 /**
649  * @brief Packs and writes process comm message.
650  *
651  * @param task Target task_struct.
652  * @return Void.
653  */
654 void proc_comm_msg(struct task_struct *task)
655 {
656         char *buf, *payload, *buf_end;
657
658         buf = get_current_buf();
659         payload = pack_basic_msg_fmt(buf, MSG_PROC_COMM);
660         buf_end = pack_proc_comm(payload, task);
661
662         set_len_msg(buf, buf_end);
663
664         write_to_buffer(buf);
665         put_current_buf();
666 }
667 EXPORT_SYMBOL_GPL(proc_comm_msg);
668
669
670
671
672
673 /* ============================================================================
674  * =                                 SAMPLE                                   =
675  * ============================================================================
676  */
677
678 /**
679  * @struct sample
680  * @brief Sampler event info.
681  */
682 struct sample {
683         u32 pid;                /**< Process ID */
684         u64 pc_addr;            /**< Instruction pointer address */
685         u32 tid;                /**< Thread ID */
686         u32 cpu_num;            /**< CPU number */
687 } __packed;
688
689 static char *pack_sample(char *payload, struct pt_regs *regs)
690 {
691         struct sample *s = (struct sample *)payload;
692         struct task_struct *task = current;
693
694         s->pid = task->tgid;
695         s->pc_addr = get_regs_ip(regs);
696         s->tid = task->pid;
697         s->cpu_num = smp_processor_id();
698
699         return payload + sizeof(*s);
700 }
701
702 /**
703  * @brief Packs and writes sample message.
704  *
705  * @param regs Pointer to CPU register data.
706  * @return Written data size on success, negative error code on error.
707  */
708 int sample_msg(struct pt_regs *regs)
709 {
710         char *buf, *payload, *buf_end;
711         int ret;
712
713         buf = get_current_buf();
714         payload = pack_basic_msg_fmt(buf, MSG_SAMPLE);
715         buf_end = pack_sample(payload, regs);
716
717         set_len_msg(buf, buf_end);
718
719         ret = write_to_buffer(buf);
720         put_current_buf();
721
722         return ret;
723 }
724 EXPORT_SYMBOL_GPL(sample_msg);
725
726
727
728
729 /* ============================================================================
730  * =                                 ENTRY                                    =
731  * ============================================================================
732  */
733
734 /**
735  * @struct msg_func_entry
736  * @brief Entry event info.
737  */
738 struct msg_func_entry {
739         u32 pid;                /**< Process ID */
740         u32 tid;                /**< Thread ID */
741         u16 probe_type;         /**< Probe type */
742         u16 probe_sub_type;     /**< Probe subtype */
743         u64 pc_addr;            /**< Instruction pointer address. */
744         u64 caller_pc_addr;     /**< Return address */
745         u32 cpu_num;            /**< CPU number */
746         u32 cnt_args;           /**< Count of args */
747         char args[0];           /**< Args format string */
748 } __packed;
749
750 static char *pack_msg_func_entry(char *payload, const char *fmt,
751                                  unsigned long func_addr, struct pt_regs *regs,
752                                  enum PROBE_TYPE pt, int sub_type)
753 {
754         struct msg_func_entry *mfe = (struct msg_func_entry *)payload;
755         struct task_struct *task = current;
756
757         mfe->pid = task->tgid;
758         mfe->tid = task->pid;
759         mfe->cpu_num = smp_processor_id();
760         mfe->pc_addr = func_addr;
761         mfe->caller_pc_addr = get_regs_ret_func(regs);
762         mfe->probe_type = pt;
763         mfe->probe_sub_type = sub_type;
764         mfe->cnt_args = strlen(fmt);
765
766         return payload + sizeof(*mfe);
767 }
768
769 static unsigned long get_arg(struct pt_regs *regs, unsigned long n)
770 {
771         return user_mode(regs) ?
772                         swap_get_uarg(regs, n) :        /* US argument */
773                         swap_get_sarg(regs, n);         /* sys_call argument */
774 }
775
776 static int pack_args(char *buf, int len, const char *fmt, struct pt_regs *regs)
777 {
778         char *buf_old = buf;
779         u32 *tmp_u32;
780         u64 *tmp_u64;
781         int i,          /* the index of the argument */
782             fmt_i,      /* format index */
783             fmt_len;    /* the number of parameters, in format */
784
785         fmt_len = strlen(fmt);
786
787         for (i = 0, fmt_i = 0; fmt_i < fmt_len; ++i, ++fmt_i) {
788                 if (len < 2)
789                         return -ENOMEM;
790
791                 *buf = fmt[fmt_i];
792                 buf += 1;
793                 len -= 1;
794
795                 switch (fmt[fmt_i]) {
796                 case 'b': /* 1 byte(bool) */
797                         *buf = (char)!!get_arg(regs, i);
798                         buf += 1;
799                         len -= 1;
800                         break;
801                 case 'c': /* 1 byte(char) */
802                         *buf = (char)get_arg(regs, i);
803                         buf += 1;
804                         len -= 1;
805                         break;
806                 case 'f': /* 4 byte(float) */
807                 case 'd': /* 4 byte(int) */
808                         if (len < 4)
809                                 return -ENOMEM;
810                         tmp_u32 = (u32 *)buf;
811                         *tmp_u32 = (u32)get_arg(regs, i);
812                         buf += 4;
813                         len -= 4;
814                         break;
815                 case 'x': /* 8 byte(long) */
816                 case 'p': /* 8 byte(pointer) */
817                         if (len < 8)
818                                 return -ENOMEM;
819                         tmp_u64 = (u64 *)buf;
820                         *tmp_u64 = (u64)get_arg(regs, i);
821                         buf += 8;
822                         len -= 8;
823                         break;
824                 case 'w': /* 8 byte(double) */
825                         if (len < 8)
826                                 return -ENOMEM;
827                         tmp_u64 = (u64 *)buf;
828                         *tmp_u64 = get_arg(regs, i);
829                         ++i;
830                         *tmp_u64 |= (u64)get_arg(regs, i) << 32;
831                         buf += 8;
832                         len -= 8;
833                         break;
834                 case 's': /* string end with '\0' */
835                 {
836                         enum { max_str_len = 512 };
837                         const char __user *user_s;
838                         int len_s, ret;
839
840                         user_s = (const char __user *)get_arg(regs, i);
841                         len_s = strnlen_user(user_s, max_str_len);
842                         if (len < len_s)
843                                 return -ENOMEM;
844
845                         ret = strncpy_from_user(buf, user_s, len_s);
846                         if (ret < 0)
847                                 return -EFAULT;
848
849                         buf[ret] = '\0';
850
851                         buf += ret + 1;
852                         len -= ret + 1;
853                 }
854                         break;
855                 default:
856                         return -EINVAL;
857                 }
858         }
859
860         return buf - buf_old;
861 }
862
863 /**
864  * @brief Packs and writes entry event message.
865  *
866  * @param fmt Arguments format string.
867  * @param func_addr Function address.
868  * @param regs CPU register data.
869  * @param pt Probe type.
870  * @param sub_type Probe sub type.
871  * @return Written data size on success, negative error code on error.
872  */
873 int entry_event(const char *fmt, unsigned long func_addr, struct pt_regs *regs,
874                 enum PROBE_TYPE pt, int sub_type)
875 {
876         char *buf, *payload, *args, *buf_end;
877         int ret;
878
879         buf = get_current_buf();
880         payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_ENTRY);
881         args = pack_msg_func_entry(payload, fmt, func_addr,
882                                    regs, pt, sub_type);
883
884         /* FIXME: len = 1024 */
885         ret = pack_args(args, 1024, fmt, regs);
886         if (ret < 0) {
887                 printk(KERN_INFO "ERROR: !!!!!\n");
888                 goto put_buf;
889         }
890
891         buf_end = args + ret;
892
893         set_len_msg(buf, buf_end);
894
895         ret = write_to_buffer(buf);
896
897 put_buf:
898         put_current_buf();
899
900         return ret;
901 }
902 EXPORT_SYMBOL_GPL(entry_event);
903
904
905
906
907
908 /* ============================================================================
909  * =                                 EXIT                                     =
910  * ============================================================================
911  */
912
913 /**
914  * @struct msg_func_exit
915  * @brief Exit event message info.
916  */
917 struct msg_func_exit {
918         u32 pid;                /**< PID */
919         u32 tid;                /**< TID */
920         u16 probe_type;         /**< Probe type */
921         u16 probe_sub_type;     /**< Probe subtype */
922         u64 pc_addr;            /**< Instruction pointer */
923         u64 caller_pc_addr;     /**< Return address */
924         u32 cpu_num;            /**< CPU number */
925         char ret_val[0];        /**< Return value */
926 } __packed;
927
928 static int pack_msg_ret_val(char *buf, int len, char ret_type,
929                               struct pt_regs *regs)
930 {
931         const char *buf_old = buf;
932         u32 *tmp_u32;
933         u64 *tmp_u64;
934
935         *buf = ret_type;
936         ++buf;
937
938         switch (ret_type) {
939         case 'b': /* 1 byte(bool) */
940                 if (len < 1)
941                         return -ENOMEM;
942                 *buf = (char)!!get_regs_ret_val(regs);
943                 ++buf;
944                 break;
945         case 'c': /* 1 byte(char) */
946                 if (len < 1)
947                         return -ENOMEM;
948                 *buf = (char)get_regs_ret_val(regs);
949                 ++buf;
950                 break;
951         case 'd': /* 4 byte(int) */
952                 if (len < 4)
953                         return -ENOMEM;
954                 tmp_u32 = (u32 *)buf;
955                 *tmp_u32 = get_regs_ret_val(regs);
956                 buf += 4;
957                 break;
958         case 'x': /* 8 byte(long) */
959         case 'p': /* 8 byte(pointer) */
960                 if (len < 8)
961                         return -ENOMEM;
962                 tmp_u64 = (u64 *)buf;
963                 *tmp_u64 = (u64)get_regs_ret_val(regs);
964                 buf += 8;
965                 break;
966         case 's': /* string end with '\0' */
967         {
968                 enum { max_str_len = 512 };
969                 const char __user *user_s;
970                 int len_s, ret;
971
972                 user_s = (const char __user *)get_regs_ret_val(regs);
973                 len_s = strnlen_user(user_s, max_str_len);
974                 if (len < len_s)
975                         return -ENOMEM;
976
977                 ret = strncpy_from_user(buf, user_s, len_s);
978                 if (ret < 0)
979                         return -EFAULT;
980
981                 buf[ret] = '\0';
982                 buf += ret + 1;
983         }
984                 break;
985         case 'n':
986         case 'v':
987                 break;
988         case 'f': /* 4 byte(float) */
989                 if (len < 4)
990                         return -ENOMEM;
991                 tmp_u32 = (u32 *)buf;
992                 *tmp_u32 = swap_get_urp_float(regs);
993                 buf += 4;
994                 break;
995         case 'w': /* 8 byte(double) */
996                 if (len < 8)
997                         return -ENOMEM;
998                 tmp_u64 = (u64 *)buf;
999                 *tmp_u64 = swap_get_urp_double(regs);
1000                 buf += 8;
1001                 break;
1002         default:
1003                 return -EINVAL;
1004         }
1005
1006         return buf - buf_old;
1007 }
1008
1009
1010 static int pack_msg_func_exit(char *buf, int len, char ret_type,
1011                               struct pt_regs *regs, int pt, int sub_type,
1012                               unsigned long func_addr, unsigned long ret_addr)
1013 {
1014         struct msg_func_exit *mfe = (struct msg_func_exit *)buf;
1015         struct task_struct *task = current;
1016         int ret;
1017
1018         mfe->pid = task->tgid;
1019         mfe->tid = task->pid;
1020         mfe->probe_type = pt;
1021         mfe->probe_sub_type = sub_type;
1022         mfe->cpu_num = smp_processor_id();
1023         mfe->pc_addr = func_addr;
1024         mfe->caller_pc_addr = ret_addr;
1025
1026         ret = pack_msg_ret_val(mfe->ret_val, len, ret_type, regs);
1027         if (ret < 0) {
1028                 printk(KERN_INFO "ERROR: packing MSG_FUNCTION_EXIT (ret=%d)\n",
1029                        ret);
1030                 return ret;
1031         }
1032
1033         return sizeof(*mfe) + ret;
1034 }
1035
1036 /**
1037  * @brief Packs and writes exit event.
1038  *
1039  * @param ret_type Return value type.
1040  * @param regs CPU register data.
1041  * @param sub_type Event subtype.
1042  * @param func_addr Function address.
1043  * @param ret_addr Return address.
1044  * @return Written data size on success, negative error code on error.
1045  */
1046 int exit_event(char ret_type, struct pt_regs *regs, int pt, int sub_type,
1047                unsigned long func_addr, unsigned long ret_addr)
1048 {
1049         char *buf, *payload, *buf_end;
1050         int ret;
1051
1052         buf = get_current_buf();
1053         payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_EXIT);
1054         /* FIXME: len=1024 */
1055         ret = pack_msg_func_exit(payload, 1024, ret_type, regs, pt, sub_type,
1056                                  func_addr, ret_addr);
1057         if (ret < 0)
1058                 goto put_buf;
1059
1060         buf_end = payload + ret;
1061         set_len_msg(buf, buf_end);
1062
1063         ret = write_to_buffer(buf);
1064
1065 put_buf:
1066         put_current_buf();
1067
1068         return ret;
1069 }
1070 EXPORT_SYMBOL_GPL(exit_event);
1071
1072
1073
1074
1075
1076 /* ============================================================================
1077  * =                            CONTEXT SWITCH                                =
1078  * ============================================================================
1079  */
1080
1081 /*
1082  * @struct msg_context_switch
1083  * @brief Context switch message info.
1084  */
1085 struct msg_context_switch {
1086         u64 pc_addr;            /**< Instruction pointer */
1087         u32 pid;                /**< PID */
1088         u32 tid;                /**< TID */
1089         u32 cpu_num;            /**< CPU number */
1090 } __packed;
1091
1092 static char *pack_msg_context_switch(char *payload, struct pt_regs *regs)
1093 {
1094         struct msg_context_switch *mcs = (struct msg_context_switch *)payload;
1095         struct task_struct *task = current;
1096
1097         mcs->pc_addr = 0;
1098         mcs->pid = task->tgid;
1099         mcs->tid = task->pid;
1100         mcs->cpu_num = smp_processor_id();
1101
1102         return payload + sizeof(*mcs);
1103 }
1104
1105 static int context_switch(struct pt_regs *regs, enum MSG_ID id)
1106 {
1107         char *buf, *payload, *buf_end;
1108         int ret;
1109
1110         buf = get_current_buf();
1111         payload = pack_basic_msg_fmt(buf, id);
1112         buf_end = pack_msg_context_switch(payload, regs);
1113         set_len_msg(buf, buf_end);
1114
1115         ret = write_to_buffer(buf);
1116         put_current_buf();
1117
1118         return ret;
1119 }
1120
1121 /**
1122  * @brief Packs and writes context switch entry message.
1123  *
1124  * @param regs CPU register data.
1125  * @return Written data size on success, negative error code on error.
1126  */
1127 int switch_entry(struct pt_regs *regs)
1128 {
1129         return context_switch(regs, MSG_CONTEXT_SWITCH_ENTRY);
1130 }
1131 EXPORT_SYMBOL_GPL(switch_entry);
1132
1133 /**
1134  * @brief Packs and writes context switch exit message.
1135  *
1136  * @param regs CPU register data.
1137  * @return Written data size on success, negative error code on error.
1138  */
1139 int switch_exit(struct pt_regs *regs)
1140 {
1141         return context_switch(regs, MSG_CONTEXT_SWITCH_EXIT);
1142 }
1143 EXPORT_SYMBOL_GPL(switch_exit);
1144
1145
1146
1147
1148 /* ============================================================================
1149  * =                                 ERROR                                    =
1150  * ============================================================================
1151  */
1152
1153 /**
1154  * @struct msg_err
1155  * @brief Error message info.
1156  */
1157 struct msg_err {
1158         char msg[0];            /**< Error message string */
1159 } __packed;
1160
1161 static char *pack_msg_err(char *payload, const char *fmt, va_list args)
1162 {
1163         struct msg_err *me = (struct msg_err *)payload;
1164         int ret;
1165
1166         ret = vsprintf(me->msg, fmt, args);
1167         if (ret < 0)
1168                 return payload;
1169
1170         return payload + sizeof(*me) + ret + 1;
1171 }
1172
1173 /**
1174  * @brief Packs and writes error message.
1175  *
1176  * @param fmt Error string format
1177  * @return Written data size on success, negative error code on error.
1178  */
1179 int error_msg(const char *fmt, ...)
1180 {
1181         char *buf, *payload, *buf_end;
1182         va_list args;
1183         int ret;
1184
1185         buf = get_current_buf();
1186         payload = pack_basic_msg_fmt(buf, MSG_ERROR);
1187
1188         va_start(args, fmt);
1189         buf_end = pack_msg_err(payload, fmt, args);
1190         va_end(args);
1191
1192         set_len_msg(buf, buf_end);
1193
1194         ret = write_to_buffer(buf);
1195         put_current_buf();
1196
1197         return ret;
1198 }
1199 EXPORT_SYMBOL_GPL(error_msg);
1200
1201
1202
1203
1204
1205 /* ============================================================================
1206  * =                         MESSAGES FROM USER SPACE                         =
1207  * ============================================================================
1208  */
1209
1210 /**
1211  * @brief Interface for writing messages from user space directly.
1212  *
1213  * @param buf Pointer to message.
1214  * @param len Message len.
1215  * @return len
1216  */
1217 int raw_msg(char *buf, size_t len)
1218 {
1219         struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)buf;
1220
1221         if (sizeof(*bmf) > len)
1222                 return -EINVAL;
1223
1224         if (bmf->len + sizeof(*bmf) != len)
1225                 return -EINVAL;
1226
1227         set_seq_num(bmf);
1228         write_to_buffer(buf);
1229
1230         return len;
1231 }
1232
1233
1234
1235 /* ============================================================================
1236  * =                              CUSTOM EVENT                                =
1237  * ============================================================================
1238  */
1239
1240 static int pack_custom_event(char *buf, int len, const char *fmt, va_list args)
1241 {
1242         enum { max_str_len = 512 };
1243         const char *p;
1244         char *buf_orig = buf;
1245
1246         for (p = fmt; *p != '\0'; p++) {
1247                 char ch = *p;
1248
1249                 if (len < 1)
1250                         return -ENOMEM;
1251
1252                 *buf = tolower(ch);
1253                 buf += 1;
1254                 len -= 1;
1255
1256                 switch (ch) {
1257                 case 'b': /* 1 byte(bool) */
1258                         if (len < 1)
1259                                 return -ENOMEM;
1260                         *buf = !!(char)va_arg(args, int);
1261                         buf += 1;
1262                         len -= 1;
1263                         break;
1264                 case 'c': /* 1 byte(char) */
1265                         if (len < 1)
1266                                 return -ENOMEM;
1267                         *buf = (char)va_arg(args, int);
1268                         buf += 1;
1269                         len -= 1;
1270                         break;
1271                 case 'f': /* 4 byte(float) */
1272                 case 'd': /* 4 byte(int) */
1273                         if (len < 4)
1274                                 return -ENOMEM;
1275                         *(u32 *)buf = va_arg(args, u32);
1276                         buf += 4;
1277                         len -= 4;
1278                         break;
1279                 case 'x': /* 8 byte(long) */
1280                 case 'w': /* 8 byte(double) */
1281                         if (len < 8)
1282                                 return -ENOMEM;
1283                         *(u64 *)buf = va_arg(args, u64);
1284                         buf += 8;
1285                         len -= 8;
1286                         break;
1287                 case 'p': /* 8 byte(pointer) */
1288                         if (len < 8)
1289                                 return -ENOMEM;
1290                         *(u64 *)buf = va_arg(args, unsigned long);
1291                         buf += 8;
1292                         len -= 8;
1293                         break;
1294                 case 's': /* userspace string with '\0' terminating byte */
1295                 {
1296                         const char __user *str;
1297                         int len_s, n;
1298
1299                         str = va_arg(args, const char __user *);
1300                         /* strnlen_user includes '\0' in its return value */
1301                         len_s = strnlen_user(str, max_str_len);
1302                         if (len < len_s)
1303                                 return -ENOMEM;
1304                         /* strncpy_from_user returns the length of the copied
1305                          * string (without '\0') */
1306                         n = strncpy_from_user(buf, str, len_s - 1);
1307                         if (n < 0)
1308                                 return n;
1309                         buf[n] = '\0';
1310
1311                         buf += n + 1;
1312                         len -= n + 1;
1313                         break;
1314                 }
1315                 case 'S': /* kernelspace string with '\0' terminating byte */
1316                 {
1317                         const char *str;
1318                         int len_s;
1319
1320                         str = va_arg(args, const char *);
1321                         len_s = strnlen(str, max_str_len);
1322                         if (len < len_s + 1) /* + '\0' */
1323                                 return -ENOMEM;
1324                         strncpy(buf, str, len_s);
1325                         buf[len_s] = '\0';
1326
1327                         buf += len_s + 1;
1328                         len -= len_s + 1;
1329                         break;
1330                 }
1331                 case 'a': /* userspace byte array (len + ptr) */
1332                 {
1333                         const void __user *ptr;
1334                         u32 len_p, n;
1335
1336                         len_p = va_arg(args, u32);
1337                         if (len < sizeof(len_p) + len_p)
1338                                 return -ENOMEM;
1339                         *(u32 *)buf = len_p;
1340                         buf += sizeof(len_p);
1341                         len -= sizeof(len_p);
1342
1343                         ptr = va_arg(args, const void __user *);
1344                         n = copy_from_user(buf, ptr, len_p);
1345                         if (n < len_p)
1346                                 return -EFAULT;
1347                         buf += len_p;
1348                         len -= len_p;
1349                         break;
1350                 }
1351                 case 'A': /* kernelspace byte array (len + ptr) */
1352                 {
1353                         const void *ptr;
1354                         u32 len_p;
1355
1356                         /* array size */
1357                         len_p = va_arg(args, u32);
1358                         if (len < sizeof(len_p) + len_p)
1359                                 return -ENOMEM;
1360                         *(u32 *)buf = len_p;
1361                         buf += sizeof(len_p);
1362                         len -= sizeof(len_p);
1363
1364                         /* byte array */
1365                         ptr = va_arg(args, const void *);
1366                         memcpy(buf, ptr, len_p);
1367                         buf += len_p;
1368                         len -= len_p;
1369                         break;
1370                 }
1371                 default:
1372                         return -EINVAL;
1373                 }
1374         }
1375
1376         return buf - buf_orig;
1377 }
1378
1379 enum { max_custom_event_size = 2048 };
1380
1381 /**
1382  * @brief Packs and writes custom entry event.
1383  *
1384  * @param func_addr Function address.
1385  * @param regs CPU register data.
1386  * @param type Probe type.
1387  * @param sub_type Probe sub type.
1388  * @param fmt Format string.
1389  * @return Written data size on success, negative error code on error.
1390  */
1391 int custom_entry_event(unsigned long func_addr, struct pt_regs *regs,
1392                        int pt, int sub_type, const char *fmt, ...)
1393 {
1394         char *buf, *payload, *args, *buf_end;
1395         va_list vargs;
1396         int ret;
1397
1398         buf = get_current_buf();
1399         payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_ENTRY);
1400         args = pack_msg_func_entry(payload, fmt, func_addr,
1401                                    regs, pt, sub_type);
1402
1403         va_start(vargs, fmt);
1404         ret = pack_custom_event(args, max_custom_event_size, fmt, vargs);
1405         va_end(vargs);
1406
1407         if (ret < 0)
1408                 goto put_buf;
1409
1410         buf_end = args + ret;
1411         set_len_msg(buf, buf_end);
1412         ret = write_to_buffer(buf);
1413
1414 put_buf:
1415         put_current_buf();
1416
1417         return ret;
1418 }
1419 EXPORT_SYMBOL_GPL(custom_entry_event);
1420
1421 /* TODO currently this function is a simple wrapper. it will be refactored when
1422  * protocol changes are applied */
1423
1424 /**
1425  * @brief Packs and writes custom exit event.
1426  *
1427  * @param func_addr Function address.
1428  * @param ret_addr Return address.
1429  * @param regs CPU register data.
1430  * @param fmt Format string.
1431  * @return Written data size on success, negative error code on error.
1432  */
1433 int custom_exit_event(unsigned long func_addr, unsigned long ret_addr,
1434                       struct pt_regs *regs, int pt, int sub_type,
1435                       const char *fmt, ...)
1436 {
1437         char *buf, *payload, *buf_end;
1438         int ret;
1439
1440         buf = get_current_buf();
1441         payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_EXIT);
1442         ret = pack_msg_func_exit(payload, max_custom_event_size,
1443                                  fmt[0], regs, pt, sub_type,
1444                                  func_addr, ret_addr);
1445         if (ret < 0)
1446                 goto put_buf;
1447
1448         buf_end = payload + ret;
1449         set_len_msg(buf, buf_end);
1450
1451         ret = write_to_buffer(buf);
1452
1453 put_buf:
1454         put_current_buf();
1455
1456         return ret;
1457 }
1458 EXPORT_SYMBOL_GPL(custom_exit_event);
1459
1460 SWAP_LIGHT_INIT_MODULE(NULL, event_filter_init, event_filter_exit,
1461                        init_debugfs_writer, exit_debugfs_writer);
1462
1463 MODULE_LICENSE("GPL");
1464 MODULE_DESCRIPTION("SWAP Writer module");
1465 MODULE_AUTHOR("Cherkashin V., Aksenov A.S.");