From ae09f5592079075e13b77b8c0484b1cf948f55ac Mon Sep 17 00:00:00 2001 From: Yunji Kim Date: Mon, 28 May 2018 21:24:19 +0900 Subject: [PATCH] [COMMON] dss: add binder log to trace binder transactions Change-Id: I5f0aa96a07dd4c9f73cc5b0f6dd8238efa9931d5 Signed-off-by: Yunji Kim Signed-off-by: Youngwan Kim --- drivers/android/binder.c | 101 ++++++++++++++++++++++++++ include/linux/debug-snapshot-binder.h | 36 +++++++++ include/linux/debug-snapshot.h | 11 +++ lib/Kconfig.debug | 5 ++ lib/debug-snapshot-log.c | 46 ++++++++++++ lib/debug-snapshot-log.h | 13 ++++ 6 files changed, 212 insertions(+) create mode 100644 include/linux/debug-snapshot-binder.h diff --git a/drivers/android/binder.c b/drivers/android/binder.c index ac976864b3d1..ee1a10f6712f 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -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 index 000000000000..e13b5307689b --- /dev/null +++ b/include/linux/debug-snapshot-binder.h @@ -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 */ diff --git a/include/linux/debug-snapshot.h b/include/linux/debug-snapshot.h index 111327481bff..f684855d4b5f 100644 --- a/include/linux/debug-snapshot.h +++ b/include/linux/debug-snapshot.h @@ -17,6 +17,7 @@ #ifdef CONFIG_DEBUG_SNAPSHOT #include #include +#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) { diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 9b514c131bed..fd8a9c0b42ae 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -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 diff --git a/lib/debug-snapshot-log.c b/lib/debug-snapshot-log.c index a51b18e24d5d..e961633a4c3b 100644 --- a/lib/debug-snapshot-log.c +++ b/lib/debug-snapshot-log.c @@ -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) { diff --git a/lib/debug-snapshot-log.h b/lib/debug-snapshot-log.h index d257aa9c4cf6..fa2cb8e11ef8 100644 --- a/lib/debug-snapshot-log.h +++ b/lib/debug-snapshot-log.h @@ -4,6 +4,10 @@ #include +#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER +#include +#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 { -- 2.20.1