diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c index c485186a8b6ddf..4c826a2e08d8bc 100644 --- a/tools/perf/util/thread-stack.c +++ b/tools/perf/util/thread-stack.c @@ -628,6 +628,23 @@ static int thread_stack__bottom(struct thread_stack *ts, true, false); } +static int thread_stack__pop_ks(struct thread *thread, struct thread_stack *ts, + struct perf_sample *sample, u64 ref) +{ + u64 tm = sample->time; + int err; + + /* Return to userspace, so pop all kernel addresses */ + while (thread_stack__in_kernel(ts)) { + err = thread_stack__call_return(thread, ts, --ts->cnt, + tm, ref, true); + if (err) + return err; + } + + return 0; +} + static int thread_stack__no_call_return(struct thread *thread, struct thread_stack *ts, struct perf_sample *sample, @@ -910,7 +927,18 @@ int thread_stack__process(struct thread *thread, struct comm *comm, ts->rstate = X86_RETPOLINE_DETECTED; } else if (sample->flags & PERF_IP_FLAG_RETURN) { - if (!sample->ip || !sample->addr) + if (!sample->addr) { + u32 return_from_kernel = PERF_IP_FLAG_SYSCALLRET | + PERF_IP_FLAG_INTERRUPT; + + if (!(sample->flags & return_from_kernel)) + return 0; + + /* Pop kernel stack */ + return thread_stack__pop_ks(thread, ts, sample, ref); + } + + if (!sample->ip) return 0; /* x86 retpoline 'return' doesn't match the stack */