]> xenbits.xensource.com Git - people/jgross/linux.git/commitdiff
s390/test_unwind: extend kretprobe test
authorVasily Gorbik <gor@linux.ibm.com>
Sat, 5 Mar 2022 17:57:44 +0000 (18:57 +0100)
committerVasily Gorbik <gor@linux.ibm.com>
Sun, 27 Mar 2022 20:18:39 +0000 (22:18 +0200)
Verify unwinding from kretprobed function.

Reviewed-by: Tobias Huschle <huschle@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/lib/test_unwind.c

index c01f02887de46741b31a01ccbb03984d88d58275..468e1ce66a33e7f931fa92b4670789b88ca94ff8 100644 (file)
@@ -132,36 +132,50 @@ static struct unwindme *unwindme;
 #define UWM_PGM                        0x40    /* Unwind from program check handler */
 #define UWM_KPROBE_ON_FTRACE   0x80    /* Unwind from kprobe handler called via ftrace. */
 #define UWM_FTRACE             0x100   /* Unwind from ftrace handler. */
-#define UWM_KRETPROBE          0x200   /* Unwind kretprobe handlers. */
+#define UWM_KRETPROBE          0x200   /* Unwind through kretprobed function. */
+#define UWM_KRETPROBE_HANDLER  0x400   /* Unwind from kretprobe handler. */
 
-static __always_inline unsigned long get_psw_addr(void)
+static __always_inline struct pt_regs fake_pt_regs(void)
 {
-       unsigned long psw_addr;
+       struct pt_regs regs;
+
+       memset(&regs, 0, sizeof(regs));
+       regs.gprs[15] = current_stack_pointer();
 
        asm volatile(
                "basr   %[psw_addr],0\n"
-               : [psw_addr] "=d" (psw_addr));
-       return psw_addr;
+               : [psw_addr] "=d" (regs.psw.addr));
+       return regs;
 }
 
 static int kretprobe_ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
 {
        struct unwindme *u = unwindme;
 
+       if (!(u->flags & UWM_KRETPROBE_HANDLER))
+               return 0;
+
        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)
+static noinline notrace int test_unwind_kretprobed_func(struct unwindme *u)
 {
-       asm volatile("  nop\n");
+       struct pt_regs regs;
+
+       if (!(u->flags & UWM_KRETPROBE))
+               return 0;
+
+       regs = fake_pt_regs();
+       return test_unwind(NULL, (u->flags & UWM_REGS) ? &regs : NULL,
+                          (u->flags & UWM_SP) ? u->sp : 0);
 }
 
-static noinline void test_unwind_kretprobed_func_caller(void)
+static noinline int test_unwind_kretprobed_func_caller(struct unwindme *u)
 {
-       test_unwind_kretprobed_func();
+       return test_unwind_kretprobed_func(u);
 }
 
 static int test_unwind_kretprobe(struct unwindme *u)
@@ -187,10 +201,12 @@ static int test_unwind_kretprobe(struct unwindme *u)
                return -EINVAL;
        }
 
-       test_unwind_kretprobed_func_caller();
+       ret = test_unwind_kretprobed_func_caller(u);
        unregister_kretprobe(&my_kretprobe);
        unwindme = NULL;
-       return u->ret;
+       if (u->flags & UWM_KRETPROBE_HANDLER)
+               ret = u->ret;
+       return ret;
 }
 
 static int kprobe_pre_handler(struct kprobe *p, struct pt_regs *regs)
@@ -304,16 +320,13 @@ static noinline int unwindme_func4(struct unwindme *u)
                return 0;
        } else if (u->flags & (UWM_PGM | UWM_KPROBE_ON_FTRACE)) {
                return test_unwind_kprobe(u);
-       } else if (u->flags & (UWM_KRETPROBE)) {
+       } else if (u->flags & (UWM_KRETPROBE | UWM_KRETPROBE_HANDLER)) {
                return test_unwind_kretprobe(u);
        } else if (u->flags & UWM_FTRACE) {
                return test_unwind_ftrace(u);
        } else {
-               struct pt_regs regs;
+               struct pt_regs regs = fake_pt_regs();
 
-               memset(&regs, 0, sizeof(regs));
-               regs.psw.addr = get_psw_addr();
-               regs.gprs[15] = current_stack_pointer();
                return test_unwind(NULL,
                                   (u->flags & UWM_REGS) ? &regs : NULL,
                                   (u->flags & UWM_SP) ? u->sp : 0);
@@ -452,6 +465,10 @@ static const struct test_params param_list[] = {
        TEST_WITH_FLAGS(UWM_KRETPROBE | UWM_SP),
        TEST_WITH_FLAGS(UWM_KRETPROBE | UWM_REGS),
        TEST_WITH_FLAGS(UWM_KRETPROBE | UWM_SP | UWM_REGS),
+       TEST_WITH_FLAGS(UWM_KRETPROBE_HANDLER),
+       TEST_WITH_FLAGS(UWM_KRETPROBE_HANDLER | UWM_SP),
+       TEST_WITH_FLAGS(UWM_KRETPROBE_HANDLER | UWM_REGS),
+       TEST_WITH_FLAGS(UWM_KRETPROBE_HANDLER | UWM_SP | UWM_REGS),
 };
 
 /*