mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
s390/test_unwind: add kretprobe tests
Add tests to verify that s390 kretprobes maintain a correct stack chain and ensure their proper function. Reviewed-by: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Tobias Huschle <huschle@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
parent
63bf38ff5b
commit
c65f677b62
1 changed files with 56 additions and 0 deletions
|
@ -132,6 +132,7 @@ static struct unwindme *unwindme;
|
||||||
#define UWM_PGM 0x40 /* Unwind from program check handler */
|
#define UWM_PGM 0x40 /* Unwind from program check handler */
|
||||||
#define UWM_KPROBE_ON_FTRACE 0x80 /* Unwind from kprobe handler called via ftrace. */
|
#define UWM_KPROBE_ON_FTRACE 0x80 /* Unwind from kprobe handler called via ftrace. */
|
||||||
#define UWM_FTRACE 0x100 /* Unwind from ftrace handler. */
|
#define UWM_FTRACE 0x100 /* Unwind from ftrace handler. */
|
||||||
|
#define UWM_KRETPROBE 0x200 /* Unwind kretprobe handlers. */
|
||||||
|
|
||||||
static __always_inline unsigned long get_psw_addr(void)
|
static __always_inline unsigned long get_psw_addr(void)
|
||||||
{
|
{
|
||||||
|
@ -143,6 +144,55 @@ static __always_inline unsigned long get_psw_addr(void)
|
||||||
return psw_addr;
|
return psw_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int kretprobe_ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
struct unwindme *u = unwindme;
|
||||||
|
|
||||||
|
u->ret = test_unwind(NULL, (u->flags & UWM_REGS) ? regs : NULL,
|
||||||
|
(u->flags & UWM_SP) ? u->sp : 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static noinline notrace void test_unwind_kretprobed_func(void)
|
||||||
|
{
|
||||||
|
asm volatile(" nop\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static noinline void test_unwind_kretprobed_func_caller(void)
|
||||||
|
{
|
||||||
|
test_unwind_kretprobed_func();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_unwind_kretprobe(struct unwindme *u)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct kretprobe my_kretprobe;
|
||||||
|
|
||||||
|
if (!IS_ENABLED(CONFIG_KPROBES))
|
||||||
|
kunit_skip(current_test, "requires CONFIG_KPROBES");
|
||||||
|
|
||||||
|
u->ret = -1; /* make sure kprobe is called */
|
||||||
|
unwindme = u;
|
||||||
|
|
||||||
|
memset(&my_kretprobe, 0, sizeof(my_kretprobe));
|
||||||
|
my_kretprobe.handler = kretprobe_ret_handler;
|
||||||
|
my_kretprobe.maxactive = 1;
|
||||||
|
my_kretprobe.kp.addr = (kprobe_opcode_t *)test_unwind_kretprobed_func;
|
||||||
|
|
||||||
|
ret = register_kretprobe(&my_kretprobe);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
kunit_err(current_test, "register_kretprobe failed %d\n", ret);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
test_unwind_kretprobed_func_caller();
|
||||||
|
unregister_kretprobe(&my_kretprobe);
|
||||||
|
unwindme = NULL;
|
||||||
|
return u->ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int kprobe_pre_handler(struct kprobe *p, struct pt_regs *regs)
|
static int kprobe_pre_handler(struct kprobe *p, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
struct unwindme *u = unwindme;
|
struct unwindme *u = unwindme;
|
||||||
|
@ -254,6 +304,8 @@ static noinline int unwindme_func4(struct unwindme *u)
|
||||||
return 0;
|
return 0;
|
||||||
} else if (u->flags & (UWM_PGM | UWM_KPROBE_ON_FTRACE)) {
|
} else if (u->flags & (UWM_PGM | UWM_KPROBE_ON_FTRACE)) {
|
||||||
return test_unwind_kprobe(u);
|
return test_unwind_kprobe(u);
|
||||||
|
} else if (u->flags & (UWM_KRETPROBE)) {
|
||||||
|
return test_unwind_kretprobe(u);
|
||||||
} else if (u->flags & UWM_FTRACE) {
|
} else if (u->flags & UWM_FTRACE) {
|
||||||
return test_unwind_ftrace(u);
|
return test_unwind_ftrace(u);
|
||||||
} else {
|
} else {
|
||||||
|
@ -396,6 +448,10 @@ static const struct test_params param_list[] = {
|
||||||
TEST_WITH_FLAGS(UWM_FTRACE | UWM_SP),
|
TEST_WITH_FLAGS(UWM_FTRACE | UWM_SP),
|
||||||
TEST_WITH_FLAGS(UWM_FTRACE | UWM_REGS),
|
TEST_WITH_FLAGS(UWM_FTRACE | UWM_REGS),
|
||||||
TEST_WITH_FLAGS(UWM_FTRACE | UWM_SP | UWM_REGS),
|
TEST_WITH_FLAGS(UWM_FTRACE | UWM_SP | UWM_REGS),
|
||||||
|
TEST_WITH_FLAGS(UWM_KRETPROBE),
|
||||||
|
TEST_WITH_FLAGS(UWM_KRETPROBE | UWM_SP),
|
||||||
|
TEST_WITH_FLAGS(UWM_KRETPROBE | UWM_REGS),
|
||||||
|
TEST_WITH_FLAGS(UWM_KRETPROBE | UWM_SP | UWM_REGS),
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Reference in a new issue