Skip to content

Commit ebd912f

Browse files
hcahcaAlexander Gordeev
authored andcommitted
s390/stacktrace: Merge perf_callchain_user() and arch_stack_walk_user()
The two functions perf_callchain_user() and arch_stack_walk_user() are nearly identical. Reduce code duplication and add a common helper which can be called by both functions. Fixes: aa44433 ("s390: add USER_STACKTRACE support") Reviewed-by: Jens Remus <jremus@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
1 parent 185445c commit ebd912f

3 files changed

Lines changed: 36 additions & 38 deletions

File tree

arch/s390/include/asm/stacktrace.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#ifndef _ASM_S390_STACKTRACE_H
33
#define _ASM_S390_STACKTRACE_H
44

5+
#include <linux/stacktrace.h>
56
#include <linux/uaccess.h>
67
#include <linux/ptrace.h>
78

@@ -12,6 +13,12 @@ struct stack_frame_user {
1213
unsigned long empty2[4];
1314
};
1415

16+
struct perf_callchain_entry_ctx;
17+
18+
void arch_stack_walk_user_common(stack_trace_consume_fn consume_entry, void *cookie,
19+
struct perf_callchain_entry_ctx *entry,
20+
const struct pt_regs *regs, bool perf);
21+
1522
enum stack_type {
1623
STACK_TYPE_UNKNOWN,
1724
STACK_TYPE_TASK,

arch/s390/kernel/perf_event.c

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -218,39 +218,7 @@ void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
218218
void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
219219
struct pt_regs *regs)
220220
{
221-
struct stack_frame_user __user *sf;
222-
unsigned long ip, sp;
223-
bool first = true;
224-
225-
if (is_compat_task())
226-
return;
227-
perf_callchain_store(entry, instruction_pointer(regs));
228-
sf = (void __user *)user_stack_pointer(regs);
229-
pagefault_disable();
230-
while (entry->nr < entry->max_stack) {
231-
if (__get_user(sp, &sf->back_chain))
232-
break;
233-
if (__get_user(ip, &sf->gprs[8]))
234-
break;
235-
if (ip & 0x1) {
236-
/*
237-
* If the instruction address is invalid, and this
238-
* is the first stack frame, assume r14 has not
239-
* been written to the stack yet. Otherwise exit.
240-
*/
241-
if (first && !(regs->gprs[14] & 0x1))
242-
ip = regs->gprs[14];
243-
else
244-
break;
245-
}
246-
perf_callchain_store(entry, ip);
247-
/* Sanity check: ABI requires SP to be aligned 8 bytes. */
248-
if (!sp || sp & 0x7)
249-
break;
250-
sf = (void __user *)sp;
251-
first = false;
252-
}
253-
pagefault_enable();
221+
arch_stack_walk_user_common(NULL, NULL, entry, regs, true);
254222
}
255223

256224
/* Perf definitions for PMU event attributes in sysfs */

arch/s390/kernel/stacktrace.c

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Copyright IBM Corp. 2006
66
*/
77

8+
#include <linux/perf_event.h>
89
#include <linux/stacktrace.h>
910
#include <linux/uaccess.h>
1011
#include <linux/compat.h>
@@ -62,16 +63,32 @@ int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
6263
return 0;
6364
}
6465

65-
void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
66-
const struct pt_regs *regs)
66+
static inline bool store_ip(stack_trace_consume_fn consume_entry, void *cookie,
67+
struct perf_callchain_entry_ctx *entry, bool perf,
68+
unsigned long ip)
69+
{
70+
#ifdef CONFIG_PERF_EVENTS
71+
if (perf) {
72+
if (perf_callchain_store(entry, ip))
73+
return false;
74+
return true;
75+
}
76+
#endif
77+
return consume_entry(cookie, ip);
78+
}
79+
80+
void arch_stack_walk_user_common(stack_trace_consume_fn consume_entry, void *cookie,
81+
struct perf_callchain_entry_ctx *entry,
82+
const struct pt_regs *regs, bool perf)
6783
{
6884
struct stack_frame_user __user *sf;
6985
unsigned long ip, sp;
7086
bool first = true;
7187

7288
if (is_compat_task())
7389
return;
74-
if (!consume_entry(cookie, instruction_pointer(regs)))
90+
ip = instruction_pointer(regs);
91+
if (!store_ip(consume_entry, cookie, entry, perf, ip))
7592
return;
7693
sf = (void __user *)user_stack_pointer(regs);
7794
pagefault_disable();
@@ -91,8 +108,8 @@ void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
91108
else
92109
break;
93110
}
94-
if (!consume_entry(cookie, ip))
95-
break;
111+
if (!store_ip(consume_entry, cookie, entry, perf, ip))
112+
return;
96113
/* Sanity check: ABI requires SP to be aligned 8 bytes. */
97114
if (!sp || sp & 0x7)
98115
break;
@@ -102,6 +119,12 @@ void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
102119
pagefault_enable();
103120
}
104121

122+
void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
123+
const struct pt_regs *regs)
124+
{
125+
arch_stack_walk_user_common(consume_entry, cookie, NULL, regs, false);
126+
}
127+
105128
unsigned long return_address(unsigned int n)
106129
{
107130
struct unwind_state state;

0 commit comments

Comments
 (0)