Skip to content

Commit fe13f95

Browse files
AKASHI Takahirowildea01
authored andcommitted
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: AKASHI Takahiro <takahiro.akashi@linaro.org> Signed-off-by: Will Deacon <will.deacon@arm.com>
1 parent 79fdee9 commit fe13f95

File tree

7 files changed

+13
-11
lines changed

7 files changed

+13
-11
lines changed

arch/arm64/include/asm/stacktrace.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,16 @@
1616
#ifndef __ASM_STACKTRACE_H
1717
#define __ASM_STACKTRACE_H
1818

19+
struct task_struct;
20+
1921
struct stackframe {
2022
unsigned long fp;
2123
unsigned long sp;
2224
unsigned long pc;
2325
};
2426

25-
extern int unwind_frame(struct stackframe *frame);
26-
extern void walk_stackframe(struct stackframe *frame,
27+
extern int unwind_frame(struct task_struct *tsk, struct stackframe *frame);
28+
extern void walk_stackframe(struct task_struct *tsk, struct stackframe *frame,
2729
int (*fn)(struct stackframe *, void *), void *data);
2830

2931
#endif /* __ASM_STACKTRACE_H */

arch/arm64/kernel/perf_callchain.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry,
165165
frame.sp = regs->sp;
166166
frame.pc = regs->pc;
167167

168-
walk_stackframe(&frame, callchain_trace, entry);
168+
walk_stackframe(current, &frame, callchain_trace, entry);
169169
}
170170

171171
unsigned long perf_instruction_pointer(struct pt_regs *regs)

arch/arm64/kernel/process.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ unsigned long get_wchan(struct task_struct *p)
348348
do {
349349
if (frame.sp < stack_page ||
350350
frame.sp >= stack_page + THREAD_SIZE ||
351-
unwind_frame(&frame))
351+
unwind_frame(p, &frame))
352352
return 0;
353353
if (!in_sched_functions(frame.pc))
354354
return frame.pc;

arch/arm64/kernel/return_address.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ void *return_address(unsigned int level)
4444
frame.sp = current_stack_pointer;
4545
frame.pc = (unsigned long)return_address; /* dummy */
4646

47-
walk_stackframe(&frame, save_return_addr, &data);
47+
walk_stackframe(current, &frame, save_return_addr, &data);
4848

4949
if (!data.level)
5050
return data.addr;

arch/arm64/kernel/stacktrace.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
* ldp x29, x30, [sp]
3737
* add sp, sp, #0x10
3838
*/
39-
int notrace unwind_frame(struct stackframe *frame)
39+
int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
4040
{
4141
unsigned long high, low;
4242
unsigned long fp = frame->fp;
@@ -99,15 +99,15 @@ int notrace unwind_frame(struct stackframe *frame)
9999
return 0;
100100
}
101101

102-
void notrace walk_stackframe(struct stackframe *frame,
102+
void notrace walk_stackframe(struct task_struct *tsk, struct stackframe *frame,
103103
int (*fn)(struct stackframe *, void *), void *data)
104104
{
105105
while (1) {
106106
int ret;
107107

108108
if (fn(frame, data))
109109
break;
110-
ret = unwind_frame(frame);
110+
ret = unwind_frame(tsk, frame);
111111
if (ret < 0)
112112
break;
113113
}
@@ -159,7 +159,7 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
159159
frame.pc = (unsigned long)save_stack_trace_tsk;
160160
}
161161

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

arch/arm64/kernel/time.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ unsigned long profile_pc(struct pt_regs *regs)
5353
frame.sp = regs->sp;
5454
frame.pc = regs->pc;
5555
do {
56-
int ret = unwind_frame(&frame);
56+
int ret = unwind_frame(NULL, &frame);
5757
if (ret < 0)
5858
return 0;
5959
} while (in_lock_functions(frame.pc));

arch/arm64/kernel/traps.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
177177
int ret;
178178

179179
dump_backtrace_entry(where);
180-
ret = unwind_frame(&frame);
180+
ret = unwind_frame(tsk, &frame);
181181
if (ret < 0)
182182
break;
183183
stack = frame.sp;

0 commit comments

Comments
 (0)