diff options
author | Igor Nabirushkin <inabirushkin@nvidia.com> | 2015-03-16 19:13:33 +0400 |
---|---|---|
committer | Winnie Hsu <whsu@nvidia.com> | 2015-05-29 14:27:04 -0700 |
commit | 7b3154608145006f8f1373ba31b4f0cc9e579054 (patch) | |
tree | 350a1a76f7aaf0971ed24079b2c476069afe7474 | |
parent | e7ee0bf5d1229e6f7d507e8d8929860410f6a854 (diff) |
misc: tegra-profiler: add unwind reason codes
Unwinding: store individual URC codes for each method.
Bug 1624134
Change-Id: I3b2045f9c9147354f3440e326fd3aeccb5e0458d
Signed-off-by: Igor Nabirushkin <inabirushkin@nvidia.com>
Reviewed-on: http://git-master/r/717848
(cherry picked from commit e5ceff53d63e668a19d36196823f6c185ce48e88)
Reviewed-on: http://git-master/r/748086
GVS: Gerrit_Virtual_Submit
Reviewed-by: Andrey Trachenko <atrachenko@nvidia.com>
Reviewed-by: Winnie Hsu <whsu@nvidia.com>
-rw-r--r-- | drivers/misc/tegra-profiler/backtrace.c | 123 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/backtrace.h | 15 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/comm.c | 1 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/dwarf_unwind.c | 18 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/eh_unwind.c | 14 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/hrt.c | 65 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/hrt.h | 4 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/ma.c | 2 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/main.c | 12 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/version.h | 2 | ||||
-rw-r--r-- | include/linux/tegra_profiler.h | 38 |
11 files changed, 142 insertions, 152 deletions
diff --git a/drivers/misc/tegra-profiler/backtrace.c b/drivers/misc/tegra-profiler/backtrace.c index 2dc39b1d018c..2d947615978d 100644 --- a/drivers/misc/tegra-profiler/backtrace.c +++ b/drivers/misc/tegra-profiler/backtrace.c @@ -29,6 +29,12 @@ #include "hrt.h" #include "tegra.h" +static inline int +is_table_unwinding(struct quadd_callchain *cc) +{ + return cc->um.ut || cc->um.dwarf; +} + unsigned long quadd_user_stack_pointer(struct pt_regs *regs) { @@ -87,12 +93,12 @@ quadd_callchain_store(struct quadd_callchain *cc, unsigned long low_addr = cc->hrt->low_addr; if (ip < low_addr || !validate_pc_addr(ip, sizeof(unsigned long))) { - cc->unw_rc = QUADD_URC_PC_INCORRECT; + cc->urc_fp = QUADD_URC_PC_INCORRECT; return 0; } if (cc->nr >= QUADD_MAX_STACK_DEPTH) { - cc->unw_rc = QUADD_URC_LEVEL_TOO_DEEP; + cc->urc_fp = QUADD_URC_LEVEL_TOO_DEEP; return 0; } @@ -130,7 +136,7 @@ user_backtrace(struct pt_regs *regs, return NULL; if (__copy_from_user_inatomic(&value, tail, sizeof(unsigned long))) { - cc->unw_rc = QUADD_URC_EACCESS; + cc->urc_fp = QUADD_URC_EACCESS; return NULL; } @@ -144,7 +150,7 @@ user_backtrace(struct pt_regs *regs, if (__copy_from_user_inatomic(&value_lr, tail + 1, sizeof(value_lr))) { - cc->unw_rc = QUADD_URC_EACCESS; + cc->urc_fp = QUADD_URC_EACCESS; return NULL; } @@ -155,7 +161,7 @@ user_backtrace(struct pt_regs *regs, /* gcc arm frame */ if (__copy_from_user_inatomic(&value_fp, tail - 1, sizeof(value_fp))) { - cc->unw_rc = QUADD_URC_EACCESS; + cc->urc_fp = QUADD_URC_EACCESS; return NULL; } @@ -175,7 +181,7 @@ user_backtrace(struct pt_regs *regs, if (nr_added == 0) return NULL; - if (cc->unw_method == QUADD_UNW_METHOD_MIXED && + if (is_table_unwinding(cc) && is_ex_entry_exist(regs, value_lr, task)) return NULL; @@ -193,10 +199,10 @@ get_user_callchain_fp(struct pt_regs *regs, struct mm_struct *mm = task->mm; cc->nr = 0; - cc->unw_rc = QUADD_URC_FP_INCORRECT; + cc->urc_fp = QUADD_URC_FP_INCORRECT; if (!regs || !mm) { - cc->unw_rc = QUADD_URC_FAILURE; + cc->urc_fp = QUADD_URC_FAILURE; return 0; } @@ -209,7 +215,7 @@ get_user_callchain_fp(struct pt_regs *regs, vma = find_vma(mm, sp); if (!vma) { - cc->unw_rc = QUADD_URC_SP_INCORRECT; + cc->urc_fp = QUADD_URC_SP_INCORRECT; return 0; } @@ -218,7 +224,7 @@ get_user_callchain_fp(struct pt_regs *regs, if (probe_kernel_address(fp, reg)) { pr_warn_once("%s: failed for address: %#lx\n", __func__, fp); - cc->unw_rc = QUADD_URC_EACCESS; + cc->urc_fp = QUADD_URC_EACCESS; return 0; } @@ -239,7 +245,7 @@ get_user_callchain_fp(struct pt_regs *regs, &value, (unsigned long __user *)fp + 1, sizeof(unsigned long))) { - cc->unw_rc = QUADD_URC_EACCESS; + cc->urc_fp = QUADD_URC_EACCESS; return 0; } @@ -279,16 +285,16 @@ __user_backtrace(struct pt_regs *regs, struct vm_area_struct *vma; unsigned long __user *tail; - cc->unw_rc = QUADD_URC_FP_INCORRECT; + cc->urc_fp = QUADD_URC_FP_INCORRECT; if (!mm) { - cc->unw_rc = QUADD_URC_FAILURE; + cc->urc_fp = QUADD_URC_FAILURE; return cc->nr; } vma = find_vma(mm, cc->curr_sp); if (!vma) { - cc->unw_rc = QUADD_URC_SP_INCORRECT; + cc->urc_fp = QUADD_URC_SP_INCORRECT; return cc->nr; } @@ -316,7 +322,7 @@ user_backtrace_compat(struct pt_regs *regs, return NULL; if (__copy_from_user_inatomic(&value, tail, sizeof(value))) { - cc->unw_rc = QUADD_URC_EACCESS; + cc->urc_fp = QUADD_URC_EACCESS; return NULL; } @@ -330,7 +336,7 @@ user_backtrace_compat(struct pt_regs *regs, if (__copy_from_user_inatomic(&value_lr, tail + 1, sizeof(value_lr))) { - cc->unw_rc = QUADD_URC_EACCESS; + cc->urc_fp = QUADD_URC_EACCESS; return NULL; } @@ -341,7 +347,7 @@ user_backtrace_compat(struct pt_regs *regs, /* gcc arm frame */ if (__copy_from_user_inatomic(&value_fp, tail - 1, sizeof(value_fp))) { - cc->unw_rc = QUADD_URC_EACCESS; + cc->urc_fp = QUADD_URC_EACCESS; return NULL; } @@ -361,7 +367,7 @@ user_backtrace_compat(struct pt_regs *regs, if (nr_added == 0) return NULL; - if (cc->unw_method == QUADD_UNW_METHOD_MIXED && + if (is_table_unwinding(cc) && is_ex_entry_exist(regs, value_lr, task)) return NULL; @@ -379,10 +385,10 @@ get_user_callchain_fp_compat(struct pt_regs *regs, struct mm_struct *mm = task->mm; cc->nr = 0; - cc->unw_rc = QUADD_URC_FP_INCORRECT; + cc->urc_fp = QUADD_URC_FP_INCORRECT; if (!regs || !mm) { - cc->unw_rc = QUADD_URC_FAILURE; + cc->urc_fp = QUADD_URC_FAILURE; return 0; } @@ -395,7 +401,7 @@ get_user_callchain_fp_compat(struct pt_regs *regs, vma = find_vma(mm, sp); if (!vma) { - cc->unw_rc = QUADD_URC_SP_INCORRECT; + cc->urc_fp = QUADD_URC_SP_INCORRECT; return 0; } @@ -404,7 +410,7 @@ get_user_callchain_fp_compat(struct pt_regs *regs, if (probe_kernel_address((unsigned long)fp, reg)) { pr_warn_once("%s: failed for address: %#x\n", __func__, fp); - cc->unw_rc = QUADD_URC_EACCESS; + cc->urc_fp = QUADD_URC_EACCESS; return 0; } @@ -425,7 +431,7 @@ get_user_callchain_fp_compat(struct pt_regs *regs, &value, (u32 __user *)(fp + sizeof(u32)), sizeof(value))) { - cc->unw_rc = QUADD_URC_EACCESS; + cc->urc_fp = QUADD_URC_EACCESS; return 0; } @@ -465,16 +471,16 @@ __user_backtrace_compat(struct pt_regs *regs, struct vm_area_struct *vma; u32 __user *tail; - cc->unw_rc = QUADD_URC_FP_INCORRECT; + cc->urc_fp = QUADD_URC_FP_INCORRECT; if (!mm) { - cc->unw_rc = QUADD_URC_FAILURE; + cc->urc_fp = QUADD_URC_FAILURE; return cc->nr; } vma = find_vma(mm, cc->curr_sp); if (!vma) { - cc->unw_rc = QUADD_URC_SP_INCORRECT; + cc->urc_fp = QUADD_URC_SP_INCORRECT; return cc->nr; } @@ -494,7 +500,7 @@ __get_user_callchain_fp(struct pt_regs *regs, struct task_struct *task) { if (cc->nr > 0) { - if (cc->unw_rc == QUADD_URC_LEVEL_TOO_DEEP) + if (cc->urc_fp == QUADD_URC_LEVEL_TOO_DEEP) return cc->nr; #ifdef CONFIG_ARM64 @@ -518,44 +524,22 @@ __get_user_callchain_fp(struct pt_regs *regs, } static unsigned int -get_user_callchain_ut(struct pt_regs *regs, - struct quadd_callchain *cc, - struct task_struct *task) -{ - int nr_prev; - unsigned long prev_sp; - - do { - nr_prev = cc->nr; - prev_sp = cc->curr_sp; - - quadd_get_user_cc_dwarf(regs, cc, task); - if (nr_prev > 0 && cc->nr == nr_prev) - break; - - nr_prev = cc->nr; - - quadd_get_user_cc_arm32_ehabi(regs, cc, task); - } while (nr_prev != cc->nr && - (cc->nr <= 1 || cc->curr_sp > prev_sp)); - - return cc->nr; -} - -static unsigned int get_user_callchain_mixed(struct pt_regs *regs, struct quadd_callchain *cc, struct task_struct *task) { int nr_prev; unsigned long prev_sp; + struct quadd_unw_methods *um = &cc->um; do { nr_prev = cc->nr; prev_sp = cc->curr_sp; - quadd_get_user_cc_dwarf(regs, cc, task); - quadd_get_user_cc_arm32_ehabi(regs, cc, task); + if (um->dwarf) + quadd_get_user_cc_dwarf(regs, cc, task); + if (um->ut) + quadd_get_user_cc_arm32_ehabi(regs, cc, task); if (nr_prev != cc->nr) { if (cc->nr > 1 && @@ -565,7 +549,8 @@ get_user_callchain_mixed(struct pt_regs *regs, continue; } - __get_user_callchain_fp(regs, cc, task); + if (um->fp) + __get_user_callchain_fp(regs, cc, task); } while (nr_prev != cc->nr && (cc->nr <= 1 || cc->curr_sp > prev_sp)); @@ -578,12 +563,12 @@ quadd_get_user_callchain(struct pt_regs *regs, struct quadd_ctx *ctx, struct task_struct *task) { - unsigned int method = cc->unw_method; - cc->nr = 0; if (!regs) { - cc->unw_rc = QUADD_URC_FAILURE; + cc->urc_fp = QUADD_URC_FAILURE; + cc->urc_ut = QUADD_URC_FAILURE; + cc->urc_dwarf = QUADD_URC_FAILURE; return 0; } @@ -598,25 +583,11 @@ quadd_get_user_callchain(struct pt_regs *regs, cc->cs_64 = 0; #endif - cc->unw_rc = 0; - - switch (method) { - case QUADD_UNW_METHOD_FP: - __get_user_callchain_fp(regs, cc, task); - break; + cc->urc_fp = QUADD_URC_NONE; + cc->urc_ut = QUADD_URC_NONE; + cc->urc_dwarf = QUADD_URC_NONE; - case QUADD_UNW_METHOD_EHT: - get_user_callchain_ut(regs, cc, task); - break; - - case QUADD_UNW_METHOD_MIXED: - get_user_callchain_mixed(regs, cc, task); - break; - - case QUADD_UNW_METHOD_NONE: - default: - break; - } + get_user_callchain_mixed(regs, cc, task); return cc->nr; } diff --git a/drivers/misc/tegra-profiler/backtrace.h b/drivers/misc/tegra-profiler/backtrace.h index 5ee544cdd496..724c614a9408 100644 --- a/drivers/misc/tegra-profiler/backtrace.h +++ b/drivers/misc/tegra-profiler/backtrace.h @@ -27,6 +27,14 @@ struct quadd_hrt_ctx; +struct quadd_unw_methods { + unsigned int + fp:1, + ut:1, + ut_ce:1, + dwarf:1; +}; + struct quadd_callchain { int nr; @@ -39,8 +47,11 @@ struct quadd_callchain { int cs_64; - unsigned int unw_method; - unsigned int unw_rc; + struct quadd_unw_methods um; + + unsigned int urc_fp; + unsigned int urc_ut; + unsigned int urc_dwarf; unsigned long curr_sp; unsigned long curr_fp; diff --git a/drivers/misc/tegra-profiler/comm.c b/drivers/misc/tegra-profiler/comm.c index 7c4b6fcb1a7a..2d70f6318d3e 100644 --- a/drivers/misc/tegra-profiler/comm.c +++ b/drivers/misc/tegra-profiler/comm.c @@ -370,6 +370,7 @@ init_mmap_hdr(struct quadd_mmap_rb_info *mmap_rb, mmap_hdr->magic = QUADD_MMAP_HEADER_MAGIC; mmap_hdr->version = QUADD_MMAP_HEADER_VERSION; mmap_hdr->cpu_id = cpu_id; + mmap_hdr->samples_version = QUADD_SAMPLES_VERSION; rb_hdr = (struct quadd_ring_buffer_hdr *)(mmap_hdr + 1); rb->rb_hdr = rb_hdr; diff --git a/drivers/misc/tegra-profiler/dwarf_unwind.c b/drivers/misc/tegra-profiler/dwarf_unwind.c index ef5c4ad420eb..2e624352c4b7 100644 --- a/drivers/misc/tegra-profiler/dwarf_unwind.c +++ b/drivers/misc/tegra-profiler/dwarf_unwind.c @@ -1905,7 +1905,7 @@ unwind_backtrace(struct quadd_callchain *cc, unsigned int unw_type; int is_eh = 1, mode = sf->mode; - cc->unw_rc = QUADD_URC_FAILURE; + cc->urc_dwarf = QUADD_URC_FAILURE; user_reg_size = get_user_reg_size(mode); while (1) { @@ -1922,7 +1922,7 @@ unwind_backtrace(struct quadd_callchain *cc, sp = sf->vregs[regnum_sp(mode)]; if (!validate_stack_addr(sp, vma_sp, user_reg_size)) { - cc->unw_rc = -QUADD_URC_SP_INCORRECT; + cc->urc_dwarf = QUADD_URC_SP_INCORRECT; break; } @@ -1935,7 +1935,7 @@ unwind_backtrace(struct quadd_callchain *cc, if (!is_vma_addr(addr, vma_pc, user_reg_size)) { err = quadd_get_dw_frames(vma_pc->vm_start, &ri_new); if (err) { - cc->unw_rc = QUADD_URC_TBL_NOT_EXIST; + cc->urc_dwarf = QUADD_URC_TBL_NOT_EXIST; break; } @@ -1947,7 +1947,7 @@ unwind_backtrace(struct quadd_callchain *cc, if (!is_fde_entry_exist(ri, sf->pc, &__is_eh, &__is_debug)) { pr_debug("eh/debug fde entries are not existed\n"); - cc->unw_rc = QUADD_URC_IDX_NOT_FOUND; + cc->urc_dwarf = QUADD_URC_IDX_NOT_FOUND; break; } pr_debug("is_eh: %d, is_debug: %d\n", __is_eh, __is_debug); @@ -1967,11 +1967,11 @@ unwind_backtrace(struct quadd_callchain *cc, err = unwind_frame(ri, sf, vma_sp, is_eh); if (err < 0) { - cc->unw_rc = -err; + cc->urc_dwarf = -err; break; } } else { - cc->unw_rc = -err; + cc->urc_dwarf = -err; break; } } @@ -2038,10 +2038,10 @@ quadd_get_user_cc_dwarf(struct pt_regs *regs, if (!regs || !mm) return 0; - if (cc->unw_rc == QUADD_URC_LEVEL_TOO_DEEP) + if (cc->urc_dwarf == QUADD_URC_LEVEL_TOO_DEEP) return nr_prev; - cc->unw_rc = QUADD_URC_FAILURE; + cc->urc_dwarf = QUADD_URC_FAILURE; if (nr_prev > 0) { ip = cc->curr_pc; @@ -2109,7 +2109,7 @@ quadd_get_user_cc_dwarf(struct pt_regs *regs, err = quadd_get_dw_frames(vma->vm_start, &ri); if (err) { - cc->unw_rc = QUADD_URC_TBL_NOT_EXIST; + cc->urc_dwarf = QUADD_URC_TBL_NOT_EXIST; return 0; } diff --git a/drivers/misc/tegra-profiler/eh_unwind.c b/drivers/misc/tegra-profiler/eh_unwind.c index bfbcd144822f..b48765678aee 100644 --- a/drivers/misc/tegra-profiler/eh_unwind.c +++ b/drivers/misc/tegra-profiler/eh_unwind.c @@ -1060,7 +1060,7 @@ unwind_backtrace(struct quadd_callchain *cc, { struct ex_region_info ri_new; - cc->unw_rc = QUADD_URC_FAILURE; + cc->urc_ut = QUADD_URC_FAILURE; pr_debug("fp_arm: %#lx, fp_thumb: %#lx, sp: %#lx, lr: %#lx, pc: %#lx\n", frame->fp_arm, frame->fp_thumb, @@ -1081,7 +1081,7 @@ unwind_backtrace(struct quadd_callchain *cc, break; if (!validate_stack_addr(frame->sp, vma_sp, sizeof(u32))) { - cc->unw_rc = -QUADD_URC_SP_INCORRECT; + cc->urc_ut = QUADD_URC_SP_INCORRECT; break; } @@ -1094,7 +1094,7 @@ unwind_backtrace(struct quadd_callchain *cc, if (!is_vma_addr(ti->addr, vma_pc, sizeof(u32))) { err = get_extabs_ehabi(vma_pc->vm_start, &ri_new); if (err) { - cc->unw_rc = QUADD_URC_TBL_NOT_EXIST; + cc->urc_ut = QUADD_URC_TBL_NOT_EXIST; break; } @@ -1104,7 +1104,7 @@ unwind_backtrace(struct quadd_callchain *cc, err = unwind_frame(ri, frame, vma_sp); if (err < 0) { pr_debug("end unwind, urc: %ld\n", err); - cc->unw_rc = -err; + cc->urc_ut = -err; break; } @@ -1144,10 +1144,10 @@ quadd_get_user_cc_arm32_ehabi(struct pt_regs *regs, return 0; #endif - if (cc->unw_rc == QUADD_URC_LEVEL_TOO_DEEP) + if (cc->urc_ut == QUADD_URC_LEVEL_TOO_DEEP) return nr_prev; - cc->unw_rc = QUADD_URC_FAILURE; + cc->urc_ut = QUADD_URC_FAILURE; if (nr_prev > 0) { ip = cc->curr_pc; @@ -1188,7 +1188,7 @@ quadd_get_user_cc_arm32_ehabi(struct pt_regs *regs, err = get_extabs_ehabi(vma->vm_start, &ri); if (err) { - cc->unw_rc = QUADD_URC_TBL_NOT_EXIST; + cc->urc_ut = QUADD_URC_TBL_NOT_EXIST; return 0; } diff --git a/drivers/misc/tegra-profiler/hrt.c b/drivers/misc/tegra-profiler/hrt.c index 88a0d967e096..214b79c56aeb 100644 --- a/drivers/misc/tegra-profiler/hrt.c +++ b/drivers/misc/tegra-profiler/hrt.c @@ -62,7 +62,7 @@ static enum hrtimer_restart hrtimer_handler(struct hrtimer *hrtimer) regs = get_irq_regs(); - if (!hrt.active) + if (!atomic_read(&hrt.active)) return HRTIMER_NORESTART; qm_debug_handler_sample(regs); @@ -193,7 +193,14 @@ static void put_header(void) hdr->reserved = 0; hdr->extra_length = 0; - hdr->reserved |= hrt.unw_method << QUADD_HDR_UNW_METHOD_SHIFT; + if (hdr->backtrace) { + struct quadd_unw_methods *um = &hrt.um; + + hdr->reserved |= um->fp ? QUADD_HDR_BT_FP : 0; + hdr->reserved |= um->ut ? QUADD_HDR_BT_UT : 0; + hdr->reserved |= um->ut_ce ? QUADD_HDR_BT_UT_CE : 0; + hdr->reserved |= um->dwarf ? QUADD_HDR_BT_DWARF : 0; + } if (hrt.use_arch_timer) hdr->reserved |= QUADD_HDR_USE_ARCH_TIMER; @@ -335,11 +342,11 @@ get_stack_offset(struct task_struct *task, static void read_all_sources(struct pt_regs *regs, struct task_struct *task) { - u32 state, extra_data = 0; + u32 state, extra_data = 0, urcs = 0; int i, vec_idx = 0, bt_size = 0; int nr_events = 0, nr_positive_events = 0; struct pt_regs *user_regs; - struct quadd_iovec vec[5]; + struct quadd_iovec vec[6]; struct hrt_event_value events[QUADD_MAX_COUNTERS]; u32 events_extra[QUADD_MAX_COUNTERS]; @@ -401,7 +408,8 @@ read_all_sources(struct pt_regs *regs, struct task_struct *task) cc->curr_pc = 0; if (ctx->param.backtrace) { - cc->unw_method = hrt.unw_method; + cc->um = hrt.um; + bt_size = quadd_get_user_callchain(user_regs, cc, ctx, task); if (!bt_size && !user_mode(regs)) { @@ -434,8 +442,18 @@ read_all_sources(struct pt_regs *regs, struct task_struct *task) extra_data |= QUADD_SED_IP64; } - extra_data |= cc->unw_method << QUADD_SED_UNW_METHOD_SHIFT; - s->reserved |= cc->unw_rc << QUADD_SAMPLE_URC_SHIFT; + urcs |= (cc->urc_fp & QUADD_SAMPLE_URC_MASK) << + QUADD_SAMPLE_URC_SHIFT_FP; + urcs |= (cc->urc_ut & QUADD_SAMPLE_URC_MASK) << + QUADD_SAMPLE_URC_SHIFT_UT; + urcs |= (cc->urc_dwarf & QUADD_SAMPLE_URC_MASK) << + QUADD_SAMPLE_URC_SHIFT_DWARF; + + s->reserved |= QUADD_SAMPLE_RES_URCS_ENABLED; + + vec[vec_idx].base = &urcs; + vec[vec_idx].len = sizeof(urcs); + vec_idx++; } s->callchain_nr = bt_size; @@ -540,7 +558,7 @@ void __quadd_task_sched_in(struct task_struct *prev, struct event_data events[QUADD_MAX_COUNTERS]; /* static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 2); */ - if (likely(!hrt.active)) + if (likely(!atomic_read(&hrt.active))) return; /* if (__ratelimit(&ratelimit_state)) @@ -578,7 +596,7 @@ void __quadd_task_sched_out(struct task_struct *prev, struct quadd_ctx *ctx = hrt.quadd_ctx; /* static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 2); */ - if (likely(!hrt.active)) + if (likely(!atomic_read(&hrt.active))) return; /* if (__ratelimit(&ratelimit_state)) @@ -612,7 +630,7 @@ void __quadd_event_mmap(struct vm_area_struct *vma) { struct quadd_parameters *param; - if (likely(!hrt.active)) + if (likely(!atomic_read(&hrt.active))) return; if (!is_profile_process(current)) @@ -665,14 +683,17 @@ int quadd_hrt_start(void) extra = param->reserved[QUADD_PARAM_IDX_EXTRA]; - if (extra & QUADD_PARAM_EXTRA_BT_MIXED) - hrt.unw_method = QUADD_UNW_METHOD_MIXED; - else if (extra & QUADD_PARAM_EXTRA_BT_UNWIND_TABLES) - hrt.unw_method = QUADD_UNW_METHOD_EHT; - else if (extra & QUADD_PARAM_EXTRA_BT_FP) - hrt.unw_method = QUADD_UNW_METHOD_FP; - else - hrt.unw_method = QUADD_UNW_METHOD_NONE; + if (param->backtrace) { + struct quadd_unw_methods *um = &hrt.um; + + um->fp = extra & QUADD_PARAM_EXTRA_BT_FP ? 1 : 0; + um->ut = extra & QUADD_PARAM_EXTRA_BT_UT ? 1 : 0; + um->ut_ce = extra & QUADD_PARAM_EXTRA_BT_UT_CE ? 1 : 0; + um->dwarf = extra & QUADD_PARAM_EXTRA_BT_DWARF ? 1 : 0; + + pr_info("unw methods: fp/ut/ut_ce/dwarf: %u/%u/%u/%u\n", + um->fp, um->ut, um->ut_ce, um->dwarf); + } if (hrt.tc && (extra & QUADD_PARAM_EXTRA_USE_ARCH_TIMER)) hrt.use_arch_timer = 1; @@ -699,7 +720,7 @@ int quadd_hrt_start(void) quadd_ma_start(&hrt); - hrt.active = 1; + atomic_set(&hrt.active, 1); pr_info("Start hrt: freq/period: %ld/%llu\n", freq, period); return 0; @@ -718,7 +739,7 @@ void quadd_hrt_stop(void) quadd_ma_stop(&hrt); - hrt.active = 0; + atomic_set(&hrt.active, 0); atomic64_set(&hrt.counter_samples, 0); atomic64_set(&hrt.skipped_samples, 0); @@ -728,7 +749,7 @@ void quadd_hrt_stop(void) void quadd_hrt_deinit(void) { - if (hrt.active) + if (atomic_read(&hrt.active)) quadd_hrt_stop(); free_percpu(hrt.cpu_ctx); @@ -758,7 +779,7 @@ struct quadd_hrt_ctx *quadd_hrt_init(struct quadd_ctx *ctx) struct quadd_cpu_context *cpu_ctx; hrt.quadd_ctx = ctx; - hrt.active = 0; + atomic_set(&hrt.active, 0); freq = ctx->param.freq; freq = max_t(long, QUADD_HRT_MIN_FREQ, freq); diff --git a/drivers/misc/tegra-profiler/hrt.h b/drivers/misc/tegra-profiler/hrt.h index 172e2f1719dd..2b5254a52fa6 100644 --- a/drivers/misc/tegra-profiler/hrt.h +++ b/drivers/misc/tegra-profiler/hrt.h @@ -49,7 +49,7 @@ struct quadd_hrt_ctx { struct quadd_ctx *quadd_ctx; - int active; + atomic_t active; atomic_t nr_active_all_core; atomic64_t counter_samples; @@ -64,7 +64,7 @@ struct quadd_hrt_ctx { struct timecounter *tc; int use_arch_timer; - unsigned int unw_method; + struct quadd_unw_methods um; int get_stack_offset; }; diff --git a/drivers/misc/tegra-profiler/ma.c b/drivers/misc/tegra-profiler/ma.c index c7ccd82ac1b0..83ae8195f80e 100644 --- a/drivers/misc/tegra-profiler/ma.c +++ b/drivers/misc/tegra-profiler/ma.c @@ -85,7 +85,7 @@ static void timer_interrupt(unsigned long data) struct quadd_hrt_ctx *hrt_ctx = (struct quadd_hrt_ctx *)data; struct timer_list *timer = &hrt_ctx->ma_timer; - if (hrt_ctx->active == 0) + if (!atomic_read(&hrt_ctx->active)) return; check_ma(hrt_ctx); diff --git a/drivers/misc/tegra-profiler/main.c b/drivers/misc/tegra-profiler/main.c index f9d7d4bcdd9b..d3236970e27a 100644 --- a/drivers/misc/tegra-profiler/main.c +++ b/drivers/misc/tegra-profiler/main.c @@ -185,7 +185,6 @@ set_parameters(struct quadd_parameters *p, uid_t *debug_app_uid) int pl310_events_id; int nr_pmu = 0, nr_pl310 = 0; struct task_struct *task; - unsigned int extra; u64 *low_addr_p; if (!validate_freq(p->freq)) { @@ -293,17 +292,6 @@ set_parameters(struct quadd_parameters *p, uid_t *debug_app_uid) } } - extra = p->reserved[QUADD_PARAM_IDX_EXTRA]; - - if (extra & QUADD_PARAM_EXTRA_BT_UNWIND_TABLES) - pr_info("unwinding: exception-handling tables\n"); - - if (extra & QUADD_PARAM_EXTRA_BT_FP) - pr_info("unwinding: frame pointers\n"); - - if (extra & QUADD_PARAM_EXTRA_BT_MIXED) - pr_info("unwinding: mixed mode\n"); - low_addr_p = (u64 *)&p->reserved[QUADD_PARAM_IDX_BT_LOWER_BOUND]; ctx.hrt->low_addr = (unsigned long)*low_addr_p; pr_info("bt lower bound: %#lx\n", ctx.hrt->low_addr); diff --git a/drivers/misc/tegra-profiler/version.h b/drivers/misc/tegra-profiler/version.h index f956c1d40861..d3254f99c063 100644 --- a/drivers/misc/tegra-profiler/version.h +++ b/drivers/misc/tegra-profiler/version.h @@ -18,7 +18,7 @@ #ifndef __QUADD_VERSION_H #define __QUADD_VERSION_H -#define QUADD_MODULE_VERSION "1.96" +#define QUADD_MODULE_VERSION "1.97" #define QUADD_MODULE_BRANCH "Dev" #endif /* __QUADD_VERSION_H */ diff --git a/include/linux/tegra_profiler.h b/include/linux/tegra_profiler.h index 66d5bf240c74..fffa74a7e7df 100644 --- a/include/linux/tegra_profiler.h +++ b/include/linux/tegra_profiler.h @@ -19,8 +19,8 @@ #include <linux/ioctl.h> -#define QUADD_SAMPLES_VERSION 32 -#define QUADD_IO_VERSION 17 +#define QUADD_SAMPLES_VERSION 33 +#define QUADD_IO_VERSION 18 #define QUADD_IO_VERSION_DYNAMIC_RB 5 #define QUADD_IO_VERSION_RB_MAX_FILL_COUNT 6 @@ -35,6 +35,7 @@ #define QUADD_IO_VERSION_BT_LOWER_BOUND 15 #define QUADD_IO_VERSION_STACK_OFFSET 16 #define QUADD_IO_VERSION_SECTIONS_INFO 17 +#define QUADD_IO_VERSION_UNW_METHODS_OPT 18 #define QUADD_SAMPLE_VERSION_THUMB_MODE_FLAG 17 #define QUADD_SAMPLE_VERSION_GROUP_SAMPLES 18 @@ -50,6 +51,7 @@ #define QUADD_SAMPLE_VERSION_HDR_ARCH_TIMER 30 #define QUADD_SAMPLE_VERSION_STACK_OFFSET 31 #define QUADD_SAMPLE_VERSION_SCHED_TASK_STATE 32 +#define QUADD_SAMPLE_VERSION_URCS 33 #define QUADD_MMAP_HEADER_VERSION 1 @@ -165,18 +167,13 @@ enum quadd_cpu_mode { #pragma pack(push, 1) -#define QUADD_SAMPLE_UNW_METHOD_SHIFT 0 -#define QUADD_SAMPLE_UNW_METHOD_MASK (1 << QUADD_SAMPLE_UNW_METHOD_SHIFT) +#define QUADD_SAMPLE_RES_URCS_ENABLED (1 << 0) -enum { - QUADD_UNW_METHOD_FP = 0, - QUADD_UNW_METHOD_EHT, - QUADD_UNW_METHOD_MIXED, - QUADD_UNW_METHOD_NONE, -}; +#define QUADD_SAMPLE_URC_MASK 0xff -#define QUADD_SAMPLE_URC_SHIFT 1 -#define QUADD_SAMPLE_URC_MASK (0x0f << QUADD_SAMPLE_URC_SHIFT) +#define QUADD_SAMPLE_URC_SHIFT_FP 0 +#define QUADD_SAMPLE_URC_SHIFT_UT (1 * 8) +#define QUADD_SAMPLE_URC_SHIFT_DWARF (2 * 8) enum { QUADD_URC_SUCCESS = 0, @@ -194,15 +191,13 @@ enum { QUADD_URC_PC_INCORRECT, QUADD_URC_LEVEL_TOO_DEEP, QUADD_URC_FP_INCORRECT, + QUADD_URC_NONE, QUADD_URC_MAX, }; #define QUADD_SED_IP64 (1 << 0) -#define QUADD_SED_UNW_METHOD_SHIFT 1 -#define QUADD_SED_UNW_METHOD_MASK (0x07 << QUADD_SED_UNW_METHOD_SHIFT) - -#define QUADD_SED_STACK_OFFSET_SHIFT 4 +#define QUADD_SED_STACK_OFFSET_SHIFT 1 #define QUADD_SED_STACK_OFFSET_MASK (0xffff << QUADD_SED_STACK_OFFSET_SHIFT) enum { @@ -318,11 +313,12 @@ struct quadd_debug_data { #define QUADD_HEADER_MAGIC 0x1122 -#define QUADD_HDR_UNW_METHOD_SHIFT 0 -#define QUADD_HDR_UNW_METHOD_MASK (0x07 << QUADD_HDR_UNW_METHOD_SHIFT) - +#define QUADD_HDR_BT_FP (1 << 0) +#define QUADD_HDR_BT_UT (1 << 1) +#define QUADD_HDR_BT_UT_CE (1 << 2) #define QUADD_HDR_USE_ARCH_TIMER (1 << 3) #define QUADD_HDR_STACK_OFFSET (1 << 4) +#define QUADD_HDR_BT_DWARF (1 << 5) struct quadd_header_data { u16 magic; @@ -372,10 +368,12 @@ enum { #define QUADD_PARAM_EXTRA_GET_MMAP (1 << 0) #define QUADD_PARAM_EXTRA_BT_FP (1 << 1) -#define QUADD_PARAM_EXTRA_BT_UNWIND_TABLES (1 << 2) +#define QUADD_PARAM_EXTRA_BT_UT (1 << 2) #define QUADD_PARAM_EXTRA_BT_MIXED (1 << 3) #define QUADD_PARAM_EXTRA_USE_ARCH_TIMER (1 << 4) #define QUADD_PARAM_EXTRA_STACK_OFFSET (1 << 5) +#define QUADD_PARAM_EXTRA_BT_UT_CE (1 << 6) +#define QUADD_PARAM_EXTRA_BT_DWARF (1 << 7) struct quadd_parameters { u32 freq; |