buffer_dir=${modules_dir}/buffer
writer_dir=${modules_dir}/writer
-driver_new_dir=${modules_dir}/driver_new
+driver_dir=${modules_dir}/driver
kprobe_dir=${modules_dir}/kprobe
kprobe_arch_dir=${kprobe_dir}/arch
ksyms_dir=${modules_dir}/ksyms
writer_inc=${modules_inc}
make CROSS_COMPILE=${cross_compile} ARCH=${arch} -C ${kernel_dir} M=${writer_dir} modules || exit 1
-driver_new_module_name=swap_driver_new.ko
-make CROSS_COMPILE=${cross_compile} ARCH=${arch} -C ${kernel_dir} M=${driver_new_dir} \
+driver_module_name=swap_driver.ko
+make CROSS_COMPILE=${cross_compile} ARCH=${arch} -C ${kernel_dir} M=${driver_dir} \
extra_cflags="-I${modules_dir}" modules || exit 1
kprobe_module_name=swap_kprobe.ko
us_manager_module_name=swap_us_manager.ko
make CROSS_COMPILE=${cross_compile} ARCH=${arch} -C ${kernel_dir} M=${us_manager_dir} \
- extra_cflags="-I${modules_dir} -I${us_manager_dir} -I${kprobe_dir} -I${kprobe_arch_dir} -I${uprobe_dir} -I${uprobe_arch_dir} -I${driver_dir} -I${common_dir} -I${ksyms_dir}" \
+ extra_cflags="-I${modules_dir} -I${us_manager_dir} -I${kprobe_dir} -I${kprobe_arch_dir} -I${uprobe_dir} -I${uprobe_arch_dir} -I${driver_dir} -I${ksyms_dir}" \
modules || exit 1
ks_features_module_name=swap_ks_features.ko
modules=\
"${buffer_dir}/${buffer_module_name} \
${writer_dir}/${writer_module_name} \
-${driver_new_dir}/${driver_new_module_name} \
+${driver_dir}/${driver_module_name} \
${kprobe_dir}/${kprobe_module_name} \
${ks_manager_dir}/${ks_manager_module_name} \
${uprobe_dir}/${uprobe_module_name} \
EXTRA_CFLAGS := $(extra_cflags)
obj-m := swap_driver.o
-swap_driver-y := error_storage.o device_driver.o ec.o legacy.o module.o probes.o \
- probes_manager.o storage.o us_proc_inst.o \
- ks_def_handler.o
+swap_driver-y := swap_driver_module.o \
+ device_driver.o \
+ driver_to_buffer.o
KERNEL_OBJECTS := swap_driver.o swap_driver.mod.c swap_driver.mod.o swap_driver_module.o device_driver.o driver_to_buffer.o
-MODULE_NAME=driver_new
+MODULE_NAME=driver
all:
make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNEL) SUBDIRS=$(TOP)/$(MODULE_NAME) extra_cflags=-I$(TOP) modules
-if MEMCHECKER
-memchecker = -DMEMORY_CHECKER
-endif
-
-if DEBUG
-debug_opt = -D__DEBUG
-endif
-
-if SPARSE
-sparse_output = C=2
-endif
-
-dev_path = @TARGET_DEVICE_PATH@
-
board_opt = -DBOARD_@BOARD@
-
target_kernel_src = @KERNEL@
target_arch = @ARCH@
-driver_module_dir = $(realpath $(srcdir))
+module_dir = $(realpath $(top_srcdir)/src/modules/driver)
module_name = swap_driver
cross_compiler = $(subst gcc,,$(CC))
-inlude_opt = -I$(realpath $(top_srcdir)/src/modules/ksyms) \
- -I$(realpath $(top_srcdir)/src/modules/driver) \
- -I$(realpath $(top_srcdir)/src/common) \
- -I$(realpath $(top_srcdir)/src/profile) \
- -I$(realpath $(top_srcdir)/src/modules/ks_manager) \
- -I$(realpath $(top_srcdir)/src/modules/kprobe) \
- -I$(realpath $(top_srcdir)/src/modules/kprobe/arch) \
- -I$(realpath $(top_srcdir)/src/modules/uprobe) \
- -I$(realpath $(top_srcdir)/src/modules/us_manager)
-extra_cflags = "$(inlude_opt) -DEC_ARCH_$(ARCH) -D__DEBUG $(memchecker) $(debug_opt) $(android_opt) $(slp_opt) $(android_app_opt) $(board_opt)"
-
-#bin_SCRIPTS = patchko.sh insmod.sh
+inlude_opt = -I$(realpath $(top_srcdir)/src/modules/)
+extra_cflags = "$(inlude_opt) $(board_opt)"
all-local:
- cp $(top_srcdir)/src/modules/kprobe/Module.symvers $(driver_module_dir)
- $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) extra_cflags=$(extra_cflags) $(AM_MAKEFLAGS) -C $(target_kernel_src) $(sparse_output) M=$(driver_module_dir) modules
+ $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) extra_cflags=$(extra_cflags) \
+ $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(module_dir) modules
echo "generate data for version patching <$(OBJDUMP)><$(READELF)>"
- $(top_srcdir)/src/modules/driver/patchko.sh -g $(driver_module_dir)/$(module_name).ko $(OBJDUMP) $(READELF)
+ PATH=$(PATH) $(top_srcdir)/src/modules/driver/patchko.sh -g $(module_dir)/$(module_name).ko $(OBJDUMP) $(READELF)
clean-local:
- $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(driver_module_dir) clean
+ $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(module_dir) clean
install-exec-local:
-
- install -m 644 $(driver_module_dir)/$(module_name).ko $(prefix)
- install -m 644 $(driver_module_dir)/$(module_name).ko.addr $(prefix)
- mkdir -p $(prefix)/bin/
- install -m 755 $(driver_module_dir)/patchko.sh $(prefix)/bin/
- install -m 755 $(driver_module_dir)/insmod.sh $(prefix)/bin/
-
- sed "s|__DEV_NAME__|`basename $(dev_path)`|" $(driver_module_dir)/$(module_name).sh | \
- sed "s|__DEV_DIR__|`dirname $(dev_path)`|" > \
- $(prefix)/$(module_name).sh ; chmod +x $(prefix)/$(module_name).sh ; \
- chmod +x $(driver_module_dir)/patchko.sh ; \
- chmod +x $(driver_module_dir)/insmod.sh ;
+ install -m 644 $(module_dir)/$(module_name).ko $(prefix)
+ install -m 644 $(module_dir)/$(module_name).ko.addr $(prefix)
+ install -m 755 $(module_dir)/$(module_name).sh $(prefix)
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: debug.h
-//
-// DESCRIPTION:
-// Debug functions for application
-//
-// SEE ALSO: N/A
-// AUTHOR: L.Komkov
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.02.15
-// VERSION: 1.0
-// REVISION DATE: 2008.12.02
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-#if !defined(__DEBUG_H__)
-#define __DEBUG_H__
-
-#include <linux/kernel.h>
-#include <linux/string.h> // strrchr
-
-#undef __DEBUG
-
-#ifdef __DEBUG
-#define DPRINTF(format, args...) do { \
- char *f = __FILE__; \
- char *n = strrchr(f, '/'); \
- printk("DRIVER[%s:%u:%s] DEBUG: " format "\n" , (n) ? n+1 : f, __LINE__, __FUNCTION__, ##args); \
- } while(0)
-#else
-#define DPRINTF(format, args...)
-#endif
-
-#define EPRINTF(format, args...) do { \
- char *f = __FILE__; \
- char *n = strrchr(f, '/'); \
- printk("DRIVER[%s:%u:%s] ERROR: " format "\n" , (n) ? n+1 : f, __LINE__, __FUNCTION__, ##args); \
- } while(0)
-
-
-#endif /* !defined(__DEBUG_H__) */
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: device_driver.c
-//
-// DESCRIPTION:
-// This file is C source for SWAP driver.
-//
-// SEE ALSO: device_driver.h
-// AUTHOR: L.Komkov, S.Dianov, S.Grekhov, A.Gerenkov
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.02.15
-// VERSION: 1.0
-// REVISION DATE: 2008.12.03
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-#include "module.h"
-#include "device_driver.h" // device driver
-#include "handlers_core.h"
-#include <linux/notifier.h>
-#include <sspt/sspt_proc.h>
-
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
-static BLOCKING_NOTIFIER_HEAD(swap_notifier_list);
-#endif
-pid_t gl_nNotifyTgid;
-EXPORT_SYMBOL_GPL(gl_nNotifyTgid);
+/*
+ * SWAP device driver
+ * modules/driver/device_driver.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Samsung Electronics, 2013
+ *
+ * 2013 Alexander Aksenov <a.aksenov@samsung.com>: SWAP device driver implement
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/ioctl.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/splice.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/wait.h>
+#include <asm/uaccess.h>
+
+#include <ksyms/ksyms.h>
+
+#include "device_driver.h"
+#include "swap_driver_errors.h"
+#include "driver_to_buffer.h"
+#include "swap_ioctl.h"
+#include "driver_defs.h"
+#include "device_driver_to_driver_to_buffer.h"
+#include "driver_to_buffer.h"
+#include "driver_to_msg.h"
+
+#define SWAP_DEVICE_NAME "swap_device"
+
+/* swap_device driver routines */
+static int swap_device_open(struct inode *inode, struct file *filp);
+static int swap_device_release(struct inode *inode, struct file *file);
+static ssize_t swap_device_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos);
+static ssize_t swap_device_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *f_pos);
+static long swap_device_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg);
+static ssize_t swap_device_splice_read(struct file *filp, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t len,
+ unsigned int flags);
+
+/* File operations structure */
+const struct file_operations swap_device_fops = {
+ .read = swap_device_read,
+ .write = swap_device_write,
+ .open = swap_device_open,
+ .release = swap_device_release,
+ .unlocked_ioctl = swap_device_ioctl,
+ .splice_read = swap_device_splice_read,
+};
-static DECLARE_WAIT_QUEUE_HEAD (notification_waiters_queue);
-static volatile unsigned notification_count;
+/* Typedefs for splice_* funcs. Prototypes are for linux-3.8.6 */
+typedef ssize_t(*splice_to_pipe_p_t)(struct pipe_inode_info *pipe,
+ struct splice_pipe_desc *spd);
+typedef int(*splice_grow_spd_p_t)(const struct pipe_inode_info *pipe,
+ struct splice_pipe_desc *spd);
-static int device_mmap (struct file *filp, struct vm_area_struct *vma);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
-static int device_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
-#else
-static long device_ioctl (struct file *file, unsigned int cmd, unsigned long arg);
-#endif
-static int device_open(struct inode *, struct file *);
-static int device_release(struct inode *, struct file *);
-static ssize_t device_read(struct file *, char __user *, size_t, loff_t *);
-static ssize_t device_write(struct file *, const char __user *, size_t, loff_t *);
-
-static int gl_nDeviceOpened = 0;
-static struct file_operations device_fops = {
- .owner = THIS_MODULE,
- .mmap = device_mmap,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
- .ioctl = device_ioctl,
-#else
- .unlocked_ioctl = device_ioctl,
-#endif
- .read = device_read,
- .write = device_write,
- .open = device_open,
- .release = device_release
-};
+static splice_to_pipe_p_t splice_to_pipe_p = NULL;
+static splice_grow_spd_p_t splice_grow_spd_p = NULL;
-typedef void (* dbi_module_callback)(void);
+static msg_handler_t msg_handler = NULL;
-int device_init (void)
-{
- int nReserved = 0;
- nReserved = register_chrdev(0, device_name, &device_fops);
- if(nReserved < 0)
- {
- unregister_chrdev(nReserved, device_name);
- EPRINTF("Cannot register character device!");
- return -1;
- }
- EPRINTF("New device node with major number [%d], was created\n", nReserved);
- device_major = nReserved;
- return 0;
-}
+/* Device numbers */
+static dev_t swap_device_no = 0;
-void device_down (void)
-{
- unregister_chrdev(device_major, device_name);
-}
+/* Device cdev struct */
+static struct cdev *swap_device_cdev = NULL;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
-void swap_register_notify (struct notifier_block *nb)
-{
- blocking_notifier_chain_register(&swap_notifier_list, nb);
-}
-EXPORT_SYMBOL_GPL(swap_register_notify);
+/* Device class struct */
+static struct class *swap_device_class = NULL;
-void swap_unregister_notify (struct notifier_block *nb)
+/* Device device struct */
+static struct device *swap_device_device = NULL;
+
+/* Reading tasks queue */
+static DECLARE_WAIT_QUEUE_HEAD(swap_device_wait);
+
+/* We need this realization of splice_shrink_spd() because of the its desing
+ * frequent changes that I have encountered in custom kernels */
+void swap_device_splice_shrink_spd(struct pipe_inode_info *pipe,
+ struct splice_pipe_desc *spd)
{
- blocking_notifier_chain_unregister(&swap_notifier_list, nb);
+ if (pipe->buffers <= PIPE_DEF_BUFFERS)
+ return;
+
+ kfree(spd->pages);
+ kfree(spd->partial);
}
-EXPORT_SYMBOL_GPL(swap_unregister_notify);
-#endif
-void notify_user (event_id_t event_id)
+
+/* Register device TODO Think of permanent major */
+int swap_device_init(void)
{
- ec_info.events_counters[event_id] += 1;
+ int result;
+
+ /* Allocating device major and minor nums for swap_device */
+ result = alloc_chrdev_region(&swap_device_no, 0, 1, SWAP_DEVICE_NAME);
+ if (result < 0) {
+ print_crit("Major number allocation has failed\n");
+ result = -E_SD_ALLOC_CHRDEV_FAIL;
+ goto init_fail;
+ }
- if (EVENT_EC_PROBE_RECORD == event_id)
- {
- // EC_PROBE_RECORD events happen to often. To reduce overhead user
- // space will be notified only once per each EVENTS_AGGREGATION_USEC
- static uint64_t timestamp_usec = 0;
+ /* Creating device class. Using IS_ERR, because class_create returns ERR_PTR
+ * on error. */
+ swap_device_class = class_create(THIS_MODULE, SWAP_DEVICE_NAME);
+ if (IS_ERR(swap_device_class)) {
+ print_crit("Class creation has failed\n");
+ result = -E_SD_CLASS_CREATE_FAIL;
+ goto init_fail;
+ }
- uint64_t current_usec;
- uint64_t delta_usec;
+ /* Cdev allocation */
+ swap_device_cdev = cdev_alloc();
+ if (!swap_device_cdev) {
+ print_crit("Cdev structure allocation has failed\n");
+ result = -E_SD_CDEV_ALLOC_FAIL;
+ goto init_fail;
+ }
- struct timeval tv;
+ /* Cdev intialization and setting file operations */
+ cdev_init(swap_device_cdev, &swap_device_fops);
- do_gettimeofday (&tv);
- current_usec = 1000000ULL * (unsigned) tv.tv_sec + (unsigned) tv.tv_usec;
+ /* Adding cdev to system */
+ result = cdev_add(swap_device_cdev, swap_device_no, 1);
+ if (result < 0) {
+ print_crit("Device adding has failed\n");
+ result = -E_SD_CDEV_ADD_FAIL;
+ goto init_fail;
+ }
- if (current_usec < timestamp_usec)
- {
- // Note: time from do_gettimeofday() may go backward
- EPRINTF ("current_usec=%llu timestamp_usec=%llu", current_usec, timestamp_usec);
- }
- else
- {
- delta_usec = current_usec - timestamp_usec;
- if (EVENTS_AGGREGATION_USEC > delta_usec)
- {
- // wait the time left
-#if defined(__DEBUG)
- unsigned UNUSED left_usec = EVENTS_AGGREGATION_USEC - delta_usec;
-#endif /* defined(__DEBUG) */
- return; // supress notification
- }
- }
- timestamp_usec = current_usec; // remember new time for the future use
- } else if (EVENT_EC_START_CONDITION_SEEN == event_id) {
- return; // supress notification
- } else if (EVENT_EC_STOP_CONDITION_SEEN == event_id) {
- return; // supress notification
+ /* Create device struct */
+ swap_device_device = device_create(swap_device_class, NULL, swap_device_no,
+ "%s", SWAP_DEVICE_NAME);
+ if (IS_ERR(swap_device_device)) {
+ print_crit("Device struct creating has failed\n");
+ result = -E_SD_DEVICE_CREATE_FAIL;
+ goto init_fail;
}
- ++notification_count;
- wake_up_interruptible (¬ification_waiters_queue);
-}
+ /* Find splice_* funcs addresses */
+ splice_to_pipe_p = (splice_to_pipe_p_t)swap_ksyms("splice_to_pipe");
+ if (!splice_to_pipe_p) {
+ print_err("splice_to_pipe() not found!\n");
+ result = -E_SD_NO_SPLICE_FUNCS;
+ goto init_fail;
+ }
-static int device_mmap (struct file *filp UNUSED, struct vm_area_struct *vma)
-{
- if(!p_buffer) {
- EPRINTF("Null pointer to buffer!");
- return -1;
+ splice_grow_spd_p = (splice_grow_spd_p_t)swap_ksyms("splice_grow_spd");
+ if (!splice_grow_spd_p) {
+ print_err("splice_grow_spd() not found!\n");
+ result = -E_SD_NO_SPLICE_FUNCS;
+ goto init_fail;
}
- return remap_vmalloc_range (vma, p_buffer, 0);
-}
-static int device_open(struct inode *inode, struct file *file)
-{
- /*if (gl_nDeviceOpened)
- return -EBUSY;*/
- gl_nDeviceOpened++;
- // TODO
- try_module_get(THIS_MODULE);
return 0;
+
+init_fail:
+ if (swap_device_cdev) {
+ cdev_del(swap_device_cdev);
+ }
+ if (swap_device_class) {
+ class_destroy(swap_device_class);
+ }
+ if (swap_device_no) {
+ unregister_chrdev_region(swap_device_no, 1);
+ }
+ return result;
}
-static int device_release(struct inode *inode, struct file *file)
+/* Unregister device TODO Check wether driver is registered */
+void swap_device_exit(void)
{
- gl_nDeviceOpened--;
- module_put(THIS_MODULE);
+ splice_to_pipe_p = NULL;
+ splice_grow_spd_p = NULL;
- return 0;
+ device_destroy(swap_device_class, swap_device_no);
+ cdev_del(swap_device_cdev);
+ class_destroy(swap_device_class);
+ unregister_chrdev_region(swap_device_no, 1);
}
-static ssize_t device_read(struct file *filp, char __user *buffer, size_t length, loff_t * offset)
+static int swap_device_open(struct inode *inode, struct file *filp)
{
- EPRINTF("Operation <<read>> not supported!");
- return -1;
+ // TODO MOD_INC_USE_COUNT
+ return 0;
}
-static ssize_t device_write(struct file *filp, const char __user *buff, size_t len, loff_t * off)
+static int swap_device_release(struct inode *inode, struct file *filp)
{
- EPRINTF("Operation <<write>> not supported!");
- return -1;
+ // TODO MOD_DEC_USE_COUNT
+ return 0;
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
-static int device_ioctl (struct inode *inode UNUSED, struct file *file UNUSED, unsigned int cmd, unsigned long arg)
-#else
-static long device_ioctl (struct file *file UNUSED, unsigned int cmd, unsigned long arg)
-#endif
+static ssize_t swap_device_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
{
- unsigned long spinlock_flags = 0L;
- int result = -1;
- void __user * arg_pointer = (void __user *) arg;
-// DPRINTF("Command=%d", cmd);
- switch (cmd)
- {
- case EC_IOCTL_SET_EC_MODE:
- {
- ioctl_general_t param;
- unsigned long nIgnoredBytes = 0;
- memset(¶m, '0', sizeof(ioctl_general_t));
- nIgnoredBytes = copy_from_user (¶m, arg_pointer, sizeof(ioctl_general_t));
- if (nIgnoredBytes > 0) {
- result = -1;
- break;
- }
- if(SetECMode(param.m_unsignedLong) == -1) {
- result = -1;
- break;
- }
- result = 0;
- DPRINTF("Set EC Mode = %lu", param.m_unsignedLong);
- break;
- }
- case EC_IOCTL_GET_EC_MODE:
- {
- ioctl_general_t param;
- unsigned long nIgnoredBytes = 0;
- memset(¶m, '0', sizeof(ioctl_general_t));
- param.m_unsignedLong = GetECMode();
- nIgnoredBytes = copy_to_user (arg_pointer, ¶m, sizeof (ioctl_general_t));
- if (nIgnoredBytes > 0) {
- result = -1;
- break;
- }
- result = 0;
-// DPRINTF("Get EC Mode = %lu", param.m_unsignedLong); // Frequent call
- break;
- }
- case EC_IOCTL_SET_BUFFER_SIZE:
- {
- ioctl_general_t param;
- unsigned long nIgnoredBytes = 0;
- memset(¶m, '0', sizeof(ioctl_general_t));
- nIgnoredBytes = copy_from_user (¶m, arg_pointer, sizeof(ioctl_general_t));
- if (nIgnoredBytes > 0) {
- result = -1;
- break;
- }
- if (SetBufferSize(param.m_unsignedLong) == -1) {
- result = -1;
- break;
- }
- result = 0;
- DPRINTF("Set Buffer Size = %lu", param.m_unsignedLong);
- break;
- }
- case EC_IOCTL_GET_BUFFER_SIZE:
- {
- ioctl_general_t param;
- unsigned long nIgnoredBytes = 0;
- memset(¶m, '0', sizeof(ioctl_general_t));
- param.m_unsignedLong = GetBufferSize();
- nIgnoredBytes = copy_to_user (arg_pointer, ¶m, sizeof (ioctl_general_t));
- if (nIgnoredBytes > 0) {
- result = -1;
- break;
- }
- result = 0;
- DPRINTF("Get Buffer Size = %lu", param.m_unsignedLong);
- break;
- }
- case EC_IOCTL_RESET_BUFFER:
- {
- if (ResetBuffer() == -1) {
- result = -1;
- break;
- }
- result = 0;
- DPRINTF("Reset Buffer");
- break;
- }
- case EC_IOCTL_GET_EC_INFO:
- {
- if (copy_ec_info_to_user_space ((ec_info_t *) arg) != 0) {
- result = -1;
- break;
- }
- result = 0;
-// DPRINTF("Get Buffer Status"); // Frequent call
- break;
- }
- case EC_IOCTL_CONSUME_BUFFER:
- {
- static ec_info_t ec_info_copy;
- int nIgnoredBytes = 0;
-
- nIgnoredBytes = copy_from_user (&ec_info_copy, (const void __user *) arg, sizeof (ec_info_t));
- if(nIgnoredBytes > 0)
- {
- EPRINTF ("copy_from_user(%08X,%08X)=%d", (unsigned) arg, (unsigned) &ec_info_copy, nIgnoredBytes);
- result = -1;
- break;
- }
+ /* Wait queue item that consists current task. It is used to be added in
+ * swap_device_wait queue if there is no data to be read. */
+ DEFINE_WAIT(wait);
+ int result;
- spin_lock_irqsave (&ec_spinlock, spinlock_flags);
+ //TODO : Think about spin_locks to prevent reading race condition.
+ while((result = driver_to_buffer_next_buffer_to_read()) != E_SD_SUCCESS) {
- // Original buffer
- if(ec_info.after_last > ec_info.first) {
- ec_info.buffer_effect = ec_info.buffer_size;
- }
- if (ec_info.after_last == ec_info.buffer_effect) {
- ec_info.first = 0;
- } else {
- ec_info.first = ec_info_copy.after_last;
- }
- ec_info.trace_size = ec_info.trace_size - ec_info_copy.trace_size;
+ /* Add process to the swap_device_wait queue and set the current task
+ * state TASK_INTERRUPTIBLE. If there is any data to be read, then the
+ * current task is removed from the swap_device_wait queue and its state
+ * is changed to this. */
+ prepare_to_wait(&swap_device_wait, &wait, TASK_INTERRUPTIBLE);
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags);
+ if (result < 0) {
result = 0;
-// DPRINTF("Consume Buffer"); // Frequent call
- break;
+ goto swap_device_read_error;
+ } else if (result == E_SD_NO_DATA_TO_READ) {
+ /* Yes, E_SD_NO_DATA_TO_READ should be positive, cause it's not
+ * really an error */
+ if (filp->f_flags & O_NONBLOCK) {
+ result = -EAGAIN;
+ goto swap_device_read_error;
+ }
+ if (signal_pending(current)) {
+ result = -ERESTARTSYS;
+ goto swap_device_read_error;
+ }
+ schedule();
+ finish_wait(&swap_device_wait, &wait);
}
- case EC_IOCTL_ADD_PROBE:
- {
- unsigned long addr = arg;
- unsigned long pre_handler = 0, jp_handler = 0, rp_handler = 0;
+ }
- dbi_find_and_set_handler_for_probe(addr, &pre_handler, &jp_handler, &rp_handler);
- result = add_probe(addr, pre_handler, jp_handler, rp_handler);
+ result = driver_to_buffer_read(buf, count);
+ /* If there is an error - return 0 */
+ if (result < 0)
+ result = 0;
- break;
- }
- //@AGv: remove_probe expects probe address instead of name
- /*case EC_IOCTL_REMOVE_PROBE:
- {
- char *probe_name = (char *) arg;
- result = remove_probe (probe_name);
- break;
- }*/
- case EC_IOCTL_SET_APPDEPS:
- {
- size_t size;
- result = copy_from_user(&size, arg_pointer, sizeof(size_t));
- if (result) {
- EPRINTF("Cannot copy deps size!");
- result = -1;
- break;
- }
- DPRINTF("Deps size has been copied (%d)", size);
+ return result;
- if (size == 0) {
- DPRINTF("Deps are size of 0");
- break;
- }
+swap_device_read_error:
+ finish_wait(&swap_device_wait, &wait);
- deps = vmalloc(size);
- if (deps == NULL) {
- EPRINTF("Cannot alloc mem for deps!");
- result = -1;
- break;
- }
- DPRINTF("Mem for deps has been allocated");
+ return result;
+}
- result = copy_from_user(deps, arg_pointer, size);
- if (result) {
- EPRINTF("Cannot copy deps!");
- result = -1;
- break;
- }
- DPRINTF("Deps has been copied successfully");
+static ssize_t swap_device_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ char *kern_buffer = NULL;
+ ssize_t result = 0;
- break;
+ kern_buffer = kmalloc(count, GFP_KERNEL);
+ if (!kern_buffer) {
+ print_err("Error allocating memory for buffer\n");
+ goto swap_device_write_out;
}
- case EC_IOCTL_SET_PID:
- {
- unsigned int _pid;
-
- result = copy_from_user(&_pid, arg_pointer, sizeof(unsigned int));
- if (result) {
- EPRINTF("Cannot copy pid!");
- result = -1;
- break;
- }
- inst_pid = _pid;
+ result = copy_from_user(kern_buffer, buf, count);
- DPRINTF("EC_IOCTL_SET_PID pid:%d", inst_pid);
+ result = count - result;
- break;
- }
- case EC_IOCTL_SET_PROFILEBUNDLE:
- {
- size_t size;
-
- result = copy_from_user(&size, arg_pointer, sizeof(size_t));
- if (result) {
- EPRINTF("Cannot copy bundle size!");
- result = -1;
- break;
- }
- DPRINTF("Bundle size has been copied");
+ /* Return 0 if there was an error while writing */
+ result = driver_to_buffer_write(result, kern_buffer);
+ if (result < 0)
+ result = 0;
- bundle = vmalloc(size);
- if (bundle == NULL) {
- EPRINTF("Cannot alloc mem for bundle!");
- result = -1;
- break;
- }
- DPRINTF("Mem for bundle has been alloced");
+ kfree(kern_buffer);
- result = copy_from_user(bundle, arg_pointer, size);
- if (result) {
- EPRINTF("Cannot copy bundle!");
- result = -1;
- break;
- }
- DPRINTF("Bundle has been copied successfully");
+swap_device_write_out:
+ return result;
+}
- if (link_bundle() == -1 || has_last_error() == -1) {
- EPRINTF("Cannot link profile bundle!");
- result = -1;
- break;
- }
+static long swap_device_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ int result;
- break;
- }
- case EC_IOCTL_RESET_PROBES:
+ switch(cmd) {
+ case SWAP_DRIVER_BUFFER_INITIALIZE:
{
- result = reset_probes();
+ struct buffer_initialize initialize_struct;
- break;
- }
- case EC_IOCTL_UPDATE_CONDS:
- {
- int args_cnt, i;
- struct cond *c, *c_tmp, *p_cond;
- unsigned char *p_data;
- int err;
- result = 0;
- err = copy_from_user(&args_cnt, arg_pointer, sizeof(int));
- if (err) {
- result = -1;
+ result = copy_from_user(&initialize_struct, (void*)arg,
+ sizeof(struct buffer_initialize));
+ if (result) {
break;
}
- /* first, delete all the conds */
- list_for_each_entry_safe(c, c_tmp, &cond_list.list, list) {
- list_del(&c->list);
- kfree(c);
- }
- /* second, add new conds */
- p_data = (unsigned char *)(arg + sizeof(int));
- for (i = 0; i < args_cnt; i++) {
- p_cond = kmalloc(sizeof(struct cond), GFP_KERNEL);
- if (!p_cond) {
- DPRINTF("Cannot alloc cond!");
- result = -1;
- break;
- }
- err = copy_from_user(&p_cond->tmpl, (const void __user *)p_data,
- sizeof(struct event_tmpl));
- if (err) {
- DPRINTF("Cannot copy cond from user!");
- result = -1;
- break;
- }
- p_cond->applied = 0;
- list_add(&(p_cond->list), &(cond_list.list));
- p_data += sizeof(struct event_tmpl);
+
+ result = driver_to_buffer_initialize(initialize_struct.size,
+ initialize_struct.count);
+ if (result < 0) {
+ print_err("Buffer initialization failed %d\n", result);
+ break;
}
+ result = E_SD_SUCCESS;
+
break;
}
- case EC_IOCTL_ATTACH:
+ case SWAP_DRIVER_BUFFER_UNINITIALIZE:
{
- unsigned long dbi_flags;
- struct dbi_modules_handlers *local_mh;
- struct dbi_modules_handlers_info *local_mhi;
- int j;
- dbi_module_callback dmc_start;
-
- // call "start"-callback for all modules according module priority
- local_mh = get_dbi_modules_handlers();
- spin_lock_irqsave(&local_mh->lock, dbi_flags);
- for (j = 0; j <= MAX_PRIORITY; j++) {
- list_for_each_entry_rcu(local_mhi, &local_mh->modules_handlers, dbi_list_head) {
- if (local_mhi->dbi_module_priority_start == j) {
- if (local_mhi->dbi_module_callback_start != NULL) {
- printk("Started module callback (start) %s\n", local_mhi->dbi_module->name);
- dmc_start = (dbi_module_callback )local_mhi->dbi_module_callback_start;
- dmc_start();
- }
- }
- }
- }
- spin_unlock_irqrestore(&local_mh->lock, dbi_flags);
+ result = driver_to_buffer_uninitialize();
+ if (result < 0)
+ print_err("Buffer uninitialization failed %d\n", result);
- result = ec_user_attach ();
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
- DPRINTF("EC_IOCTL_ATTACH calling notification chain");
- blocking_notifier_call_chain(&swap_notifier_list, EC_IOCTL_ATTACH, (void*)NULL);
-#endif
- DPRINTF("Attach Probes");
break;
}
- case EC_IOCTL_ACTIVATE:
- result = ec_user_activate ();
- DPRINTF("Activate Probes");
- break;
- case EC_IOCTL_STOP_AND_DETACH:
- {
- unsigned long nIgnoredBytes = 0;
- unsigned long dbi_flags;
- struct dbi_modules_handlers *local_mh;
- struct dbi_modules_handlers_info *local_mhi;
- unsigned int local_module_refcount = 0;
- int j;
- dbi_module_callback dmc_stop;
-
- local_mh = get_dbi_modules_handlers();
- if(ec_user_stop() != 0) {
- result = -1;
- goto sad_cleanup;
- }
- nIgnoredBytes = copy_ec_info_to_user_space ((ec_info_t*)arg);
- if(nIgnoredBytes > 0) {
- result = -1;
- goto sad_cleanup;
- }
-
- vfree(bundle);
- result = 0;
- DPRINTF("Stop and Detach Probes");
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
- DPRINTF("EC_IOCTL_STOP_AND_DETACH calling notification chain");
- blocking_notifier_call_chain(&swap_notifier_list, EC_IOCTL_STOP_AND_DETACH, (void*)&gl_nNotifyTgid);
-#endif
- // call "stop"-callback for all modules according module priority
- spin_lock_irqsave(&local_mh->lock, dbi_flags);
- for (j = 0; j <= MAX_PRIORITY; j++) {
- list_for_each_entry_rcu(local_mhi, &local_mh->modules_handlers, dbi_list_head) {
- if (local_mhi->dbi_module_priority_stop == j) {
- if (local_mhi->dbi_module_callback_stop != NULL) {
- printk("Started module callback (stop) %s\n", local_mhi->dbi_module->name);
- dmc_stop = (dbi_module_callback )local_mhi->dbi_module_callback_stop;
- dmc_stop();
- }
- }
- }
- }
- spin_unlock_irqrestore(&local_mh->lock, dbi_flags);
-sad_cleanup:
- spin_lock_irqsave(&local_mh->lock, dbi_flags);
- list_for_each_entry_rcu(local_mhi, &local_mh->modules_handlers, dbi_list_head) {
- local_module_refcount = module_refcount(local_mhi->dbi_module);
- if (local_module_refcount == 1) {
- module_put(local_mhi->dbi_module);
- }
- else if (local_module_refcount > 1) {
- printk("local_module_refcount too much - force set refcount to zero\n");
- while (local_module_refcount--)
- module_put(local_mhi->dbi_module);
- }
- }
- spin_unlock_irqrestore(&local_mh->lock, dbi_flags);
- break;
- }
- case EC_IOCTL_US_EVENT:
+ case SWAP_DRIVER_NEXT_BUFFER_TO_READ:
{
- ioctl_us_event_t ioctl_args;
- result = copy_from_user (&ioctl_args, (const void __user *) arg, sizeof (ioctl_args));
- if (result)
- {
- result = -1;
- EPRINTF ("copy_from_user() failure");
- }
- else
- {
- if(ioctl_args.len == 0){
- result = -EINVAL;
- EPRINTF ("invalid event length!");
- }
- else {
- char *buf = kmalloc(ioctl_args.len, GFP_KERNEL);
- if(!buf){
- result = -ENOMEM;
- EPRINTF ("failed to alloc mem for event!");
- }
- else {
- result = copy_from_user (buf, (const void __user *) ioctl_args.data, ioctl_args.len);
- if (result){
- result = -1;
- EPRINTF ("failed to copy event from user space!");
- }
- else
- result = put_us_event(buf, ioctl_args.len);
- kfree(buf);
- }
- }
+ /* Use this carefully */
+ result = driver_to_buffer_next_buffer_to_read();
+ if (result == E_SD_NO_DATA_TO_READ) {
+ /* TODO Do what we usually do when there are no subbuffers to
+ * read (make daemon sleep ?) */
}
-// DPRINTF("User Space Event"); // Frequent call
break;
}
-
- case EC_IOCTL_SET_EVENT_MASK:
+ case SWAP_DRIVER_FLUSH_BUFFER:
{
- int mask;
- result = copy_from_user (&mask, arg_pointer, sizeof (mask));
- if (result)
- {
- result = -EFAULT;
- break;
- }
-
- result = set_event_mask (mask);
- if (result)
- {
- break;
- }
- DPRINTF("Set Event Mask = %d", mask);
+ result = driver_to_buffer_flush();
break;
}
-
- case EC_IOCTL_GET_EVENT_MASK:
- {
- int mask = 0;
- result = get_event_mask(&mask);
- if (result)
- {
- result = -EFAULT;
- }
- result = copy_to_user (arg_pointer, &mask, sizeof (mask));
- if (result)
- {
- result = -EFAULT;
+ case SWAP_DRIVER_MSG:
+ if (msg_handler) {
+ result = msg_handler((void __user *)arg);
+ } else {
+ print_warn("msg_handler() is not register\n");
+ result = -EINVAL;
}
- DPRINTF("Get Event Mask = %d", mask);
break;
- }
-
- case EC_IOCTL_GET_PREDEF_UPROBES:
- {
- result = get_predef_uprobes((ioctl_predef_uprobes_info_t *)arg);
- if (result)
- {
- result = -EFAULT;
- }
- DPRINTF("Get Predefined User Space Probes");
+ default:
+ print_warn("Unknown command %d\n", cmd);
+ result = -EINVAL;
break;
- }
- case EC_IOCTL_GET_PREDEF_UPROBES_SIZE:
- {
- int size = 0;
- result = get_predef_uprobes_size(&size);
- if (result)
- {
- result = -EFAULT;
+ }
+ return result;
+}
+
+static void swap_device_pipe_buf_release(struct pipe_inode_info *inode,
+ struct pipe_buffer *pipe)
+{
+ __free_page(pipe->page);
+}
+
+static void swap_device_page_release(struct splice_pipe_desc *spd,
+ unsigned int i)
+{
+ __free_page(spd->pages[i]);
+}
+
+static const struct pipe_buf_operations swap_device_pipe_buf_ops = {
+ .can_merge = 0,
+ .map = generic_pipe_buf_map,
+ .unmap = generic_pipe_buf_unmap,
+ .confirm = generic_pipe_buf_confirm,
+ .release = swap_device_pipe_buf_release,
+ .steal = generic_pipe_buf_steal,
+ .get = generic_pipe_buf_get
+};
+
+static ssize_t swap_device_splice_read(struct file *filp, loff_t *ppos,
+ struct pipe_inode_info *pipe,
+ size_t len, unsigned int flags)
+{
+ /* Wait queue item that consists current task. It is used to be added in
+ * swap_device_wait queue if there is no data to be read. */
+ DEFINE_WAIT(wait);
+
+ int result;
+ struct page *pages[PIPE_DEF_BUFFERS];
+ struct partial_page partial[PIPE_DEF_BUFFERS];
+ struct splice_pipe_desc spd = {
+ .pages = pages,
+ .partial = partial,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 5))
+ .nr_pages_max = PIPE_DEF_BUFFERS,
+#endif
+ .nr_pages = 0,
+ .flags = flags,
+ .ops = &swap_device_pipe_buf_ops,
+ .spd_release = swap_device_page_release,
+ };
+
+ /* Get next buffer to read */
+ //TODO : Think about spin_locks to prevent reading race condition.
+ while((result = driver_to_buffer_next_buffer_to_read()) != E_SD_SUCCESS) {
+
+ /* Add process to the swap_device_wait queue and set the current task
+ * state TASK_INTERRUPTIBLE. If there is any data to be read, then the
+ * current task is removed from the swap_device_wait queue and its state
+ * is changed. */
+ prepare_to_wait(&swap_device_wait, &wait, TASK_INTERRUPTIBLE);
+ if (result < 0) {
+ print_err("driver_to_buffer_next_buffer_to_read error %d\n", result);
+ //TODO Error return to OS
+ result = 0;
+ goto swap_device_splice_read_error;
+ } else if (result == E_SD_NO_DATA_TO_READ) {
+ if (filp->f_flags & O_NONBLOCK) {
+ result = -EAGAIN;
+ goto swap_device_splice_read_error;
}
- result = copy_to_user (arg_pointer, &size, sizeof (size));
- if (result)
- {
- result = -EFAULT;
+ if (signal_pending(current)) {
+ result = -ERESTARTSYS;
+ goto swap_device_splice_read_error;
}
- DPRINTF("Get Size of Predefined User Space Probes");
- break;
+ schedule();
+ finish_wait(&swap_device_wait, &wait);
}
- case EC_IOCTL_GET_LAST_ERROR:
- {
- result = get_last_error((void*)arg);
- DPRINTF("Get last error buffer");
- break;
- }
- default:
- EPRINTF ("Unknown driver command = %u", cmd);
- result = -EINVAL;
- break;
}
+ if (splice_grow_spd_p(pipe, &spd)) {
+ result = -ENOMEM;
+ goto swap_device_splice_read_out;
+ }
+
+ result = driver_to_buffer_fill_spd(&spd);
+ if (result != 0) {
+ print_err("Cannot fill spd for splice\n");
+ goto swap_device_shrink_spd;
+ }
+
+ result = splice_to_pipe_p(pipe, &spd);
+
+swap_device_shrink_spd:
+ swap_device_splice_shrink_spd(pipe, &spd);
+
+swap_device_splice_read_out:
+ return result;
+
+swap_device_splice_read_error:
+ finish_wait(&swap_device_wait, &wait);
+
return result;
}
+
+void swap_device_wake_up_process(void)
+{
+ wake_up_interruptible(&swap_device_wait);
+}
+
+void set_msg_handler(msg_handler_t mh)
+{
+ msg_handler = mh;
+}
+EXPORT_SYMBOL_GPL(set_msg_handler);
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: device_driver.h
-//
-// DESCRIPTION:
-//
-// SEE ALSO: device_driver.c
-// AUTHOR: L.Komkov, S.Dianov, S.Grekhov, A.Gerenkov
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.02.15
-// VERSION: 1.0
-// REVISION DATE: 2008.12.03
-//
-////////////////////////////////////////////////////////////////////////////////////
+/*
+ * SWAP driver
+ * modules/driver/device_driver.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Samsung Electronics, 2013
+ *
+ * 2013 Alexander Aksenov <a.aksenov@samsung.com>: SWAP device driver implement
+ *
+ */
-#if !defined(device_driver_h)
-#define device_driver_h
+#ifndef __SWAP_DRIVER_DEVICE_DRIVER_H__
+#define __SWAP_DRIVER_DEVICE_DRIVER_H__
-#include "ec_info.h" // ec_info_t
-#include "ec_probe.h" // probe_id_t
-#include "stdswap_defs.h"
+/* Create and register device */
+int swap_device_init(void);
-#define DEFAULT_DEVICE_NAME "swap_drv"
-#define DEFAULT_DEVICE_MAJOR 250
-#define EVENTS_AGGREGATION_USEC (5 * 1000000UL)
-#define MAX_PRIORITY 255
+/* Delete device */
+void swap_device_exit(void);
-extern int device_init (void);
-extern void device_down (void);
-extern void notify_user (event_id_t event_id);
-extern char *deps;
-extern char *bundle;
-extern struct dbi_modules_handlers *get_dbi_modules_handlers(void);
-
-#endif /* !defined(device_driver_h) */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
-void swap_register_notify (struct notifier_block *nb);
-void swap_unregister_notify (struct notifier_block *nb);
-#endif
+#endif /* __SWAP_DRIVER_DEVICE_DRIVER_H__ */
/*
* SWAP device driver
- * modules/driver_new/driver_defs.h
+ * modules/driver/driver_defs.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
/*
* SWAP driver
- * modules/driver_new/driver_to_buffer.c
+ * modules/driver/driver_to_buffer.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
/*
* SWAP driver
- * modules/driver_new/driver_to_buffer.h
+ * modules/driver/driver_to_buffer.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
/*
* SWAP device driver
- * modules/driver_new/driver_to_msg.h
+ * modules/driver/driver_to_msg.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: ec.c
-//
-// DESCRIPTION:
-// This file is C++ source for SWAP driver.
-//
-// SEE ALSO: ec.h
-// AUTHOR: L.Komkov, A.Gerenkov
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.02.15
-// VERSION: 1.0
-// REVISION DATE: 2008.12.03
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-#include "module.h"
-#include "ec.h"
-#include <us_manager.h>
-
-////////////////////////////////////////////////////////////////////////////////////////////
-
-ec_info_t ec_info = {
- .ec_state = EC_STATE_IDLE,
- .m_nMode = 0L,
- .buffer_size = EC_BUFFER_SIZE_DEFAULT,
- .ignored_events_count = 0,
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
-spinlock_t ec_spinlock; // protects 'ec_info'
-#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-spinlock_t ec_spinlock = SPIN_LOCK_UNLOCKED;
-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-
-ec_probe_info_t ec_probe_info = {
- .probe_id = -1,
- .probe_selected = 0,
- .jprobe_active = 0,
- .retprobe_active = 0,
- .address = NULL,
-};
-
-ec_state_t GetECState(void) { return ec_info.ec_state; };
-
-void reset_ec_info_nolock(void)
-{
- ec_info.trace_size = 0;
- ec_info.first = 0;
- ec_info.after_last = 0;
- ec_info.ignored_events_count = 0;
- ec_info.saved_events_count = 0;
- ec_info.discarded_events_count = 0;
- ec_info.collision_count = 0;
- ec_info.lost_events_count = 0;
-}
-
-void ResetECInfo(void)
-{
- unsigned long spinlock_flags = 0L;
-
- spin_lock_irqsave (&ec_spinlock, spinlock_flags);
- reset_ec_info_nolock();
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags);
-}
-
-void CleanECInfo(void)
-{
- unsigned long spinlock_flags = 0L;
-
- spin_lock_irqsave (&ec_spinlock, spinlock_flags);
- ec_info.buffer_effect = 0;
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags);
-
- ResetECInfo();
-
-}
-
-int IsECMode(unsigned long nMask)
-{
- return ((ec_info.m_nMode & nMask) != 0);
-}
-
-int IsContinuousRetrieval(void)
-{
- return IsECMode(MODEMASK_CONTINUOUS_RETRIEVAL);
-}
-
-int SetECMode(unsigned long nECMode)
-{
- unsigned long spinlock_flags = 0L;
-
- if((nECMode & MODEMASK_CONTINUOUS_RETRIEVAL) != 0) {
- if(EnableContinuousRetrieval() == -1) {
- EPRINTF("Cannot enable continuous retrieval!");
- return -1;
- }
- } else {
- if(DisableContinuousRetrieval() == -1) {
- EPRINTF("Cannot disable continuous retrieval!");
- return -1;
- }
- }
-
- spin_lock_irqsave (&ec_spinlock, spinlock_flags);
- ec_info.m_nMode = nECMode;
- reset_ec_info_nolock();
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags);
-
- return 0;
-}
-
-unsigned long GetECMode(void)
-{
- unsigned long ec_mode;
- unsigned long spinlock_flags = 0L;
-
- spin_lock_irqsave(&ec_spinlock, spinlock_flags);
- ec_mode = ec_info.m_nMode;
- spin_unlock_irqrestore(&ec_spinlock, spinlock_flags);
-
- return ec_mode;
-}
-
-int is_java_inst_enabled(void)
-{
- return !!(GetECMode() & MODEMASK_JAVA_INST);
-}
-
-#if defined(__DEBUG)
-static UNUSED char * ec_state_name (ec_state_t ec_state)
-{
- static char *ec_state_names[EC_STATE_TAG_COUNT] = { "IDLE", "ATTACHED", "ACTIVE", "STOPPED" };
-
- if (((unsigned) ec_info.ec_state) < EC_STATE_TAG_COUNT)
- {
- return ec_state_names[ec_info.ec_state];
- }
- else
- {
- return "<unknown>";
- }
-}
-#endif /* defined(__DEBUG) */
-
-
-/*
- On user request user space EC may change state in the following order:
- IDLE -> ATTACHED (on "attach")
- IDLE | ATTACHED -> ACTIVE (on "activate")
- ATTACHED | ACTIVE | STOPPED -> IDLE (on "stop"/"detach")
-*/
-int ec_user_attach (void)
-{
- unsigned long spinlock_flags;
- int result;
-
- spin_lock_irqsave (&ec_spinlock, spinlock_flags); // make other CPUs wait
- if (EC_STATE_IDLE == ec_info.ec_state)
- {
- int tmp;
- struct timeval tv;
- struct cond *p_cond;
- struct event_tmpl *p_tmpl;
-
- ec_info.ec_state = EC_STATE_ATTACHED;
-
- /* save 'start' time */
- do_gettimeofday(&tv);
- memcpy(&last_attach_time, &tv, sizeof(struct timeval));
-
- /* unpause if paused */
- paused = 0;
-
- /* if there is at least one start condition in the list
- we are paused at the beginning */
- list_for_each_entry(p_cond, &cond_list.list, list) {
- p_tmpl = &p_cond->tmpl;
- if (p_tmpl->type == ET_TYPE_START_COND) {
- paused = 1;
- break;
- }
- }
-
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
-
- //first of all put event with event format
- tmp = event_mask;
- event_mask = 0;
- pack_event_info(EVENT_FMT_PROBE_ID, RECORD_ENTRY, "x", tmp);
- event_mask = tmp;
-
- result = usm_start();
- if (result == 0) // instrument user space process
- result = set_kernel_probes();
- // FIXME: SAFETY CHECK
- if (result)
- { // return to safe state
- unset_kernel_probes();
-
- spin_lock_irqsave (&ec_spinlock, spinlock_flags); // make other CPUs wait
- ec_info.ec_state = EC_STATE_IDLE;
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
- }
- // FIXME: SAFETY CHECK
-
- notify_user (EVENT_EC_STATE_CHANGE);
-
- }
- else
- {
-
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
- result = -EINVAL;
-
- }
-
- return result;
-}
-
-int ec_user_activate (void)
-{
- unsigned long spinlock_flags;
- int result;
-
- spin_lock_irqsave (&ec_spinlock, spinlock_flags); // make other CPUs wait
- if (EC_STATE_IDLE == ec_info.ec_state)
- {
- int tmp;
- ec_info.ec_state = EC_STATE_ACTIVE;
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
- //first of all put event with event format
- tmp = event_mask;
- event_mask = 0;
- pack_event_info(EVENT_FMT_PROBE_ID, RECORD_ENTRY, "x", tmp);
- event_mask = tmp;
-
- result = usm_start();
- if (result == 0) // instrument user space process
- result = set_kernel_probes();
-
- // FIXME: SAFETY CHECK
- if (result)
- { // return to safe state
- unset_kernel_probes();
-
- spin_lock_irqsave (&ec_spinlock, spinlock_flags); // make other CPUs wait
- ec_info.ec_state = EC_STATE_IDLE;
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
- }
- // FIXME: SAFETY CHECK
-
- notify_user (EVENT_EC_STATE_CHANGE);
-
- }
- else if (EC_STATE_ATTACHED == ec_info.ec_state)
- {
-
- ec_info.ec_state = EC_STATE_ACTIVE;
- result = 0;
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
-
- notify_user (EVENT_EC_STATE_CHANGE);
-
- }
- else
- {
-
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
- result = -EINVAL;
- }
-
- return result;
-}
-
-int ec_user_stop (void)
-{
- unsigned long spinlock_flags;
- int result = 0, ret = 0;
-
- spin_lock_irqsave (&ec_spinlock, spinlock_flags); // make other CPUs wait
- if (EC_STATE_ATTACHED == ec_info.ec_state || EC_STATE_ACTIVE == ec_info.ec_state || EC_STATE_STOPPED == ec_info.ec_state)
- {
-
- ec_info.ec_state = EC_STATE_IDLE;
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
-
- ret = usm_stop();
- result = unset_kernel_probes();
- if (result == 0)
- result = ret;
-
- notify_user (EVENT_EC_STATE_CHANGE);
-
- }
- else
- {
-
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
- result = -EINVAL;
-
- }
-
- return result;
-}
-
-/*
- Kernel space EC may change state in the following order:
- ATTACHED -> ACTIVE (when start condition is satisfied)
- ACTIVE -> STOPPED (when stop condition is satisfied)
-*/
-int ec_kernel_activate (void)
-{
- unsigned long spinlock_flags;
- int result;
-
- spin_lock_irqsave (&ec_spinlock, spinlock_flags); // make other CPUs wait
- if (EC_STATE_ATTACHED == ec_info.ec_state)
- {
- ec_info.ec_state = EC_STATE_ACTIVE;
- result = 0;
- }
- else
- {
- result = -EINVAL;
- }
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
-
- notify_user (EVENT_EC_STATE_CHANGE);
-
- return result;
-}
-
-int ec_kernel_stop (void)
-{
- unsigned long spinlock_flags;
- int result;
-
- spin_lock_irqsave (&ec_spinlock, spinlock_flags); // make other CPUs wait
- if (EC_STATE_ACTIVE == ec_info.ec_state)
- {
- ec_info.ec_state = EC_STATE_STOPPED;
- result = 0;
- }
- else
- {
- result = -EINVAL;
- }
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
-
- notify_user (EVENT_EC_STATE_CHANGE);
-
- return result;
-}
-
-// Copies EC info to user space
-// Since "copy_to_user" may block, an intermediate copy of ec_info is used here
-int copy_ec_info_to_user_space (ec_info_t * p_user_ec_info)
-{
- /*
- WARNING: to avoid stack overflow the following data structure was made
- static. As result, simultaneous users of this function will share it
- and must use additional synchronization to avoid collisions.
- */
- // FIXME: synchronization is necessary here (ec_info_copy must be locked).
- static ec_info_t ec_info_copy;
- unsigned long spinlock_flags;
- int result;
-
- // ENTER_CRITICAL_SECTION
- // lock semaphore here
-
-
- // ENTER_CRITICAL_SECTION
- spin_lock_irqsave (&ec_spinlock, spinlock_flags); // make other CPUs wait
-
- // copy
- memcpy (&ec_info_copy, &ec_info, sizeof (ec_info_copy));
-
- // LEAVE_CRITICAL_SECTION
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
-
-
- result = copy_to_user ((void __user *) p_user_ec_info, &ec_info_copy, sizeof (ec_info_t));
-
- // LEAVE_CRITICAL_SECTION
- // unlock semaphore here
-
- if (result)
- {
- EPRINTF ("copy_to_user(%08X,%08X)=%d", (unsigned) p_user_ec_info, (unsigned) &ec_info_copy, result);
- result = -EFAULT;
- }
- return result;
-}
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: ec.h
-//
-// DESCRIPTION:
-//
-// SEE ALSO: ec.c
-// AUTHOR: L.Komkov, A.Gerenkov
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.02.15
-// VERSION: 1.0
-// REVISION DATE: 2008.12.03
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-#if !defined(__EC_H__)
-#define __EC_H__
-
-#include "ec_ioctl.h"
-#include "ec_info.h"
-#include "ec_probe.h"
-#include "picl.h"
-#include "stdswap_defs.h"
-
-extern ec_info_t ec_info;
-extern ec_probe_info_t ec_probe_info;
-extern spinlock_t ec_spinlock;
-
-extern int ec_user_attach (void);
-extern int ec_user_activate (void);
-extern int ec_user_stop (void);
-extern int ec_kernel_activate (void);
-extern int ec_kernel_stop (void);
-
-extern int copy_ec_info_to_user_space (ec_info_t * p_user_ec_info);
-extern ec_state_t GetECState(void);
-extern void reset_ec_info_nolock(void);
-extern void ResetECInfo(void);
-extern void CleanECInfo(void);
-extern int IsECMode(unsigned long nMask);
-extern int IsContinuousRetrieval(void);
-extern int SetECMode(unsigned long nECMode);
-extern unsigned long GetECMode(void);
-extern int is_java_inst_enabled(void);
-extern struct timeval last_attach_time;
-extern int paused;
-
-#endif /* !defined(__EC_H__) */
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: ec_module.h
-//
-// DESCRIPTION:
-//
-// SEE ALSO: N/A
-// AUTHOR: L.Komkov, S.Dianov, A.Gerenkov
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.02.15
-// VERSION: 1.0
-// REVISION DATE: 2008.12.02
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-#if !defined(ec_ioctl_h)
-#define ec_ioctl_h
-
-#include "ec_info.h" // ec_info_t
-#include "picl.h"
-
-typedef enum
-{
- // modes
- EC_IOCTL_SET_EC_MODE,
- EC_IOCTL_GET_EC_MODE,
-
- // buffer manipulation
- EC_IOCTL_SET_BUFFER_SIZE,
- EC_IOCTL_GET_BUFFER_SIZE,
- EC_IOCTL_RESET_BUFFER,
-
- // probes management
- EC_IOCTL_SELECT_PROBE,
- EC_IOCTL_DESELECT_PROBE,
- EC_IOCTL_GET_PROBE_INFO,
- EC_IOCTL_ADD_PROBE,
- EC_IOCTL_SET_APPDEPS,
- EC_IOCTL_SET_PROFILEBUNDLE,
- //EC_IOCTL_REMOVE_PROBE,
- EC_IOCTL_RESET_PROBES,
- EC_IOCTL_SET_COMPLEX_PROBES,
-
- // tracing
- EC_IOCTL_ATTACH, // attaches selected probes
- EC_IOCTL_ACTIVATE, // START
-
- // stop is common for both tracing and profiling
- EC_IOCTL_STOP_AND_DETACH, // STOP (and detach for TRACING)
-
- // kernel to user notification delivery
- EC_IOCTL_WAIT_NOTIFICATION,
-
- // get ec_info
- EC_IOCTL_GET_EC_INFO,
- EC_IOCTL_GET_COMPLEX_STATUS,
- EC_IOCTL_CONSUME_BUFFER,
-
- // conditions
- EC_IOCTL_UPDATE_CONDS,
-
- //user space event
- EC_IOCTL_US_EVENT,
-
- //event format
- EC_IOCTL_SET_EVENT_MASK,
- EC_IOCTL_GET_EVENT_MASK,
-
- // pre-defined user space probes
- EC_IOCTL_SET_PREDEF_UPROBES,
- EC_IOCTL_GET_PREDEF_UPROBES,
- EC_IOCTL_GET_PREDEF_UPROBES_SIZE,
-
- EC_IOCTL_SET_PID,
-
- // error consist of wrong path to apps or libs
- EC_IOCTL_GET_LAST_ERROR,
-} EC_IOCTL_CMD;
-
-typedef struct
-{
- unsigned notification_count;
- ec_info_t *p_ec_info;
-} ioctl_wait_notification_t;
-
-typedef struct
-{
- int m_signedInt;
- unsigned int m_unsignedInt;
- long m_signedLong;
- unsigned long m_unsignedLong;
- char* m_ptrChar;
-} ioctl_general_t;
-
-typedef enum
-{
- OPERATION_ANY, // means do not check value
- OPERATION_EQUAL,
- OPERATION_NOT_EQUAL,
- OPERATION_LESS,
- OPERATION_GREATER
-} operation_t;
-
-typedef struct
-{
- unsigned m_condition_always_false;
- unsigned m_op_time;
- unsigned m_op_pid;
- unsigned m_op_tid;
- unsigned m_op_probe_id;
-// char m_probe_name[SWAP_COMMON_STRING_SIZE];
- unsigned m_op_record_type;
- unsigned m_time_sec;
- unsigned m_time_usec;
- unsigned m_pid;
- unsigned m_tid;
- unsigned m_probe_id;
- unsigned m_record_type;
-} condition_t;
-
-
-
-// condition matching any event
-#define CONDITION_ANY \
-{ \
- .m_condition_always_false = 0, \
- .m_op_time = OPERATION_ANY, \
- .m_op_pid = OPERATION_ANY, \
- .m_op_tid = OPERATION_ANY, \
- .m_op_probe_id = OPERATION_ANY, \
- .m_op_record_type = OPERATION_ANY, \
-} \
-
-// never matching condition
-#define CONDITION_FALSE \
-{ \
- .m_condition_always_false = 1, \
- .m_op_time = OPERATION_ANY, \
- .m_op_pid = OPERATION_ANY, \
- .m_op_tid = OPERATION_ANY, \
- .m_op_probe_id = OPERATION_ANY, \
- .m_op_record_type = OPERATION_ANY, \
-} \
-
-// default start condition - start immediately
-#define DEFAULT_START_CONDITION CONDITION_ANY
-// default stop condition - never stop
-#define DEFAULT_STOP_CONDITION CONDITION_FALSE
-
-
-typedef struct
-{
- unsigned count;
- int *p_pids;
-} ioctl_set_pids_to_ignore_t;
-
-
-typedef struct
-{
- char *name;
- unsigned long addr;
- char type;
- unsigned long size;
- signed char reg; // -1 - memory, 0..127 - register number
- long off;
-} ioctl_usr_space_vtp_t;
-
-typedef struct
-{
- //char *name;
- //unsigned name_len;
- unsigned long addr;
-} ioctl_usr_space_ip_t;
-
-typedef struct
-{
- char *path;
- //unsigned path_len;
- unsigned ips_count;
- ioctl_usr_space_ip_t *p_ips;
- unsigned vtps_count;
- ioctl_usr_space_vtp_t *p_vtps;
-} ioctl_usr_space_lib_t;
-
-typedef struct
-{
- char *path;
- //unsigned path_len;
- unsigned libs_count;
- ioctl_usr_space_lib_t *p_libs;
-} ioctl_inst_usr_space_proc_t;
-
-typedef struct
-{
- char *proc_name;
- unsigned count;
-} ioctl_set_proc_to_ignore_t;
-
-typedef struct
-{
- char *data;
- unsigned len;
-} ioctl_us_event_t;
-
-// exclude entry events
-#define IOCTL_EMASK_ENTRY 0x01
-// exclude exit events
-#define IOCTL_EMASK_EXIT 0x02
-// timestamp
-#define IOCTL_EMASK_TIME 0x04
-// PID
-#define IOCTL_EMASK_PID 0x08
-// TID
-#define IOCTL_EMASK_TID 0x10
-// CPU
-#define IOCTL_EMASK_CPU 0x20
-// Args
-#define IOCTL_EMASK_ARGS 0x40
-
-typedef struct
-{
- unsigned probes_count;
- char *p_probes;
-} ioctl_predef_uprobes_info_t;
-
-
-#endif /* !defined(ec_ioctl_h) */
+++ /dev/null
-#include <linux/string.h>
-#include <linux/vmalloc.h>
-#include <asm/uaccess.h>
-#include "error_storage.h"
-
-static int create_errno_buffer(void);
-static void delete_errno_buffer(void);
-static unsigned int get_max_error_buffer_size(void);
-
-struct errno_struct
-{
- unsigned int size;
- char *buffer;
-};
-
-static struct errno_struct *last_error = NULL;
-
-static int create_errno_buffer(void)
-{
- struct errno_struct *error = NULL;
- if (last_error != NULL){
- return -1;
- }
- error = (struct errno_struct*)vmalloc(sizeof(struct errno_struct));
- if (error == NULL){
- return -1;
- }
- error->buffer = vmalloc(MAX_ERROR_BUF_PATH);
- if (error->buffer == NULL)
- {
- vfree(error);
- return -1;
- }
- error->buffer[0] = '\0';
- error->size = 0;
- last_error = (struct errno_struct*) error;
-
- return 0;
-}
-
-static unsigned int get_max_error_buffer_size(void)
-{
- return (unsigned int)MAX_ERROR_BUF_PATH;
-}
-
-int update_errno_buffer(char *buffer, const unsigned int type)
-{
- unsigned int size;
- char* tmp_buffer;
- int return_value = 0;
-
- if (last_error == NULL) {
- if (create_errno_buffer() != 0)
- return -1;
- }
-
- if (buffer == NULL) {
- if (type == IS_LIB) {
- tmp_buffer = "Unknown lib path. Zero pointer";
- } else if(type == IS_APP) {
- tmp_buffer = "Unknown app path. Zero pointer";
- } else {
- tmp_buffer = "Undefined instrumentation type. Zero pointer";
- }
-
- return_value = -1;
- } else {
- tmp_buffer = buffer;
- }
-
- size = strlen(tmp_buffer);
-
- if (last_error->size + size + 2 >= get_max_error_buffer_size()) {
- return -1;
- }
-
- strncat((char*)(last_error->buffer), tmp_buffer, size);
-
- last_error->size += size + 1;
- last_error->buffer[last_error->size - 1] = ',';
- last_error->buffer[last_error->size] = '\0';
-
- return return_value;
-}
-
-static void delete_errno_buffer(void)
-{
- if (last_error == NULL) {
- return;
- }
-
- vfree((char*)last_error->buffer);
- vfree(last_error);
-
- last_error = NULL;
-
- return;
-}
-
-int get_last_error(void* u_addr)
-{
- int result;
-
- if (last_error == NULL) {
- return -1;
- }
-
- result = copy_to_user ((void*)u_addr, (void*)(last_error->buffer), last_error->size + 1);
- if (result) {
- result = -EFAULT;
- }
-
- delete_errno_buffer();
-
- return result;
-}
-
-int has_last_error()
-{
- if(last_error == NULL) {
- return 0;
- }
- return -1;
-}
+++ /dev/null
-#define MAX_ERROR_BUF_PATH 256
-#define IS_APP 0
-#define IS_LIB 1
-
-// copy error buffer from kernelspace to userspace
-int get_last_error(void* u_addr);
-int has_last_error(void);
-int update_errno_buffer(char *buffer, const unsigned int type);
+++ /dev/null
-#ifndef EVENTS_H_
-#define EVENTS_H_
-
-#define UNUSED __attribute__((unused))
-
-#ifdef __KERNEL__
-#include <asm/uaccess.h> // copy_from_user
-#include "debug.h" // //DPRINTF
-#else
-#include <string.h>
-#include <stdarg.h>
-#endif
-#include "picl.h"
-#include "ec_ioctl.h"
-#include "ec_probe.h"
-
-static TYPE_ARGUMENT GetArgumentType (char ch)
-{
- switch (ch)
- {
- case 'c':
- return AT_CHAR;
- break;
- case 'h':
- return AT_SHORT;
- break;
- case 'd':
- return AT_INT;
- break;
- case 'x':
- return AT_LONG;
- break;
- case 'p':
- return AT_PTR;
- break;
- case 'f':
- return AT_FLOAT;
- break;
- case 'w':
- return AT_DOUBLE;
- break;
- case 's':
- return AT_STRING;
- break;
- case 'a':
- return AT_ARRAY;
- break;
- };
- return AT_UNKNOWN;
-}
-
-static char *PackArguments (char *pBuffer, unsigned long nLen, const char *szFormat, va_list args)
-{
- TYPE_ARGUMENT nArgType = AT_UNKNOWN;
- const char *pChar = NULL;
- char chCode = '\0';
- char *pResult = pBuffer;
- unsigned long nLengthOfDescriptor = 0, nFree = nLen;
- unsigned long nSizeOfDescriptor = 0;
-
- // Descriptor
- nLengthOfDescriptor = strlen (szFormat) + 1;
- nSizeOfDescriptor = ALIGN_VALUE(nLengthOfDescriptor);
- if(nFree < nSizeOfDescriptor)
- return NULL; // no space for descriptor
- memcpy (pResult, szFormat, nLengthOfDescriptor);
- pResult += nSizeOfDescriptor;
- nFree -= nSizeOfDescriptor;
-
- for (pChar = szFormat; (chCode = *pChar) != '\0'; pChar++)
- {
- nArgType = GetArgumentType(chCode);
- switch (nArgType)
- {
- case AT_CHAR:
- {
- int ch = va_arg (args, int);
- if(nFree < sizeof(ch))
- return NULL; // no space for arg
- memcpy(pResult, &ch, sizeof (ch));
- pResult += sizeof (ch);
- nFree -= sizeof (ch);
- }
- break;
- case AT_SHORT:
- {
- int nShort = va_arg (args, int);
- if(nFree < sizeof(nShort))
- return NULL; // no space for arg
- memcpy(pResult, &nShort, sizeof (nShort));
- pResult += sizeof (nShort);
- nFree -= sizeof (nShort);
- }
- break;
- case AT_INT:
- {
- int nInt = va_arg (args, int);
- if(nFree < sizeof(nInt))
- return NULL; // no space for arg
- memcpy(pResult, &nInt, sizeof (nInt));
- pResult += sizeof (nInt);
- nFree -= sizeof (nInt);
- }
- break;
- case AT_LONG:
- {
- long nLong = va_arg (args, long);
- if(nFree < sizeof(nLong))
- return NULL; // no space for arg
- memcpy (pResult, &nLong, sizeof (nLong));
- pResult += sizeof (nLong);
- nFree -= sizeof (nLong);
- }
- break;
- case AT_PTR:
- {
- void *p = va_arg (args, void *);
- if(nFree < sizeof(p))
- return NULL; // no space for arg
- memcpy (pResult, &p, sizeof (p));
- pResult += sizeof (p);
- nFree -= sizeof (p);
- }
- break;
- case AT_FLOAT:
- {
- double fValue = va_arg (args, double);
- if(nFree < sizeof(fValue))
- return NULL; // no space for arg
- memcpy (pResult, &fValue, sizeof (fValue));
- pResult += sizeof (fValue);
- nFree -= sizeof (fValue);
- }
- break;
- case AT_DOUBLE:
- {
- double fDouble = va_arg (args, double);
- if(nFree < sizeof(fDouble))
- return NULL; // no space for arg
- memcpy (pResult, &fDouble, sizeof (fDouble));
- pResult += sizeof (fDouble);
- nFree -= sizeof (fDouble);
- }
- break;
- case AT_STRING:
- {
- const char *s = va_arg (args, const char *);
- int nLengthOfString = 0, nSizeOfString;
- if(!s) {
- /* If string poiner is NULL then */
- s = "(null)";
- }
-#ifdef __KERNEL__
- if((void *)s < (void *)TASK_SIZE) {
- const char __user *user_s = (const char __user *)s;
- nLengthOfString = strlen_user(user_s);
- if(nFree < nLengthOfString)
- return NULL; // no space for arg
- if(strncpy_from_user(pResult,
- user_s,
- nLengthOfString) != (nLengthOfString-1)) {
- const char err_str[] =
- "(failed strcpy_from_user)";
- EPRINTF("failed to copy string from user %p, bytes %d",
- user_s, nLengthOfString);
- nLengthOfString = sizeof(err_str);
- memcpy(pResult, err_str, nLengthOfString);
- }
- }
- else
-#endif
- {
- nLengthOfString = strlen (s) + 1;
- if(nFree < nLengthOfString)
- return NULL; // no space for arg
- memcpy (pResult, s, nLengthOfString);
- }
- nSizeOfString = ALIGN_VALUE (nLengthOfString);
- if(nFree < nSizeOfString)
- return NULL; // no space for arg
- pResult += nSizeOfString;
- nFree -= nSizeOfString;
- }
- break;
- case AT_ARRAY:
- {
- int nLength = va_arg (args, int);
- void *p = NULL;
- int nSize = 0;
- nSize = ALIGN_VALUE (nLength);
- if(nFree < nSize)
- return NULL; // no space for arg
- memcpy (pResult, &nLength, sizeof (int));
- pResult += sizeof (int);
- p = va_arg (args, void *);
-#ifdef __KERNEL__
- if((void *)p < (void *)TASK_SIZE) {
- const void __user *P = (void __user *) va_arg(args, void*);
- if(copy_from_user(pResult, P, nLength)!= 0)
- EPRINTF ("failed to copy array from user %p, bytes %d", P, nLength);
- }
- else
-#endif
- memcpy (pResult, p, nLength);
- pResult += nSize;
- nFree -= nSize;
- }
- break;
- default:
- break;
- };
- }
- return pResult;
-}
-
-static UNUSED TYPEOF_EVENT_LENGTH VPackEvent(char *buf, unsigned long buf_len, int mask, TYPEOF_PROBE_ID probe_id,
- TYPEOF_EVENT_TYPE record_type, TYPEOF_TIME *tv, TYPEOF_PROCESS_ID pid,
- TYPEOF_THREAD_ID tid, TYPEOF_CPU_NUMBER cpu, const char *fmt, va_list args)
-{
- char *cur = buf;
- SWAP_TYPE_EVENT_HEADER *pEventHeader = (SWAP_TYPE_EVENT_HEADER *)buf;
-
- if(buf_len < sizeof(SWAP_TYPE_EVENT_HEADER))
- return 0; // no space for header
-
- pEventHeader->m_nLength = 0;
- cur += sizeof(TYPEOF_EVENT_LENGTH);
- pEventHeader->m_nType = record_type;
- cur += sizeof(TYPEOF_EVENT_TYPE);
- pEventHeader->m_nProbeID = probe_id;
- cur += sizeof(TYPEOF_PROBE_ID);
- //pEventHeader->m_time.tv_sec = tv->tv_sec;
- //pEventHeader->m_time.tv_usec = tv->tv_usec;
- if((probe_id == EVENT_FMT_PROBE_ID) || !(mask & IOCTL_EMASK_TIME)){
- memcpy(cur, tv, sizeof(TYPEOF_TIME));
- cur += sizeof(TYPEOF_TIME);
- }
- //pEventHeader->m_nProcessID = pid;
- if((probe_id == EVENT_FMT_PROBE_ID) || !(mask & IOCTL_EMASK_PID)){
- (*(TYPEOF_PROCESS_ID *)cur) = pid;
- cur += sizeof(TYPEOF_PROCESS_ID);
- }
- //pEventHeader->m_nThreadID = tid;
- if((probe_id == EVENT_FMT_PROBE_ID) || !(mask & IOCTL_EMASK_TID)){
- (*(TYPEOF_THREAD_ID *)cur) = tid;
- cur += sizeof(TYPEOF_THREAD_ID);
- }
- //pEventHeader->m_nCPU = cpu;
- if((probe_id == EVENT_FMT_PROBE_ID) || !(mask & IOCTL_EMASK_CPU)){
- (*(TYPEOF_CPU_NUMBER *)cur) = cpu;
- cur += sizeof(TYPEOF_CPU_NUMBER);
- }
- // dyn lib event should have all args, it is for internal use and not visible to user
- if((probe_id == EVENT_FMT_PROBE_ID) || (probe_id == DYN_LIB_PROBE_ID) || !(mask & IOCTL_EMASK_ARGS)){
- (*(TYPEOF_NUMBER_OF_ARGS *)cur) = strlen(fmt);
- cur += sizeof(TYPEOF_NUMBER_OF_ARGS);
- cur = PackArguments(cur, buf_len-(cur-buf), fmt, args);
- if(!cur) return 0; // no space for args
- }
- else {
- // user space and dynamic kernel probes should have at least one argument
- // to identify them
- if((probe_id == US_PROBE_ID) || (probe_id == VTP_PROBE_ID) || (probe_id == KS_PROBE_ID)){
- char fmt2[2];
- (*(TYPEOF_NUMBER_OF_ARGS *)cur) = 1;
- cur += sizeof(TYPEOF_NUMBER_OF_ARGS);
- // pack args using format string for the 1st arg only
- fmt2[0] = fmt[0]; fmt2[1] = '\0';
- cur = PackArguments(cur, buf_len-(cur-buf), fmt2, args);
- if(!cur) return 0; // no space for args
- }
- else {
- (*(TYPEOF_NUMBER_OF_ARGS *)cur) = 0;
- cur += sizeof(TYPEOF_NUMBER_OF_ARGS);
- }
- }
-
- pEventHeader->m_nLength = cur - buf + sizeof(TYPEOF_EVENT_LENGTH);
- if(buf_len < pEventHeader->m_nLength)
- return 0;// no space for back length
- //memcpy(cur, &pEventHeader->m_nLength, sizeof(TYPEOF_EVENT_LENGTH));
- *((TYPEOF_EVENT_LENGTH *)cur) = pEventHeader->m_nLength;
-
- return pEventHeader->m_nLength;
-}
-
-/*static TYPEOF_EVENT_LENGTH PackEvent(char *buf, unsigned long buf_len, TYPEOF_PROBE_ID probe_id,
- TYPEOF_EVENT_TYPE record_type, TYPEOF_TIME *tv, TYPEOF_PROCESS_ID pid,
- TYPEOF_THREAD_ID tid, TYPEOF_CPU_NUMBER cpu, const char *fmt, ...)
-{
- va_list args;
- TYPEOF_EVENT_LENGTH len;
-
- va_start (args, fmt);
- len = VPackEvent(buf, buf_len, probe_id, record_type, tv, pid, tid, cpu, fmt, args);
- va_end (args);
-
- return len;
-}*/
-
-#endif /*EVENTS_H_*/
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: handlers_core.h
-//
-// DESCRIPTION:
-// This file is C source for SWAP.
-//
-// SEE ALSO: storage.c
-// AUTHOR: S. Andreev
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2012.07.25
-// VERSION: 1.0
-// REVISION DATE: 2012.07.25
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-#if !defined(__HANDLERS_CORE_H__)
-#define __HANDLERS_CORE_H__
-
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-
-// multiple handlers stuff
-struct dbi_modules_handlers {
- struct list_head modules_handlers;
- spinlock_t lock;
-};
-
-struct dbi_modules_handlers_info {
- struct module *dbi_module;
- struct handler_map *dbi_handlers;
- int dbi_nr_handlers;
- struct list_head dbi_list_head;
- void * dbi_module_callback_start;
- void * dbi_module_callback_stop;
- int dbi_module_priority_start;
- int dbi_module_priority_stop;
- void * (*get_uprobes)(void);
-};
-
-extern int dbi_register_handlers_module(struct dbi_modules_handlers_info *dbi_mhi);
-extern int dbi_unregister_handlers_module(struct dbi_modules_handlers_info *dbi_mhi);
-//unsigned long get_dbi_modules_handlers(void);
-
-#endif /* !defined(__HANDLERS_CORE_H__) */
+++ /dev/null
-#!/bin/sh
-
-module=$1
-
-DEBUG_OFF=1
-
-debug(){
- if [ $DEBUG_OFF -eq 0 ];then
- echo $1
- fi
-}
-
-debug ">insmod with patch"
-
-par1=`echo $@ | awk '{print $1}'`
-add_params=${@#*$par1}
-
-if [ -f ${module} ];then
- tmp_ver=`mktemp`
- tmp_mod=`mktemp`
-
- version=`uname -r`
-
- echo "$version" > $tmp_ver
- debug "<`cat $tmp_ver`>"
- debug "./bin/patchko.sh -p <$module> <$tmp_mod> <$tmp_ver>"
- ./bin/patchko.sh -p $module $tmp_mod $tmp_ver
- chmod 644 $tmp_mod
- debug "insmod $tmp_mod $add_params"
- insmod $tmp_mod $add_params
- rm $tmp_mod
- rm $tmp_ver
-fi
--- /dev/null
+/*
+ * SWAP Driver
+ * modules/driver/kernel_operations.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Samsung Electronics, 2013
+ *
+ * 2013 Alexander Aksenov <a.aksenov@samsung.com>: SWAP Driver implement
+ *
+ */
+
+/* Kernel functions wrap */
+
+#ifndef __KERNEL_OPERATIONS_H__
+#define __KERNEL_OPERATIONS_H__
+
+#include <linux/kernel.h>
+
+/* MESSAGES */
+#define print_debug(msg, args...) \
+ printk(KERN_DEBUG "SWAP_DRIVER DEBUG : " msg, ##args)
+#define print_msg(msg, args...) \
+ printk(KERN_INFO "SWAP_DRIVER : " msg, ##args)
+#define print_warn(msg, args...) \
+ printk(KERN_WARNING "SWAP_DRIVER WARNING : " msg, ##args)
+#define print_err(msg, args...) \
+ printk(KERN_ERR "SWAP_DRIVER ERROR : " msg, ##args)
+#define print_crit(msg, args...) \
+ printk(KERN_CRIT "SWAP_DRIVER CRITICAL : " msg, ##args)
+
+#endif /* __KERNEL_OPERATIONS_H__ */
+++ /dev/null
-#include <linux/module.h>
-#include <asm/percpu.h>
-#include <ks_manager.h>
-#include <ec_probe.h>
-#include <picl.h>
-#include <storage.h>
-
-DEFINE_PER_CPU(struct kern_probe *, gpKernProbe) = NULL;
-EXPORT_PER_CPU_SYMBOL_GPL(gpKernProbe);
-
-unsigned long def_jprobe_event_pre_handler(struct kern_probe *p,
- struct pt_regs *regs)
-{
- __get_cpu_var(gpKernProbe) = p;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(def_jprobe_event_pre_handler);
-
-void def_jprobe_event_handler(unsigned long arg0, unsigned long arg1,
- unsigned long arg2, unsigned long arg3,
- unsigned long arg4, unsigned long arg5)
-{
- struct kern_probe *p = __get_cpu_var(gpKernProbe);
-
- pack_event_info(KS_PROBE_ID, RECORD_ENTRY, "pxxxxxx", p->jp.kp.addr,
- arg0, arg1, arg2, arg3, arg4, arg5);
- dbi_jprobe_return();
-}
-EXPORT_SYMBOL_GPL(def_jprobe_event_handler);
-
-int def_retprobe_event_handler(struct kretprobe_instance *ri,
- struct pt_regs *regs, struct kern_probe *p)
-{
- int ret_val;
-
- ret_val = regs_return_value(regs);
- pack_event_info(KS_PROBE_ID, RECORD_RET, "pd", p->rp.kp.addr, ret_val);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(def_retprobe_event_handler);
+++ /dev/null
-#ifndef _KS_DEF_HANDLER_H
-#define _KS_DEF_HANDLER_H
-
-#include <asm/percpu.h>
-
-struct pt_regs;
-struct kern_probe;
-struct kretprobe_instance;
-
-DECLARE_PER_CPU(struct kern_probe *, gpKernProbe);
-
-unsigned long def_jprobe_event_pre_handler(struct kern_probe *p,
- struct pt_regs *regs);
-void def_jprobe_event_handler(unsigned long arg0, unsigned long arg1,
- unsigned long arg2, unsigned long arg3,
- unsigned long arg4, unsigned long arg5);
-int def_retprobe_event_handler(struct kretprobe_instance *ri,
- struct pt_regs *regs, struct kern_probe *p);
-
-#endif /* _KS_DEF_HANDLER_H */
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: legacy.c
-//
-// DESCRIPTION:
-// This file is C source for SWAP driver.
-//
-// SEE ALSO: legacy.h
-// AUTHOR: L.Komkov
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.02.15
-// VERSION: 1.0
-// REVISION DATE: 2008.12.02
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-#include "module.h"
-#include "legacy.h"
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
-signed long
-schedule_timeout_interruptible (signed long timeout)
-{
- __set_current_state (TASK_INTERRUPTIBLE);
- return schedule_timeout (timeout);
-}
-#endif /* kernel without schedule_timeout_interruptible */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
-int
-remap_vmalloc_range (struct vm_area_struct *vma, void *addr, unsigned long pgoff)
-{
- unsigned long uaddr = vma->vm_start;
- unsigned long usize = vma->vm_end - vma->vm_start;
- int ret = -EINVAL;
-
- if ((PAGE_SIZE - 1) & (unsigned long) addr)
- {
- return -EINVAL;
- }
-
- if (pgoff)
- {
- return -EINVAL;
- }
-
- while (usize)
- {
- ret = remap_pfn_range (vma, uaddr, vmalloc_to_pfn (addr), PAGE_SIZE, PAGE_SHARED);
- if (ret)
- {
- break;
- }
- uaddr += PAGE_SIZE;
- addr += PAGE_SIZE;
- usize -= PAGE_SIZE;
- };
-
- return ret;
-}
-#endif /* kernel without remap_vmalloc_range() */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
-/*
- To be mappable to user space, pages of memory allocated via "vmalloc" must
- be marked with "PG_reserved" flag. Memory allocated via "vmalloc_user"
- doesn't need it.
-*/
-static void
-_reserve_pages (void *p, unsigned size)
-{
- unsigned pages = (size + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
- while (pages)
- {
- SetPageReserved (vmalloc_to_page (p));
-
- p += PAGE_SIZE;
- --pages;
- }
-}
-
-static void
-_unreserve_pages (void *p, unsigned size)
-{
- unsigned pages = (size + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
- while (pages)
- {
- ClearPageReserved (vmalloc_to_page (p));
-
- p += PAGE_SIZE;
- --pages;
- }
-}
-
-void *
-vmalloc_user (unsigned long size)
-{
- void *p = __vmalloc (size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
- if (p)
- {
- memset (p, 0, size);
- _reserve_pages (p, size);
- }
- return p;
-}
-
-void
-vfree_user (void *address, unsigned long size)
-{
- _unreserve_pages (address, size);
- vfree (address);
-}
-#endif /* kernel without vmalloc_user() */
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: legacy.h
-//
-// DESCRIPTION:
-//
-// SEE ALSO: legacy.c
-// AUTHOR: L.Komkov
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.02.15
-// VERSION: 1.0
-// REVISION DATE: 2008.12.03
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-/*
- Support for legacy Linux kernel versions
-*/
-#if !defined(__LEGACY_H__)
-#define __LEGACY_H__
-
-#include <linux/mm.h>
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
-extern signed long schedule_timeout_interruptible (signed long timeout);
-#endif /* kernel without schedule_timeout_interruptible */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
-extern int remap_vmalloc_range (struct vm_area_struct *vma, void *addr, unsigned long pgoff);
-#endif /* kernel without remap_vmalloc_range() */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
-extern void *vmalloc_user (unsigned long size);
-extern void vfree_user (void *address, unsigned long size);
-#define VFREE_USER(address, size) \
- { \
- if(address != NULL) { \
- vfree_user(address, size); \
- address = NULL; \
- } \
- }
-#else
-#define VFREE_USER(address, size) \
- { \
- if(address != NULL) { \
- vfree(address); \
- address = NULL; \
- } \
- }
-#endif /* kernel without vmalloc_user() */
-
-#endif /* !defined(__LEGACY_H__) */
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: module.c
-//
-// DESCRIPTION:
-// This file is C source for SWAP driver.
-//
-// SEE ALSO: module.h
-// AUTHOR: L.Komkov, A.Gerenkov
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.02.15
-// VERSION: 1.0
-// REVISION DATE: 2008.12.03
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-#include "module.h"
-#include <ksyms.h>
-#include "helper.h"
-
-static char gl_szDefaultDeviceName[128] = DEFAULT_DEVICE_NAME;
-char* device_name = NULL;
-module_param (device_name, charp, 0);
-MODULE_PARM_DESC (device_name, "device name for '/proc/devices'");
-
-unsigned int device_major = 0;
-module_param (device_major, uint, 0);
-MODULE_PARM_DESC (device_major, "default device major number");
-
-#if (LINUX_VERSION_CODE != KERNEL_VERSION(2, 6, 16))
-static void (*__real_put_task_struct) (struct task_struct * tsk);
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11))
-#define SWAPDRV_PUT_TASK_STRUCT "put_task_struct"
-void
-put_task_struct (struct task_struct *tsk)
-{
- __real_put_task_struct (tsk);
-}
-#else
-#define SWAPDRV_PUT_TASK_STRUCT "__put_task_struct"
-void
-__put_task_struct (struct task_struct *tsk)
-{
- __real_put_task_struct (tsk);
-}
-#endif
-#else /*2.6.16 */
-void (*__real_put_task_struct) (struct rcu_head * rhp);
-#define SWAPDRV_PUT_TASK_STRUCT "__put_task_struct_cb"
-void
-__put_task_struct_cb (struct rcu_head *rhp)
-{
- __real_put_task_struct (rhp);
-}
-#endif
-/*void (*__real_put_task_struct)(struct task_struct *tsk);
-void __put_task_struct(struct task_struct *tsk)
-{
- __real_put_task_struct(tsk);
-}*/
-
-#if defined(CONFIG_MIPS)
-void (*flush_cache_page) (struct vm_area_struct * vma, unsigned long page);
-#endif
-
-static int probes_manager_init(void)
-{
- int ret;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
- spin_lock_init(&ec_spinlock);
-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-
- return storage_init();
-}
-
-static void probes_manager_down(void)
-{
- unset_kernel_probes();
- storage_down();
-}
-
-static int __init InitializeModule(void)
-{
- if(device_name == NULL) {
- EPRINTF("Using default device name!");
- device_name = gl_szDefaultDeviceName;
- }
- if(device_major == 0) {
- EPRINTF("Using default device major number!");
- device_major = DEFAULT_DEVICE_MAJOR;
- }
-
- __real_put_task_struct = (void *)swap_ksyms(SWAPDRV_PUT_TASK_STRUCT);
- if (!__real_put_task_struct)
- {
- EPRINTF (SWAPDRV_PUT_TASK_STRUCT " is not found! Oops. Where is it?");
- return -ESRCH;
- }
-
-#if defined(CONFIG_MIPS)
- flush_cache_page = (void *)swap_ksyms("r4k_flush_cache_page");
- if (!flush_cache_page)
- {
- EPRINTF ("failed to resolve 'flush_cache_page'!\n");
- return -ESRCH;
- }
-#endif
-
- if(probes_manager_init() < 0) {
- EPRINTF ("Cannot initialize probe manager!");
- return -1;
- }
- if(device_init() < 0) {
- EPRINTF ("Cannot initialize device!");
- return -1;
- }
-
- INIT_LIST_HEAD(&cond_list.list);
-
- DPRINTF ("is successfully initialized.");
-
- return 0;
-}
-
-static void __exit UninitializeModule (void)
-{
- ec_user_stop ();
- device_down ();
- probes_manager_down ();
- DPRINTF ("is successfully finished.");
-}
-
-module_init (InitializeModule);
-module_exit (UninitializeModule);
-MODULE_LICENSE ("GPL");
-MODULE_AUTHOR("Adwanced Software Group (SRC, Moscow)");
-MODULE_DESCRIPTION("SWAP Device Driver");
-MODULE_VERSION("4:1.0");
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: module.h
-//
-// DESCRIPTION:
-//
-// SEE ALSO: module.c
-// AUTHOR: L.Komkov, A.Gerenkov
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.02.15
-// VERSION: 1.0
-// REVISION DATE: 2008.12.03
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-#if !defined(__MODULE_H__)
-#define __MODULE_H__
-
-#define UNUSED __attribute__((unused))
-
-#include <linux/types.h>
-#include <asm/current.h>
-#include <asm/page.h>
-#include <asm/uaccess.h>
-#include <asm/local.h>
-#include <asm/string.h>
-#include <asm/mman.h>
-
-#include <net/sock.h>
-#include <net/tcp.h>
-#include <net/inet_common.h>
-
-#include <linux/gfp.h>
-#include <linux/mm.h>
-#include <linux/page-flags.h>
-#include <linux/vmalloc.h>
-#include <linux/errno.h>
-#include <linux/spinlock.h>
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/genhd.h>
-#include <linux/fs.h>
-#include <linux/bio.h>
-#include <linux/file.h>
-#include <linux/tcp.h>
-#include <linux/skbuff.h>
-#include <linux/ipsec.h>
-#include <linux/sysctl.h>
-#include <linux/dcache.h>
-#include <linux/kernel.h>
-#include <linux/stddef.h>
-#include <linux/audit.h>
-#include <linux/namei.h>
-#include <linux/signal.h>
-#include <linux/highmem.h>
-#include <linux/pagemap.h>
-#include <linux/types.h>
-#include <linux/cdev.h>
-#include <linux/jiffies.h>
-#include <linux/time.h>
-
-#include "events.h"
-
-#include "debug.h"
-#include "ec.h"
-#include "legacy.h"
-#include "storage.h"
-#include "us_proc_inst.h"
-#include "device_driver.h"
-#include "probes_manager.h"
-#include "probes.h"
-
-extern char *device_name;
-extern unsigned int device_major;
-
-struct handler_map {
- unsigned long func_addr;
- unsigned long jp_handler_addr;
- unsigned long rp_handler_addr;
- char * func_name;
-};
-
-#endif /* !defined(module_h) */
+++ /dev/null
-#!/bin/sh
-opt=$1
-patch_file=$2
-output_file=$3
-data_file=$4
-
-objdump=$3
-readelf=$4
-
-howto()
-{
- echo " $0 -r <patchingfile.ko> <readelf> <objdump>"
- echo " $0 -g <patchingfile.ko> <readelf> <objdump>"
- echo " $0 -p <patchingfile.ko> <outputfile.ko> <patchdata>"
-}
-
-DEBUG_OFF=1
-
-debug(){
- if [ $DEBUG_OFF -eq 0 ];then
- echo "patchko.sh) $1"
- fi
-}
-
-debugmk(){
- echo "patchko.sh) $1"
-}
-
-error(){
- debugmk "[Err]$1"
-}
-
-#toolchain=~/Work/tools/u1_slp/toolchai
-#cross=${toolchain}/bin/arm-none-linux-gnueabi-
-#cross=arm-none-linux-gnueabi-
-
-sect_name="modinfo"
-varname="vermagic"
-debug "patchfile <$patch_file>"
-
-if [ -f "$patch_file" ]; then
-
- if [ "$opt" = "-p" ];then
- #set version (use only on target)
- debug "Set version (patching) to <$patch_file>"
- if [ -f "$data_file" ];then
- cp -f "${patch_file}" "${output_file}"
-
- #get patching adderes
- pos=$((`cat $patch_file.addr | awk '{print \$1}'`))
- abs_len=$((`cat $patch_file.addr | awk '{print \$2}'`))
-
- key_before=`dd if="$patch_file" bs=1 skip=${pos}c count=${abs_len}c 2>/dev/null`
- debug "key_before<$key_before>"
- key_before_tail=${key_before#*\ }
- debug "key_before_tail<$key_before_tail>"
- echo -ne "`cat $data_file` $key_before_tail\000">$data_file
-
- key_len="`cat $data_file`"
- key_len=$((${#key_len}+1))
-
- debug "POS>$pos<"
- debug "OLDLEN>$abs_len<"
- debug "NEWLEN>$key_len<"
- debug "PATCH_TO>`cat $data_file`<"
-
- debug "key_len=$key_len"
- if [ $key_len -le ${abs_len} ];then
- debug "before=<$key_before>"
- res=`dd if="${data_file}" of="${output_file}" bs=1 seek=${pos} skip=0c count=${key_len}c conv=notrunc 2>/dev/null`
-
- res=`dd if="$output_file" bs=1 skip=${pos}c count=${abs_len}c 2>/dev/null`
- debug "patched=<$res>"
- else
- error "Error on patching <${patch_file}>:data file <$data_file> NEW KEY TOO LONG"
- error "CHECK YOUR KERNEL USED ON COMPILE SWAP IF YOU READ IT"
- exit 254
- fi
- else
- error "Error on patching <${patch_file}>:data file <$data_file> not found"
- exit 255
- fi
- else
- #if[ "$opt" != "-p" ];then
- debug "+not p"
-
- $readelf -v
- if [ $? -ne 0 ];then
- error "readelf not found on path <$readelf>"
- exit 2
- fi
- $objdump -v
- if [ $? -ne 0 ];then
- error "objdump not found on path <$objdump>"
- exit 1
- fi
-
- file_size=$((`ls -la "$patch_file" | awk '{print \$5}'`))
- debugmk "file_size=$file_size"
-
- section=`$readelf -e $patch_file | grep ${sect_name}`
- section=${section##*${sect_name}}
- debugmk "section=$section"
-
- addr=$((0x`echo $section | awk '{print $2}'`))
- offs=$((0x`echo $section | awk '{print $3}'`))
- size=$((0x`echo $section | awk '{print $4}'`))
- debugmk $addr:$offs:$size
-
- abs_len=$((0x`$objdump -t -j .${sect_name} "$patch_file" | grep _${varname} | awk '{print $5}'`))
- abs_len=$(($abs_len-${#varname}-1))
- sect_off=$((0x`$objdump -t -j .${sect_name} "$patch_file" | grep _${varname} | awk '{print $1}'`))
- add_off=$((${#varname}+1))
-
- abs_addr=$((${addr}+${offs}+${sect_off}+${add_off}))
- debugmk "abs_addr=$abs_addr;"
- debugmk "abs_len=$abs_len"
- if [ "$opt" = "-r" ];then
- #read version (for patch testing)
- debugmk "Read version in <$patch_file>"
- res=`dd if="$patch_file" bs=1 skip=${abs_addr}c count=${abs_len}c 2>/dev/null`
- debugmk "ver<$res>"
- elif [ "$opt" = "-g" ];then
- #gen file version (use only on host)
- debugmk "Generate version data for <$patch_file>"
- #res=`dd if="$patch_file" of="$patch_file.addr" bs=1 skip=${abs_addr}c count=${abs_len}c`
- if [ "$abs_addr" = "" ];then
- debugmk "ERROR cannot get absolute addres of module info line for patching"
- exit 253
- elif [ "$abs_len" = "" ];then
- debugmk "ERROR cannot get length of module info line for patching"
- exit 252
- else
- echo "$abs_addr $abs_len">"$patch_file.addr"
- fi
- debugmk "patch_addr=`cat $patch_file.addr`"
- else
- error "Wrong param <$opt>"
- fi
- fi
-else
- error "file for patchig not found <$patch_file>"
- fi
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: PICL.h
-//
-// DESCRIPTION:
-//
-// SEE ALSO: PICL.cpp
-// AUTHOR: L.Komkov
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.02.15
-// VERSION: 1.0
-// REVISION DATE: 2008.12.02
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-#if !defined(PICL_h)
-#define PICL_h
-
-#ifdef SWAP_HOST
-#include <sys/time.h> // struct timeval
-#else // SWAP_TARGET
-#ifdef __KERNEL__
-#include <linux/time.h> // struct timeval
-#else
-#include <sys/time.h> // struct timeval
-#endif
-#endif
-
-#define MAX_ARGS_DATA 200
-
-#define EVENT_MAX_SIZE 2048*5
-
-/* EvenRecord format
- ______________________________________________________________________________________________________________
-| Len | RecType | EventType | Time | Pid | Tid | CPU | ArgsCount | ArgTypes | ArgValues | PreEventLen |
- __4b_____4b________4b________8b_____4b____4b_____4b______4b________ArgCount___variable-length._______4b_____
-
-*/
-
-typedef enum
-{
- RECORD_ENTRY = 0,
- RECORD_RET,
- RECORD_PROFILE,
-
- RECORD_TYPE_COUNT // fictional record type used to count real record types
-} record_type_t;
-
-const char *ec_record_type_to_name (record_type_t record_type);
-int ec_record_type_by_name (record_type_t * p_record_type, const char *record_type_name);
-
-// old Picl.h
-
-#define _TRACE_TYPE 0
-#define _TRACE_STATS_TYPE 2
-
-typedef union tagArgValueType
-{
- char m_char;
- int m_int;
- long m_long;
- float m_float;
- double m_double;
- void *m_pointer;
- char *m_string;
-} _ARG_VALUE_TYPE;
-
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef __KERNEL__
-#include <linux/types.h>
-#else
-#include <sys/types.h>
-#include <stdint.h>
-#endif
-
-struct common_timeval {
- uint32_t tv_sec;
- uint32_t tv_usec;
-};
-
-typedef uint32_t TYPEOF_EVENT_LENGTH;
-typedef uint32_t TYPEOF_EVENT_TYPE;
-typedef uint32_t TYPEOF_PROBE_ID;
-typedef struct common_timeval TYPEOF_TIME;
-typedef uint32_t TYPEOF_PROCESS_ID;
-typedef uint32_t TYPEOF_THREAD_ID;
-typedef uint32_t TYPEOF_CPU_NUMBER;
-typedef uint32_t TYPEOF_NUMBER_OF_ARGS;
-
-typedef struct tagEventHeader
-{
- TYPEOF_EVENT_LENGTH m_nLength;
- TYPEOF_EVENT_TYPE m_nType;
- TYPEOF_PROBE_ID m_nProbeID;
- TYPEOF_TIME m_time;
- TYPEOF_PROCESS_ID m_nProcessID;
- TYPEOF_THREAD_ID m_nThreadID;
- TYPEOF_CPU_NUMBER m_nCPU;
- TYPEOF_NUMBER_OF_ARGS m_nNumberOfArgs;
-} SWAP_TYPE_EVENT_HEADER;
-
-typedef struct tagEvent
-{
- SWAP_TYPE_EVENT_HEADER *m_pHeader;
- char *m_pDescriptor;
- char *m_pData;
-} SWAP_TYPE_EVENT;
-
-/*
- Argument Descriptors
-
- c - char
- h - short
- d - int
- x - long
- p - pointer
- f - float
- w - double
- s - string
-*/
-
-typedef enum
-{
- AT_UNKNOWN,
- AT_CHAR,
- AT_SHORT,
- AT_INT,
- AT_LONG,
- AT_PTR,
- AT_FLOAT,
- AT_DOUBLE,
- AT_STRING,
- AT_ARRAY
-} TYPE_ARGUMENT;
-
-#define ALIGN_VALUE(x) ((x) + (4 - ((x) % 4)))
-
-#endif /* !defined(PICL_h) */
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: probes.c
-//
-// DESCRIPTION:
-// This file is C source for SWAP driver.
-//
-// SEE ALSO: probes.h
-// AUTHOR: L.Komkov, S.Grekhov, A.Gerenkov
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.02.15
-// VERSION: 1.0
-// REVISION DATE: 2008.12.03
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-#include "module.h"
-#include "probes.h"
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
-#define tcp_opt tcp_sock
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
-#define kmem_cache_t struct kmem_cache
-#endif
-
-/*
-#define UNUSED __attribute__((unused))
-
-#define USER_PRIO(p) ((p)-MAX_RT_PRIO)
-#define MAX_USER_PRIO (USER_PRIO(MAX_PRIO))
-
-#define PRIO_BONUS_RATIO 25
-#define MAX_BONUS (MAX_USER_PRIO * PRIO_BONUS_RATIO / 100)
-#define INTERACTIVE_DELTA 2
-
-#define PRIO_TO_NICE(prio) ((prio) - MAX_RT_PRIO - 20)
-#define TASK_NICE(p) PRIO_TO_NICE((p)->static_prio)
-
-#define SCALE(v1,v1_max,v2_max) (v1) * (v2_max) / (v1_max)
-
-#define DELTA(p) (SCALE(TASK_NICE(p), 40, MAX_BONUS) + INTERACTIVE_DELTA)
-
-#define TASK_INTERACTIVE(p) ((p)->prio <= (p)->static_prio - DELTA(p))
-*/
-
-const char *ec_probe_name[] = {
- "ks_probe_id",
- "us_probe_id",
- "vtp_probe_id",
- "dyn_lib_probe_id",
- "plt_addr_probe_id",
- "event_fmt_probe_id",
- "rq_profile",
- "pid_rq_profile"
-};
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: probes.h
-//
-// DESCRIPTION:
-//
-// SEE ALSO: probes.c
-// AUTHOR: L.Komkov, S.Grekhov, A.Gerenkov
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.02.15
-// VERSION: 1.0
-// REVISION DATE: 2008.12.03
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-#ifndef __PROBES_H__
-#define __PROBES_H__
-
-#include "ec_probe.h"
-#include "storage.h"
-#include "../kprobe/dbi_kprobes.h"
-
-#ifndef regs_return_value
-/* "regs_return_value" is ARCH-dependent. ARCH is passed via "EC_ARCH_*" */
-
-#if defined(CONFIG_ARM)
-#define regs_return_value(regs) ((regs)->ARM_r0)
-#elif defined(CONFIG_X86)
-#define regs_return_value(regs) ((regs)->ax)
-#elif defined(CONFIG_MIPS)
-#define regs_return_value(regs) ((regs)->regs[2])
-#else
-#error this architecture is not supported
-#endif
-
-#endif /* ndef regs_return_value */
-
-extern struct jprobe my_jprobe[];
-extern const char *ec_probe_name[];
-
-extern struct kretprobe my_kretprobe[];
-
-#define MY_JPROBE_ENTRY(handler_entry) { .entry = JPROBE_ENTRY(handler_entry) }
-
-/* Probe up to 20 instances concurrently. */
-#define MAXACTIVE 20
-
-#define MY_RETPROBE_HANDLER(handler_entry) { .handler = (handler_entry), .maxactive = MAXACTIVE }
-
-#define MY_UAPP(_ips_arr) { .path="", .m_f_dentry=NULL, \
- .ips_count=sizeof(_ips_arr)/sizeof(us_proc_ip_t), .p_ips=_ips_arr, \
- .vtps_count=0, .p_vtps=NULL, .loaded=0}
-#define MY_ULIB(_lib, _ips_arr) { .path=#_lib, .m_f_dentry=NULL, \
- .ips_count=sizeof(_ips_arr)/sizeof(us_proc_ip_t), .p_ips=_ips_arr, \
- .vtps_count=0, .p_vtps=NULL, .loaded=0}
-#define MY_UPROBE_ENTRY(_name, _entry_hand, _exit_hand) {.name = #_name, \
- .jprobe.entry = JPROBE_ENTRY(_entry_hand), \
- .retprobe.handler = (uretprobe_handler_t)_exit_hand}
-#define MY_UPROBE_ENTRY_EXT(_name, _pre_entry_hand, _entry_hand, _exit_hand) {.name = #_name, .jprobe.pre_entry = (kprobe_pre_entry_handler_t)_pre_entry_hand, .jprobe.entry = JPROBE_ENTRY(_entry_hand), .retprobe.handler = (kretprobe_handler_t)_exit_hand}
-
-#endif // __PROBES_H__
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: probes_manager.c
-//
-// DESCRIPTION:
-// This file is C source for SWAP driver.
-//
-// SEE ALSO: probes_manager.h
-// AUTHOR: L.Komkov, A.Gerenkov
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.02.15
-// VERSION: 1.0
-// REVISION DATE: 2008.12.03
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-#include <linux/module.h>
-#include <ks_manager.h>
-
-
-int set_kernel_probes(void)
-{
- return 0;
-}
-
-int unset_kernel_probes(void)
-{
- return ksm_unregister_probe_all();
-}
-
-int add_probe(unsigned long addr,
- unsigned long pre_handler,
- unsigned long jp_handler,
- unsigned long rp_handler)
-{
- return ksm_register_probe(addr, pre_handler, jp_handler, rp_handler);
-}
-
-int reset_probes(void)
-{
- return 0;
-}
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: probes_manager.h
-//
-// DESCRIPTION:
-//
-// SEE ALSO: probes_manager.c
-// AUTHOR: L.Komkov, A.Gerenkov
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.02.15
-// VERSION: 1.0
-// REVISION DATE: 2008.12.03
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-#if !defined(__PROBES_MANAGER_H__)
-#define __PROBES_MANAGER_H__
-
-extern int add_probe(unsigned long addr,
- unsigned long pre_handler,
- unsigned long jp_handler,
- unsigned long rp_handler);
-extern int reset_probes(void);
-
-int set_kernel_probes(void);
-int unset_kernel_probes(void);
-
-void dbi_install_user_handlers(void);
-void dbi_uninstall_user_handlers(void);
-
-#endif // !defined(__PROBES_MANAGER_H__)
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: storage.c
-//
-// DESCRIPTION:
-// This file is C source for SWAP.
-//
-// SEE ALSO: storage.h
-// AUTHOR: L.Komkov, S.Dianov, A.Gerenkov, S.Andreev
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.02.15
-// VERSION: 1.0
-// REVISION DATE: 2008.12.03
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-#include <linux/types.h>
-#include <linux/hash.h>
-#include <linux/list.h>
-#include <linux/unistd.h>
-#include <linux/spinlock.h>
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <ksyms.h>
-#include <dbi_kprobes_deps.h>
-#include "module.h"
-#include "storage.h"
-#include "handlers_core.h"
-#include "CProfile.h"
-#include "sspt/sspt.h"
-#include "sspt/sspt_debug.h"
-#include "ks_def_handler.h"
-#include "../us_manager/us_manager.h"
-
-#define after_buffer ec_info.buffer_size
-
-char *p_buffer = NULL;
-inst_us_proc_t us_proc_info;
-inst_dex_proc_t dex_proc_info;
-char *deps;
-char *bundle;
-unsigned int inst_pid = 0;
-int event_mask = 0L;
-struct cond cond_list;
-int paused = 0; /* a state after a stop condition (events are not collected) */
-struct timeval last_attach_time = {0, 0};
-
-static struct dbi_modules_handlers dbi_mh;
-
-struct dbi_modules_handlers *get_dbi_modules_handlers(void)
-{
- return &dbi_mh;
-}
-EXPORT_SYMBOL_GPL(get_dbi_modules_handlers);
-
-inline unsigned long find_dbi_jp_handler(unsigned long p_addr, struct dbi_modules_handlers_info *mhi)
-{
- int i;
-
- /* Possibly we can find less expensive way */
- for (i = 0; i < mhi->dbi_nr_handlers; i++) {
- if (mhi->dbi_handlers[i].func_addr == p_addr) {
- printk("Found jp_handler for %0lX address of %s module\n", p_addr, mhi->dbi_module->name);
- return mhi->dbi_handlers[i].jp_handler_addr;
- }
- }
- return 0;
-}
-
-inline unsigned long find_dbi_rp_handler(unsigned long p_addr, struct dbi_modules_handlers_info *mhi)
-{
- int i;
-
- /* Possibly we can find less expensive way */
- for (i = 0; i < mhi->dbi_nr_handlers; i++) {
- if (mhi->dbi_handlers[i].func_addr == p_addr) {
- printk("Found rp_handler for %0lX address of %s module\n", p_addr, mhi->dbi_module->name);
- return mhi->dbi_handlers[i].rp_handler_addr;
- }
- }
- return 0;
-}
-
-/**
- * Search of handler in global list of modules for defined probe
- */
-void dbi_find_and_set_handler_for_probe(unsigned long addr,
- unsigned long *pre_entry,
- unsigned long *jp_handler,
- unsigned long *rp_handler)
-{
- unsigned long jp_handler_addr, rp_handler_addr;
- struct dbi_modules_handlers_info *local_mhi;
- unsigned long dbi_flags;
- unsigned int local_module_refcount = 0;
-
- spin_lock_irqsave(&dbi_mh.lock, dbi_flags);
- list_for_each_entry_rcu(local_mhi, &dbi_mh.modules_handlers, dbi_list_head) {
- printk("Searching handlers in %s module for %0lX address\n",
- (local_mhi->dbi_module)->name, addr);
- // XXX: absent code for pre_handlers because we suppose that they are not used
- if ((jp_handler_addr = find_dbi_jp_handler(addr, local_mhi)) != 0) {
- if (*jp_handler) {
- printk("Skipping jp_handler for %s module (address %0lX)\n",
- (local_mhi->dbi_module)->name, addr);
- } else {
- local_module_refcount = module_refcount(local_mhi->dbi_module);
- if (local_module_refcount == 0) {
- if (!try_module_get(local_mhi->dbi_module))
- printk("Error of try_module_get() for module %s\n",
- (local_mhi->dbi_module)->name);
- else
- printk("Module %s in use now\n",
- (local_mhi->dbi_module)->name);
- }
-
- *jp_handler = jp_handler_addr;
- printk("Set jp_handler for %s module (address %0lX)\n",
- (local_mhi->dbi_module)->name, addr);
- }
- }
-
- if ((rp_handler_addr = find_dbi_rp_handler(addr, local_mhi)) != 0) {
- if (*rp_handler) {
- printk("Skipping kretprobe_handler for %s module (address %0lX)\n",
- (local_mhi->dbi_module)->name, addr);
- } else {
- local_module_refcount = module_refcount(local_mhi->dbi_module);
- if (local_module_refcount == 0) {
- if (!try_module_get(local_mhi->dbi_module))
- printk("Error of try_module_get() for module %s\n",
- (local_mhi->dbi_module)->name);
- else
- printk("Module %s in use now\n",
- (local_mhi->dbi_module)->name);
- }
-
- *rp_handler = rp_handler_addr;
- printk("Set rp_handler for %s module (address %0lX)\n",
- (local_mhi->dbi_module)->name, addr);
- }
- }
- }
-
- // not found pre_handler - set default (always true for now since pre_handlers not used)
- if (*pre_entry == 0) {
- *pre_entry = (unsigned long)def_jprobe_event_pre_handler;
- printk("Set default pre_handler (address %0lX)\n", addr);
- }
-
- // not found jp_handler - set default
- if (*jp_handler == 0) {
- *jp_handler = (unsigned long)def_jprobe_event_handler;
- printk("Set default jp_handler (address %0lX)\n", addr);
- }
-
- // not found kretprobe_handler - set default
- if (*rp_handler == 0) {
- *rp_handler = (unsigned long)def_retprobe_event_handler;
- printk("Set default rp_handler (address %0lX)\n", addr);
- }
- spin_unlock_irqrestore(&dbi_mh.lock, dbi_flags);
-}
-
-// XXX TODO: possible mess when start-register/unregister-stop operation
-// so we should refuse register/unregister operation while we are in unsafe state
-int dbi_register_handlers_module(struct dbi_modules_handlers_info *dbi_mhi)
-{
- unsigned long dbi_flags;
-// struct dbi_modules_handlers_info *local_mhi;
- int i=0;
- int nr_handlers=dbi_mhi->dbi_nr_handlers;
-
- for (i = 0; i < nr_handlers; ++i) {
- dbi_mhi->dbi_handlers[i].func_addr = swap_ksyms(dbi_mhi->dbi_handlers[i].func_name);
- printk("[0x%08lx]-%s\n", dbi_mhi->dbi_handlers[i].func_addr, dbi_mhi->dbi_handlers[i].func_name);
- }
-
- spin_lock_irqsave(&dbi_mh.lock, dbi_flags);
-// local_mhi = container_of(&dbi_mhi->dbi_list_head, struct dbi_modules_handlers_info, dbi_list_head);
- list_add_rcu(&dbi_mhi->dbi_list_head, &dbi_mh.modules_handlers);
- printk("Added module %s (head is %p)\n", (dbi_mhi->dbi_module)->name, &dbi_mhi->dbi_list_head);
- spin_unlock_irqrestore(&dbi_mh.lock, dbi_flags);
- return 0;
-}
-EXPORT_SYMBOL_GPL(dbi_register_handlers_module);
-
-// XXX TODO: possible mess when start-register/unregister-stop operation
-// so we should refuse register/unregister operation while we are in unsafe state
-int dbi_unregister_handlers_module(struct dbi_modules_handlers_info *dbi_mhi)
-{
- unsigned long dbi_flags;
- // Next code block is for far future possible usage in case when removing will be implemented for unsafe state
- // (i.e. between attach and stop)
- /*kernel_probe_t *p;
- struct hlist_node *node;
- unsigned long jp_handler_addr, rp_handler_addr, pre_handler_addr;*/
-
- spin_lock_irqsave(&dbi_mh.lock, dbi_flags);
- list_del_rcu(&dbi_mhi->dbi_list_head);
- // Next code block is for far future possible usage in case when removing will be implemented for unsafe state
- // (i.e. between attach and stop)
- /*swap_hlist_for_each_entry_rcu (p, node, &kernel_probes, hlist) {
- // XXX: absent code for pre_handlers because we suppose that they are not used
- if ((p->jprobe.entry != ((kprobe_pre_entry_handler_t )def_jprobe_event_pre_handler)) ||
- (p->retprobe.handler != ((kretprobe_handler_t )def_retprobe_event_handler))) {
- printk("Searching handlers for %p address for removing in %s registered module...\n",
- p->addr, (dbi_mhi->dbi_module)->name);
- jp_handler_addr = find_dbi_jp_handler(p->addr, dbi_mhi);
- rp_handler_addr = find_dbi_rp_handler(p->addr, dbi_mhi);
- if ((jp_handler_addr != 0) || (rp_handler_addr != 0)) {
- // search and set to another handlers or default
- dbi_find_and_set_handler_for_probe(p);
- printk("Removed handler(s) for %s module (address %p)\n",
- (dbi_mhi->dbi_module)->name, p->addr);
- }
- }
- }*/
- printk("Removed module %s (head was %p)\n", (dbi_mhi->dbi_module)->name, &dbi_mhi->dbi_list_head);
- spin_unlock_irqrestore(&dbi_mh.lock, dbi_flags);
- return 0;
-}
-EXPORT_SYMBOL_GPL(dbi_unregister_handlers_module);
-
-static inst_us_proc_t empty_uprobes_info =
-{
- .libs_count = 0,
- .p_libs = NULL,
-};
-
-static inst_us_proc_t *get_uprobes(void)
-{
- unsigned long dbi_flags;
- inst_us_proc_t *ret = &empty_uprobes_info;
- struct dbi_modules_handlers_info *mhi;
- struct list_head *head = &dbi_mh.modules_handlers;
-
- spin_lock_irqsave(&dbi_mh.lock, dbi_flags);
- list_for_each_entry_rcu(mhi, head, dbi_list_head) {
- if (mhi->get_uprobes) {
- ret = mhi->get_uprobes();
- break;
- }
- }
- spin_unlock_irqrestore(&dbi_mh.lock, dbi_flags);
-
- return ret;
-}
-
-EXPORT_SYMBOL_GPL(us_proc_info);
-EXPORT_SYMBOL_GPL(dex_proc_info);
-typedef void *(*get_my_uprobes_info_t)(void);
-#ifdef MEMORY_CHECKER
-typedef int (*mec_post_event_pointer)(char *data, unsigned long len);
-static mec_post_event_pointer mec_post_event = NULL;
-#endif
-
-static unsigned copy_into_cyclic_buffer (char *buffer, unsigned dst_offset,
- char *src, unsigned size)
-{
- memcpy(buffer + dst_offset, src, size);
- return dst_offset + size;
-}
-
-static int CheckBufferSize (unsigned int nSize)
-{
- if (nSize < EC_BUFFER_SIZE_MIN) {
- EPRINTF("Too small buffer size! [Size=%u KB]", nSize / 1024);
- return -1;
- }
- if (nSize > EC_BUFFER_SIZE_MAX) {
- EPRINTF("Too big buffer size! [Size=%u KB]", nSize / 1024);
- return -1;
- }
- return 0;
-}
-
-static int AllocateSingleBuffer(unsigned int nSize)
-{
- unsigned long spinlock_flags = 0L;
-
- p_buffer = vmalloc_user(nSize);
- if(!p_buffer) {
- EPRINTF("Memory allocation error! [Size=%u KB]", nSize / 1024);
- return -1;
- }
-
- spin_lock_irqsave (&ec_spinlock, spinlock_flags);
- ec_info.buffer_effect = ec_info.buffer_size = nSize;
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags);
-
- return 0;
-}
-
-static void FreeSingleBuffer (void)
-{
- VFREE_USER(p_buffer, ec_info.buffer_size);
- CleanECInfo();
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-int EnableContinuousRetrieval(void)
-{
- unsigned long spinlock_flags = 0L;
-
- spin_lock_irqsave (&ec_spinlock, spinlock_flags);
- ec_info.m_nMode |= MODEMASK_CONTINUOUS_RETRIEVAL;
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags);
-
- return 0;
-}
-
-int DisableContinuousRetrieval(void)
-{
- unsigned long spinlock_flags = 0L;
-
- spin_lock_irqsave (&ec_spinlock, spinlock_flags);
- ec_info.m_nMode &= ~MODEMASK_CONTINUOUS_RETRIEVAL;
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags);
-
- return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-static int InitializeBuffer(unsigned int nSize) {
- return AllocateSingleBuffer(nSize);
-}
-
-static int UninitializeBuffer(void) {
- FreeSingleBuffer();
- return 0;
-}
-
-unsigned int GetBufferSize(void) { return ec_info.buffer_size; };
-
-int SetBufferSize(unsigned int nSize) {
- if (GetECState() != EC_STATE_IDLE) {
- EPRINTF("Buffer changes are allowed in IDLE state only (%d)!", GetECState());
- return -1;
- }
- if(GetBufferSize() == nSize)
- return 0;
- if(CheckBufferSize(nSize) == -1) {
- EPRINTF("Invalid buffer size!");
- return -1;
- }
- unset_kernel_probes();
- if(UninitializeBuffer() == -1)
- EPRINTF("Cannot uninitialize buffer!");
- if(InitializeBuffer(nSize) == -1) {
- EPRINTF("Cannot initialize buffer! [Size=%u KB]", nSize / 1024);
- return -1;
- }
- return 0;
-}
-
-int SetPid(unsigned int pid)
-{
- if (GetECState() != EC_STATE_IDLE)
- {
- EPRINTF("PID changes are allowed in IDLE state only (%d)!", GetECState());
- return -1;
- }
-
- inst_pid = pid;
- DPRINTF("SetPid pid:%d\n", pid);
- return 0;
-}
-
-static void ResetSingleBuffer(void) {
-}
-
-int ResetBuffer(void) {
- unsigned long spinlock_flags = 0L;
-
- if (GetECState() != EC_STATE_IDLE) {
- EPRINTF("Buffer changes are allowed in IDLE state only!");
- return -1;
- }
-
- ResetSingleBuffer();
-
- unset_kernel_probes();
-
- spin_lock_irqsave (&ec_spinlock, spinlock_flags);
- ec_info.buffer_effect = ec_info.buffer_size;
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags);
-
- ResetECInfo();
-
- return 0;
-}
-
-static int WriteEventIntoSingleBuffer(char* pEvent, unsigned long nEventSize) {
- unsigned int unused_space;
-
- if(!p_buffer) {
- EPRINTF("Invalid pointer to buffer!");
- ++ec_info.lost_events_count;
- return -1;
- }
- if (ec_info.trace_size == 0 || ec_info.after_last > ec_info.first) {
- unused_space = ec_info.buffer_size - ec_info.after_last;
- if (unused_space > nEventSize) {
- ec_info.after_last = copy_into_cyclic_buffer(p_buffer,
- ec_info.after_last,
- pEvent,
- nEventSize);
- ec_info.saved_events_count++;
- ec_info.buffer_effect = ec_info.buffer_size;
- ec_info.trace_size = ec_info.after_last - ec_info.first;
- } else {
- if (ec_info.first > nEventSize) {
- ec_info.buffer_effect = ec_info.after_last;
- ec_info.after_last = copy_into_cyclic_buffer(p_buffer,
- 0,
- pEvent,
- nEventSize);
- ec_info.saved_events_count++;
- ec_info.trace_size = ec_info.buffer_effect
- - ec_info.first
- + ec_info.after_last;
- } else {
- // TODO: consider two variants!
- // Do nothing
- ec_info.discarded_events_count++;
- }
- }
- } else {
- unused_space = ec_info.first - ec_info.after_last;
- if (unused_space > nEventSize) {
- ec_info.after_last = copy_into_cyclic_buffer(p_buffer,
- ec_info.after_last,
- pEvent,
- nEventSize);
- ec_info.saved_events_count++;
- ec_info.trace_size = ec_info.buffer_effect
- - ec_info.first
- + ec_info.after_last;
- } else {
- // Do nothing
- ec_info.discarded_events_count++;
- }
- }
- return 0;
-}
-
-static int WriteEventIntoBuffer(char* pEvent, unsigned long nEventSize) {
-
- /*unsigned long i;
- for(i = 0; i < nEventSize; i++)
- printk("%02X ", pEvent[i]);
- printk("\n");*/
-
- return WriteEventIntoSingleBuffer(pEvent, nEventSize);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-int set_event_mask (int new_mask)
-{
- unsigned long spinlock_flags = 0L;
- spin_lock_irqsave (&ec_spinlock, spinlock_flags);
- event_mask = new_mask;
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags);
- return 0;
-}
-
-int
-get_event_mask (int *mask)
-{
- *mask = event_mask;
- return 0;
-}
-
-static void
-generic_swap (void *a, void *b, int size)
-{
- char t;
- do {
- t = *(char *) a;
- *(char *) a++ = *(char *) b;
- *(char *) b++ = t;
- } while (--size > 0);
-}
-
-static void sort (void *base, size_t num, size_t size, int (*cmp) (const void *, const void *), void (*fswap) (void *, void *, int size))
-{
- /* pre-scale counters for performance */
- int i = (num / 2) * size, n = num * size, c, r;
-
- /* heapify */
- for (; i >= 0; i -= size)
- {
- for (r = i; r * 2 < n; r = c)
- {
- c = r * 2;
- if (c < n - size && cmp (base + c, base + c + size) < 0)
- c += size;
- if (cmp (base + r, base + c) >= 0)
- break;
- fswap (base + r, base + c, size);
- }
- }
-
- /* sort */
- for (i = n - size; i >= 0; i -= size)
- {
- fswap (base, base + i, size);
- for (r = 0; r * 2 < i; r = c)
- {
- c = r * 2;
- if (c < i - size && cmp (base + c, base + c + size) < 0)
- c += size;
- if (cmp (base + r, base + c) >= 0)
- break;
- fswap (base + r, base + c, size);
- }
- }
-}
-
-static int addr_cmp (const void *a, const void *b)
-{
- return *(unsigned long *) a > *(unsigned long *) b ? -1 : 1;
-}
-
-static char *find_lib_path(const char *lib_name)
-{
- char *p = deps + sizeof(size_t);
- char *match;
- size_t len;
-
- while (*p != '\0') {
- DPRINTF("p is at %s", p);
- len = strlen(p) + 1;
- match = strstr(p, lib_name);
- p += len;
- len = strlen(p) + 1; /* we are at path now */
- if (!match) {
- p += len;
- } else {
- DPRINTF("Found match: %s", match);
- return p;
- }
- }
-
- return NULL;
-}
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27)
-#define list_for_each_rcu(pos, head) __list_for_each_rcu(pos, head)
-#endif
-
-void unlink_bundle(void)
-{
- int i, k;
- us_proc_lib_t *d_lib;
- char *path;
- struct list_head *pos; //, *tmp;
-
- path = us_proc_info.path;
- us_proc_info.path = NULL;
-
- // first make sure "d_lib" is not used any more and only
- // then release storage
- if (us_proc_info.p_libs)
- {
- int count1 = us_proc_info.libs_count;
- us_proc_info.libs_count = 0;
- for (i = 0; i < count1; i++)
- {
- d_lib = &us_proc_info.p_libs[i];
- if (d_lib->p_ips)
- {
- // first make sure "d_lib->p_ips" is not used any more and only
- // then release storage
- //int count2 = d_lib->ips_count;
- d_lib->ips_count = 0;
- /*for (k = 0; k < count2; k++)
- kfree ((void *) d_lib->p_ips[k].name);*/
- vfree ((void *) d_lib->p_ips);
- }
- if (d_lib->p_vtps)
- {
- // first make sure "d_lib->p_vtps" is not used any more and only
- // then release storage
- int count2 = d_lib->vtps_count;
- d_lib->vtps_count = 0;
- for (k = 0; k < count2; k++)
- {
- //list_for_each_safe_rcu(pos, tmp, &d_lib->p_vtps[k].list) {
- list_for_each (pos, &d_lib->p_vtps[k].list)
- {
- us_proc_vtp_data_t *vtp = list_entry (pos, us_proc_vtp_data_t, list);
- list_del_rcu (pos);
- //kfree (vtp->name);
- kfree (vtp);
- }
- }
- kfree ((void *) d_lib->p_vtps);
- }
- d_lib->plt_count = 0;
- kfree((void*) d_lib->p_plt);
- us_proc_info.is_plt = 0;
- }
- kfree ((void *) us_proc_info.p_libs);
- us_proc_info.p_libs = NULL;
- }
- /* if (path) */
- /* { */
- /* kfree ((void *) path); */
- /* //putname(path); */
- /* } */
-
- us_proc_info.tgid = 0;
-}
-
-extern struct dentry *dentry_by_path(const char *path);
-
-int link_bundle(void)
-{
- inst_us_proc_t *my_uprobes_info = get_uprobes();
- char *p = bundle; /* read pointer for bundle */
- int nr_kern_probes;
- int i, j, l, k;
- int len;
- us_proc_lib_t *d_lib, *pd_lib;
- ioctl_usr_space_lib_t s_lib;
- ioctl_usr_space_vtp_t *s_vtp;
- us_proc_vtp_t *mvtp;
- int is_app = 0;
- char *ptr;
- us_proc_ip_t *d_ip;
- struct cond *c, *c_tmp, *p_cond;
- size_t nr_conds;
- int lib_name_len;
- int handler_index;
-
- DPRINTF("Going to release us_proc_info");
- if (us_proc_info.path)
- unlink_bundle();
-
- /* Skip size - it has been used before */
- p += sizeof(u_int32_t);
-
- /* Set mode */
- if (SetECMode(*(u_int32_t *)p) == -1)
- {
- EPRINTF("Cannot set mode!\n");
- return -1;
- }
-
- p += sizeof(u_int32_t);
-
- /* Buffer size */
- if (SetBufferSize(*(u_int32_t *)p) == -1)
- {
- EPRINTF("Cannot set buffer size!\n");
- return -1;
- }
-
- p += sizeof(u_int32_t);
-
- /* Pid */
- if (SetPid(*(u_int32_t *)p) == -1)
- {
- EPRINTF("Cannot set pid!\n");
- return -1;
- }
-
- p += sizeof(u_int32_t);
-
- /* Kernel probes */
- nr_kern_probes = *(u_int32_t *)p;
- p += sizeof(u_int32_t);
- for (i = 0; i < nr_kern_probes; i++)
- {
- unsigned long addr = *(u_int32_t *)p;
- unsigned long pre_handler = 0, jp_handler = 0, rp_handler = 0;
-
- dbi_find_and_set_handler_for_probe(addr, &pre_handler, &jp_handler, &rp_handler);
-
- if (add_probe(addr, pre_handler, jp_handler, rp_handler)) {
- EPRINTF("Cannot add kernel probe at 0x%x!\n", addr);
- return -1;
- }
- p += sizeof(u_int32_t);
- }
-
- /* Us probes */
- len = *(u_int32_t *)p; /* App path len */
- p += sizeof(u_int32_t);
-
- us_proc_info.is_plt = 0;
- if ( len == 0 )
- {
- us_proc_info.path = NULL;
- }
- else
- {
- int lib_path_len;
- char *lib_path;
-
- us_proc_info.path = (char *)p;
- DPRINTF("app path = %s", us_proc_info.path);
- p += len;
-
- if (strcmp(us_proc_info.path, "*")) {
- us_proc_info.m_f_dentry = dentry_by_path(us_proc_info.path);
- if (us_proc_info.m_f_dentry == NULL) {
- update_errno_buffer(us_proc_info.path, IS_APP);
- return -1;
- }
- }
- else
- {
- us_proc_info.m_f_dentry = NULL;
- }
-
- us_proc_info.libs_count = *(u_int32_t *)p;
- DPRINTF("nr of libs = %d", us_proc_info.libs_count);
- p += sizeof(u_int32_t);
- us_proc_info.p_libs =
- kmalloc(us_proc_info.libs_count * sizeof(us_proc_lib_t), GFP_KERNEL);
-
- if (!us_proc_info.p_libs)
- {
- EPRINTF("Cannot alloc p_libs!");
- return -1;
- }
- memset(us_proc_info.p_libs, 0,
- us_proc_info.libs_count * sizeof(us_proc_lib_t));
-
- for (i = 0; i < us_proc_info.libs_count; i++)
- {
- int abs_handler_idx = 0;
-
- d_lib = &us_proc_info.p_libs[i];
-
- lib_name_len = *(u_int32_t *)p;
- p += sizeof(u_int32_t);
- d_lib->path = (char *)p;
- DPRINTF("d_lib->path = %s", d_lib->path);
- p += lib_name_len;
-
- if ( i != 0 ) {
- lib_name_len = *(u_int32_t *)p;
- p += sizeof(u_int32_t);
- d_lib->path_dyn = (char *)p;
- DPRINTF("d_lib->path_dyn = %s", d_lib->path_dyn);
- p += lib_name_len;
- }
-
- d_lib->ips_count = *(u_int32_t *)p;
- DPRINTF("d_lib->ips_count = %d", d_lib->ips_count);
- p += sizeof(u_int32_t);
-
- /* If there are any probes for "*" app we have to drop them */
- if (strcmp(d_lib->path, "*") == 0)
- {
- p += d_lib->ips_count * 3 * sizeof(u_int32_t);
- d_lib->ips_count = 0;
- d_lib->plt_count = *(u_int32_t*)p;
- p += sizeof(u_int32_t);
- p += d_lib->plt_count * 2 * sizeof(u_int32_t);
- d_lib->plt_count = 0;
- continue;
- }
-
- if (strcmp(us_proc_info.path, d_lib->path) == 0)
- is_app = 1;
- else
- {
- is_app = 0;
- DPRINTF("Searching path for lib %s", d_lib->path);
- d_lib->path = find_lib_path(d_lib->path);
- if (!d_lib->path)
- {
- if (strcmp(d_lib->path_dyn, "") == 0) {
- EPRINTF("Cannot find path for lib %s!", d_lib->path);
- if (update_errno_buffer(d_lib->path, IS_LIB) == -1) {
- return -1;
- }
- /* Just skip all the IPs and go to next lib */
- p += d_lib->ips_count * 3 * sizeof(u_int32_t);
- d_lib->ips_count = 0;
- d_lib->plt_count = *(u_int32_t*)p;
- p += sizeof(u_int32_t);
- p += d_lib->plt_count * 2 * sizeof(u_int32_t);
- d_lib->plt_count = 0;
- continue;
- }
- else {
- d_lib->path = d_lib->path_dyn;
- DPRINTF("Assign path for lib as %s (in suggestion of dyn lib)", d_lib->path);
- }
- }
- }
-
- d_lib->m_f_dentry = dentry_by_path(d_lib->path);
- if (d_lib->m_f_dentry == NULL) {
- EPRINTF ("failed to lookup dentry for path %s!", d_lib->path);
- if (update_errno_buffer(d_lib->path, IS_LIB) == -1) {
- return -1;
- }
- /* Just skip all the IPs and go to next lib */
- p += d_lib->ips_count * 3 * sizeof(u_int32_t);
- d_lib->ips_count = 0;
- d_lib->plt_count = *(u_int32_t*)p;
- p += sizeof(u_int32_t);
- p += d_lib->plt_count * 2 * sizeof(u_int32_t);
- d_lib->plt_count = 0;
- continue;
- }
-
- pd_lib = NULL;
- ptr = strrchr(d_lib->path, '/');
- if (ptr)
- ptr++;
- else
- ptr = d_lib->path;
-
- for (l = 0; l < my_uprobes_info->libs_count; l++)
- {
- if ((strcmp(ptr, my_uprobes_info->p_libs[l].path) == 0) ||
- (is_app && *(my_uprobes_info->p_libs[l].path) == '\0'))
- {
- pd_lib = &my_uprobes_info->p_libs[l];
- break;
- }
- abs_handler_idx += my_uprobes_info->p_libs[l].ips_count;
- }
-
- if (d_lib->ips_count > 0)
- {
- us_proc_info.unres_ips_count += d_lib->ips_count;
- d_lib->p_ips = vmalloc(d_lib->ips_count * sizeof(us_proc_ip_t));
- DPRINTF("d_lib[%i]->p_ips=%p/%u [%s]", i, d_lib->p_ips,
- us_proc_info.unres_ips_count, d_lib->path);
-
- if (!d_lib->p_ips)
- {
- EPRINTF("Cannot alloc p_ips!\n");
- return -1;
- }
-
- memset (d_lib->p_ips, 0, d_lib->ips_count * sizeof(us_proc_ip_t));
- for (k = 0; k < d_lib->ips_count; k++)
- {
- d_ip = &d_lib->p_ips[k];
- d_ip->offset = *(u_int32_t *)p;
- p += sizeof(u_int32_t);
- p += sizeof(u_int32_t); /* Skip inst type */
- handler_index = *(u_int32_t *)p;
- p += sizeof(u_int32_t);
-
- if (pd_lib)
- {
- DPRINTF("pd_lib->ips_count = 0x%x", pd_lib->ips_count);
- if (handler_index != -1)
- {
- DPRINTF("found handler for 0x%x", d_ip->offset);
- d_ip->jprobe.pre_entry =
- pd_lib->p_ips[handler_index - abs_handler_idx].jprobe.pre_entry;
- d_ip->jprobe.entry =
- pd_lib->p_ips[handler_index - abs_handler_idx].jprobe.entry;
- d_ip->retprobe.handler =
- pd_lib->p_ips[handler_index - abs_handler_idx].retprobe.handler;
- }
- }
- }
- }
-
- d_lib->plt_count = *(u_int32_t*)p;
- p += sizeof(u_int32_t);
- if (d_lib->plt_count > 0)
- {
- int j;
- us_proc_info.is_plt = 1;
- d_lib->p_plt = kmalloc(d_lib->plt_count * sizeof(us_proc_plt_t), GFP_KERNEL);
- if (!d_lib->p_plt)
- {
- EPRINTF("Cannot alloc p_plt!");
- return -1;
- }
- memset(d_lib->p_plt, 0, d_lib->plt_count * sizeof(us_proc_plt_t));
- for (j = 0; j < d_lib->plt_count; j++)
- {
- d_lib->p_plt[j].func_addr = *(u_int32_t*)p;
- p += sizeof(u_int32_t);
- d_lib->p_plt[j].got_addr = *(u_int32_t*)p;
- p += sizeof(u_int32_t);
- d_lib->p_plt[j].real_func_addr = 0;
- }
- }
- }
-
- /* Lib path */
- lib_path_len = *(u_int32_t *)p;
- DPRINTF("lib_path_len = %d", lib_path_len);
- p += sizeof(u_int32_t);
- lib_path = p;
- DPRINTF("lib_path = %s", lib_path);
- p += lib_path_len;
-
- /* Link FBI info */
- d_lib = &us_proc_info.p_libs[0];
- s_lib.vtps_count = *(u_int32_t *)p;
- DPRINTF("s_lib.vtps_count = %d", s_lib.vtps_count);
- p += sizeof(u_int32_t);
- if (s_lib.vtps_count > 0)
- {
- unsigned long ucount = 1, pre_addr;
- unsigned long *addrs;
-
- s_lib.p_vtps = kmalloc(s_lib.vtps_count
- * sizeof(ioctl_usr_space_vtp_t), GFP_KERNEL);
- if (!s_lib.p_vtps)
- {
- //kfree (addrs);
- return -1;
- }
-
- for (i = 0; i < s_lib.vtps_count; i++)
- {
- int var_name_len = *(u_int32_t *)p;
- p += sizeof(u_int32_t);
- s_lib.p_vtps[i].name = p;
- p += var_name_len;
- s_lib.p_vtps[i].addr = *(u_int32_t *)p;
- p += sizeof(u_int32_t);
- s_lib.p_vtps[i].type = *(u_int32_t *)p;
- p += sizeof(u_int32_t);
- s_lib.p_vtps[i].size = *(u_int32_t *)p;
- p += sizeof(u_int32_t);
- s_lib.p_vtps[i].reg = *(u_int32_t *)p;
- p += sizeof(u_int32_t);
- s_lib.p_vtps[i].off = *(u_int32_t *)p;
- p += sizeof(u_int32_t);
- }
-
- // array containing elements like (addr, index)
- addrs = kmalloc (s_lib.vtps_count * 2 * sizeof (unsigned long), GFP_KERNEL);
- // DPRINTF ("addrs=%p/%u", addrs, s_lib.vtps_count);
- if (!addrs)
- {
- //note: storage will released next time or at clean-up moment
- return -ENOMEM;
- }
- memset (addrs, 0, s_lib.vtps_count * 2 * sizeof (unsigned long));
- // fill the array in
- for (k = 0; k < s_lib.vtps_count; k++)
- {
- s_vtp = &s_lib.p_vtps[k];
- addrs[2 * k] = s_vtp->addr;
- addrs[2 * k + 1] = k;
- }
- // sort by VTP addresses, i.e. make VTPs with the same addresses adjacent;
- // organize them into bundles
- sort (addrs, s_lib.vtps_count, 2 * sizeof (unsigned long), addr_cmp, generic_swap);
-
- // calc number of VTPs with unique addresses
- for (k = 1, pre_addr = addrs[0]; k < s_lib.vtps_count; k++)
- {
- if (addrs[2 * k] != pre_addr)
- ucount++; // count different only
- pre_addr = addrs[2 * k];
- }
- us_proc_info.unres_vtps_count += ucount;
- d_lib->vtps_count = ucount;
- d_lib->p_vtps = kmalloc (ucount * sizeof (us_proc_vtp_t), GFP_KERNEL);
- DPRINTF ("d_lib[%i]->p_vtps=%p/%lu", i, d_lib->p_vtps, ucount); //, d_lib->path);
- if (!d_lib->p_vtps)
- {
- //note: storage will released next time or at clean-up moment
- kfree (addrs);
- return -ENOMEM;
- }
- memset (d_lib->p_vtps, 0, d_lib->vtps_count * sizeof (us_proc_vtp_t));
- // go through sorted VTPS.
- for (k = 0, j = 0, pre_addr = 0, mvtp = NULL; k < s_lib.vtps_count; k++)
- {
- us_proc_vtp_data_t *vtp_data;
- // copy VTP data
- s_vtp = &s_lib.p_vtps[addrs[2 * k + 1]];
- // if this is the first VTP in bundle (master VTP)
- if (addrs[2 * k] != pre_addr)
- {
- // data are in the array of master VTPs
- mvtp = &d_lib->p_vtps[j++];
- mvtp->addr = s_vtp->addr;
- INIT_LIST_HEAD (&mvtp->list);
- }
- // data are in the list of slave VTPs
- vtp_data = kmalloc (sizeof (us_proc_vtp_data_t), GFP_KERNEL);
- if (!vtp_data)
- {
- //note: storage will released next time or at clean-up moment
- kfree (addrs);
- return -ENOMEM;
- }
-
- /*len = strlen_user (s_vtp->name);
- vtp_data->name = kmalloc (len, GFP_KERNEL);
- if (!vtp_data->name)
- {
- //note: storage will released next time or at clean-up moment
- kfree (vtp_data);
- kfree (addrs);
- return -ENOMEM;
- }
- if (strncpy_from_user (vtp_data->name, s_vtp->name, len) != (len-1))
- {
- //note: storage will released next time or at clean-up moment
- EPRINTF ("strncpy_from_user VTP name failed %p (%ld)", vtp_data->name, len);
- kfree (vtp_data->name);
- kfree (vtp_data);
- kfree (addrs);
- return -EFAULT;
- }
- //vtp_data->name[len] = 0;*/
- vtp_data->name = s_vtp->name;
- vtp_data->type = s_vtp->type;
- vtp_data->size = s_vtp->size;
- vtp_data->reg = s_vtp->reg;
- vtp_data->off = s_vtp->off;
- list_add_tail_rcu (&vtp_data->list, &mvtp->list);
- pre_addr = addrs[2 * k];
- }
- kfree (addrs);
- kfree(s_lib.p_vtps);
- }
- }
-
- /* Conds */
- /* first, delete all the conds */
- list_for_each_entry_safe(c, c_tmp, &cond_list.list, list) {
- list_del(&c->list);
- kfree(c);
- }
- /* second, add new conds */
- /* This can be improved (by placing conds into array) */
- nr_conds = *(u_int32_t *)p;
- DPRINTF("nr_conds = %d", nr_conds);
- p += sizeof(u_int32_t);
- for (i = 0; i < nr_conds; i++) {
- p_cond = kmalloc(sizeof(struct cond), GFP_KERNEL);
- if (!p_cond) {
- EPRINTF("Cannot alloc cond!\n");
- return -1;
- break;
- }
- memcpy(&p_cond->tmpl, p, sizeof(struct event_tmpl));
- p_cond->applied = 0;
- list_add(&(p_cond->list), &(cond_list.list));
- p += sizeof(struct event_tmpl);
- }
-
- /* Event mask */
- if (set_event_mask(*(u_int32_t *)p)) {
- EPRINTF("Cannot set event mask!");
- return -1;
- }
-
- p += sizeof(u_int32_t);
-
- // print
-// print_inst_us_proc(&us_proc_info);
-
- us_proc_info.pp = get_file_probes(&us_proc_info);
-
- return 0;
-}
-
-void pack_task_event_info(struct task_struct *task, probe_id_t probe_id,
- record_type_t record_type, const char *fmt, ...);
-
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
-int storage_init (void)
-{
- unsigned long spinlock_flags = 0L;
-
- spin_lock_irqsave (&ec_spinlock, spinlock_flags);
- ec_info.m_nMode = 0; // MASK IS CLEAR (SINGLE NON_CONTINUOUS BUFFER)
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags);
-
- if(InitializeBuffer(EC_BUFFER_SIZE_DEFAULT) == -1) {
- EPRINTF("Cannot initialize buffer! [Size=%u KB]", EC_BUFFER_SIZE_DEFAULT / 1024 );
- return -1;
- }
-
- spin_lock_init(&dbi_mh.lock);
- INIT_LIST_HEAD(&dbi_mh.modules_handlers);
-
- ptr_pack_task_event_info = pack_task_event_info;
-
- return 0;
-}
-
-/*
- Shuts down "storage".
- Assumes that all probes are already deactivated.
-*/
-void storage_down (void)
-{
- if(UninitializeBuffer() == -1)
- EPRINTF("Cannot uninitialize buffer!");
-
- if (ec_info.collision_count)
- EPRINTF ("ec_info.collision_count=%d", ec_info.collision_count);
- if (ec_info.lost_events_count)
- EPRINTF ("ec_info.lost_events_count=%d", ec_info.lost_events_count);
-}
-
-static u_int32_t get_probe_func_addr(const char *fmt, va_list args)
-{
- if (fmt[0] != 'p')
- return 0;
-
- return va_arg(args, u_int32_t);
-}
-
-void pack_task_event_info(struct task_struct *task, probe_id_t probe_id,
- record_type_t record_type, const char *fmt, ...)
-{
- unsigned long spinlock_flags = 0L;
- static char buf[EVENT_MAX_SIZE] = "";
- TYPEOF_EVENT_LENGTH event_len = 0L;
- struct timeval tv = { 0, 0 };
- TYPEOF_THREAD_ID current_pid = task->pid;
- TYPEOF_PROCESS_ID current_tgid = task->tgid;
- unsigned current_cpu = task_cpu(task);
- va_list args;
- unsigned long addr = 0;
- struct cond *p_cond;
- struct event_tmpl *p_tmpl;
-
- do_gettimeofday (&tv);
-
- if (probe_id == KS_PROBE_ID) {
- va_start(args, fmt);
- addr = get_probe_func_addr(fmt, args);
- va_end(args);
- }
- if (probe_id == US_PROBE_ID) {
- va_start(args, fmt);
- addr = get_probe_func_addr(fmt, args);
- va_end(args);
- }
-
- /* Checking for all the conditions
- * except stop condition that we process after saving the event */
- list_for_each_entry(p_cond, &cond_list.list, list) {
- p_tmpl = &p_cond->tmpl;
- switch (p_tmpl->type) {
- case ET_TYPE_START_COND:
- if ((!ET_FIELD_ISSET(p_tmpl->flags, ET_MATCH_ADDR) ||
- (addr == p_tmpl->addr)) &&
- (!ET_FIELD_ISSET(p_tmpl->flags, ET_MATCH_PID) ||
- (current_tgid == p_tmpl->pid)) &&
- (!ET_FIELD_ISSET(p_tmpl->flags, ET_MATCH_TID) ||
- (current_pid == p_tmpl->tid)) &&
- (!ET_FIELD_ISSET(p_tmpl->flags, ET_MATCH_CPU_NUM) ||
- (current_cpu == p_tmpl->cpu_num)) &&
- (!ET_FIELD_ISSET(p_tmpl->flags, ET_MATCH_BIN_NAME) ||
- (strcmp(task->comm, p_tmpl->bin_name) == 0)) &&
- (!ET_FIELD_ISSET(p_tmpl->flags, ET_MATCH_TIME) ||
- (tv.tv_sec > last_attach_time.tv_sec + p_tmpl->sec) ||
- (tv.tv_sec == last_attach_time.tv_sec + p_tmpl->sec &&
- tv.tv_usec >= last_attach_time.tv_usec + p_tmpl->usec)) &&
- !p_cond->applied) {
- spin_lock_irqsave(&ec_spinlock, spinlock_flags);
- paused = 0;
- p_cond->applied = 1;
- spin_unlock_irqrestore(&ec_spinlock, spinlock_flags);
- }
- break;
- case ET_TYPE_IGNORE_COND:
- /* if (probe_id == PROBE_SCHEDULE) */
- /* break; */
- if ((!ET_FIELD_ISSET(p_tmpl->flags, ET_MATCH_ADDR) ||
- (addr == p_tmpl->addr)) &&
- (!ET_FIELD_ISSET(p_tmpl->flags, ET_MATCH_PID) ||
- (current_tgid == p_tmpl->pid)) &&
- (!ET_FIELD_ISSET(p_tmpl->flags, ET_MATCH_TID) ||
- (current_pid == p_tmpl->tid)) &&
- (!ET_FIELD_ISSET(p_tmpl->flags, ET_MATCH_CPU_NUM) ||
- (current_cpu == p_tmpl->cpu_num)) &&
- (!ET_FIELD_ISSET(p_tmpl->flags, ET_MATCH_BIN_NAME) ||
- (strcmp(task->comm, p_tmpl->bin_name) == 0))) {
- spin_lock_irqsave(&ec_spinlock, spinlock_flags);
- ec_info.ignored_events_count++;
- spin_unlock_irqrestore(&ec_spinlock, spinlock_flags);
- return;
- }
- break;
- }
- }
-
- /* Save only not masked entry or return kernel and user space events */
- if (likely(!((probe_id == KS_PROBE_ID || probe_id == US_PROBE_ID)
- && ((record_type == RECORD_ENTRY && (event_mask & IOCTL_EMASK_ENTRY))
- || (record_type == RECORD_RET && (event_mask & IOCTL_EMASK_EXIT)))))) {
-
- spin_lock_irqsave (&ec_spinlock, spinlock_flags);
-
- if (paused && (!(probe_id == EVENT_FMT_PROBE_ID || probe_id == DYN_LIB_PROBE_ID))) {
- ec_info.ignored_events_count++;
- spin_unlock_irqrestore(&ec_spinlock, spinlock_flags);
- return;
- }
-
- va_start (args, fmt);
- event_len = VPackEvent(buf, sizeof(buf), event_mask, probe_id, record_type, (TYPEOF_TIME *)&tv,
- current_tgid, current_pid, current_cpu, fmt, args);
- va_end (args);
-
- if(event_len == 0) {
- EPRINTF ("ERROR: failed to pack event!");
- ++ec_info.lost_events_count;
-
- } else if(WriteEventIntoBuffer(buf, event_len) == -1) {
- EPRINTF("Cannot write event into buffer!");
- ++ec_info.lost_events_count;
- }
- spin_unlock_irqrestore(&ec_spinlock, spinlock_flags);
-
- }
-
- /* Check for stop condition. We pause collecting the trace right after
- * storing this event */
- list_for_each_entry(p_cond, &cond_list.list, list) {
- p_tmpl = &p_cond->tmpl;
- switch (p_tmpl->type) {
- case ET_TYPE_STOP_COND:
- if ((!ET_FIELD_ISSET(p_tmpl->flags, ET_MATCH_ADDR) ||
- (addr == p_tmpl->addr)) &&
- (!ET_FIELD_ISSET(p_tmpl->flags, ET_MATCH_PID) ||
- (current_tgid == p_tmpl->pid)) &&
- (!ET_FIELD_ISSET(p_tmpl->flags, ET_MATCH_TID) ||
- (current_pid == p_tmpl->tid)) &&
- (!ET_FIELD_ISSET(p_tmpl->flags, ET_MATCH_CPU_NUM) ||
- (current_cpu == p_tmpl->cpu_num)) &&
- (!ET_FIELD_ISSET(p_tmpl->flags, ET_MATCH_BIN_NAME) ||
- (strcmp(task->comm, p_tmpl->bin_name) == 0)) &&
- (!ET_FIELD_ISSET(p_tmpl->flags, ET_MATCH_TIME) ||
- (tv.tv_sec > last_attach_time.tv_sec + p_tmpl->sec) ||
- (tv.tv_sec == last_attach_time.tv_sec + p_tmpl->sec &&
- tv.tv_usec >= last_attach_time.tv_usec + p_tmpl->usec)) &&
- !p_cond->applied) {
- spin_lock_irqsave(&ec_spinlock, spinlock_flags);
- paused = 1;
- p_cond->applied = 1;
- spin_unlock_irqrestore(&ec_spinlock, spinlock_flags);
- }
- break;
- }
- }
-}
-EXPORT_SYMBOL_GPL(pack_task_event_info);
-
-int put_us_event (char *data, unsigned long len)
-{
- unsigned long spinlock_flags = 0L;
-
- SWAP_TYPE_EVENT_HEADER *pEventHeader = (SWAP_TYPE_EVENT_HEADER *)data;
- char *cur = data + sizeof(TYPEOF_EVENT_LENGTH) + sizeof(TYPEOF_EVENT_TYPE)
- + sizeof(TYPEOF_PROBE_ID);
- TYPEOF_NUMBER_OF_ARGS nArgs = pEventHeader->m_nNumberOfArgs;
- TYPEOF_PROBE_ID probe_id = pEventHeader->m_nProbeID;
- //int i;
-
- /*if(probe_id == US_PROBE_ID){
- printk("esrc %p/%d[", data, len);
- for(i = 0; i < len; i++)
- printk("%02x ", data[i]);
- printk("]\n");
- }*/
-
- // set pid/tid/cpu/time i
- //pEventHeader->m_time.tv_sec = tv.tv_sec;
- //pEventHeader->m_time.tv_usec = tv.tv_usec;
-
-#ifdef MEMORY_CHECKER
- //TODO: move this part to special MEC event posting routine, new IOCTL is needed
- if((probe_id >= MEC_PROBE_ID_MIN) && (probe_id <= MEC_PROBE_ID_MAX))
- {
- if(mec_post_event != NULL)
- {
- int res = mec_post_event(data, len);
- if(res == -1)
- {
- return -1;
- }
- }
- else
- {
- // FIXME: 'mec_post_event' - not found
- mec_post_event = (mec_post_event_pointer) swap_ksyms("mec_post_event");
- if(mec_post_event == NULL)
- {
- EPRINTF ("Failed to find function 'mec_post_event' from mec_handlers.ko. Memory Error Checker will work incorrectly.");
- }
- else
- {
- int res = mec_post_event(data, len);
- if(res == -1)
- {
- return -1;
- }
- }
- }
- }
-#endif
-
- if((probe_id == EVENT_FMT_PROBE_ID) || !(event_mask & IOCTL_EMASK_TIME)){
- struct timeval tv = { 0, 0 };
- do_gettimeofday (&tv);
- memcpy(cur, &tv, sizeof(TYPEOF_TIME));
- cur += sizeof(TYPEOF_TIME);
- }
- //pEventHeader->m_nProcessID = current_tgid;
- if((probe_id == EVENT_FMT_PROBE_ID) || !(event_mask & IOCTL_EMASK_PID)){
- //TYPEOF_PROCESS_ID current_tgid = current->tgid;
- (*(TYPEOF_PROCESS_ID *)cur) = current->tgid;
- cur += sizeof(TYPEOF_PROCESS_ID);
- }
- //pEventHeader->m_nThreadID = current_pid;
- if((probe_id == EVENT_FMT_PROBE_ID) || !(event_mask & IOCTL_EMASK_TID)){
- //TYPEOF_THREAD_ID current_pid = current->pid;
- (*(TYPEOF_THREAD_ID *)cur) = current->pid;
- cur += sizeof(TYPEOF_THREAD_ID);
- }
- //pEventHeader->m_nCPU = current_cpu;
- if((probe_id == EVENT_FMT_PROBE_ID) || !(event_mask & IOCTL_EMASK_CPU)){
- //TYPEOF_CPU_NUMBER current_cpu = task_cpu(current);
- (*(TYPEOF_CPU_NUMBER *)cur) = task_cpu(current);
- cur += sizeof(TYPEOF_CPU_NUMBER);
- }
- //printk("%d %x", probe_id, event_mask);
- // dyn lib event should have all args, it is for internal use and not visible to user
- if((probe_id == EVENT_FMT_PROBE_ID) || (probe_id == DYN_LIB_PROBE_ID) || !(event_mask & IOCTL_EMASK_ARGS)){
- // move only if any of prev fields has been skipped
- if(event_mask & (IOCTL_EMASK_TIME|IOCTL_EMASK_PID|IOCTL_EMASK_TID|IOCTL_EMASK_CPU)){
- memmove(cur, data+sizeof(SWAP_TYPE_EVENT_HEADER)-sizeof(TYPEOF_NUMBER_OF_ARGS),
- len-sizeof(SWAP_TYPE_EVENT_HEADER)+sizeof(TYPEOF_NUMBER_OF_ARGS)
- -sizeof(TYPEOF_EVENT_LENGTH));
- }
- cur += len-sizeof(SWAP_TYPE_EVENT_HEADER)+sizeof(TYPEOF_NUMBER_OF_ARGS)
- -sizeof(TYPEOF_EVENT_LENGTH);
- }
- else{
- // user space probes should have at least one argument to identify them
- if((probe_id == US_PROBE_ID) || (probe_id == VTP_PROBE_ID)){
- char *pArg1;
- (*(TYPEOF_NUMBER_OF_ARGS *)cur) = 1;
- cur += sizeof(TYPEOF_NUMBER_OF_ARGS);
- // pack args using format string for the 1st arg only
- memset(cur, 0, ALIGN_VALUE(2));
- cur[0] = 'p'; cur[1] = '\0';
- cur += ALIGN_VALUE(2);
- pArg1 = data + sizeof(SWAP_TYPE_EVENT_HEADER)+ALIGN_VALUE(nArgs+1);
- memmove(cur, pArg1, sizeof(unsigned long));
- cur += sizeof(unsigned long);
- }
- else {
- (*(TYPEOF_NUMBER_OF_ARGS *)cur) = 0;
- cur += sizeof(TYPEOF_NUMBER_OF_ARGS);
- }
- }
- pEventHeader->m_nLength = cur - data + sizeof(TYPEOF_EVENT_LENGTH);
- *((TYPEOF_EVENT_LENGTH *)cur) = pEventHeader->m_nLength;
- len = pEventHeader->m_nLength;
-
- if(WriteEventIntoBuffer(data, len) == -1) {
- EPRINTF("Cannot write event into buffer!");
-
- spin_lock_irqsave (&ec_spinlock, spinlock_flags);
- ++ec_info.lost_events_count;
- spin_unlock_irqrestore (&ec_spinlock, spinlock_flags);
- }
-
- return 0;
-}
-
-
-int get_predef_uprobes_size(int *size)
-{
- int i, k;
- inst_us_proc_t *my_uprobes_info = get_uprobes();
-
- *size = 0;
- for(i = 0; i < my_uprobes_info->libs_count; i++)
- {
- int lib_size = strlen(my_uprobes_info->p_libs[i].path);
- for(k = 0; k < my_uprobes_info->p_libs[i].ips_count; k++)
- {
- // libc.so.6:printf:
- *size += lib_size + 1 + strlen(my_uprobes_info->p_libs[i].p_ips[k].name) + 2;
- }
- }
-
- return 0;
-}
-
-int get_predef_uprobes(ioctl_predef_uprobes_info_t *udata)
-{
- ioctl_predef_uprobes_info_t data;
- int i, k, size, lib_size, func_size, result;
- unsigned count = 0;
- char sep[] = ":";
- inst_us_proc_t *my_uprobes_info = get_uprobes();
-
- // get addr of array
- if (copy_from_user ((void *)&data, (void __user *) udata, sizeof (data)))
- {
- EPRINTF("failed to copy from user!");
- return -EFAULT;
- }
-
- size = 0;
- for(i = 0; i < my_uprobes_info->libs_count; i++)
- {
- lib_size = strlen(my_uprobes_info->p_libs[i].path);
- for(k = 0; k < my_uprobes_info->p_libs[i].ips_count; k++)
- {
- // libname
- result = copy_to_user ((void __user *)(data.p_probes+size),
- (void *) my_uprobes_info->p_libs[i].path, lib_size);
- if (result)
- {
- EPRINTF("failed to copy to user!");
- return -EFAULT;
- }
- size += lib_size;
- // ":"
- result = copy_to_user ((void __user *)(data.p_probes+size), sep, 1);
- if (result)
- {
- EPRINTF("failed to copy to user!");
- return -EFAULT;
- }
- size++;
- // probename
- //DPRINTF("'%s'", my_uprobes_info->p_libs[i].p_ips[k].name);
- func_size = strlen(my_uprobes_info->p_libs[i].p_ips[k].name);
- result = copy_to_user ((void __user *)(data.p_probes+size), my_uprobes_info->p_libs[i].p_ips[k].name, func_size);
- if (result)
- {
- EPRINTF("failed to copy to user!");
- return -EFAULT;
- }
- size += func_size;
- // ":\0"
- result = copy_to_user ((void __user *)(data.p_probes+size), sep, 2);
- if (result)
- {
- EPRINTF("failed to copy to user!");
- return -EFAULT;
- }
- size += 2;
- count++;
- }
- }
-
- // set probes_count
- result = copy_to_user ((void __user *)&(udata->probes_count), &count, sizeof(count));
- if (result)
- {
- EPRINTF("failed to copy to user!");
- return -EFAULT;
- }
-
- return 0;
-}
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: storage.h
-//
-// DESCRIPTION:
-// This file is C source for SWAP.
-//
-// SEE ALSO: storage.c
-// AUTHOR: L.Komkov, S.Dianov, A.Gerenkov
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.02.15
-// VERSION: 1.0
-// REVISION DATE: 2008.12.03
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-#if !defined(__STORAGE_H__)
-#define __STORAGE_H__
-
-#include <linux/mount.h>
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <dbi_kprobes.h>
-#include "picl.h"
-#include "ec_ioctl.h"
-#include "ec_probe.h"
-#include "probes_manager.h"
-#include "probes.h"
-#include "event_tmpl.h"
-#include "error_storage.h"
-
-extern int EnableContinuousRetrieval(void);
-extern int DisableContinuousRetrieval(void);
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-extern unsigned int GetBufferSize(void);
-extern int SetBufferSize(unsigned int nSize);
-extern int ResetBuffer(void);
-
-extern int SetPid(unsigned int pid);
-
-//extern spinlock_t buffer_spinlock;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-/*
- Functions "storage_init()" and "storage_down()" are for initialization and
- shutdown respectively.
-*/
-extern int storage_init (void);
-extern void storage_down (void);
-
-/*
- Function "pack_event_info()" saves information about event into buffer. It
- is used in 'probes' to pack and save event data.
-*/
-
-extern void (*ptr_pack_task_event_info)(struct task_struct *task,
- int probe_id,
- int record_type,
- const char *fmt, ...);
-
-#define pack_event_info(probe_id, record_type, fmt, ...) \
- ptr_pack_task_event_info(current, probe_id, record_type, \
- fmt, __VA_ARGS__)
-
-/* Set most links from us_proc_info to data in the bundle */
-int link_bundle(void);
-/* Undo the actions of link_bundle() */
-void unlink_bundle(void);
-
-void dbi_find_and_set_handler_for_probe(unsigned long addr,
- unsigned long *pre_entry,
- unsigned long *jp_handler,
- unsigned long *rp_handler);
-
-/*
- Copies event from user space to buffer and updates its pid/tid/cpu/time.
-*/
-extern int put_us_event (char *data, unsigned long len);
-
-/*
- Sets event mask.
-*/
-extern int set_event_mask (int new_mask);
-
-/*
- Gets event mask.
-*/
-extern int get_event_mask (int *mask);
-
-/*
- Sets predefined user space probes info.
-*/
-extern int set_predef_uprobes (ioctl_predef_uprobes_info_t *data);
-/*
- Gets predefined user space probes info length.
-*/
-extern int get_predef_uprobes_size(int *size);
-/*
- Gets predefined user space probes info.
-*/
-extern int get_predef_uprobes(ioctl_predef_uprobes_info_t *data);
-
-
-// internal bookkeeping of storage
-extern char *p_buffer;
-
-// multiple handlers stuff
-/*struct dbi_modules_handlers {
- struct list_head modules_handlers;
- spinlock_t lock;
-};
-
-struct dbi_modules_handlers_info {
- struct module *dbi_module;
- struct handler_map *dbi_handlers;
- int dbi_nr_handlers;
- struct list_head dbi_list_head;
-};
-
-extern int dbi_register_handlers_module(struct dbi_modules_handlers_info *dbi_mhi);
-extern int dbi_unregister_handlers_module(struct dbi_modules_handlers_info *dbi_mhi);
-//unsigned long get_dbi_modules_handlers(void);*/
-
-// event mask
-extern int event_mask;
-
-// process pid to instrument
-extern unsigned int inst_pid;
-
-typedef struct
-{
- struct list_head list;
- char *name;
- int installed;
- struct jprobe jprobe;
- struct kretprobe retprobe;
- unsigned long offset;
- unsigned long got_addr;
-
- unsigned flag_retprobe:1;
- unsigned flag_got:1;
-} us_proc_ip_t;
-
-typedef struct
-{
- int installed;
- struct jprobe jprobe;
- unsigned long addr;
- struct list_head list;
-} us_proc_vtp_t;
-
-typedef struct
-{
- char *name;
- char type;
- unsigned long size;
- signed char reg; // -1 - memory, 0..127 - register number
- long off;
- struct list_head list;
-} us_proc_vtp_data_t;
-
-typedef struct
-{
- unsigned func_addr;
- unsigned got_addr;
- unsigned real_func_addr;
-} us_proc_plt_t;
-
-typedef struct
-{
- char *path;
- char *path_dyn;
- struct dentry *m_f_dentry;
- unsigned ips_count;
- us_proc_ip_t *p_ips;
- unsigned vtps_count;
- us_proc_vtp_t *p_vtps;
- int loaded;
- unsigned plt_count;
- us_proc_plt_t *p_plt;
- unsigned long vma_start;
- unsigned long vma_end;
- unsigned vma_flag;
-} us_proc_lib_t;
-
-
-typedef struct
-{
- char *path;
- struct dentry *m_f_dentry;
- pid_t tgid;
- unsigned unres_ips_count;
- unsigned unres_vtps_count;
- //kprobe_opcode_t *mapped_codelets;
- int is_plt;
- unsigned libs_count;
- us_proc_lib_t *p_libs;
-
- // new_dpf
- struct sspt_proc *pp;
-} inst_us_proc_t;
-
-typedef struct
-{
- unsigned int addr;
- unsigned int inst_type;
- char *name;
- char *class_name;
- char *method_name;
- char *prototype;
-
-}dex_proc_ip_t;
-
-typedef struct
-{
- char *path;
- unsigned ips_count;
- dex_proc_ip_t *p_ips;
-
-}inst_dex_proc_t;
-
-
-struct cond {
- /* cond data itself */
- struct event_tmpl tmpl;
- /* linked list */
- struct list_head list;
- /* has been applied (for start and stop conditions) */
- int applied;
-};
-
-extern struct cond cond_list;
-
-/* macros for testing flags */
-#define ET_FIELD_CLR(flags, field) (flags &= ~field)
-#define ET_FIELD_SET(flags, field) (flags |= field)
-#define ET_FIELD_ISSET(flags, field) ((flags & field) != 0)
-
-extern inst_us_proc_t us_proc_info;
-extern inst_dex_proc_t dex_proc_info;
-
-#endif /* !defined(__STORAGE_H__) */
+++ /dev/null
-#!/bin/sh
-
-
-# name of the file with module
-MODULE_FILE=swap_driver
-
-# device name
-DEVICE=__DEV_NAME__
-
-# name of device visible in /proc/devices
-DEVICE_NAME=${DEVICE}
-
-# name of the device
-DEVICE_FILE=__DEV_DIR__/${DEVICE}
-
-MAJOR=`sed "/${DEVICE_NAME}/ ! d" /proc/devices | sed "s/ ${DEVICE_NAME}//"`
-if [ "${MAJOR}" != "" ] ; then
- echo "SWAP Driver is already loaded!"
- exit 1
- rmmod ${MODULE_FILE}
- MAJOR=`sed "/${DEVICE_NAME}/ ! d" /proc/devices | sed "s/ ${DEVICE_NAME}//"`
- if [ "${MAJOR}" != "" ] ; then
- echo "Error: Unable to unload driver module '${MODULE_FILE}'"
- exit 1
- fi
-fi
-
-# load driver module
-echo "loading module '${MODULE_FILE}'"
-./bin/insmod.sh ${MODULE_FILE}.ko device_name=${DEVICE_NAME}
-if [ $? -ne 0 ]; then
- echo "Error: Unable to load Swap Driver!"
- exit 1
-fi
-
-MAJOR=`sed "/${DEVICE_NAME}/ ! d" /proc/devices | sed "s/ ${DEVICE_NAME}//"`
-DEVICE_MAJOR=${MAJOR}
-if [ ! -c ${DEVICE_FILE} ] ; then
- echo "WARNING: Creating device node with major number [${DEVICE_MAJOR}]!"
- mknod ${DEVICE_FILE} c ${DEVICE_MAJOR} 0
- if [ $? -ne 0 ]; then
- echo "Error: Unable to create device node!"
- exit 1
- fi
- chmod a+r ${DEVICE_FILE}
-fi
/*
- * SWAP Buffer Module
+ * SWAP Driver Module
* modules/buffer/swap_driver_errors.h
*
* This program is free software; you can redistribute it and/or modify
*
* Copyright (C) Samsung Electronics, 2013
*
- * 2013 Alexander Aksenov <a.aksenov@samsung.com>: SWAP Buffer implement
+ * 2013 Alexander Aksenov <a.aksenov@samsung.com>: SWAP Driver implement
*
*/
/*
- * SWAP driver
- * modules/driver_new/swap_driver_module.c
+ * SWAP Driver
+ * modules/driver/swap_driver_module.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
/*
* SWAP driver
- * modules/driver_new/swap_ioctl.h
+ * modules/driver/swap_ioctl.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+++ /dev/null
-#include <linux/module.h>
-#include <asm/percpu.h>
-#include <ec_probe.h>
-#include <picl.h>
-#include <swap_uprobes.h>
-#include <sspt/ip.h>
-#include <dbi_kprobes_deps.h>
-#include "storage.h"
-#include "us_proc_inst.h"
-#include <sspt/sspt.h>
-#include <writer/swap_writer_module.h>
-
-DEFINE_PER_CPU(struct us_ip *, gpCurIp) = NULL;
-EXPORT_PER_CPU_SYMBOL_GPL(gpCurIp);
-DEFINE_PER_CPU(struct pt_regs *, gpUserRegs) = NULL;
-EXPORT_PER_CPU_SYMBOL_GPL(gpUserRegs);
-
-unsigned long ujprobe_event_pre_handler(struct us_ip *ip, struct pt_regs *regs)
-{
- __get_cpu_var(gpCurIp) = ip;
- __get_cpu_var(gpUserRegs) = regs;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(ujprobe_event_pre_handler);
-
-void ujprobe_event_handler(unsigned long arg0, unsigned long arg1,
- unsigned long arg2, unsigned long arg3,
- unsigned long arg4, unsigned long arg5)
-{
- struct us_ip *ip = __get_cpu_var(gpCurIp);
- struct us_ip *regs = __get_cpu_var(gpUserRegs);
- unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
-
-#if defined(CONFIG_ARM)
- addr = ip->offset & 0x01 ? addr | 0x01 : addr;
-#endif
-
- entry_event(ip->jprobe.args, regs, PT_US, PST_NONE);
-
- swap_ujprobe_return();
-}
-EXPORT_SYMBOL_GPL(ujprobe_event_handler);
-
-static void send_plt(struct us_ip *ip)
-{
- unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
- struct vm_area_struct *vma = find_vma(current->mm, addr);
-
- if (vma && check_vma(vma)) {
- char *name = NULL;
- unsigned long real_addr;
- unsigned long real_got = current->mm->exe_file == vma->vm_file ?
- ip->got_addr :
- ip->got_addr + vma->vm_start;
-
- if (!read_proc_vm_atomic(current, real_got, &real_addr, sizeof(real_addr))) {
- printk("Failed to read got %lx at memory address %lx!\n", ip->got_addr, real_got);
- return;
- }
-
- vma = find_vma(current->mm, real_addr);
- if (vma && (vma->vm_start <= real_addr) && (vma->vm_end > real_addr)) {
- name = vma->vm_file ? vma->vm_file->f_dentry->d_iname : NULL;
- } else {
- printk("Failed to get vma, includes %lx address\n", real_addr);
- return;
- }
-
- if (name)
- pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppsp",
- addr, real_addr, name,
- real_addr - vma->vm_start);
- else
- pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppp",
- addr, real_addr,
- real_addr - vma->vm_start);
- }
-}
-
-int uretprobe_event_handler(struct uretprobe_instance *probe,
- struct pt_regs *regs,
- struct us_ip *ip)
-{
- int retval = regs_return_value(regs);
- unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
-
- if (ip->got_addr && ip->flag_got == 0) {
- send_plt(ip);
- ip->flag_got = 1;
- }
-
-#if defined(CONFIG_ARM)
- addr = ip->offset & 0x01 ? addr | 0x01 : addr;
-#endif
-
- exit_event(regs);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(uretprobe_event_handler);
+++ /dev/null
-#ifndef _US_DEF_HANDLER_H
-#define _US_DEF_HANDLER_H
-
-#include <asm/percpu.h>
-
-struct us_ip;
-struct pt_regs;
-struct uretprobe_instance;
-
-DECLARE_PER_CPU(struct us_ip *, gpCurIp);
-DECLARE_PER_CPU(struct pt_regs *, gpUserRegs);
-
-unsigned long ujprobe_event_pre_handler(struct us_ip *ip,
- struct pt_regs *regs);
-void ujprobe_event_handler(unsigned long arg0, unsigned long arg1,
- unsigned long arg2, unsigned long arg3,
- unsigned long arg4, unsigned long arg5);
-int uretprobe_event_handler(struct uretprobe_instance *p,
- struct pt_regs *regs, struct us_ip *ip);
-
-#endif /* _US_DEF_HANDLER_H */
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: us_proc_inst.c
-//
-// DESCRIPTION:
-// This file is C source for SWAP driver.
-//
-// SEE ALSO: us_proc_inst.h
-// AUTHOR: A.Gerenkov, E. Gorelkina
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.06.02
-// VERSION: 1.0
-// REVISION DATE: 2008.12.02
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-#include "module.h"
-#include "us_proc_inst.h"
-
-#include "../kprobe/dbi_kprobes_deps.h"
-#include "../uprobe/swap_uprobes.h"
-
-#include "sspt/sspt.h"
-#include "helper.h"
-#include "us_slot_manager.h"
-
-#define print_event(fmt, args...) \
-{ \
- char *buf[1024]; \
- sprintf(buf, fmt, ##args); \
- pack_event_info(US_PROBE_ID, RECORD_ENTRY, "ds", 0x0badc0de, buf); \
-}
-
-struct dentry *dentry_by_path(const char *path)
-{
- struct dentry *dentry;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
- struct path st_path;
- if (kern_path(path, LOOKUP_FOLLOW, &st_path) != 0) {
-#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
- struct nameidata nd;
- if (path_lookup(path, LOOKUP_FOLLOW, &nd) != 0) {
-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
- EPRINTF("failed to lookup dentry for path %s!", path);
- return NULL;
- }
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
- dentry = nd.dentry;
- path_release(&nd);
-#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 38)
- dentry = nd.path.dentry;
- path_put(&nd.path);
-#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
- dentry = st_path.dentry;
- path_put(&st_path);
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) */
- return dentry;
-}
-
-void print_vma(struct mm_struct *mm);
-
-void print_vma(struct mm_struct *mm)
-{
- struct vm_area_struct *vma;
- printk("### print_vma: START\n");\
- printk("### print_vma: START\n");
-
- for (vma = mm->mmap; vma; vma = vma->vm_next) {
- char *x = vma->vm_flags & VM_EXEC ? "x" : "-";
- char *r = vma->vm_flags & VM_READ ? "r" : "-";
- char *w = vma->vm_flags & VM_WRITE ? "w" : "-";
- char *name = vma->vm_file ? (char *)vma->vm_file->f_dentry->d_iname : "N/A";
-
- printk("### [%8lx..%8lx] %s%s%s pgoff=\'%8lu\' %s\n",
- vma->vm_start, vma->vm_end, x, r, w, vma->vm_pgoff, name);
- }
- printk("### print_vma: END\n");
-}
+++ /dev/null
-////////////////////////////////////////////////////////////////////////////////////
-//
-// FILE: us_proc_inst.h
-//
-// DESCRIPTION:
-//
-// SEE ALSO: us_proc_inst.c
-// AUTHOR: A.Gerenkov
-// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
-// CREATED: 2008.06.02
-// VERSION: 1.0
-// REVISION DATE: 2008.12.03
-//
-////////////////////////////////////////////////////////////////////////////////////
-
-/*
- Functions in "us_proc_inst.h" file .
-*/
-
-#if !defined(__US_PROC_INST_H__)
-#define __US_PROC_INST_H__
-
-#include <linux/signal.h> // struct sigpending
-
-extern pid_t gl_nNotifyTgid;
-
-/* forward declarations */
-struct task_struct;
-struct pt_regs;
-struct us_proc_ip_t;
-struct us_ip;
-struct sspt_file;
-struct sspt_page;
-struct vm_area_struct;
-enum US_FLAGS;
-
-struct dentry *dentry_by_path(const char *path);
-
-#endif /* !defined(__US_PROC_INST_H__) */
+++ /dev/null
-EXTRA_CFLAGS := $(extra_cflags)
-
-obj-m := swap_driver_new.o
-swap_driver_new-y := swap_driver_module.o \
- device_driver.o \
- driver_to_buffer.o
+++ /dev/null
-board_opt = -DBOARD_@BOARD@
-target_kernel_src = @KERNEL@
-target_arch = @ARCH@
-module_dir = $(realpath $(top_srcdir)/src/modules/driver_new)
-module_name = swap_driver_new
-cross_compiler = $(subst gcc,,$(CC))
-
-inlude_opt = -I$(realpath $(top_srcdir)/src/modules/)
-extra_cflags = "$(inlude_opt) $(board_opt)"
-
-all-local:
- $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) extra_cflags=$(extra_cflags) \
- $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(module_dir) modules
-
- echo "generate data for version patching <$(OBJDUMP)><$(READELF)>"
- PATH=$(PATH) $(top_srcdir)/src/modules/driver/patchko.sh -g $(module_dir)/$(module_name).ko $(OBJDUMP) $(READELF)
-
-clean-local:
- $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(module_dir) clean
-
-install-exec-local:
- install -m 644 $(module_dir)/$(module_name).ko $(prefix)
- install -m 644 $(module_dir)/$(module_name).ko.addr $(prefix)
- install -m 755 $(module_dir)/$(module_name).sh $(prefix)
+++ /dev/null
-/*
- * SWAP device driver
- * modules/driver_new/device_driver.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Copyright (C) Samsung Electronics, 2013
- *
- * 2013 Alexander Aksenov <a.aksenov@samsung.com>: SWAP device driver implement
- *
- */
-
-#include <linux/types.h>
-#include <linux/fs.h>
-#include <linux/cdev.h>
-#include <linux/err.h>
-#include <linux/device.h>
-#include <linux/ioctl.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/splice.h>
-#include <linux/sched.h>
-#include <linux/module.h>
-#include <linux/wait.h>
-#include <asm/uaccess.h>
-
-#include <ksyms/ksyms.h>
-
-#include "device_driver.h"
-#include "swap_driver_errors.h"
-#include "driver_to_buffer.h"
-#include "swap_ioctl.h"
-#include "driver_defs.h"
-#include "device_driver_to_driver_to_buffer.h"
-#include "driver_to_buffer.h"
-#include "driver_to_msg.h"
-
-#define SWAP_DEVICE_NAME "swap_device"
-
-/* swap_device driver routines */
-static int swap_device_open(struct inode *inode, struct file *filp);
-static int swap_device_release(struct inode *inode, struct file *file);
-static ssize_t swap_device_read(struct file *filp, char __user *buf,
- size_t count, loff_t *f_pos);
-static ssize_t swap_device_write(struct file *filp, const char __user *buf,
- size_t count, loff_t *f_pos);
-static long swap_device_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg);
-static ssize_t swap_device_splice_read(struct file *filp, loff_t *ppos,
- struct pipe_inode_info *pipe, size_t len,
- unsigned int flags);
-
-/* File operations structure */
-const struct file_operations swap_device_fops = {
- .read = swap_device_read,
- .write = swap_device_write,
- .open = swap_device_open,
- .release = swap_device_release,
- .unlocked_ioctl = swap_device_ioctl,
- .splice_read = swap_device_splice_read,
-};
-
-/* Typedefs for splice_* funcs. Prototypes are for linux-3.8.6 */
-typedef ssize_t(*splice_to_pipe_p_t)(struct pipe_inode_info *pipe,
- struct splice_pipe_desc *spd);
-typedef int(*splice_grow_spd_p_t)(const struct pipe_inode_info *pipe,
- struct splice_pipe_desc *spd);
-
-static splice_to_pipe_p_t splice_to_pipe_p = NULL;
-static splice_grow_spd_p_t splice_grow_spd_p = NULL;
-
-static msg_handler_t msg_handler = NULL;
-
-/* Device numbers */
-static dev_t swap_device_no = 0;
-
-/* Device cdev struct */
-static struct cdev *swap_device_cdev = NULL;
-
-/* Device class struct */
-static struct class *swap_device_class = NULL;
-
-/* Device device struct */
-static struct device *swap_device_device = NULL;
-
-/* Reading tasks queue */
-static DECLARE_WAIT_QUEUE_HEAD(swap_device_wait);
-
-/* We need this realization of splice_shrink_spd() because of the its desing
- * frequent changes that I have encountered in custom kernels */
-void swap_device_splice_shrink_spd(struct pipe_inode_info *pipe,
- struct splice_pipe_desc *spd)
-{
- if (pipe->buffers <= PIPE_DEF_BUFFERS)
- return;
-
- kfree(spd->pages);
- kfree(spd->partial);
-}
-
-
-/* Register device TODO Think of permanent major */
-int swap_device_init(void)
-{
- int result;
-
- /* Allocating device major and minor nums for swap_device */
- result = alloc_chrdev_region(&swap_device_no, 0, 1, SWAP_DEVICE_NAME);
- if (result < 0) {
- print_crit("Major number allocation has failed\n");
- result = -E_SD_ALLOC_CHRDEV_FAIL;
- goto init_fail;
- }
-
- /* Creating device class. Using IS_ERR, because class_create returns ERR_PTR
- * on error. */
- swap_device_class = class_create(THIS_MODULE, SWAP_DEVICE_NAME);
- if (IS_ERR(swap_device_class)) {
- print_crit("Class creation has failed\n");
- result = -E_SD_CLASS_CREATE_FAIL;
- goto init_fail;
- }
-
- /* Cdev allocation */
- swap_device_cdev = cdev_alloc();
- if (!swap_device_cdev) {
- print_crit("Cdev structure allocation has failed\n");
- result = -E_SD_CDEV_ALLOC_FAIL;
- goto init_fail;
- }
-
- /* Cdev intialization and setting file operations */
- cdev_init(swap_device_cdev, &swap_device_fops);
-
- /* Adding cdev to system */
- result = cdev_add(swap_device_cdev, swap_device_no, 1);
- if (result < 0) {
- print_crit("Device adding has failed\n");
- result = -E_SD_CDEV_ADD_FAIL;
- goto init_fail;
- }
-
- /* Create device struct */
- swap_device_device = device_create(swap_device_class, NULL, swap_device_no,
- "%s", SWAP_DEVICE_NAME);
- if (IS_ERR(swap_device_device)) {
- print_crit("Device struct creating has failed\n");
- result = -E_SD_DEVICE_CREATE_FAIL;
- goto init_fail;
- }
-
- /* Find splice_* funcs addresses */
- splice_to_pipe_p = (splice_to_pipe_p_t)swap_ksyms("splice_to_pipe");
- if (!splice_to_pipe_p) {
- print_err("splice_to_pipe() not found!\n");
- result = -E_SD_NO_SPLICE_FUNCS;
- goto init_fail;
- }
-
- splice_grow_spd_p = (splice_grow_spd_p_t)swap_ksyms("splice_grow_spd");
- if (!splice_grow_spd_p) {
- print_err("splice_grow_spd() not found!\n");
- result = -E_SD_NO_SPLICE_FUNCS;
- goto init_fail;
- }
-
- return 0;
-
-init_fail:
- if (swap_device_cdev) {
- cdev_del(swap_device_cdev);
- }
- if (swap_device_class) {
- class_destroy(swap_device_class);
- }
- if (swap_device_no) {
- unregister_chrdev_region(swap_device_no, 1);
- }
- return result;
-}
-
-/* Unregister device TODO Check wether driver is registered */
-void swap_device_exit(void)
-{
- splice_to_pipe_p = NULL;
- splice_grow_spd_p = NULL;
-
- device_destroy(swap_device_class, swap_device_no);
- cdev_del(swap_device_cdev);
- class_destroy(swap_device_class);
- unregister_chrdev_region(swap_device_no, 1);
-}
-
-static int swap_device_open(struct inode *inode, struct file *filp)
-{
- // TODO MOD_INC_USE_COUNT
- return 0;
-}
-
-static int swap_device_release(struct inode *inode, struct file *filp)
-{
- // TODO MOD_DEC_USE_COUNT
- return 0;
-}
-
-static ssize_t swap_device_read(struct file *filp, char __user *buf,
- size_t count, loff_t *f_pos)
-{
- /* Wait queue item that consists current task. It is used to be added in
- * swap_device_wait queue if there is no data to be read. */
- DEFINE_WAIT(wait);
- int result;
-
- //TODO : Think about spin_locks to prevent reading race condition.
- while((result = driver_to_buffer_next_buffer_to_read()) != E_SD_SUCCESS) {
-
- /* Add process to the swap_device_wait queue and set the current task
- * state TASK_INTERRUPTIBLE. If there is any data to be read, then the
- * current task is removed from the swap_device_wait queue and its state
- * is changed to this. */
- prepare_to_wait(&swap_device_wait, &wait, TASK_INTERRUPTIBLE);
-
- if (result < 0) {
- result = 0;
- goto swap_device_read_error;
- } else if (result == E_SD_NO_DATA_TO_READ) {
- /* Yes, E_SD_NO_DATA_TO_READ should be positive, cause it's not
- * really an error */
- if (filp->f_flags & O_NONBLOCK) {
- result = -EAGAIN;
- goto swap_device_read_error;
- }
- if (signal_pending(current)) {
- result = -ERESTARTSYS;
- goto swap_device_read_error;
- }
- schedule();
- finish_wait(&swap_device_wait, &wait);
- }
- }
-
- result = driver_to_buffer_read(buf, count);
- /* If there is an error - return 0 */
- if (result < 0)
- result = 0;
-
-
- return result;
-
-swap_device_read_error:
- finish_wait(&swap_device_wait, &wait);
-
- return result;
-}
-
-static ssize_t swap_device_write(struct file *filp, const char __user *buf,
- size_t count, loff_t *f_pos)
-{
- char *kern_buffer = NULL;
- ssize_t result = 0;
-
- kern_buffer = kmalloc(count, GFP_KERNEL);
- if (!kern_buffer) {
- print_err("Error allocating memory for buffer\n");
- goto swap_device_write_out;
- }
-
- result = copy_from_user(kern_buffer, buf, count);
-
- result = count - result;
-
- /* Return 0 if there was an error while writing */
- result = driver_to_buffer_write(result, kern_buffer);
- if (result < 0)
- result = 0;
-
- kfree(kern_buffer);
-
-swap_device_write_out:
- return result;
-}
-
-static long swap_device_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- int result;
-
- switch(cmd) {
- case SWAP_DRIVER_BUFFER_INITIALIZE:
- {
- struct buffer_initialize initialize_struct;
-
- result = copy_from_user(&initialize_struct, (void*)arg,
- sizeof(struct buffer_initialize));
- if (result) {
- break;
- }
-
- result = driver_to_buffer_initialize(initialize_struct.size,
- initialize_struct.count);
- if (result < 0) {
- print_err("Buffer initialization failed %d\n", result);
- break;
- }
- result = E_SD_SUCCESS;
-
- break;
- }
- case SWAP_DRIVER_BUFFER_UNINITIALIZE:
- {
- result = driver_to_buffer_uninitialize();
- if (result < 0)
- print_err("Buffer uninitialization failed %d\n", result);
-
- break;
- }
- case SWAP_DRIVER_NEXT_BUFFER_TO_READ:
- {
- /* Use this carefully */
- result = driver_to_buffer_next_buffer_to_read();
- if (result == E_SD_NO_DATA_TO_READ) {
- /* TODO Do what we usually do when there are no subbuffers to
- * read (make daemon sleep ?) */
- }
- break;
- }
- case SWAP_DRIVER_FLUSH_BUFFER:
- {
- result = driver_to_buffer_flush();
- break;
- }
- case SWAP_DRIVER_MSG:
- if (msg_handler) {
- result = msg_handler((void __user *)arg);
- } else {
- print_warn("msg_handler() is not register\n");
- result = -EINVAL;
- }
- break;
- default:
- print_warn("Unknown command %d\n", cmd);
- result = -EINVAL;
- break;
-
- }
- return result;
-}
-
-static void swap_device_pipe_buf_release(struct pipe_inode_info *inode,
- struct pipe_buffer *pipe)
-{
- __free_page(pipe->page);
-}
-
-static void swap_device_page_release(struct splice_pipe_desc *spd,
- unsigned int i)
-{
- __free_page(spd->pages[i]);
-}
-
-static const struct pipe_buf_operations swap_device_pipe_buf_ops = {
- .can_merge = 0,
- .map = generic_pipe_buf_map,
- .unmap = generic_pipe_buf_unmap,
- .confirm = generic_pipe_buf_confirm,
- .release = swap_device_pipe_buf_release,
- .steal = generic_pipe_buf_steal,
- .get = generic_pipe_buf_get
-};
-
-static ssize_t swap_device_splice_read(struct file *filp, loff_t *ppos,
- struct pipe_inode_info *pipe,
- size_t len, unsigned int flags)
-{
- /* Wait queue item that consists current task. It is used to be added in
- * swap_device_wait queue if there is no data to be read. */
- DEFINE_WAIT(wait);
-
- int result;
- struct page *pages[PIPE_DEF_BUFFERS];
- struct partial_page partial[PIPE_DEF_BUFFERS];
- struct splice_pipe_desc spd = {
- .pages = pages,
- .partial = partial,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 5))
- .nr_pages_max = PIPE_DEF_BUFFERS,
-#endif
- .nr_pages = 0,
- .flags = flags,
- .ops = &swap_device_pipe_buf_ops,
- .spd_release = swap_device_page_release,
- };
-
- /* Get next buffer to read */
- //TODO : Think about spin_locks to prevent reading race condition.
- while((result = driver_to_buffer_next_buffer_to_read()) != E_SD_SUCCESS) {
-
- /* Add process to the swap_device_wait queue and set the current task
- * state TASK_INTERRUPTIBLE. If there is any data to be read, then the
- * current task is removed from the swap_device_wait queue and its state
- * is changed. */
- prepare_to_wait(&swap_device_wait, &wait, TASK_INTERRUPTIBLE);
- if (result < 0) {
- print_err("driver_to_buffer_next_buffer_to_read error %d\n", result);
- //TODO Error return to OS
- result = 0;
- goto swap_device_splice_read_error;
- } else if (result == E_SD_NO_DATA_TO_READ) {
- if (filp->f_flags & O_NONBLOCK) {
- result = -EAGAIN;
- goto swap_device_splice_read_error;
- }
- if (signal_pending(current)) {
- result = -ERESTARTSYS;
- goto swap_device_splice_read_error;
- }
- schedule();
- finish_wait(&swap_device_wait, &wait);
- }
- }
-
- if (splice_grow_spd_p(pipe, &spd)) {
- result = -ENOMEM;
- goto swap_device_splice_read_out;
- }
-
- result = driver_to_buffer_fill_spd(&spd);
- if (result != 0) {
- print_err("Cannot fill spd for splice\n");
- goto swap_device_shrink_spd;
- }
-
- result = splice_to_pipe_p(pipe, &spd);
-
-swap_device_shrink_spd:
- swap_device_splice_shrink_spd(pipe, &spd);
-
-swap_device_splice_read_out:
- return result;
-
-swap_device_splice_read_error:
- finish_wait(&swap_device_wait, &wait);
-
- return result;
-}
-
-void swap_device_wake_up_process(void)
-{
- wake_up_interruptible(&swap_device_wait);
-}
-
-void set_msg_handler(msg_handler_t mh)
-{
- msg_handler = mh;
-}
-EXPORT_SYMBOL_GPL(set_msg_handler);
+++ /dev/null
-/*
- * SWAP driver
- * modules/driver_new/device_driver.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Copyright (C) Samsung Electronics, 2013
- *
- * 2013 Alexander Aksenov <a.aksenov@samsung.com>: SWAP device driver implement
- *
- */
-
-#ifndef __SWAP_DRIVER_DEVICE_DRIVER_H__
-#define __SWAP_DRIVER_DEVICE_DRIVER_H__
-
-/* Create and register device */
-int swap_device_init(void);
-
-/* Delete device */
-void swap_device_exit(void);
-
-#endif /* __SWAP_DRIVER_DEVICE_DRIVER_H__ */
+++ /dev/null
-/*
- * SWAP Buffer Module
- * modules/buffer/kernel_operations.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Copyright (C) Samsung Electronics, 2013
- *
- * 2013 Alexander Aksenov <a.aksenov@samsung.com>: SWAP Buffer implement
- *
- */
-
-/* Kernel functions wrap */
-
-#ifndef __KERNEL_OPERATIONS_H__
-#define __KERNEL_OPERATIONS_H__
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/semaphore.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/gfp.h>
-#include <linux/mm.h>
-
-
-/* LOCKS */
-
-/* Using spinlocks as sync primitives */
-typedef spinlock_t sync_t;
-
-/* Spinlock flags */
-static unsigned long flags;
-
-/* Spinlocks initialization */
-static inline void sync_init(sync_t *buffer_sync)
-{
- spin_lock_init(buffer_sync);
-}
-
-/* Lock spinlock */
-static inline void sync_lock(sync_t *buffer_sync)
-{
- spin_lock_irqsave(buffer_sync, flags);
-}
-
-/* Unlock spinlock */
-static inline void sync_unlock(sync_t *buffer_sync)
-{
- spin_unlock_irqrestore(buffer_sync, flags);
-}
-
-
-/* SWAP SUBBUFER */
-
-/* swap_subbuffer_ptr points to the first memory page of the subbuffer */
-typedef struct page *swap_subbuffer_ptr;
-
-/* We alloc memory for swap_subbuffer structures with common kmalloc */
-#define memory_allocation(memory_size) kmalloc(memory_size, GFP_KERNEL)
-#define memory_free(ptr) kfree(ptr)
-
-/* For subbuffers themselves, we allocate memory with alloc_pages, so, we have
- * to evaluate required pages order */
-#define buffer_allocation(memory_size) \
- alloc_pages(GFP_KERNEL, (pages_order_in_subbuffer >= 0) ? \
- pages_order_in_subbuffer : \
- get_order_for_alloc_pages(memory_size))
-
-#define buffer_free(ptr, subbuf_size) \
- __free_pages(ptr, (pages_order_in_subbuffer >= 0) ? \
- pages_order_in_subbuffer : \
- get_order_for_alloc_pages(subbuf_size))
-
-#define buffer_address(buffer_ptr) page_address(buffer_ptr)
-#define set_pages_order_in_subbuffer(memory_size) \
- pages_order_in_subbuffer = get_order_for_alloc_pages(memory_size)
-
-/* Functions for pages allocation */
-static inline unsigned int nearest_power_of_two(unsigned int number)
-{
- unsigned int result = 0;
- unsigned int two_to_the_power = 1;
-
- /* If aligned_size == PAGE_SIZE we need only one page, so return 0 */
- if (number == 1)
- return result;
-
- while (two_to_the_power < number) {
- two_to_the_power <<= 1;
- result++;
- }
-
- return result;
-}
-
-static inline unsigned int get_order_for_alloc_pages(size_t memory_size)
-{
- /* First evaluate remainder of the division memory_size by PAGE_SIZE.
- * If memory_size is divisible by PAGE_SIZE, then remainder equals 0. */
- size_t remainder = (memory_size % PAGE_SIZE) ?
- (memory_size % PAGE_SIZE) : PAGE_SIZE;
-
- /* Align memory_size to the PAGE_SIZE. aligned_size >= memory_size */
- size_t aligned_size = memory_size + (PAGE_SIZE - remainder);
-
- return nearest_power_of_two(aligned_size / PAGE_SIZE);
-}
-
-
-/* MESSAGES */
-#define print_debug(msg, args...) \
- printk(KERN_DEBUG "SWAP_BUFFER DEBUG : " msg, ##args)
-#define print_msg(msg, args...) \
- printk(KERN_INFO "SWAP_BUFFER : " msg, ##args)
-#define print_warn(msg, args...) \
- printk(KERN_WARNING "SWAP_BUFFER WARNING : " msg, ##args)
-#define print_err(msg, args...) \
- printk(KERN_ERR "SWAP_BUFFER ERROR : " msg, ##args)
-#define print_crit(msg, args...) \
- printk(KERN_CRIT "SWAP_BUFFER CRITICAL : " msg, ##args)
-
-#endif /* __KERNEL_OPERATIONS_H__ */
#include "msg_buf.h"
#include "msg_cmd.h"
-#include <driver_new/driver_to_msg.h>
-#include <driver_new/swap_ioctl.h>
+#include <driver/driver_to_msg.h>
+#include <driver/swap_ioctl.h>
enum MSG_ID {
MSG_KEEP_ALIVE = 0x0001,
insmod swap_buffer.ko || exit 1 # buffer is loaded
insmod swap_writer.ko || exit 1
-insmod swap_driver_new.ko || exit 1 # driver_new is loaded
+insmod swap_driver.ko || exit 1 # driver is loaded
insmod swap_kprobe.ko || exit 1 # kprobe is loaded
insmod swap_ks_manager.ko || exit 1 # ks_manager is loaded
insmod swap_uprobe.ko || exit 1 # uprobe is loaded
rmmod swap_uprobe
rmmod swap_ks_manager
rmmod swap_kprobe
-rmmod swap_driver_new
+rmmod swap_driver
rmmod swap_writer
rmmod swap_buffer
/*
* SWAP Writer
- * modules/driver_new/swap_writer_module.c
+ * modules/writer/swap_writer_module.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
/*
* SWAP Writer
- * modules/driver_new/swap_writer_errors.h
+ * modules/writer/swap_writer_errors.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
/*
* SWAP Writer
- * modules/driver_new/swap_writer_module.c
+ * modules/writer/swap_writer_module.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
/*
* SWAP Writer
- * modules/driver_new/swap_writer_module.c
+ * modules/writer/swap_writer_module.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by