Discussion:
[PATCH 1/3] MIPS: oprofile: fix backtrace on 64-bit kernel
Aaro Koskinen
2014-10-17 15:10:24 UTC
Permalink
Fix incorrect cast that always results in wrong address for the new
frame on 64-bit kernels.

Cc: ***@vger.kernel.org
Signed-off-by: Aaro Koskinen <***@nsn.com>
---
arch/mips/oprofile/backtrace.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/oprofile/backtrace.c b/arch/mips/oprofile/backtrace.c
index 6854ed5..83a1dfd 100644
--- a/arch/mips/oprofile/backtrace.c
+++ b/arch/mips/oprofile/backtrace.c
@@ -92,7 +92,7 @@ static inline int unwind_user_frame(struct stackframe *old_frame,
/* This marks the end of the previous function,
which means we overran. */
break;
- stack_size = (unsigned) stack_adjustment;
+ stack_size = (unsigned long) stack_adjustment;
} else if (is_ra_save_ins(&ip)) {
int ra_slot = ip.i_format.simmediate;
if (ra_slot < 0)
--
1.9.1
Aaro Koskinen
2014-10-17 15:10:25 UTC
Permalink
Allow unsupported CPU types to use backtrace with timer-based profiling.
Some CPUs (notably OCTEON) lack architecture-specific oprofile driver. In
such case oprofile can fallback to timer-based mode, and arch code can
still provide the backtrace functionality. So just set up the backtrace
hook always.

Signed-off-by: Aaro Koskinen <***@nsn.com>
---
arch/mips/oprofile/common.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index e747324..6183d05 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -106,6 +106,12 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
break;
};

+ /*
+ * Always set the backtrace. This allows unsupported CPU types to still
+ * use timer-based oprofile.
+ */
+ ops->backtrace = op_mips_backtrace;
+
if (!lmodel)
return -ENODEV;

@@ -121,7 +127,6 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
ops->start = op_mips_start;
ops->stop = op_mips_stop;
ops->cpu_type = lmodel->cpu_type;
- ops->backtrace = op_mips_backtrace;

printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
lmodel->cpu_type);
--
1.9.1
Aaro Koskinen
2014-10-17 15:10:26 UTC
Permalink
Continue the backtrace if we cannot find SP adjustment and RA save. In
that case, just assume the current RA. This allows us to get samples of
frequent callers of e.g. GLIBC memset().

Signed-off-by: Aaro Koskinen <***@nsn.com>
---
arch/mips/oprofile/backtrace.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/mips/oprofile/backtrace.c b/arch/mips/oprofile/backtrace.c
index 83a1dfd..5e645c9 100644
--- a/arch/mips/oprofile/backtrace.c
+++ b/arch/mips/oprofile/backtrace.c
@@ -65,7 +65,7 @@ static inline int is_end_of_function_marker(union mips_instruction *ip)
* - handle cases where the stack is adjusted inside a function
* (generally doesn't happen)
* - find optimal value for max_instr_check
- * - try to find a way to handle leaf functions
+ * - try to find a better way to handle leaf functions
*/

static inline int unwind_user_frame(struct stackframe *old_frame,
@@ -104,7 +104,7 @@ static inline int unwind_user_frame(struct stackframe *old_frame,
}

if (!ra_offset || !stack_size)
- return -1;
+ goto done;

if (ra_offset) {
new_frame.ra = old_frame->sp + ra_offset;
@@ -121,6 +121,7 @@ static inline int unwind_user_frame(struct stackframe *old_frame,
if (new_frame.sp > old_frame->sp)
return -2;

+done:
new_frame.pc = old_frame->ra;
*old_frame = new_frame;
--
1.9.1
Loading...