Merge "[REFACTOR] Buffer: move getting next queue element into separate function"
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Thu, 27 Feb 2014 12:39:15 +0000 (04:39 -0800)
committerGerrit Code Review <gerrit@review.vlan103.tizen.org>
Thu, 27 Feb 2014 12:39:15 +0000 (04:39 -0800)
22 files changed:
buffer/buffer_queue.c
buffer/swap_buffer_module.c
driver/device_driver.c
energy/Kbuild
energy/lcd/lcd_base.c
energy/lcd/lcd_base.h
energy/lcd/maru.c
energy/lcd/s6e8aa0.c
energy/lcd/s6e8aa0_panel.c [new file with mode: 0644]
kprobe/arch/asm-arm/dbi_kprobes.c
kprobe/arch/asm-arm/dbi_kprobes.h
kprobe/arch/asm-x86/dbi_kprobes.c
kprobe/dbi_kprobes.c
kprobe/dbi_kprobes.h
ks_features/ks_features.c
parser/msg_buf.c
parser/msg_parser.c
parser/msg_parser.h
parser/swap_msg_parser.c
parser/us_inst.c
uprobe/arch/asm-x86/swap_uprobes.c
us_manager/us_manager_common.h

index 6163b4b..8744b21 100644 (file)
@@ -123,7 +123,7 @@ int buffer_queue_allocation(size_t subbuffer_size,
        sync_init(&buffer_busy_sync);
 
        /* Memory allocation for queue_busy */
-       queue_busy = memory_allocation(sizeof(**queue_busy) * queue_subbuffer_count);
+       queue_busy = memory_allocation(sizeof(*queue_busy) * queue_subbuffer_count);
 
        if (!queue_busy) {
                result = -E_SB_NO_MEM_QUEUE_BUSY;
index 0d228c1..3f3880a 100644 (file)
@@ -69,7 +69,7 @@ static inline int areas_overlap(const void *area1,const void *area2, size_t size
        int i;
 
        for (i = 0; i < size; i++)
-               if ((area1 + i == area2) || (area1 + i == area2))
+               if ((area1 + i == area2) || (area2 + i == area1))
                        return 1;
 
        return 0;
index 07913d3..af7f9e5 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/sched.h>
 #include <linux/module.h>
 #include <linux/wait.h>
+#include <linux/workqueue.h>
 #include <asm/uaccess.h>
 
 #include <ksyms/ksyms.h>
@@ -96,6 +97,32 @@ static struct device *swap_device_device = NULL;
 /* Reading tasks queue */
 static DECLARE_WAIT_QUEUE_HEAD(swap_device_wait);
 
+
+static atomic_t flag_wake_up = ATOMIC_INIT(0);
+
+static void __bottom_wake_up(void)
+{
+       if (waitqueue_active(&swap_device_wait))
+               wake_up_interruptible(&swap_device_wait);
+}
+
+static void bottom_wake_up(struct work_struct *work)
+{
+       if (atomic_read(&flag_wake_up)) {
+               atomic_set(&flag_wake_up, 0);
+               __bottom_wake_up();
+       }
+}
+
+static DECLARE_WORK(w_wake_up, bottom_wake_up);
+
+static void exit_w_wake_up(void)
+{
+       flush_scheduled_work();
+       __bottom_wake_up();
+}
+
+
 /* 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,
@@ -192,6 +219,8 @@ init_fail:
 /* Unregister device TODO Check wether driver is registered */
 void swap_device_exit(void)
 {
+       exit_w_wake_up();
+
        splice_to_pipe_p = NULL;
        splice_grow_spd_p = NULL;
 
@@ -436,7 +465,10 @@ swap_device_splice_read_error:
 
 void swap_device_wake_up_process(void)
 {
-       wake_up_interruptible(&swap_device_wait);
+       if (atomic_read(&flag_wake_up) == 0) {
+               atomic_set(&flag_wake_up, 1);
+               schedule_work(&w_wake_up);
+       }
 }
 
 void set_msg_handler(msg_handler_t mh)
index 2ea75da..80d23c9 100644 (file)
@@ -32,6 +32,13 @@ ifeq ($(CONFIG_LCD_S6E8AA0), y)
 endif
 
 
+# PANEL_S6E8AA0:
+ifeq ($(CONFIG_DISPLAY_PANEL_S6E8AA0), y)
+    swap_energy-y += lcd/s6e8aa0_panel.o
+    LCD_FUNC_LIST += s6e8aa0_panel
+endif
+
+
 # MARU:
 ifeq ($(CONFIG_MARU_BACKLIGHT), y)
     swap_energy-y += lcd/maru.o
index a2521ba..0c9938a 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
+#include <linux/fb.h>
 #include <energy/tm_stat.h>
 #include "lcd_base.h"
 #include "lcd_debugfs.h"
@@ -64,6 +65,11 @@ enum {
        brt_cnt = 10
 };
 
+enum power_t {
+       PW_ON,
+       PW_OFF
+};
+
 struct lcd_priv_data {
        int min_brt;
        int max_brt;
@@ -72,6 +78,7 @@ struct lcd_priv_data {
        struct tm_stat *tms_brt;
        spinlock_t lock_tms;
        int brt_old;
+       enum power_t power;
 
        u64 min_denom;
        u64 min_num;
@@ -108,6 +115,7 @@ static void *create_lcd_priv(struct lcd_ops *ops, size_t tms_brt_cnt)
        spin_lock_init(&lcd->lock_tms);
 
        lcd->brt_old = brt_no_init;
+       lcd->power = PW_OFF;
 
        lcd->min_denom = 1;
        lcd->min_num = 1;
@@ -140,11 +148,8 @@ static void clean_brightness(struct lcd_ops *ops)
        spin_unlock(&lcd->lock_tms);
 }
 
-static void set_brightness(struct lcd_ops *ops, int brt)
+static int get_brt_num_of_array(struct lcd_priv_data *lcd, int brt)
 {
-       struct lcd_priv_data *lcd = get_lcd_priv(ops);
-       int n;
-
        if (brt > lcd->max_brt || brt < lcd->min_brt) {
                printk("LCD energy error: set brightness=%d, "
                       "when brightness[%d..%d]\n",
@@ -152,18 +157,80 @@ static void set_brightness(struct lcd_ops *ops, int brt)
                brt = brt > lcd->max_brt ? lcd->max_brt : lcd->min_brt;
        }
 
-       n = lcd->tms_brt_cnt * (brt - lcd->min_brt) /
-           (lcd->max_brt - lcd->min_brt + 1);
+       return lcd->tms_brt_cnt * (brt - lcd->min_brt) /
+              (lcd->max_brt - lcd->min_brt + 1);
+}
+
+static void set_brightness(struct lcd_ops *ops, int brt)
+{
+       struct lcd_priv_data *lcd = get_lcd_priv(ops);
+       int n = get_brt_num_of_array(lcd, brt);
 
        spin_lock(&lcd->lock_tms);
-       if (lcd->brt_old != n) {
+
+       if (lcd->power == PW_ON && lcd->brt_old != n) {
                u64 time = get_ntime();
                if (lcd->brt_old != brt_no_init)
                        tm_stat_update(&lcd->tms_brt[lcd->brt_old], time);
 
                tm_stat_set_timestamp(&lcd->tms_brt[n], time);
-               lcd->brt_old = n;
        }
+       lcd->brt_old = n;
+
+       spin_unlock(&lcd->lock_tms);
+}
+
+static void set_power_on_set_brt(struct lcd_priv_data *lcd)
+{
+       if (lcd->brt_old != brt_no_init) {
+               u64 time = get_ntime();
+               tm_stat_set_timestamp(&lcd->tms_brt[lcd->brt_old], time);
+       }
+}
+
+static void set_power_on(struct lcd_priv_data *lcd)
+{
+       if (lcd->power == PW_OFF)
+               set_power_on_set_brt(lcd);
+
+       lcd->power = PW_ON;
+}
+
+static void set_power_off_update_brt(struct lcd_priv_data *lcd)
+{
+       if (lcd->brt_old != brt_no_init) {
+               u64 time = get_ntime();
+               tm_stat_update(&lcd->tms_brt[lcd->brt_old], time);
+               lcd->brt_old = brt_no_init;
+       }
+}
+
+static void set_power_off(struct lcd_priv_data *lcd)
+{
+       if (lcd->power == PW_ON)
+               set_power_off_update_brt(lcd);
+
+       lcd->power = PW_OFF;
+}
+
+static void set_power(struct lcd_ops *ops, int val)
+{
+       struct lcd_priv_data *lcd = get_lcd_priv(ops);
+
+       spin_lock(&lcd->lock_tms);
+
+       switch (val) {
+       case FB_BLANK_UNBLANK:
+               set_power_on(lcd);
+               break;
+       case FB_BLANK_POWERDOWN:
+               set_power_off(lcd);
+               break;
+       default:
+               printk("LCD energy error: set power=%d\n", val);
+               break;
+       }
+
        spin_unlock(&lcd->lock_tms);
 }
 
@@ -174,7 +241,11 @@ static int func_notifier_lcd(struct lcd_ops *ops, enum lcd_action_type action,
        case LAT_BRIGHTNESS:
                set_brightness(ops, (int)data);
                break;
+       case LAT_POWER:
+               set_power(ops, (int)data);
+               break;
        default:
+               printk("LCD energy error: action=%d\n", action);
                return -EINVAL;
        }
 
@@ -194,11 +265,14 @@ void get_lcd_array_time(struct lcd_ops *ops, u64 *array_time)
        int i;
 
        spin_lock(&lcd->lock_tms);
-       for (i = 0; i < lcd->tms_brt_cnt; ++i) {
+       for (i = 0; i < lcd->tms_brt_cnt; ++i)
                array_time[i] = tm_stat_running(&lcd->tms_brt[i]);
-               if (i == lcd->brt_old)
-                       array_time[i] += get_ntime() -
-                                        tm_stat_timestamp(&lcd->tms_brt[i]);
+
+       if (lcd->power == PW_ON && lcd->brt_old != brt_no_init) {
+               int old = lcd->brt_old;
+               struct tm_stat *tm = &lcd->tms_brt[old];
+
+               array_time[old] += get_ntime() - tm_stat_timestamp(tm);
        }
        spin_unlock(&lcd->lock_tms);
 }
@@ -330,6 +404,7 @@ int lcd_set_energy(void)
                        }
 
                        set_brightness(ops, ops->get(ops, LPD_BRIGHTNESS));
+                       set_power(ops, ops->get(ops, LPD_POWER));
 
                        stat_lcd_ops[i] |= SLO_SET;
                        ++count;
index 5115cb3..3e210f6 100644 (file)
 
 
 enum lcd_action_type {
-       LAT_BRIGHTNESS
+       LAT_BRIGHTNESS,
+       LAT_POWER
 };
 
 enum lcd_parameter_type {
        LPD_MIN_BRIGHTNESS,
        LPD_MAX_BRIGHTNESS,
-       LPD_BRIGHTNESS
+       LPD_BRIGHTNESS,
+
+       LPD_POWER
 };
 
 struct lcd_ops;
index 7adb170..fb75f88 100644 (file)
 static const char path_backlight[]     = "/sys/class/backlight/emulator/brightness";
 static const char path_backlight_min[] = "/sys/class/backlight/emulator/min_brightness";
 static const char path_backlight_max[] = "/sys/class/backlight/emulator/max_brightness";
+static const char path_power[]         = "/sys/class/lcd/emulator/lcd_power";
 
 static const char *all_path[] = {
        path_backlight,
        path_backlight_min,
-       path_backlight_max
+       path_backlight_max,
+       path_power
 };
 
 enum {
@@ -68,9 +70,11 @@ static unsigned long maru_get_parameter(struct lcd_ops *ops,
                return read_val(path_backlight_max);
        case LPD_BRIGHTNESS:
                return read_val(path_backlight);
+       case LPD_POWER:
+               return read_val(path_power);
+       default:
+               return -EINVAL;
        }
-
-       return -EINVAL;
 }
 
 
index e90a4e8..b607557 100644 (file)
@@ -5,11 +5,13 @@
 static const char path_backlight[]     = "/sys/class/backlight/s6e8aa0-bl/brightness";
 static const char path_backlight_min[] = "/sys/class/backlight/s6e8aa0-bl/min_brightness";
 static const char path_backlight_max[] = "/sys/class/backlight/s6e8aa0-bl/max_brightness";
+static const char path_power[]         = "/sys/class/lcd/s6e8aa0/lcd_power";
 
 static const char *all_path[] = {
        path_backlight,
        path_backlight_min,
-       path_backlight_max
+       path_backlight_max,
+       path_power
 };
 
 enum {
@@ -42,48 +44,19 @@ static unsigned long s6e8aa0_get_parameter(struct lcd_ops *ops,
                return read_val(path_backlight_max);
        case LPD_BRIGHTNESS:
                return read_val(path_backlight);
+       case LPD_POWER:
+               return read_val(path_power);
+       default:
+               return -EINVAL;
        }
-
-       return -EINVAL;
 }
 
 
 
-
-
-#if 0 /* is not supported */
-/* ============================================================================
- * ===                               POWER                                  ===
- * ============================================================================
- */
-static int get_power(void)
-{
-       const char *power_path = "/sys/class/lcd/s6e8aa0/lcd_power";
-
-       return read_val(power_path);
-}
-
 static int entry_handler_set_power(struct kretprobe_instance *ri,
-                                  struct pt_regs *regs)
-{
-       int *power = (int *)ri->data;
-
-       *power = (int)regs->ARM_r1;
-
-       return 0;
-}
-
+                                  struct pt_regs *regs);
 static int ret_handler_set_power(struct kretprobe_instance *ri,
-                                struct pt_regs *regs)
-{
-       int ret = regs_return_value(regs);
-       int *power = (int *)ri->data;
-
-       if (!ret && ops_s && ops_s->set_power)
-               ops_s->set_power(*power);
-
-       return 0;
-}
+                                struct pt_regs *regs);
 
 static struct kretprobe set_power_krp = {
        .kp.symbol_name = "s6e8aa0_set_power",
@@ -91,8 +64,6 @@ static struct kretprobe set_power_krp = {
        .handler = ret_handler_set_power,
        .data_size = sizeof(int)
 };
-#endif
-
 
 
 static int entry_handler_set_backlight(struct kretprobe_instance *ri,
@@ -109,12 +80,24 @@ static struct kretprobe set_backlight_krp = {
 
 int s6e8aa0_set(struct lcd_ops *ops)
 {
-       return dbi_register_kretprobe(&set_backlight_krp);
+       int ret;
+
+       ret = dbi_register_kretprobe(&set_power_krp);
+       if (ret)
+               return ret;
+
+       ret = dbi_register_kretprobe(&set_backlight_krp);
+       if (ret)
+               dbi_unregister_kretprobe(&set_power_krp);
+
+       return ret;
 }
 
 int s6e8aa0_unset(struct lcd_ops *ops)
 {
        dbi_unregister_kretprobe(&set_backlight_krp);
+       dbi_unregister_kretprobe(&set_power_krp);
+
        return 0;
 }
 
@@ -136,6 +119,36 @@ struct lcd_ops *LCD_MAKE_FNAME(s6e8aa0)(void)
 
 
 /* ============================================================================
+ * ===                               POWER                                  ===
+ * ============================================================================
+ */
+static int entry_handler_set_power(struct kretprobe_instance *ri,
+                                  struct pt_regs *regs)
+{
+       int *power = (int *)ri->data;
+
+       *power = (int)swap_get_karg(regs, 1);
+
+       return 0;
+}
+
+static int ret_handler_set_power(struct kretprobe_instance *ri,
+                                struct pt_regs *regs)
+{
+       int ret = regs_return_value(regs);
+       int *power = (int *)ri->data;
+
+       if (!ret && s6e8aa0_ops.notifier)
+               s6e8aa0_ops.notifier(&s6e8aa0_ops, LAT_POWER, (void *)*power);
+
+       return 0;
+}
+
+
+
+
+
+/* ============================================================================
  * ===                              BACKLIGHT                               ===
  * ============================================================================
  */
diff --git a/energy/lcd/s6e8aa0_panel.c b/energy/lcd/s6e8aa0_panel.c
new file mode 100644 (file)
index 0000000..1b5abfa
--- /dev/null
@@ -0,0 +1,178 @@
+#include <kprobe/dbi_kprobes.h>
+#include <linux/backlight.h>
+#include "lcd_base.h"
+
+
+static const char path_backlight[]     = "/sys/class/backlight/s6e8aa0-bl/brightness";
+static const char path_backlight_max[] = "/sys/class/backlight/s6e8aa0-bl/max_brightness";
+static const char path_power[]         = "/sys/class/lcd/s6e8aa0/lcd_power";
+
+static const char *all_path[] = {
+       path_backlight,
+       path_backlight_max,
+       path_power
+};
+
+enum {
+       all_path_cnt = sizeof(all_path) / sizeof(char *)
+};
+
+
+
+static int s6e8aa0_check(struct lcd_ops *ops)
+{
+       int i;
+
+       for (i = 0; i < all_path_cnt; ++i) {
+               int ret = read_val(all_path[i]);
+
+               if (IS_ERR_VALUE(ret))
+                       return 0;
+       }
+
+       return 1;
+}
+
+static unsigned long s6e8aa0_get_parameter(struct lcd_ops *ops,
+                                          enum lcd_parameter_type type)
+{
+       switch (type) {
+       case LPD_MIN_BRIGHTNESS:
+               return 0;
+       case LPD_MAX_BRIGHTNESS:
+               return read_val(path_backlight_max);
+       case LPD_BRIGHTNESS:
+               return read_val(path_backlight);
+       case LPD_POWER:
+               return read_val(path_power);
+       }
+
+       return -EINVAL;
+}
+
+
+
+static int entry_handler_set_power(struct kretprobe_instance *ri,
+                                  struct pt_regs *regs);
+static int ret_handler_set_power(struct kretprobe_instance *ri,
+                                struct pt_regs *regs);
+
+static struct kretprobe set_power_krp = {
+       .kp.symbol_name = "s6e8aa0_set_power",
+       .entry_handler = entry_handler_set_power,
+       .handler = ret_handler_set_power,
+       .data_size = sizeof(int)
+};
+
+
+static int entry_handler_set_backlight(struct kretprobe_instance *ri,
+                                      struct pt_regs *regs);
+static int ret_handler_set_backlight(struct kretprobe_instance *ri,
+                                    struct pt_regs *regs);
+
+static struct kretprobe set_backlight_krp = {
+       .kp.symbol_name = "s6e8aa0_update_status",
+       .entry_handler = entry_handler_set_backlight,
+       .handler = ret_handler_set_backlight,
+       .data_size = sizeof(int)
+};
+
+int s6e8aa0_set(struct lcd_ops *ops)
+{
+       int ret;
+
+       ret = dbi_register_kretprobe(&set_power_krp);
+       if (ret)
+               return ret;
+
+       ret = dbi_register_kretprobe(&set_backlight_krp);
+       if (ret)
+               dbi_unregister_kretprobe(&set_power_krp);
+
+       return ret;
+}
+
+int s6e8aa0_unset(struct lcd_ops *ops)
+{
+       dbi_unregister_kretprobe(&set_backlight_krp);
+       dbi_unregister_kretprobe(&set_power_krp);
+
+       return 0;
+}
+
+static struct lcd_ops s6e8aa0_ops = {
+       .name = "s6e8aa0_panel",
+       .check = s6e8aa0_check,
+       .set = s6e8aa0_set,
+       .unset = s6e8aa0_unset,
+       .get = s6e8aa0_get_parameter
+};
+
+struct lcd_ops *LCD_MAKE_FNAME(s6e8aa0_panel)(void)
+{
+       return &s6e8aa0_ops;
+}
+
+
+
+
+
+/* ============================================================================
+ * ===                               POWER                                  ===
+ * ============================================================================
+ */
+static int entry_handler_set_power(struct kretprobe_instance *ri,
+                                  struct pt_regs *regs)
+{
+       int *power = (int *)ri->data;
+
+       *power = (int)swap_get_karg(regs, 1);
+
+       return 0;
+}
+
+static int ret_handler_set_power(struct kretprobe_instance *ri,
+                                struct pt_regs *regs)
+{
+       int ret = regs_return_value(regs);
+       int *power = (int *)ri->data;
+
+       if (!ret && s6e8aa0_ops.notifier)
+               s6e8aa0_ops.notifier(&s6e8aa0_ops, LAT_POWER,
+                                    (void *)*power);
+
+       return 0;
+}
+
+
+
+
+
+/* ============================================================================
+ * ===                              BACKLIGHT                               ===
+ * ============================================================================
+ */
+static int entry_handler_set_backlight(struct kretprobe_instance *ri,
+                                      struct pt_regs *regs)
+{
+       int *brightness = (int *)ri->data;
+       struct backlight_device *bd;
+
+       bd = (struct backlight_device *)swap_get_karg(regs, 0);
+       *brightness = bd->props.brightness;
+
+       return 0;
+}
+
+static int ret_handler_set_backlight(struct kretprobe_instance *ri,
+                                    struct pt_regs *regs)
+{
+       int ret = regs_return_value(regs);
+       int *brightness = (int *)ri->data;
+
+       if (!ret && s6e8aa0_ops.notifier)
+               s6e8aa0_ops.notifier(&s6e8aa0_ops, LAT_BRIGHTNESS,
+                                    (void *)*brightness);
+
+       return 0;
+}
index f5ccf4b..92ede61 100644 (file)
@@ -163,7 +163,7 @@ int arch_prepare_kprobe(struct kprobe *p, struct slot_manager *sm)
                return -ENOMEM;
 
        memcpy(insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
-       ainsn.insn_arm = ainsn.insn = insn;
+       ainsn.insn = insn;
        ret = arch_check_insn_arm(insn[0]);
        if (!ret) {
                p->opcode = *p->addr;
index 08deda2..2e2c85d 100644 (file)
@@ -468,8 +468,6 @@ struct kprobe_ctlblk {
 struct arch_specific_insn {
        /* copy of the original instruction */
        kprobe_opcode_t *insn;
-       kprobe_opcode_t *insn_arm;
-       kprobe_opcode_t *insn_thumb;
 };
 
 typedef kprobe_opcode_t (*entry_point_t) (unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
index a6c8c17..38ce8b0 100644 (file)
@@ -745,7 +745,7 @@ int kprobe_exceptions_notify (struct notifier_block *self, unsigned long val, vo
 
        DBPRINTF ("val = %ld, data = 0x%X", val, (unsigned int) data);
 
-       if (args->regs && user_mode_vm(args->regs))
+       if (args->regs == NULL || user_mode_vm(args->regs))
                return ret;
 
        DBPRINTF ("switch (val) %lu %d %d", val, DIE_INT3, DIE_TRAP);
index 40ee61b..7a9febf 100644 (file)
@@ -75,8 +75,7 @@ struct slot_manager sm;
 DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
 static DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
-DEFINE_SPINLOCK(kretprobe_lock);       /* Protects kretprobe_inst_table */
-EXPORT_SYMBOL_GPL(kretprobe_lock);
+static DEFINE_SPINLOCK(kretprobe_lock);        /* Protects kretprobe_inst_table */
 static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
 
 struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
@@ -504,8 +503,11 @@ int dbi_register_kprobe(struct kprobe *p)
         * and add it to the address.  That way the addr
         * field can either be global or relative to a symbol.
         */
-       if (p->symbol_name)
+       if (p->symbol_name) {
+               if (p->addr)
+                       return -EINVAL;
                p->addr = (kprobe_opcode_t *)swap_ksyms(p->symbol_name);
+       }
 
        if (!p->addr)
                return -EINVAL;
@@ -543,64 +545,54 @@ out:
        return ret;
 }
 
-void dbi_unregister_kprobe(struct kprobe *p)
+static void dbi_unregister_valid_kprobe(struct kprobe *p, struct kprobe *old_p)
 {
-       struct kprobe *old_p, *list_p;
-       int cleanup_p;
-
-       old_p = get_kprobe(p->addr);
-       DBPRINTF ("dbi_unregister_kprobe p=%p old_p=%p", p, old_p);
-       if (unlikely (!old_p))
-               return;
+       struct kprobe *list_p;
 
-       if (p != old_p) {
-               list_for_each_entry_rcu(list_p, &old_p->list, list)
-                       if (list_p == p)
-                               /* kprobe p is a valid probe */
-                               goto valid_p;
-               return;
-       }
-
-valid_p:
-       DBPRINTF ("dbi_unregister_kprobe valid_p");
        if ((old_p == p) || ((old_p->pre_handler == aggr_pre_handler) &&
            (p->list.next == &old_p->list) && (p->list.prev == &old_p->list))) {
                /* Only probe on the hash list */
                arch_disarm_kprobe(p);
                hlist_del_rcu(&old_p->hlist);
-               cleanup_p = 1;
-       } else {
-               list_del_rcu(&p->list);
-               cleanup_p = 0;
-       }
-       DBPRINTF ("dbi_unregister_kprobe cleanup_p=%d", cleanup_p);
 
-       if (cleanup_p) {
-               if (p != old_p) {
-                       list_del_rcu(&p->list);
+               if (p != old_p)
                        kfree(old_p);
-               }
-
-               if (!in_atomic()) {
-                       synchronize_sched();
-               }
-
-               remove_kprobe(p);
+               /* Synchronize and remove probe in bottom */
        } else {
+               list_del_rcu(&p->list);
+
                if (p->break_handler)
                        old_p->break_handler = NULL;
                if (p->post_handler) {
-                       list_for_each_entry_rcu(list_p, &old_p->list, list) {
-                               if (list_p->post_handler) {
-                                       cleanup_p = 2;
-                                       break;
-                               }
-                       }
-
-                       if (cleanup_p == 0)
-                               old_p->post_handler = NULL;
+                       list_for_each_entry_rcu(list_p, &old_p->list, list)
+                               if (list_p->post_handler)
+                                       return;
+
+                       old_p->post_handler = NULL;
                }
        }
+       /* Set NULL addr for reusability if symbol_name is used */
+       if (p->symbol_name)
+               p->addr = NULL;
+}
+
+void dbi_unregister_kprobe(struct kprobe *kp)
+{
+       struct kprobe *old_p, *list_p;
+
+       old_p = get_kprobe(kp->addr);
+       if (unlikely (!old_p))
+               return;
+
+       if (kp != old_p) {
+               list_for_each_entry_rcu(list_p, &old_p->list, list)
+                       if (list_p == kp)
+                               /* kprobe p is a valid probe */
+                               dbi_unregister_valid_kprobe(kp, old_p);
+               return;
+       }
+
+       dbi_unregister_valid_kprobe(kp, old_p);
 }
 
 int dbi_register_jprobe(struct jprobe *jp)
@@ -832,15 +824,11 @@ static int dbi_disarm_krp_inst(struct kretprobe_instance *ri);
 
 static void dbi_unregister_kretprobe_top(struct kretprobe *rp)
 {
-       unsigned long flags;
        struct kretprobe_instance *ri;
        DECLARE_NODE_PTR_FOR_HLIST(node);
 
        dbi_unregister_kprobe(&rp->kp);
 
-       /* No race here */
-       spin_lock_irqsave(&kretprobe_lock, flags);
-
        swap_hlist_for_each_entry(ri, node, &rp->used_instances, uflist) {
                if (!dbi_disarm_krp_inst(ri)) {
                        printk("%s (%d/%d): cannot disarm krp instance (%08lx)\n",
@@ -848,7 +836,6 @@ static void dbi_unregister_kretprobe_top(struct kretprobe *rp)
                                        (unsigned long)rp->kp.addr);
                }
        }
-       spin_unlock_irqrestore(&kretprobe_lock, flags);
 }
 
 static void dbi_unregister_kretprobe_bottom(struct kretprobe *rp)
@@ -856,18 +843,41 @@ static void dbi_unregister_kretprobe_bottom(struct kretprobe *rp)
        unsigned long flags;
        struct kretprobe_instance *ri;
 
+       if (list_empty(&rp->kp.list))
+               remove_kprobe(&rp->kp);
+
        spin_lock_irqsave(&kretprobe_lock, flags);
+
        while ((ri = get_used_rp_inst(rp)) != NULL) {
                recycle_rp_inst(ri);
        }
-       spin_unlock_irqrestore(&kretprobe_lock, flags);
        free_rp_inst(rp);
+
+       spin_unlock_irqrestore(&kretprobe_lock, flags);
+}
+
+void dbi_unregister_kretprobes(struct kretprobe **rpp, size_t size)
+{
+       size_t i;
+       unsigned long flags;
+
+       spin_lock_irqsave(&kretprobe_lock, flags);
+
+       for (i = 0; i < size; i++)
+               dbi_unregister_kretprobe_top(rpp[i]);
+
+       spin_unlock_irqrestore(&kretprobe_lock, flags);
+
+       if (!in_atomic())
+               synchronize_sched();
+
+       for (i = 0; i < size; i++)
+               dbi_unregister_kretprobe_bottom(rpp[i]);
 }
 
 void dbi_unregister_kretprobe(struct kretprobe *rp)
 {
-       dbi_unregister_kretprobe_top(rp);
-       dbi_unregister_kretprobe_bottom(rp);
+       dbi_unregister_kretprobes(&rp, 1);
 }
 
 struct kretprobe *clone_kretprobe(struct kretprobe *rp)
@@ -1037,6 +1047,7 @@ EXPORT_SYMBOL_GPL(dbi_register_jprobe);
 EXPORT_SYMBOL_GPL(dbi_unregister_jprobe);
 EXPORT_SYMBOL_GPL(dbi_jprobe_return);
 EXPORT_SYMBOL_GPL(dbi_register_kretprobe);
+EXPORT_SYMBOL_GPL(dbi_unregister_kretprobes);
 EXPORT_SYMBOL_GPL(dbi_unregister_kretprobe);
 
 MODULE_LICENSE("Dual BSD/GPL");
index 9b187aa..7c6a479 100644 (file)
@@ -254,6 +254,7 @@ struct kretprobe_instance * get_used_rp_inst (struct kretprobe *rp);
 int alloc_nodes_kretprobe(struct kretprobe *rp);
 int dbi_register_kretprobe (struct kretprobe *rp);
 void dbi_unregister_kretprobe (struct kretprobe *rp);
+void dbi_unregister_kretprobes(struct kretprobe **rpp, size_t size);
 
 void kretprobe_assert (struct kretprobe_instance *ri,
                unsigned long orig_ret_address, unsigned long trampoline_address);
@@ -274,7 +275,6 @@ void set_normalized_timeval (struct timeval *tv, time_t sec, suseconds_t usec);
 #endif
 
 extern DEFINE_PER_CPU (struct kprobe *, current_kprobe);
-extern spinlock_t kretprobe_lock;
 extern struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
 //extern struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
 extern atomic_t kprobe_count;
index 4ce55de..8af0d36 100644 (file)
@@ -24,6 +24,8 @@
 
 
 #include <linux/module.h>
+#include <linux/slab.h>
+
 #include <asm/errno.h>
 #include <ksyms/ksyms.h>
 #include <kprobe/dbi_kprobes.h>
@@ -229,6 +231,7 @@ static int register_syscall(size_t id)
        return ret;
 }
 
+
 static int unregister_syscall(size_t id)
 {
        printk("unregister_syscall: %s\n", get_sys_name(id));
@@ -241,6 +244,42 @@ static int unregister_syscall(size_t id)
        return 0;
 }
 
+static int unregister_multiple_syscalls(size_t *id_p, size_t cnt)
+{
+       struct kretprobe **rpp;
+       const size_t end = ((size_t) 0) - 1;
+       size_t i = 0, id;
+       int ret = 0;
+
+       if (cnt == 1)
+               return unregister_syscall(id_p[0]);
+
+       --cnt;
+
+       rpp = kmalloc(GFP_KERNEL, sizeof(&(((struct ks_probe *) 0)->rp)) * cnt);
+       if (rpp == NULL) {
+               for (; cnt != end; --cnt) {
+                       ret = unregister_syscall(id_p[cnt]);
+                       if (ret)
+                               return ret;
+        }
+               return ret;
+       }
+
+       for (; cnt != end; --cnt) {
+               id = id_p[cnt];
+               if (ksp[id].rp.kp.addr != NULL) {
+                               rpp[i] = &ksp[id].rp;
+                               ++i;
+               }
+       }
+
+       dbi_unregister_kretprobes(rpp, i);
+       kfree(rpp);
+
+       return 0;
+}
+
 static void set_pst(struct feature *f, size_t id)
 {
        ksp[id].sub_type |= f->sub_type;
@@ -254,30 +293,45 @@ static void unset_pst(struct feature *f, size_t id)
 static void do_uninstall_features(struct feature *f, size_t i)
 {
        int ret;
+       size_t *id_p;
        size_t id;
+       size_t cnt = 0;
        const size_t end = ((size_t) 0) - 1;
 
+       id_p = kmalloc(GFP_KERNEL, sizeof(id) * (i + 1));
+       /* NULL check is below in loop */
+
        for (; i != end; --i) {
                id = f->feature_list[i];
 
                if (get_counter(id) == 0) {
                        printk("syscall %s not installed\n",
                               get_sys_name(id));
+                       kfree(id_p);
                        BUG();
                }
 
                dec_counter(id);
 
                if (get_counter(id) == 0) {
-                       ret = unregister_syscall(id);
-                       if (ret)
-                               printk("syscall %s uninstall error, ret=%d\n",
-                                      get_sys_name(id), ret);
-
+                       if (id_p != NULL) {
+                               id_p[cnt] = id;
+                               ++cnt;
+                       } else {
+                               ret = unregister_syscall(id);
+                               if (ret)
+                                       printk("syscall %s uninstall error, ret=%d\n",
+                                                  get_sys_name(id), ret);
+                       }
                }
 
                unset_pst(f, id);
        }
+
+       if (id_p != NULL) {
+               unregister_multiple_syscalls(id_p, cnt);
+               kfree(id_p);
+       }
 }
 
 static int do_install_features(struct feature *f)
@@ -337,12 +391,11 @@ static int uninstall_features(struct feature *f)
                ret = -EINVAL;
                goto unlock;
        }
-
        do_uninstall_features(f, f->cnt - 1);
-
        f->enable = 0;
 unlock:
        mutex_unlock(&mutex_features);
+
        return ret;
 }
 
index 031215e..3520874 100644 (file)
@@ -114,19 +114,22 @@ int get_u64(struct msg_buf *mb, u64 *val)
 int get_string(struct msg_buf *mb, char **str)
 {
        size_t len, len_max;
+       enum { min_len_str = 1 };
 
-       len_max = mb->end - mb->ptr - 1;
-       if(len_max < 0)
+       if (cmp_mb(mb, min_len_str) < 0)
                return -EINVAL;
 
-       len = strlen(mb->ptr) + 1;
+       len_max = remained_mb(mb) - 1;
+       len = strnlen(mb->ptr, len_max);
 
-       *str = kmalloc(len, GFP_KERNEL);
+       *str = kmalloc(len + 1, GFP_KERNEL);
        if (*str == NULL)
                return -ENOMEM;
 
        memcpy(*str, mb->ptr, len);
-       mb->ptr += len;
+       (*str)[len] = '\0';
+
+       mb->ptr += len + 1;
 
        print_parse_debug("str->'%s'\n", *str);
        return 0;
index 3335732..394aae2 100644 (file)
@@ -93,15 +93,20 @@ struct app_info_data *create_app_info(struct msg_buf *mb)
 
        switch (app_type) {
        case AT_TIZEN_NATIVE_APP:
+       case AT_TIZEN_WEB_APP:
        case AT_COMMON_EXEC:
                ai->tgid = 0;
                break;
        case AT_PID: {
-               u32 tgid;
-               ret = str_to_u32(ta_id, &tgid);
-               if (ret) {
-                       print_err("converting string to PID, str='%s'\n", ta_id);
-                       goto free_ai;
+               u32 tgid = 0;
+
+               if (*ta_id != '\0') {
+                       ret = str_to_u32(ta_id, &tgid);
+                       if (ret) {
+                               print_err("converting string to PID, "
+                                         "str='%s'\n", ta_id);
+                               goto free_ai;
+                       }
                }
 
                ai->tgid = tgid;
@@ -285,12 +290,12 @@ struct lib_inst_data *create_lib_inst_data(struct msg_buf *mb)
        print_parse_debug("func count:");
        if (get_u32(mb, &cnt)) {
                print_err("failed to read count of functions\n");
-               return NULL;
+               goto free_path;
        }
 
        if (remained_mb(mb) / MIN_SIZE_FUNC_INST < cnt) {
                print_err("to match count of functions(%u)\n", cnt);
-               return NULL;
+               goto free_path;
        }
 
        li = kmalloc(sizeof(*li), GFP_KERNEL);
index 6543bb1..55751ac 100644 (file)
@@ -33,7 +33,8 @@ struct msg_buf;
 enum APP_TYPE {
        AT_TIZEN_NATIVE_APP     = 0x01,
        AT_PID                  = 0x02,
-       AT_COMMON_EXEC          = 0x03
+       AT_COMMON_EXEC          = 0x03,
+       AT_TIZEN_WEB_APP        = 0x04
 };
 
 enum {
index 23127fa..e374bf6 100644 (file)
@@ -56,12 +56,18 @@ static int msg_handler(void __user *msg)
        struct msg_buf mb;
        void __user *payload;
        struct basic_msg_fmt bmf;
+       enum { size_max = 128 * 1024 * 1024 };
 
        ret = copy_from_user(&bmf, (void*)msg, sizeof(bmf));
        if (ret)
                return ret;
 
        size = bmf.len;
+       if (size >= size_max) {
+               printk("%s: too large message, size=%u\n", __func__, size);
+               return -ENOMEM;
+       }
+
        ret = init_mb(&mb, size);
        if (ret)
                return ret;
index e402277..aa0489e 100644 (file)
@@ -114,10 +114,15 @@ static int get_pfg_by_app_info(struct app_info_data *app_info, struct pf_group *
 
        switch (app_info->app_type) {
        case AT_PID:
+               if (app_info->tgid == 0)
+                       goto pf_dentry;
+
                *pfg = get_pf_group_by_tgid(app_info->tgid, dentry);
                break;
        case AT_TIZEN_NATIVE_APP:
+       case AT_TIZEN_WEB_APP:
        case AT_COMMON_EXEC:
+ pf_dentry:
                *pfg = get_pf_group_by_dentry(dentry, dentry);
                break;
        default:
index 0d09c77..2ec59ac 100644 (file)
@@ -375,7 +375,7 @@ static int uprobe_exceptions_notify(struct notifier_block *self, unsigned long v
        struct die_args *args = (struct die_args *)data;
        int ret = NOTIFY_DONE;
 
-       if (args->regs && !user_mode_vm(args->regs))
+       if (args->regs == NULL || !user_mode_vm(args->regs))
                return ret;
 
        switch (val) {
index 7febc1b..d888b26 100644 (file)
@@ -32,11 +32,13 @@ static inline unsigned long swap_do_mmap(struct file *filp, unsigned long addr,
                                         unsigned long flag,
                                         unsigned long offset)
 {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
        unsigned long populate;
 
        return do_mmap_pgoff(filp, addr, len, prot, flag, offset, &populate);
-#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) */
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+       return do_mmap_pgoff(filp, addr, len, prot, flag, offset);
+#else
        return do_mmap(filp, addr, len, prot, flag, offset);
 #endif
 }