Skip to content

Commit 0b45252

Browse files
author
Vasily Gorbik
committed
s390/test_unwind: extend kretprobe test
Verify unwinding from kretprobed function. Reviewed-by: Tobias Huschle <huschle@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
1 parent a7e196f commit 0b45252

1 file changed

Lines changed: 33 additions & 16 deletions

File tree

arch/s390/lib/test_unwind.c

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -132,36 +132,50 @@ static struct unwindme *unwindme;
132132
#define UWM_PGM 0x40 /* Unwind from program check handler */
133133
#define UWM_KPROBE_ON_FTRACE 0x80 /* Unwind from kprobe handler called via ftrace. */
134134
#define UWM_FTRACE 0x100 /* Unwind from ftrace handler. */
135-
#define UWM_KRETPROBE 0x200 /* Unwind kretprobe handlers. */
135+
#define UWM_KRETPROBE 0x200 /* Unwind through kretprobed function. */
136+
#define UWM_KRETPROBE_HANDLER 0x400 /* Unwind from kretprobe handler. */
136137

137-
static __always_inline unsigned long get_psw_addr(void)
138+
static __always_inline struct pt_regs fake_pt_regs(void)
138139
{
139-
unsigned long psw_addr;
140+
struct pt_regs regs;
141+
142+
memset(&regs, 0, sizeof(regs));
143+
regs.gprs[15] = current_stack_pointer();
140144

141145
asm volatile(
142146
"basr %[psw_addr],0\n"
143-
: [psw_addr] "=d" (psw_addr));
144-
return psw_addr;
147+
: [psw_addr] "=d" (regs.psw.addr));
148+
return regs;
145149
}
146150

147151
static int kretprobe_ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
148152
{
149153
struct unwindme *u = unwindme;
150154

155+
if (!(u->flags & UWM_KRETPROBE_HANDLER))
156+
return 0;
157+
151158
u->ret = test_unwind(NULL, (u->flags & UWM_REGS) ? regs : NULL,
152159
(u->flags & UWM_SP) ? u->sp : 0);
153160

154161
return 0;
155162
}
156163

157-
static noinline notrace void test_unwind_kretprobed_func(void)
164+
static noinline notrace int test_unwind_kretprobed_func(struct unwindme *u)
158165
{
159-
asm volatile(" nop\n");
166+
struct pt_regs regs;
167+
168+
if (!(u->flags & UWM_KRETPROBE))
169+
return 0;
170+
171+
regs = fake_pt_regs();
172+
return test_unwind(NULL, (u->flags & UWM_REGS) ? &regs : NULL,
173+
(u->flags & UWM_SP) ? u->sp : 0);
160174
}
161175

162-
static noinline void test_unwind_kretprobed_func_caller(void)
176+
static noinline int test_unwind_kretprobed_func_caller(struct unwindme *u)
163177
{
164-
test_unwind_kretprobed_func();
178+
return test_unwind_kretprobed_func(u);
165179
}
166180

167181
static int test_unwind_kretprobe(struct unwindme *u)
@@ -187,10 +201,12 @@ static int test_unwind_kretprobe(struct unwindme *u)
187201
return -EINVAL;
188202
}
189203

190-
test_unwind_kretprobed_func_caller();
204+
ret = test_unwind_kretprobed_func_caller(u);
191205
unregister_kretprobe(&my_kretprobe);
192206
unwindme = NULL;
193-
return u->ret;
207+
if (u->flags & UWM_KRETPROBE_HANDLER)
208+
ret = u->ret;
209+
return ret;
194210
}
195211

196212
static int kprobe_pre_handler(struct kprobe *p, struct pt_regs *regs)
@@ -304,16 +320,13 @@ static noinline int unwindme_func4(struct unwindme *u)
304320
return 0;
305321
} else if (u->flags & (UWM_PGM | UWM_KPROBE_ON_FTRACE)) {
306322
return test_unwind_kprobe(u);
307-
} else if (u->flags & (UWM_KRETPROBE)) {
323+
} else if (u->flags & (UWM_KRETPROBE | UWM_KRETPROBE_HANDLER)) {
308324
return test_unwind_kretprobe(u);
309325
} else if (u->flags & UWM_FTRACE) {
310326
return test_unwind_ftrace(u);
311327
} else {
312-
struct pt_regs regs;
328+
struct pt_regs regs = fake_pt_regs();
313329

314-
memset(&regs, 0, sizeof(regs));
315-
regs.psw.addr = get_psw_addr();
316-
regs.gprs[15] = current_stack_pointer();
317330
return test_unwind(NULL,
318331
(u->flags & UWM_REGS) ? &regs : NULL,
319332
(u->flags & UWM_SP) ? u->sp : 0);
@@ -452,6 +465,10 @@ static const struct test_params param_list[] = {
452465
TEST_WITH_FLAGS(UWM_KRETPROBE | UWM_SP),
453466
TEST_WITH_FLAGS(UWM_KRETPROBE | UWM_REGS),
454467
TEST_WITH_FLAGS(UWM_KRETPROBE | UWM_SP | UWM_REGS),
468+
TEST_WITH_FLAGS(UWM_KRETPROBE_HANDLER),
469+
TEST_WITH_FLAGS(UWM_KRETPROBE_HANDLER | UWM_SP),
470+
TEST_WITH_FLAGS(UWM_KRETPROBE_HANDLER | UWM_REGS),
471+
TEST_WITH_FLAGS(UWM_KRETPROBE_HANDLER | UWM_SP | UWM_REGS),
455472
};
456473

457474
/*

0 commit comments

Comments
 (0)