[COMMON] dss: add binder log to trace binder transactions
authorYunji Kim <yunji.kim@samsung.com>
Mon, 28 May 2018 12:24:19 +0000 (21:24 +0900)
committerSunyoung Kang <sy0816.kang@samsung.com>
Mon, 23 Jul 2018 08:04:47 +0000 (17:04 +0900)
Change-Id: I5f0aa96a07dd4c9f73cc5b0f6dd8238efa9931d5
Signed-off-by: Yunji Kim <yunji.kim@samsung.com>
Signed-off-by: Youngwan Kim <y103.kim@samsung.com>
drivers/android/binder.c
include/linux/debug-snapshot-binder.h [new file with mode: 0644]
include/linux/debug-snapshot.h
lib/Kconfig.debug
lib/debug-snapshot-log.c
lib/debug-snapshot-log.h

index ac976864b3d1401cd89ea5628f589d510e7a5832..ee1a10f6712f42cfbe1b51c67cba509641249537 100644 (file)
@@ -792,6 +792,98 @@ _binder_node_inner_unlock(struct binder_node *node, int line)
        spin_unlock(&node->lock);
 }
 
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+/*
+ * Binder Debug Snapshot
+ */
+static void init_binder_transaction_base(int type, struct trace_binder_transaction_base *base,
+                                        struct binder_transaction *t, struct binder_thread *from,
+                                        struct binder_thread *to)
+{
+       struct binder_thread *t_from;
+       struct binder_thread *t_to;
+
+       if (base == NULL)
+               return;
+
+       t_from = t->from ? t->from : (from ? from : NULL);
+       t_to = t->to_thread ? t->to_thread : (to ? to : NULL);
+       base->trace_type = type;
+       base->transaction_id = t->debug_id;
+       base->from_pid = t_from ? t_from->proc->pid : 0;
+       base->from_tid = t_from ? t_from->pid : 0;
+       base->to_pid = t->to_proc ? t->to_proc->pid : 0;
+       base->to_tid = t_to ? t_to->pid : 0;
+       if (t_from) {
+               strncpy(base->from_pid_comm, t_from->proc->tsk->comm, TASK_COMM_LEN);
+               strncpy(base->from_tid_comm, t_from->task->comm, TASK_COMM_LEN);
+       } else {
+               base->from_pid_comm[0] = '\0';
+               base->from_tid_comm[0] = '\0';
+       }
+       if (t->to_proc)
+               strncpy(base->to_pid_comm, t->to_proc->tsk->comm, TASK_COMM_LEN);
+       else
+               base->to_pid_comm[0] = '\0';
+       if (t_to)
+               strncpy(base->to_tid_comm, t_to->task->comm, TASK_COMM_LEN);
+       else
+               base->to_tid_comm[0] = '\0';
+}
+
+static void dss_binder_transaction(int reply, struct binder_transaction *t, struct binder_thread *from, int to_node_id)
+{
+       struct trace_binder_transaction_base base;
+       struct trace_binder_transaction transaction;
+
+       init_binder_transaction_base(TRANSACTION, &base, t, from, NULL);
+       transaction.to_node_id = to_node_id;
+       transaction.reply = reply;
+       transaction.flags = t->flags;
+       transaction.code = t->code;
+
+       dbg_snapshot_binder(&base, &transaction, NULL);
+}
+
+static void dss_binder_transaction_received(struct binder_transaction *t, struct binder_thread *to)
+{
+       struct trace_binder_transaction_base base;
+
+       init_binder_transaction_base(TRANSACTION_DONE, &base, t, NULL, to);
+
+       dbg_snapshot_binder(&base, NULL, NULL);
+}
+
+static void dss_binder_transaction_failed(int reply, struct binder_transaction_log_entry *e,
+                                         char *from_pid_comm, char *from_tid_comm,
+                                         unsigned int flags, unsigned int code)
+{
+       struct trace_binder_transaction_base base;
+       struct trace_binder_transaction transaction;
+       struct trace_binder_transaction_error error;
+
+       base.trace_type = TRANSACTION_ERROR;
+       base.transaction_id = e->debug_id;
+       base.from_pid = e->from_proc;
+       base.from_tid = e->from_thread;
+       base.to_pid = e->to_proc;
+       base.to_tid = e->to_thread;
+       strncpy(base.from_pid_comm, from_pid_comm, TASK_COMM_LEN);
+       strncpy(base.from_tid_comm, from_tid_comm, TASK_COMM_LEN);
+       base.to_pid_comm[0] = '\0';
+       base.to_tid_comm[0] = '\0';
+       transaction.to_node_id = e->to_node;
+       transaction.reply = reply;
+       transaction.flags = flags;
+       transaction.code = code;
+       error.return_error = e->return_error;
+       error.return_error_param = e->return_error_param;
+       error.return_error_line = e->return_error_line;
+
+       dbg_snapshot_binder(&base, &transaction, &error);
+}
+#endif /* CONFIG_DEBUG_SNAPSHOT_BINDER */
+
 static bool binder_worklist_empty_ilocked(struct list_head *list)
 {
        return list_empty(list);
@@ -3116,6 +3208,9 @@ static void binder_transaction(struct binder_proc *proc,
                t->priority = target_proc->default_priority;
        }
 
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+       dss_binder_transaction(reply, t, t->from ? t->from : thread, target_node ? target_node->debug_id : 0);
+#endif
        trace_binder_transaction(reply, t, target_node);
 
        t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size,
@@ -3434,6 +3529,9 @@ err_invalid_target_handle:
                e->return_error = return_error;
                e->return_error_param = return_error_param;
                e->return_error_line = return_error_line;
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+               dss_binder_transaction_failed(reply, e, proc->tsk->comm, thread->task->comm, tr->flags, tr->code);
+#endif
                fe = binder_transaction_log_add(&binder_transaction_log_failed);
                *fe = *e;
                /*
@@ -4300,6 +4398,9 @@ retry:
                }
                ptr += sizeof(tr);
 
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+               dss_binder_transaction_received(t, thread);
+#endif
                trace_binder_transaction_received(t);
                binder_stat_br(proc, thread, cmd);
                binder_debug(BINDER_DEBUG_TRANSACTION,
diff --git a/include/linux/debug-snapshot-binder.h b/include/linux/debug-snapshot-binder.h
new file mode 100644 (file)
index 0000000..e13b530
--- /dev/null
@@ -0,0 +1,36 @@
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+#ifndef DEBUG_SNAPSHOT_BINDER_H
+#define DEBUG_SNAPSHOT_BINDER_H
+
+#define TASK_COMM_LEN 16
+
+enum binder_trace_type {
+       TRANSACTION = 1,
+       TRANSACTION_DONE,
+       TRANSACTION_ERROR,
+};
+struct trace_binder_transaction_base {
+       int trace_type;
+       int transaction_id;
+       int from_pid;
+       int from_tid;
+       int to_pid;
+       int to_tid;
+       char from_pid_comm[TASK_COMM_LEN];
+       char from_tid_comm[TASK_COMM_LEN];
+       char to_pid_comm[TASK_COMM_LEN];
+       char to_tid_comm[TASK_COMM_LEN];
+};
+struct trace_binder_transaction {
+       int to_node_id;
+       int reply;
+       unsigned int flags;
+       unsigned int code;
+};
+struct trace_binder_transaction_error {
+       unsigned int return_error;
+       unsigned int return_error_param;
+       unsigned int return_error_line;
+};
+#endif /* DEBUG_SNAPSHOT_BINDER_H */
+#endif /* CONFIG_DEBUG_SNAPSHOT_BINDER */
index 111327481bffb3a5fdade7fb90ff9fc978622147..f684855d4b5ff043ed586dc8616cfac30110f769 100644 (file)
@@ -17,6 +17,7 @@
 #ifdef CONFIG_DEBUG_SNAPSHOT
 #include <asm/ptrace.h>
 #include <linux/bug.h>
+#include "debug-snapshot-binder.h"
 
 /* mandatory */
 extern void dbg_snapshot_task(int cpu, void *v_task);
@@ -171,6 +172,14 @@ extern int s3c2410wdt_keepalive_emergency(bool reset, int index);
 #define s3c2410wdt_keepalive_emergency(a, b)   do { } while(0)
 #endif
 
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+extern void dbg_snapshot_binder(struct trace_binder_transaction_base *base,
+                               struct trace_binder_transaction *transaction,
+                               struct trace_binder_transaction_error *error);
+#else
+#define dbg_snapshot_binder(a,b,c)     do { } while(0)
+#endif
+
 #else
 #define dbg_snapshot_acpm(a,b,c)               do { } while(0)
 #define dbg_snapshot_task(a,b)         do { } while(0)
@@ -216,6 +225,8 @@ extern int s3c2410wdt_keepalive_emergency(bool reset, int index);
 #define dbg_snapshot_get_last_pc_paddr()       do { } while(0)
 #define dbg_snapshot_hook_hardlockup_entry(a) do { } while(0)
 #define dbg_snapshot_hook_hardlockup_exit() do { } while(0)
+#define dbg_snapshot_binder(a,b,c)     do { } while(0)
+
 
 static inline unsigned int dbg_snapshot_get_item_size(char *name)
 {
index 9b514c131bedad2a903e7cc8496962a40fc84598..fd8a9c0b42ae3900918eab0067417e58ac27a5f1 100644 (file)
@@ -2087,6 +2087,11 @@ config DEBUG_SNAPSHOT_SPI
        depends on DEBUG_SNAPSHOT && !DEBUG_SNAPSHOT_MINIMIZED_MODE
        default y
 
+config DEBUG_SNAPSHOT_BINDER
+       bool "Enable debugging of binder driver"
+       depends on DEBUG_SNAPSHOT && !DEBUG_SNAPSHOT_MINIMIZED_MODE
+       default y
+
 config DEBUG_SNAPSHOT_PANIC_REBOOT
        bool "Enable forced reboot after panic for ramdump"
        depends on DEBUG_SNAPSHOT
index a51b18e24d5defbb6848ad40997bf2c5661efb03..e961633a4c3b5c875e35044147739d54262bdc56 100644 (file)
@@ -119,6 +119,9 @@ struct dbg_snapshot_log_idx {
 #ifdef CONFIG_DEBUG_SNAPSHOT_SPI
        atomic_t spi_log_idx;
 #endif
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+       atomic_t binder_log_idx;
+#endif
 #ifndef CONFIG_DEBUG_SNAPSHOT_MINIMIZED_MODE
        atomic_t clockevent_log_idx[DSS_NR_CPUS];
        atomic_t printkl_log_idx;
@@ -218,6 +221,9 @@ void __init dbg_snapshot_log_idx_init(void)
 #endif
 #ifdef CONFIG_DEBUG_SNAPSHOT_SPI
        atomic_set(&(dss_idx.spi_log_idx), -1);
+#endif
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+       atomic_set(&(dss_idx.binder_log_idx), -1);
 #endif
        atomic_set(&(dss_idx.suspend_log_idx), -1);
 
@@ -1240,6 +1246,46 @@ void dbg_snapshot_spi(struct spi_controller *ctlr, struct spi_message *cur_msg,
 }
 #endif
 
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+void dbg_snapshot_binder(struct trace_binder_transaction_base *base,
+                        struct trace_binder_transaction *transaction,
+                        struct trace_binder_transaction_error *error)
+{
+       struct dbg_snapshot_item *item = &dss_items[dss_desc.kevents_num];
+       int cpu;
+       unsigned long i;
+
+       if (unlikely(!dss_base.enabled || !item->entry.enabled))
+               return;
+       if (base == NULL)
+               return;
+
+       cpu = raw_smp_processor_id();
+       i = atomic_inc_return(&dss_idx.binder_log_idx) &
+                               (ARRAY_SIZE(dss_log->binder) - 1);
+
+       dss_log->binder[i].time = cpu_clock(cpu);
+       dss_log->binder[i].cpu = cpu;
+       dss_log->binder[i].base = *base;
+
+       if (transaction) {
+               dss_log->binder[i].transaction = *transaction;
+       } else {
+               dss_log->binder[i].transaction.to_node_id = 0;
+               dss_log->binder[i].transaction.reply = 0;
+               dss_log->binder[i].transaction.flags = 0;
+               dss_log->binder[i].transaction.code = 0;
+       }
+       if (error) {
+               dss_log->binder[i].error = *error;
+       } else {
+               dss_log->binder[i].error.return_error = 0;
+               dss_log->binder[i].error.return_error_param = 0;
+               dss_log->binder[i].error.return_error_line = 0;
+       }
+}
+#endif
+
 #ifdef CONFIG_DEBUG_SNAPSHOT_ACPM
 void dbg_snapshot_acpm(unsigned long long timestamp, const char *log, unsigned int data)
 {
index d257aa9c4cf65d759762382461b5326313b0d90f..fa2cb8e11ef8e057e2416b70659b9349ea8e4c72 100644 (file)
@@ -4,6 +4,10 @@
 
 #include <generated/autoconf.h>
 
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+#include <linux/debug-snapshot-binder.h>
+#endif
+
 #ifdef DSS_ANALYZER
 
 #define TASK_COMM_LEN 16
@@ -314,6 +318,15 @@ struct dbg_snapshot_log {
                int en;
        } spi[DSS_LOG_MAX_NUM];
 #endif
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+       struct __binder_log {
+               unsigned long long time;
+               int cpu;
+               struct trace_binder_transaction_base base;
+               struct trace_binder_transaction transaction;
+               struct trace_binder_transaction_error error;
+       } binder[DSS_API_MAX_NUM << 2];
+#endif
 
 #ifndef CONFIG_DEBUG_SNAPSHOT_MINIMIZED_MODE
        struct __clockevent_log {