Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe13f95b authored by AKASHI Takahiro's avatar AKASHI Takahiro Committed by Will Deacon
Browse files

arm64: pass a task parameter to unwind_frame()



Function graph tracer modifies a return address (LR) in a stack frame
to hook a function's return. This will result in many useless entries
(return_to_handler) showing up in a call stack list.
We will fix this problem in a later patch ("arm64: ftrace: fix a stack
tracer's output under function graph tracer"). But since real return
addresses are saved in ret_stack[] array in struct task_struct,
unwind functions need to be notified of, in addition to a stack pointer
address, which task is being traced in order to find out real return
addresses.

This patch extends unwind functions' interfaces by adding an extra
argument of a pointer to task_struct.

Signed-off-by: default avatarAKASHI Takahiro <takahiro.akashi@linaro.org>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
parent 79fdee9b
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -16,14 +16,16 @@
#ifndef __ASM_STACKTRACE_H
#define __ASM_STACKTRACE_H

struct task_struct;

struct stackframe {
	unsigned long fp;
	unsigned long sp;
	unsigned long pc;
};

extern int unwind_frame(struct stackframe *frame);
extern void walk_stackframe(struct stackframe *frame,
extern int unwind_frame(struct task_struct *tsk, struct stackframe *frame);
extern void walk_stackframe(struct task_struct *tsk, struct stackframe *frame,
			    int (*fn)(struct stackframe *, void *), void *data);

#endif	/* __ASM_STACKTRACE_H */
+1 −1
Original line number Diff line number Diff line
@@ -165,7 +165,7 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry,
	frame.sp = regs->sp;
	frame.pc = regs->pc;

	walk_stackframe(&frame, callchain_trace, entry);
	walk_stackframe(current, &frame, callchain_trace, entry);
}

unsigned long perf_instruction_pointer(struct pt_regs *regs)
+1 −1
Original line number Diff line number Diff line
@@ -348,7 +348,7 @@ unsigned long get_wchan(struct task_struct *p)
	do {
		if (frame.sp < stack_page ||
		    frame.sp >= stack_page + THREAD_SIZE ||
		    unwind_frame(&frame))
		    unwind_frame(p, &frame))
			return 0;
		if (!in_sched_functions(frame.pc))
			return frame.pc;
+1 −1
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ void *return_address(unsigned int level)
	frame.sp = current_stack_pointer;
	frame.pc = (unsigned long)return_address; /* dummy */

	walk_stackframe(&frame, save_return_addr, &data);
	walk_stackframe(current, &frame, save_return_addr, &data);

	if (!data.level)
		return data.addr;
+4 −4
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@
 *	ldp	x29, x30, [sp]
 *	add	sp, sp, #0x10
 */
int notrace unwind_frame(struct stackframe *frame)
int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
{
	unsigned long high, low;
	unsigned long fp = frame->fp;
@@ -99,7 +99,7 @@ int notrace unwind_frame(struct stackframe *frame)
	return 0;
}

void notrace walk_stackframe(struct stackframe *frame,
void notrace walk_stackframe(struct task_struct *tsk, struct stackframe *frame,
		     int (*fn)(struct stackframe *, void *), void *data)
{
	while (1) {
@@ -107,7 +107,7 @@ void notrace walk_stackframe(struct stackframe *frame,

		if (fn(frame, data))
			break;
		ret = unwind_frame(frame);
		ret = unwind_frame(tsk, frame);
		if (ret < 0)
			break;
	}
@@ -159,7 +159,7 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
		frame.pc = (unsigned long)save_stack_trace_tsk;
	}

	walk_stackframe(&frame, save_trace, &data);
	walk_stackframe(tsk, &frame, save_trace, &data);
	if (trace->nr_entries < trace->max_entries)
		trace->entries[trace->nr_entries++] = ULONG_MAX;
}
Loading