From patchwork Tue Nov 8 15:49:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 17109 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2789910wru; Tue, 8 Nov 2022 07:50:49 -0800 (PST) X-Google-Smtp-Source: AMsMyM6E8TvNE4SNr9MgkMsMfcJJzVTK8tnsXTDlZIFdPFhuOolmV5N5lXXEVQ48D+IzSWoQEhEz X-Received: by 2002:a17:906:6a02:b0:7ae:2793:aa19 with SMTP id qw2-20020a1709066a0200b007ae2793aa19mr25612662ejc.265.1667922649020; Tue, 08 Nov 2022 07:50:49 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1667922649; cv=none; d=google.com; s=arc-20160816; b=HCI3Hew1xeQn8ReLSdTQL8w77CZSIQtbZZ8vLI/fHdjNeFVma80lyY8jsbgsVAo6k3 UFbAU5vC1CEqeSvKeLBSSSa9gPls8dE/MpgUNkHdj/jQYGX3+tEFBdciYoPOzw13tFfh BikJlcZLescBS1KQ137Lo826KuL/ianqCNlL44Rxio/UGZG7hy1z5NACAS4vue1lCzHU 05HraKPzpxPm1k2MSPEwoDnd/bt6Vk1fgdkI/07XFG1IzJQe3fq4TGZnZTC+6jIVYWB9 aE1snfDEjNd5XtuQT0eXMgAff0VcsT7aUNWwKEKbKDZzODFUyj5cPMgdgIgPsPuEO+IE KdfQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=bhJUyA552U4FqaRakyJu+yZIIGSvBKJx3aZwgIBBrNU=; b=sLKQzwuYHvuvIK4k0YLaYajJO19o4XeU0T92QlRwhUox+RQTZLrU8Y4cWx5buPwhqs oX7NUGkD1NtoDyfl7H/SUBogYZNhQ4SaA5qcDyFOV89ipmv9zs+5XongH//JZzDYaWYC 69gUTqRPOqgqimhrrlrpUT/7bVGH4zI0r9ZSd9IWbhqbVg9TzLpJ8I7PODg+y9jhIUOY THFlX988bt3C+ZhdaJXJnSAHkfnPAq9TNxxvfwXm/e/DbgE9w8WDhFiosKRifJxlM6o+ xcNeEva8MEKcanGdfc0HBwCpRIH12E/F2FIBhB+bEigqZ3Ga7MkUT06EDXbKmE901ag0 OJMg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=e5uC95qV; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ga38-20020a1709070c2600b0078cc4a8a956si14044447ejc.881.2022.11.08.07.50.23; Tue, 08 Nov 2022 07:50:49 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=e5uC95qV; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234500AbiKHPtg (ORCPT + 99 others); Tue, 8 Nov 2022 10:49:36 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37568 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234503AbiKHPtc (ORCPT ); Tue, 8 Nov 2022 10:49:32 -0500 Received: from sin.source.kernel.org (sin.source.kernel.org [IPv6:2604:1380:40e1:4800::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 598721F632; Tue, 8 Nov 2022 07:49:30 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sin.source.kernel.org (Postfix) with ESMTPS id 6BC93CE1BCA; Tue, 8 Nov 2022 15:49:28 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3E83FC433D6; Tue, 8 Nov 2022 15:49:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667922566; bh=tenO832RXqIzUnct3PpqMDsII++XyS6MTBY9g9P85NM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=e5uC95qV8vPg4IZ5WeeExGQVZ4GsMyNBAnC4sPZbuJjM4tJDOoZJkLmigCbjaa7Gr t1GoUxswc2Xcron/MLuzYUaPhi4H+g4rPyinGWZUge8Zgo0u4rGk11Mv0arru2A6N4 JWPFDNnDhV+AxqcZdJ7A7cFQoxa2svfd6A/c+epU0MbDZq3SeJJ9ip8rMr0Cy4Ohq2 giY+eLHszhkMJD0nes5Ch/N6YZ/1QvE3wFdw5OpTME9D9TSiHSmPIDR7CVi34ywuFm Cj7qid+baiR1UhCbyTcGMRvGVS7rAk1965/Ort7BggIf51nALPXY3i7CO4OViWGYYC y6SovrSDWgrLQ== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Florent Revest , Mark Rutland , Will Deacon Subject: [RFC PATCH 1/9] fprobe: Pass entry_data to handlers Date: Wed, 9 Nov 2022 00:49:23 +0900 Message-Id: <166792256330.919356.14776044963704066797.stgit@devnote3> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog In-Reply-To: <166792255429.919356.14116090269057513181.stgit@devnote3> References: <166792255429.919356.14116090269057513181.stgit@devnote3> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1748943659561879301?= X-GMAIL-MSGID: =?utf-8?q?1748943659561879301?= From: Masami Hiramatsu (Google) Pass the private entry_data to the entry and exit handlers so that they can share the context data, something like saved function arguments etc. User must specify the private entry_data size by @entry_data_size field before registering the fprobe. Signed-off-by: Masami Hiramatsu (Google) --- include/linux/fprobe.h | 8 ++++++-- kernel/trace/bpf_trace.c | 2 +- kernel/trace/fprobe.c | 21 ++++++++++++++------- lib/test_fprobe.c | 6 ++++-- samples/fprobe/fprobe_example.c | 6 ++++-- 5 files changed, 29 insertions(+), 14 deletions(-) diff --git a/include/linux/fprobe.h b/include/linux/fprobe.h index 1c2bde0ead73..e0d4e6136249 100644 --- a/include/linux/fprobe.h +++ b/include/linux/fprobe.h @@ -13,6 +13,7 @@ * @nmissed: The counter for missing events. * @flags: The status flag. * @rethook: The rethook data structure. (internal data) + * @entry_data_size: The private data storage size. * @entry_handler: The callback function for function entry. * @exit_handler: The callback function for function exit. */ @@ -29,9 +30,12 @@ struct fprobe { unsigned long nmissed; unsigned int flags; struct rethook *rethook; + size_t entry_data_size; - void (*entry_handler)(struct fprobe *fp, unsigned long entry_ip, struct pt_regs *regs); - void (*exit_handler)(struct fprobe *fp, unsigned long entry_ip, struct pt_regs *regs); + void (*entry_handler)(struct fprobe *fp, unsigned long entry_ip, + struct pt_regs *regs, void *entry_data); + void (*exit_handler)(struct fprobe *fp, unsigned long entry_ip, + struct pt_regs *regs, void *entry_data); }; /* This fprobe is soft-disabled. */ diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 1ed08967fb97..68c369452680 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -2625,7 +2625,7 @@ kprobe_multi_link_prog_run(struct bpf_kprobe_multi_link *link, static void kprobe_multi_link_handler(struct fprobe *fp, unsigned long fentry_ip, - struct pt_regs *regs) + struct pt_regs *regs, void *data) { struct bpf_kprobe_multi_link *link; diff --git a/kernel/trace/fprobe.c b/kernel/trace/fprobe.c index e8143e368074..fa25d09c9d57 100644 --- a/kernel/trace/fprobe.c +++ b/kernel/trace/fprobe.c @@ -17,14 +17,16 @@ struct fprobe_rethook_node { struct rethook_node node; unsigned long entry_ip; + char data[]; }; static void fprobe_handler(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *ops, struct ftrace_regs *fregs) { struct fprobe_rethook_node *fpr; - struct rethook_node *rh; + struct rethook_node *rh = NULL; struct fprobe *fp; + void *entry_data = NULL; int bit; fp = container_of(ops, struct fprobe, ops); @@ -37,9 +39,6 @@ static void fprobe_handler(unsigned long ip, unsigned long parent_ip, return; } - if (fp->entry_handler) - fp->entry_handler(fp, ip, ftrace_get_regs(fregs)); - if (fp->exit_handler) { rh = rethook_try_get(fp->rethook); if (!rh) { @@ -48,9 +47,16 @@ static void fprobe_handler(unsigned long ip, unsigned long parent_ip, } fpr = container_of(rh, struct fprobe_rethook_node, node); fpr->entry_ip = ip; - rethook_hook(rh, ftrace_get_regs(fregs), true); + if (fp->entry_data_size) + entry_data = fpr->data; } + if (fp->entry_handler) + fp->entry_handler(fp, ip, ftrace_get_regs(fregs), entry_data); + + if (rh) + rethook_hook(rh, ftrace_get_regs(fregs), true); + out: ftrace_test_recursion_unlock(bit); } @@ -81,7 +87,8 @@ static void fprobe_exit_handler(struct rethook_node *rh, void *data, fpr = container_of(rh, struct fprobe_rethook_node, node); - fp->exit_handler(fp, fpr->entry_ip, regs); + fp->exit_handler(fp, fpr->entry_ip, regs, + fp->entry_data_size ? (void *)fpr->data : NULL); } NOKPROBE_SYMBOL(fprobe_exit_handler); @@ -146,7 +153,7 @@ static int fprobe_init_rethook(struct fprobe *fp, int num) for (i = 0; i < size; i++) { struct fprobe_rethook_node *node; - node = kzalloc(sizeof(*node), GFP_KERNEL); + node = kzalloc(sizeof(*node) + fp->entry_data_size, GFP_KERNEL); if (!node) { rethook_free(fp->rethook); fp->rethook = NULL; diff --git a/lib/test_fprobe.c b/lib/test_fprobe.c index e0381b3ec410..34fa5a5bbda1 100644 --- a/lib/test_fprobe.c +++ b/lib/test_fprobe.c @@ -30,7 +30,8 @@ static noinline u32 fprobe_selftest_target2(u32 value) return (value / div_factor) + 1; } -static notrace void fp_entry_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs) +static notrace void fp_entry_handler(struct fprobe *fp, unsigned long ip, + struct pt_regs *regs, void *data) { KUNIT_EXPECT_FALSE(current_test, preemptible()); /* This can be called on the fprobe_selftest_target and the fprobe_selftest_target2 */ @@ -39,7 +40,8 @@ static notrace void fp_entry_handler(struct fprobe *fp, unsigned long ip, struct entry_val = (rand1 / div_factor); } -static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs) +static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip, + struct pt_regs *regs, void *data) { unsigned long ret = regs_return_value(regs); diff --git a/samples/fprobe/fprobe_example.c b/samples/fprobe/fprobe_example.c index e22da8573116..dd794990ad7e 100644 --- a/samples/fprobe/fprobe_example.c +++ b/samples/fprobe/fprobe_example.c @@ -48,7 +48,8 @@ static void show_backtrace(void) stack_trace_print(stacks, len, 24); } -static void sample_entry_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs) +static void sample_entry_handler(struct fprobe *fp, unsigned long ip, + struct pt_regs *regs, void *data) { if (use_trace) /* @@ -63,7 +64,8 @@ static void sample_entry_handler(struct fprobe *fp, unsigned long ip, struct pt_ show_backtrace(); } -static void sample_exit_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs) +static void sample_exit_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs, + void *data) { unsigned long rip = instruction_pointer(regs); From patchwork Tue Nov 8 15:49:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 17108 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2789745wru; Tue, 8 Nov 2022 07:50:32 -0800 (PST) X-Google-Smtp-Source: AMsMyM5KR3gZyZ9VlhzDyOxvlvcS1LOYjrWHccoqUnAsKR/zqOB90/vJuQki685UhJGANDiSz/Lo X-Received: by 2002:a05:6402:40c7:b0:461:ecdb:1c41 with SMTP id z7-20020a05640240c700b00461ecdb1c41mr54988821edb.288.1667922632394; Tue, 08 Nov 2022 07:50:32 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1667922632; cv=none; d=google.com; s=arc-20160816; b=mAhixqKqHaaIN+WaDeZBWTdw3kAhtkwtKIv432wmSSkuwQbi6TjwjCTQmVdPCZqjKJ KaUyxNU9Yx0qWp5WPwDHHpazk1PrdE4XqfLt9hn/ZLFPCUlf+SkbfDQEtOUVdfQ6FiLe TiCR5Or5qhdVqGEf8JAylQgQWNetaCXDrLcdpljza27rR1QrdV0Wdu4ubB59sWCZoD9n wrqIbBx6j6nkI6omZybnUy6CYHUinPSFB2TjA4bxFcP0bA6EH007c056fn3GZqUKOLmg U3froB3XtJY9sY/0v0PbpeIGkZDUfSIoYqK79+GIMxRwxoLBNlTB6GYf8R7CjFH5yH1I C3pw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=OFpLSl+nFxebjkjzw5ROOxcn3fMZN0n+b856RWhrEEc=; b=JFB6AN2r2Y/gyuF6cXHR81po3mS54V9pBRwlnfkBjbUrfAMnMM8pcQtHaXtP73emQj Wu0+xtQztzIgp8cBp//s3tSEbsWTJ1dQIXLsc/KmKQMqL6JudRhcMMD4nhsVrOS1HCEp 1lGQGfHan22hF8MHWAA2UkB2AlZ/5sNtCAkSuVJ5HcbOeIeuoV57DRajVU/PbhizLQkZ BXGA1y5O4PLwVAjsu6PqxcUPxlUyQWWMDj+WKf+66sbzrj1UYBuIXVV9nX3cWajI2Xa1 c7irCG4FrSRIWjA8Z6CYaXuAIIWztexMN2Qe49xaswa3HL+BlbxTzBAwT6zkz8jrWOSw /rDQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=X51RIF5N; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id eb14-20020a0564020d0e00b004667ef1bc6csi5799871edb.14.2022.11.08.07.50.09; Tue, 08 Nov 2022 07:50:32 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=X51RIF5N; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234530AbiKHPtn (ORCPT + 99 others); Tue, 8 Nov 2022 10:49:43 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37640 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234506AbiKHPtj (ORCPT ); Tue, 8 Nov 2022 10:49:39 -0500 Received: from sin.source.kernel.org (sin.source.kernel.org [145.40.73.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 98DB41A05C; Tue, 8 Nov 2022 07:49:38 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sin.source.kernel.org (Postfix) with ESMTPS id 11B35CE1C04; Tue, 8 Nov 2022 15:49:37 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1CA5DC433D6; Tue, 8 Nov 2022 15:49:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667922575; bh=/kBV/jdXFFKQ7g+a2x8FqSBZ13fmPZyh2fMeYv/CAeI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=X51RIF5NnDzgd9OUoZAaVIRxeEIQeJ55JFZxRL72D+H7Vcbtz7IFOEzIjxeQyc+12 /ZDkVDuDKdiIHfhHJ2xZdpiv+EWrq+/yuMMqHHtsxPov2s/zWtKuhc0+9sSD2yMM3v 7x9ywFabpoQ3dkQLAbDRqTm2Nwi9pppz6sErxXwOhrxMuW1UloMvOemPvI9ULmfI4E 3vSobm5MO9BHP3lBXSM8gVDpnVjPktzC+NwNV3KcHqyJnqvsJx7heNYWQxjw4FKE2Y ZmRAik0KSTNYu5hGghwjvXM3r+QlLZTynq2a4PPDAa5m1K709CzCuwK6M114iOdlZl cS5oesrBMrH/A== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Florent Revest , Mark Rutland , Will Deacon Subject: [RFC PATCH 2/9] lib/test_fprobe: Add private entry_data testcases Date: Wed, 9 Nov 2022 00:49:32 +0900 Message-Id: <166792257200.919356.18367653034787369847.stgit@devnote3> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog In-Reply-To: <166792255429.919356.14116090269057513181.stgit@devnote3> References: <166792255429.919356.14116090269057513181.stgit@devnote3> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1748943642421989993?= X-GMAIL-MSGID: =?utf-8?q?1748943642421989993?= From: Masami Hiramatsu (Google) Add test cases for checking whether private entry_data is correctly passed or not. Signed-off-by: Masami Hiramatsu (Google) --- lib/test_fprobe.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/lib/test_fprobe.c b/lib/test_fprobe.c index 34fa5a5bbda1..941bf5234c31 100644 --- a/lib/test_fprobe.c +++ b/lib/test_fprobe.c @@ -38,6 +38,12 @@ static notrace void fp_entry_handler(struct fprobe *fp, unsigned long ip, if (ip != target_ip) KUNIT_EXPECT_EQ(current_test, ip, target2_ip); entry_val = (rand1 / div_factor); + if (fp->entry_data_size) { + KUNIT_EXPECT_NOT_NULL(current_test, data); + if (data) + *(u32 *)data = entry_val; + } else + KUNIT_EXPECT_NULL(current_test, data); } static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip, @@ -53,6 +59,12 @@ static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip, KUNIT_EXPECT_EQ(current_test, ret, (rand1 / div_factor)); KUNIT_EXPECT_EQ(current_test, entry_val, (rand1 / div_factor)); exit_val = entry_val + div_factor; + if (fp->entry_data_size) { + KUNIT_EXPECT_NOT_NULL(current_test, data); + if (data) + KUNIT_EXPECT_EQ(current_test, *(u32 *)data, entry_val); + } else + KUNIT_EXPECT_NULL(current_test, data); } /* Test entry only (no rethook) */ @@ -134,6 +146,23 @@ static void test_fprobe_syms(struct kunit *test) KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp)); } +/* Test private entry_data */ +static void test_fprobe_data(struct kunit *test) +{ + struct fprobe fp = { + .entry_handler = fp_entry_handler, + .exit_handler = fp_exit_handler, + .entry_data_size = sizeof(u32), + }; + + current_test = test; + KUNIT_EXPECT_EQ(test, 0, register_fprobe(&fp, "fprobe_selftest_target", NULL)); + + target(rand1); + + KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp)); +} + static unsigned long get_ftrace_location(void *func) { unsigned long size, addr = (unsigned long)func; @@ -162,6 +191,7 @@ static struct kunit_case fprobe_testcases[] = { KUNIT_CASE(test_fprobe_entry), KUNIT_CASE(test_fprobe), KUNIT_CASE(test_fprobe_syms), + KUNIT_CASE(test_fprobe_data), {} }; From patchwork Tue Nov 8 15:49:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 17110 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2789919wru; Tue, 8 Nov 2022 07:50:50 -0800 (PST) X-Google-Smtp-Source: AMsMyM6CgVzrso9rDkPC9Pqxrw4wERVuN40NvORMUK4KQX3rkuZ9Cfz46Z/GHOqFvQxYDpXCC5kx X-Received: by 2002:a05:6402:414f:b0:456:c2c1:23ec with SMTP id x15-20020a056402414f00b00456c2c123ecmr57242413eda.420.1667922650211; Tue, 08 Nov 2022 07:50:50 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1667922650; cv=none; d=google.com; s=arc-20160816; b=g9UQ/ZRvad617qjTjbvF9cmic2dTvok5o2PbFY5X3L1oLBVlwJP98lXsyymb77jZkN uIZ48Svrf6TYOmbDzk5iVBM2u0NlBDaOvfSsfTQopOFuVBy9GH3Pnm7x80FXPrP1avtD lPHRZKCojPOpECS60c/m1gKeqlVC7RYc2fNXj22/QQFR42aU8/wEwC26ufDGOCwg6s9k AcbOpK2l110wCxdY1EDdKHqDwJBADgz9+SLGxaHEnGDBILAYB+WKg04fXLc3QaHwC5P5 39oVZhVIc8cBmDmz+X0eP7mnX9jOpO3M3XvciqTtNejkErBfo+jM+Ck8Ty06XmmOSk01 NG9w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=m8ZD7OdX+naM8TDvuxfAXgHmlWN3WM5LibwsMO+5WzY=; b=wx/UOqrx0N+Bs2XJ+P1KXA2O5yFEyQU0uea9JQRYwZQU5gLEEAkspIOq3fcq4mIlvK zOjNM0LXbVA1k6DMSQLWPa9SPBakMI6ECJ4nWpdllQ/nbAbBoV+LW+QNM7dVsV13wW/y A3eY5pesbfuszvla8Yo+qelFxHG6UO046tyYaTQRgZVgR+9Hkdxx67Z5gKl5juzrI8pz X853NQ6HcLgSUfo+huY3EpsYPGjRFKmKNlysKpvcgXgpi+flRfY6jCgD0SOqHXu9Lzfb m6jETiMC+YFj5RhqioFP81jO1F8QsyjNqau1becwqA+Bx4I60K3EVgkIZcxRnoOv6Iwf XidQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=FnpNtXzD; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id rp16-20020a170906d97000b007ad86f97b36si10064874ejb.560.2022.11.08.07.50.25; Tue, 08 Nov 2022 07:50:50 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=FnpNtXzD; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234539AbiKHPt5 (ORCPT + 99 others); Tue, 8 Nov 2022 10:49:57 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37804 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234534AbiKHPtr (ORCPT ); Tue, 8 Nov 2022 10:49:47 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1A4CD59FD1; Tue, 8 Nov 2022 07:49:47 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id CADA6B81B4E; Tue, 8 Nov 2022 15:49:45 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id E1BD1C433C1; Tue, 8 Nov 2022 15:49:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667922584; bh=uMXIDE3N6tRBHy0qXfA/qokcfkSD+HhNMwAWfevtvoA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FnpNtXzDxAK2M6pLW9kmncWOhCnju9bsKZbgWOiCYcpFvFaxcReDv/KxBA48ZcWoA QgQ22yAHHLYksfvtv3faGTRtAXU3szPKsmiwM9dWyjY2ZHT8DPV6lzDViNIkGrJP/t J8Eu1mvbAg+TAxIVnT2BWKwiTjID7VJOgVZL8TB9StnjE0iuJ03B9E3/oK+c73qgnS yODE9YrDGn0CTGkarxF6xdONjbxk/vzDo9v9aoNxIAzTlkie4gw6AY4+n1Fa2ZDgew TQPL2XiuTg0694xRAGAOsQXJFYmRkqn1nSr89f6NOZbN4It7+xs1Msl5VT89kYL5nr hInTg/gdFVQgA== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Florent Revest , Mark Rutland , Will Deacon Subject: [RFC PATCH 3/9] fprobe: Add nr_maxactive to specify rethook_node pool size Date: Wed, 9 Nov 2022 00:49:40 +0900 Message-Id: <166792258067.919356.10757785431344618724.stgit@devnote3> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog In-Reply-To: <166792255429.919356.14116090269057513181.stgit@devnote3> References: <166792255429.919356.14116090269057513181.stgit@devnote3> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1748943661081480795?= X-GMAIL-MSGID: =?utf-8?q?1748943661081480795?= From: Masami Hiramatsu (Google) Add nr_maxactive to specify rethook_node pool size. This means the maximum number of actively running target functions concurrently for probing by exit_handler. Note that if the running function is preempted or sleep, it is still counted as 'active'. Signed-off-by: Masami Hiramatsu (Google) --- include/linux/fprobe.h | 2 ++ kernel/trace/fprobe.c | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/linux/fprobe.h b/include/linux/fprobe.h index e0d4e6136249..678f741a7b33 100644 --- a/include/linux/fprobe.h +++ b/include/linux/fprobe.h @@ -14,6 +14,7 @@ * @flags: The status flag. * @rethook: The rethook data structure. (internal data) * @entry_data_size: The private data storage size. + * @nr_maxactive: The max number of active functions. * @entry_handler: The callback function for function entry. * @exit_handler: The callback function for function exit. */ @@ -31,6 +32,7 @@ struct fprobe { unsigned int flags; struct rethook *rethook; size_t entry_data_size; + int nr_maxactive; void (*entry_handler)(struct fprobe *fp, unsigned long entry_ip, struct pt_regs *regs, void *entry_data); diff --git a/kernel/trace/fprobe.c b/kernel/trace/fprobe.c index fa25d09c9d57..f222848571f2 100644 --- a/kernel/trace/fprobe.c +++ b/kernel/trace/fprobe.c @@ -143,7 +143,10 @@ static int fprobe_init_rethook(struct fprobe *fp, int num) } /* Initialize rethook if needed */ - size = num * num_possible_cpus() * 2; + if (fp->nr_maxactive) + size = fp->nr_maxactive; + else + size = num * num_possible_cpus() * 2; if (size < 0) return -E2BIG; From patchwork Tue Nov 8 15:49:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 17111 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2790038wru; Tue, 8 Nov 2022 07:51:02 -0800 (PST) X-Google-Smtp-Source: AMsMyM4YTCqOH+3fX3SC4ErGVu6twY2SlZc+l7JvEPGqQu/VeKXg0JlHnuxixemHbwc6KpjBvMNN X-Received: by 2002:a17:906:444d:b0:7ad:eb7f:8697 with SMTP id i13-20020a170906444d00b007adeb7f8697mr36521628ejp.770.1667922662024; Tue, 08 Nov 2022 07:51:02 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1667922662; cv=none; d=google.com; s=arc-20160816; b=B2UAbmQV7SZEoGbryGRqQ1ro9Ap/51HyvKG04UaFZT7yRnDsY/W6gySk7zod23Vjfy ZsGOyp0N6DaAD8tAqbp+gfKiNLZ+EqdxCq0O4GMB9o2PuD0PFE8GF4zykKvubsV3Q0gs EoQIccR1HWI83uwfeZPEdGqRHTGTWZBFVoVzYh9GCjze6m9MsosKjCQ+3rGW9MWThBBF 448U07v0icvhxtqWqVR+DngGCpCvPPYDvnVXRIEaHvMwkGcp64oVDgMNT7KcnxUhBaks dDOV22fU2lvq63up5eW48x0F5Q5YIIOjzW+ELTVcWe/o+dTeR+hVrM0Rj8zr1mzDJ6Om hVEQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=bnwtxv94kpFRRs/ijDiWd71Pp+DTWIN+th+HeMQnsYs=; b=pbRw7aujC+RoxBF65XV19KxlkAECH1S0slk5JuWdvQZvhuyAhQpSFlPya21iqevuQv J907fXAy2RtBeLSq+Fq3Hm04aCfnj1DfoF7K+k5Kpqwh/xecs8T1/eHAT5Z1Uh2qEs6V pHgIUUWDD4GizghflvkOV3KOBQgZMgFUVZ+1k5soPbp6g60aqMki5zeBzpVv8GPw/lUC 8ON19OOWKaIsXpIgNqAckjPmRX2Gpm90eGXBjfUoaqMzRlV/ec9yhgJ2KyJ58S88vntZ jftQhQ+WyHhWtrHNHhs18ezNZiizdiX7lGutDSjPQmeHLeNIXyT+YVZCg81oIdWOme/m Pouw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=U8FmuCdM; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id g13-20020aa7c58d000000b0046437459191si11638648edq.476.2022.11.08.07.50.36; Tue, 08 Nov 2022 07:51:02 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=U8FmuCdM; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234493AbiKHPuH (ORCPT + 99 others); Tue, 8 Nov 2022 10:50:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37782 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234532AbiKHPt5 (ORCPT ); Tue, 8 Nov 2022 10:49:57 -0500 Received: from sin.source.kernel.org (sin.source.kernel.org [145.40.73.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A11645C764; Tue, 8 Nov 2022 07:49:56 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sin.source.kernel.org (Postfix) with ESMTPS id 1D2F7CE1BD9; Tue, 8 Nov 2022 15:49:55 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1AE6AC433D6; Tue, 8 Nov 2022 15:49:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667922593; bh=F/6mNWeMxsAl5sO9bPrQ/z7sSueL8mpIe+JI9wyTpYI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=U8FmuCdMpK+lpMhQo9J82CHO7rwMk1BCa7U0M97ydkONfEyQEEyVVpxw4oSF+EgPK yKv6X0HxVdO+8VeIRCG1fWqO+MaQsTAVxBDt7HTRWsAg7iVWw1UX86cgLng8RY1YrY aOzQxaQ/I3sKuBojHDCq7T3Yvk8cAj3YrOai2l5mK6mFZV+yZj5hXpKOAfYbK4IsSC 8U15dj5bTc1ehQVQlVBNHWbzUod08f//omP9ZKLjJuwtHPcP6qBg9ATuRGdk8+5n1O ycPdUV4siXqESznuqvTwSmcEG7tmcKJkhRQ1qdzLRuJ77VTtqwLG/ffMUTWDnXdnpS 1ucBLdHPd4q9w== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Florent Revest , Mark Rutland , Will Deacon Subject: [RFC PATCH 4/9] lib/test_fprobe: Add a test case for nr_maxactive Date: Wed, 9 Nov 2022 00:49:49 +0900 Message-Id: <166792258988.919356.1550112303992706866.stgit@devnote3> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog In-Reply-To: <166792255429.919356.14116090269057513181.stgit@devnote3> References: <166792255429.919356.14116090269057513181.stgit@devnote3> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1748943673420062400?= X-GMAIL-MSGID: =?utf-8?q?1748943673420062400?= From: Masami Hiramatsu (Google) Add a test case for nr_maxactive. If the number of active functions is more than nr_maxactive, it must be skipped. Signed-off-by: Masami Hiramatsu (Google) --- lib/test_fprobe.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/lib/test_fprobe.c b/lib/test_fprobe.c index 941bf5234c31..976fb3f7cb01 100644 --- a/lib/test_fprobe.c +++ b/lib/test_fprobe.c @@ -17,8 +17,10 @@ static u32 rand1, entry_val, exit_val; /* Use indirect calls to avoid inlining the target functions */ static u32 (*target)(u32 value); static u32 (*target2)(u32 value); +static u32 (*target_nest)(u32 value, u32 (*nest)(u32)); static unsigned long target_ip; static unsigned long target2_ip; +static unsigned long target_nest_ip; static noinline u32 fprobe_selftest_target(u32 value) { @@ -30,6 +32,11 @@ static noinline u32 fprobe_selftest_target2(u32 value) return (value / div_factor) + 1; } +static noinline u32 fprobe_selftest_nest_target(u32 value, u32 (*nest)(u32)) +{ + return nest(value + 2); +} + static notrace void fp_entry_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs, void *data) { @@ -67,6 +74,19 @@ static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip, KUNIT_EXPECT_NULL(current_test, data); } +static notrace void nest_entry_handler(struct fprobe *fp, unsigned long ip, + struct pt_regs *regs, void *data) +{ + KUNIT_EXPECT_FALSE(current_test, preemptible()); +} + +static notrace void nest_exit_handler(struct fprobe *fp, unsigned long ip, + struct pt_regs *regs, void *data) +{ + KUNIT_EXPECT_FALSE(current_test, preemptible()); + KUNIT_EXPECT_EQ(current_test, ip, target_nest_ip); +} + /* Test entry only (no rethook) */ static void test_fprobe_entry(struct kunit *test) { @@ -163,6 +183,25 @@ static void test_fprobe_data(struct kunit *test) KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp)); } +/* Test nr_maxactive */ +static void test_fprobe_nest(struct kunit *test) +{ + static const char *syms[] = {"fprobe_selftest_target", "fprobe_selftest_nest_target"}; + struct fprobe fp = { + .entry_handler = nest_entry_handler, + .exit_handler = nest_exit_handler, + .nr_maxactive = 1, + }; + + current_test = test; + KUNIT_EXPECT_EQ(test, 0, register_fprobe_syms(&fp, syms, 2)); + + target_nest(rand1, target); + KUNIT_EXPECT_EQ(test, 1, fp.nmissed); + + KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp)); +} + static unsigned long get_ftrace_location(void *func) { unsigned long size, addr = (unsigned long)func; @@ -181,8 +220,10 @@ static int fprobe_test_init(struct kunit *test) target = fprobe_selftest_target; target2 = fprobe_selftest_target2; + target_nest = fprobe_selftest_nest_target; target_ip = get_ftrace_location(target); target2_ip = get_ftrace_location(target2); + target_nest_ip = get_ftrace_location(target_nest); return 0; } @@ -192,6 +233,7 @@ static struct kunit_case fprobe_testcases[] = { KUNIT_CASE(test_fprobe), KUNIT_CASE(test_fprobe_syms), KUNIT_CASE(test_fprobe_data), + KUNIT_CASE(test_fprobe_nest), {} }; From patchwork Tue Nov 8 15:49:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 17112 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2790053wru; Tue, 8 Nov 2022 07:51:04 -0800 (PST) X-Google-Smtp-Source: AMsMyM7cRkJ3sbNw6hVjqW09sUBDCFAFBzFMbmWNr3iOmh5NW5peZsGx49s42JTUyqmW8mQOvEkR X-Received: by 2002:aa7:c792:0:b0:453:98b7:213c with SMTP id n18-20020aa7c792000000b0045398b7213cmr55992610eds.159.1667922663855; Tue, 08 Nov 2022 07:51:03 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1667922663; cv=none; d=google.com; s=arc-20160816; b=AngEbtOSuTGp/FIX+cMu/nCQ/UfDSz7lpb1d9Es0HnAfXEzKcrruGIi2I9sFBuRgUA wmYgOuA/yPj2syO2YuAypk544E4RQ0mPQ6mMz+irdjlbnZAaEwZ1AP8MtKGyXB/mCshd O3hk/lLdN+hf9IgYDYm61NaNyqd1Bu6YehGc17v5hRNDsMf2FjpMPiVzPYXjjQansbAu 2hp3hv6Va9WlwHD9O756ajVMnpdSqTxU07/eDTnU7OXsnwKMqCk1DUSa3MLCXtYTUxOQ a8unPg4VzLAr58UuJXadWGpyRUQoEjrdOE3VL8JxDaZnobMRB88g4uBCaYYZqNN7y/nL rSCg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=368pu2yjMVUqGGy3LEf+9T2Ye8WKSYUAK4fRYzIIQz8=; b=rlJIEeM9ltUe/YPl7ZTPHfcgqyf3NUudX8UI70y/NqEUQALv24vjugpet2ODCMYQWy HvP2xOjJNmz6ZsDGaQRLE4Oe4mHw2qi7YuDElOnEoZJvqBUH18BWn+P9+MZdkshso5ji ft7cf3CB6ZIKaHHoDCJfd0ubOaasf9HPkCgNPhad8HYMEPTWxRE2lo+ZkAX5sSsbkgQT MWPD/NZ7rIbsbmUZnwcVoExqJRRRICyAJeO7kgaD7Sl3IZvWP5hi4llGPjdRdtvw+XhS p6fX86aIax4wufQuvI0+Oib533oZG81LpmUXEBHF/2oSpuETtXXIEHHN/w8PqbR6eicp 3HIQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=tVLKzFOm; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id gb28-20020a170907961c00b007707b853e46si12641761ejc.882.2022.11.08.07.50.38; Tue, 08 Nov 2022 07:51:03 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=tVLKzFOm; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234387AbiKHPuK (ORCPT + 99 others); Tue, 8 Nov 2022 10:50:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38050 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234563AbiKHPuD (ORCPT ); Tue, 8 Nov 2022 10:50:03 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 156515C758; Tue, 8 Nov 2022 07:50:03 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id A639061646; Tue, 8 Nov 2022 15:50:02 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id DFA17C4314C; Tue, 8 Nov 2022 15:50:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667922602; bh=MHHslVLlQavpqBMVzMqaHP+31Fg1qy0ktAOkl4B6S/M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tVLKzFOmK5FuxvbyRCCUUgY60moICzyWNKSZkxSo7BZhvvUDaBrbCDOFNTwj9Crt/ /ZKyzCDMnssQo5EULcoTOODkCBlyrM8rF/hkDTWlHxnPv1OZMJ9UJ6Lat1R0hdNnDx dCi/ny1zmagXr3iueZvaGmlWiFbGPJL2ufnN+Y3/F3XunFVTm7WLMH6GcpZgfLHkW+ J/ubXcgbQ1BHmjAMLHrm9iX637k2XhEXg59yJ/WMuRP/OQORDX/OZadkFCjb0mnBZE 9oMtOaVAlQa6WdSSgetaGKoINIqxoDTVuCXyxUAwz82lZ1hjH1Qx/VrlrDFb5ZNmCz s+SHkxH5ejMNg== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Florent Revest , Mark Rutland , Will Deacon Subject: [RFC PATCH 5/9] fprobe: Skip exit_handler if entry_handler returns !0 Date: Wed, 9 Nov 2022 00:49:58 +0900 Message-Id: <166792259869.919356.8529453996904377437.stgit@devnote3> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog In-Reply-To: <166792255429.919356.14116090269057513181.stgit@devnote3> References: <166792255429.919356.14116090269057513181.stgit@devnote3> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1748943674882061056?= X-GMAIL-MSGID: =?utf-8?q?1748943674882061056?= From: Masami Hiramatsu (Google) Skip hooking function return and calling exit_handler if the entry_handler() returns !0. Signed-off-by: Masami Hiramatsu (Google) --- include/linux/fprobe.h | 4 ++-- kernel/trace/bpf_trace.c | 15 +++++++++++++-- kernel/trace/fprobe.c | 14 +++++++++----- lib/test_fprobe.c | 7 +++++-- samples/fprobe/fprobe_example.c | 5 +++-- 5 files changed, 32 insertions(+), 13 deletions(-) diff --git a/include/linux/fprobe.h b/include/linux/fprobe.h index 678f741a7b33..47fefc7f363b 100644 --- a/include/linux/fprobe.h +++ b/include/linux/fprobe.h @@ -34,8 +34,8 @@ struct fprobe { size_t entry_data_size; int nr_maxactive; - void (*entry_handler)(struct fprobe *fp, unsigned long entry_ip, - struct pt_regs *regs, void *entry_data); + int (*entry_handler)(struct fprobe *fp, unsigned long entry_ip, + struct pt_regs *regs, void *entry_data); void (*exit_handler)(struct fprobe *fp, unsigned long entry_ip, struct pt_regs *regs, void *entry_data); }; diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 68c369452680..dadcddb6a429 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -2623,12 +2623,23 @@ kprobe_multi_link_prog_run(struct bpf_kprobe_multi_link *link, return err; } -static void +static int kprobe_multi_link_handler(struct fprobe *fp, unsigned long fentry_ip, struct pt_regs *regs, void *data) { struct bpf_kprobe_multi_link *link; + link = container_of(fp, struct bpf_kprobe_multi_link, fp); + kprobe_multi_link_prog_run(link, get_entry_ip(fentry_ip), regs); + return 0; +} + +static void +kprobe_multi_link_exit_handler(struct fprobe *fp, unsigned long fentry_ip, + struct pt_regs *regs, void *data) +{ + struct bpf_kprobe_multi_link *link; + link = container_of(fp, struct bpf_kprobe_multi_link, fp); kprobe_multi_link_prog_run(link, get_entry_ip(fentry_ip), regs); } @@ -2754,7 +2765,7 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr goto error; if (flags & BPF_F_KPROBE_MULTI_RETURN) - link->fp.exit_handler = kprobe_multi_link_handler; + link->fp.exit_handler = kprobe_multi_link_exit_handler; else link->fp.entry_handler = kprobe_multi_link_handler; diff --git a/kernel/trace/fprobe.c b/kernel/trace/fprobe.c index f222848571f2..9abb3905bc8e 100644 --- a/kernel/trace/fprobe.c +++ b/kernel/trace/fprobe.c @@ -27,7 +27,7 @@ static void fprobe_handler(unsigned long ip, unsigned long parent_ip, struct rethook_node *rh = NULL; struct fprobe *fp; void *entry_data = NULL; - int bit; + int bit, ret; fp = container_of(ops, struct fprobe, ops); if (fprobe_disabled(fp)) @@ -52,11 +52,15 @@ static void fprobe_handler(unsigned long ip, unsigned long parent_ip, } if (fp->entry_handler) - fp->entry_handler(fp, ip, ftrace_get_regs(fregs), entry_data); - - if (rh) - rethook_hook(rh, ftrace_get_regs(fregs), true); + ret = fp->entry_handler(fp, ip, ftrace_get_regs(fregs), entry_data); + /* If entry_handler returns !0, nmissed is not counted. */ + if (rh) { + if (ret) + rethook_recycle(rh); + else + rethook_hook(rh, ftrace_get_regs(fregs), true); + } out: ftrace_test_recursion_unlock(bit); } diff --git a/lib/test_fprobe.c b/lib/test_fprobe.c index 976fb3f7cb01..e78176d252ae 100644 --- a/lib/test_fprobe.c +++ b/lib/test_fprobe.c @@ -37,7 +37,7 @@ static noinline u32 fprobe_selftest_nest_target(u32 value, u32 (*nest)(u32)) return nest(value + 2); } -static notrace void fp_entry_handler(struct fprobe *fp, unsigned long ip, +static notrace int fp_entry_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs, void *data) { KUNIT_EXPECT_FALSE(current_test, preemptible()); @@ -51,6 +51,8 @@ static notrace void fp_entry_handler(struct fprobe *fp, unsigned long ip, *(u32 *)data = entry_val; } else KUNIT_EXPECT_NULL(current_test, data); + + return 0; } static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip, @@ -74,10 +76,11 @@ static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip, KUNIT_EXPECT_NULL(current_test, data); } -static notrace void nest_entry_handler(struct fprobe *fp, unsigned long ip, +static notrace int nest_entry_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs, void *data) { KUNIT_EXPECT_FALSE(current_test, preemptible()); + return 0; } static notrace void nest_exit_handler(struct fprobe *fp, unsigned long ip, diff --git a/samples/fprobe/fprobe_example.c b/samples/fprobe/fprobe_example.c index dd794990ad7e..4efc8feb6277 100644 --- a/samples/fprobe/fprobe_example.c +++ b/samples/fprobe/fprobe_example.c @@ -48,8 +48,8 @@ static void show_backtrace(void) stack_trace_print(stacks, len, 24); } -static void sample_entry_handler(struct fprobe *fp, unsigned long ip, - struct pt_regs *regs, void *data) +static int sample_entry_handler(struct fprobe *fp, unsigned long ip, + struct pt_regs *regs, void *data) { if (use_trace) /* @@ -62,6 +62,7 @@ static void sample_entry_handler(struct fprobe *fp, unsigned long ip, nhit++; if (stackdump) show_backtrace(); + return 0; } static void sample_exit_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs, From patchwork Tue Nov 8 15:50:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 17113 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2790182wru; Tue, 8 Nov 2022 07:51:16 -0800 (PST) X-Google-Smtp-Source: AMsMyM5a5sNc6aoG2vMSY3yYTnjkMl0qoODJPc4c39A/iY6YoNkO+W/zJz92ahLLpkGu3FgI4pnp X-Received: by 2002:a05:6402:1004:b0:464:778:c516 with SMTP id c4-20020a056402100400b004640778c516mr34710617edu.348.1667922676279; Tue, 08 Nov 2022 07:51:16 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1667922676; cv=none; d=google.com; s=arc-20160816; b=ewCxzMEHBwzkU3bFLdhRyoEHxfMHd9bLYpZyk6ZZE/FyHyi/dI8gGEeNFxiOD4ZXg4 /CIWOddFcwa95gGTeor4mcdiG0tDbfVH/EfacA99ALvxHomvFUheh+W6mSHSqe90sLvA /NoQyv4czl1gMqYnsnSwWwY8yY+CtbzpoGqIBsAXkL/3OLwiwAjeMwEzc0H0RmK1pnDt uGBy4ciM+/i27AEj2pFf77CcpSiMqG/5+XGSWrKenLLHgETtAtCJHSi5C6sRg9JH8FrS HPNOVeDSvuNZuQaFWBda8er/pz1Nf4fHVJQ7K754HGXevbl2nOYMPlpRnuQ8q97v04vg ULEA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=Em3I7kB9syzxEmBE65aR38zzGes8pI9JL8Crnp8b/k0=; b=AJUBaXqgJFR1cniqsK9Vpv82ut/1lIgofC3ILaENxBctxB9PyPxy3zGhQCLE+bihDO wWQSvIUkO67cXiEZrXQxamtZ4Tw1sJ4VQqVS+qy1xopTUS7b+3JEfZiXHUhpJV/jTvPb 6V/3OSE1pspImxb0tP3ASdeEcnYkujjJngPUYsGQpw8kiVTsTPh6QnerSyOAtiOxeBR4 /aFZwBU9DElbefVugTBOUAwsl/FnVqvyWR4XSB+Ol0FxZFWmep+V8mN153KpfqPiX3DE 57N8fivCtlOkCm/dt8pHaeD5F3nfKxuErTs7A5LO2FlDcaERiYZcFLj90k1s/pveq6DU tm1Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=jmJOd5tL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id mp23-20020a1709071b1700b00782a5657512si14344640ejc.416.2022.11.08.07.50.52; Tue, 08 Nov 2022 07:51:16 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=jmJOd5tL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234610AbiKHPu0 (ORCPT + 99 others); Tue, 8 Nov 2022 10:50:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38420 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234606AbiKHPuP (ORCPT ); Tue, 8 Nov 2022 10:50:15 -0500 Received: from sin.source.kernel.org (sin.source.kernel.org [145.40.73.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 626835C778; Tue, 8 Nov 2022 07:50:14 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sin.source.kernel.org (Postfix) with ESMTPS id CEFC9CE1C04; Tue, 8 Nov 2022 15:50:12 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 96DF5C433C1; Tue, 8 Nov 2022 15:50:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667922611; bh=5l8khZ1P9sioaYF0TNk9KOSmOx0dNhLQfbQv88Ag2GU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jmJOd5tLr2rZ8+4PpywGm9an1ASrxZWDnV/e5slb8g2RnRHqCmGwINtQ0pcWTLyxL kUU8pqouH6BHKUWc9ZtJJxv121Iptz13Rw9+dsSqBFM3g4OjNvd+UFN+a8Jv4yDdH9 XvCXTYAX487i4T5i/NYCVHTAzsX/yEi4R78qq+1lBEjzDPdACh/c+oPezk/ASygmGS GkLs8T8xw9H7khaioLq/GJuPMMVd2IfahFyNB81K2wJqVy1IqtVM62Sxf8fiPsAahb grW3AjO+4cirMehZnRH3AbU8Af2/O/cUDy/sLM4z6WJNQ4QqyV0SFOzopf+QxVbN9N yWbeH/GzR+KaQ== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Florent Revest , Mark Rutland , Will Deacon Subject: [RFC PATCH 6/9] lib/test_fprobe: Add a testcase for skipping exit_handler Date: Wed, 9 Nov 2022 00:50:07 +0900 Message-Id: <166792260740.919356.5736843826698103180.stgit@devnote3> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog In-Reply-To: <166792255429.919356.14116090269057513181.stgit@devnote3> References: <166792255429.919356.14116090269057513181.stgit@devnote3> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1748943688150931528?= X-GMAIL-MSGID: =?utf-8?q?1748943688150931528?= From: Masami Hiramatsu (Google) Add a testcase for skipping exit_handler if entry_handler returns !0. Signed-off-by: Masami Hiramatsu (Google) --- lib/test_fprobe.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/test_fprobe.c b/lib/test_fprobe.c index e78176d252ae..926d5104b291 100644 --- a/lib/test_fprobe.c +++ b/lib/test_fprobe.c @@ -21,6 +21,7 @@ static u32 (*target_nest)(u32 value, u32 (*nest)(u32)); static unsigned long target_ip; static unsigned long target2_ip; static unsigned long target_nest_ip; +static int entry_return_value; static noinline u32 fprobe_selftest_target(u32 value) { @@ -52,7 +53,7 @@ static notrace int fp_entry_handler(struct fprobe *fp, unsigned long ip, } else KUNIT_EXPECT_NULL(current_test, data); - return 0; + return entry_return_value; } static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip, @@ -205,6 +206,28 @@ static void test_fprobe_nest(struct kunit *test) KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp)); } +static void test_fprobe_skip(struct kunit *test) +{ + struct fprobe fp = { + .entry_handler = fp_entry_handler, + .exit_handler = fp_exit_handler, + }; + + current_test = test; + KUNIT_EXPECT_EQ(test, 0, register_fprobe(&fp, "fprobe_selftest_target", NULL)); + + entry_return_value = 1; + entry_val = 0; + exit_val = 0; + target(rand1); + KUNIT_EXPECT_NE(test, 0, entry_val); + KUNIT_EXPECT_EQ(test, 0, exit_val); + KUNIT_EXPECT_EQ(test, 0, fp.nmissed); + entry_return_value = 0; + + KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp)); +} + static unsigned long get_ftrace_location(void *func) { unsigned long size, addr = (unsigned long)func; @@ -237,6 +260,7 @@ static struct kunit_case fprobe_testcases[] = { KUNIT_CASE(test_fprobe_syms), KUNIT_CASE(test_fprobe_data), KUNIT_CASE(test_fprobe_nest), + KUNIT_CASE(test_fprobe_skip), {} }; From patchwork Tue Nov 8 15:50:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 17114 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2790274wru; Tue, 8 Nov 2022 07:51:27 -0800 (PST) X-Google-Smtp-Source: AMsMyM70YddnGV25UYnSKAI0EayX0xRAFjd2qy1C3FwMEBl7ypgsIHTHZDZKJK7LrtUsqJlsLDrf X-Received: by 2002:a05:6402:298b:b0:44f:20a:2db2 with SMTP id eq11-20020a056402298b00b0044f020a2db2mr56496577edb.138.1667922687728; Tue, 08 Nov 2022 07:51:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1667922687; cv=none; d=google.com; s=arc-20160816; b=B4gL6yV+YcrGdvCWUzHF7I/tcIajsZSjKvMB0NVk/TAOeUWlVYT6N9iOHbYnl/BFH9 xcjqjdJw6tEpWJHLldoQ0QuNfG/2vrVSDqQPdPnmQ31qYTZIRRZHX9cmW31OJ9xsCtGh riRcsEl6Ep/IJv+xu8lTaz/eU1x8a2Uq8eRVIZelBy6P1X0I3kYMjuMA5uOMqwbl7cro va6cLVJqhADoCqMGRsna7BHM/+ZHPkq5yN8GK2kzfcKEVxxZaVp6oqFLZc67OYj19peH G5AgI1EXK4e5F+03xfpzV0YXF7QJ4jcacXMJcK89GkqxZ9xHk8BDMISBJtaXYqP9AF2r nqTg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=uKNQqf7a+Wr/Mp+a8DPaiTaEGh+3/l3O+6MGzs0VJ+k=; b=dncHD+oFZJU1APTuS2pVHqhOGcKeAQn09hPyPwMqk21zjCpL7k7j0YM/Memps6khQr tVTsUVZERFwU536EH60LvoTJ7H7KhzIZsP3kZqPOgbmD0c4koZjEzvMmT2EmJNBYoGRM 6jkveKMaG/cw0UTbnSd67GBKDy4x/GQrUdkygung/7l4SN8PsQzxWYXkI9ACRwM+gRkx e2N6Huj2P5fjxm0hv7pZDt0tV5q5aqswziofls+H0ar/kkrgm0qmbtIhaqqlI/y0Zuoj G+QYVl9Guc1D1Nj+rdbAxlEpGzvZx89ATfalJfRdzQ2zMIN6jmwlydgTcSUOoFGNLuuZ 2usQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=qZM6OR4Y; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ji4-20020a170907980400b007add882fe58si7990270ejc.796.2022.11.08.07.51.03; Tue, 08 Nov 2022 07:51:27 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=qZM6OR4Y; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234623AbiKHPug (ORCPT + 99 others); Tue, 8 Nov 2022 10:50:36 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38386 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234589AbiKHPuW (ORCPT ); Tue, 8 Nov 2022 10:50:22 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 430A120BFC; Tue, 8 Nov 2022 07:50:22 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 057FBB81B4F; Tue, 8 Nov 2022 15:50:21 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6819CC433D6; Tue, 8 Nov 2022 15:50:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667922619; bh=ZwW0qCRKBchNeu3whdSe71nh1Tm4+42ATA3rao4qIss=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qZM6OR4Y6Aqyo0+pNKeQSN6ge0SinOEsVZPWkr9UbGKgpet+lrD9PcSMptsHZqtIl vZvT2XTI4UbpvlMMGO3VA9E10Am+ksSUT5uY0J7u2WT1P4BGFTFCXmhLUcECSTTvdf w0LJPqXvFgnMRagRg51V6qD+OnK0uxA41g4K5jBblsJBxFTp8Zi4x1UvI34sgztBBh B5iqXIuDhuO6qSE1OV3Jap3vuJPbbJy5jOo3RUUic/1x3S3h4WHWRXtqe6zZglekEd y126OPYUB8CqyUsMgxRBManfAEI+4wg1hFMdl0CyL2/G4Nrx6jb5c23hQ6YFN5wQ4r M4r3DPjQ3FOjw== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Florent Revest , Mark Rutland , Will Deacon Subject: [RFC PATCH 7/9] docs: tracing: Update fprobe documentation Date: Wed, 9 Nov 2022 00:50:16 +0900 Message-Id: <166792261641.919356.4627265153244048545.stgit@devnote3> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog In-Reply-To: <166792255429.919356.14116090269057513181.stgit@devnote3> References: <166792255429.919356.14116090269057513181.stgit@devnote3> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1748943700091242357?= X-GMAIL-MSGID: =?utf-8?q?1748943700091242357?= From: Masami Hiramatsu (Google) Update fprobe.rst for - the private entry_data argument - the return value of the entry handler - the nr_rethook_node field. Signed-off-by: Masami Hiramatsu (Google) --- Documentation/trace/fprobe.rst | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Documentation/trace/fprobe.rst b/Documentation/trace/fprobe.rst index b64bec1ce144..40dd2fbce861 100644 --- a/Documentation/trace/fprobe.rst +++ b/Documentation/trace/fprobe.rst @@ -87,14 +87,16 @@ returns as same as unregister_ftrace_function(). The fprobe entry/exit handler ============================= -The prototype of the entry/exit callback function is as follows: +The prototype of the entry/exit callback function are as follows: .. code-block:: c - void callback_func(struct fprobe *fp, unsigned long entry_ip, struct pt_regs *regs); + int entry_callback(struct fprobe *fp, unsigned long entry_ip, struct pt_regs *regs, void *entry_data); -Note that both entry and exit callbacks have same ptototype. The @entry_ip is -saved at function entry and passed to exit handler. + void exit_callback(struct fprobe *fp, unsigned long entry_ip, struct pt_regs *regs, void *entry_data); + +Note that the @entry_ip is saved at function entry and passed to exit handler. +If the entry callback function returns !0, the corresponding exit callback will be cancelled. @fp This is the address of `fprobe` data structure related to this handler. @@ -113,6 +115,12 @@ saved at function entry and passed to exit handler. to use @entry_ip. On the other hand, in the exit_handler, the instruction pointer of @regs is set to the currect return address. +@entry_data + This is a local storage to share the data between entry and exit handlers. + This storage is NULL by default. If the user specify `exit_handler` field + and `entry_data_size` field when registering the fprobe, the storage is + allocated and passed to both `entry_handler` and `exit_handler`. + Share the callbacks with kprobes ================================ From patchwork Tue Nov 8 15:50:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 17115 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2790499wru; Tue, 8 Nov 2022 07:51:56 -0800 (PST) X-Google-Smtp-Source: AMsMyM6KgL3hm0VFfm9EK2fuS7jYF8Tws+MiFRa/fRSxJNkY+difLP+TtDRg5XU7bJ2Tb0zqm75u X-Received: by 2002:a50:ee0a:0:b0:463:4055:9db4 with SMTP id g10-20020a50ee0a000000b0046340559db4mr50814033eds.421.1667922715951; Tue, 08 Nov 2022 07:51:55 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1667922715; cv=none; d=google.com; s=arc-20160816; b=e1noy8v2d59FbYtBAjqd79nRVSpkY9/A+xy7Jp7RplDLHgLIamxzOy/Q0y3HOZxXMw CkNJ+s40itGK+ZoD/FHeJSCbsHK/1DEFggFkrpnBOIYOdk5Ls693eOPU45BvYqkW6Twf b9pxzdf5mWDDv1YEfq4C00oReK+IRuWtCSJJxi/u1drrU8znuDnIkJUeXzXray50Lm+j Tn9tWIgiPwOtUYNM/7+GKpoLlCsK+F8NiFIGfVcpWKuMJ2Q7Ky3sfZH0UWkc+h7jbRDr jrrTeBixsrq+3koZkxHPOMI6bY0RqQv0wZkvx7MppKUdcXZ5PW1S4pLf6jLQCum1ONoC 5uWQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=oL0mpDAAvBsaX2xwS6Nbu1+PEk4E0zIUlJvleZlUwdM=; b=jb02E3zuG+8Rmkbv5g12X+6MU/QLe/pyltuc0xoJTkBHmZy77wV0dEUbV2ng6uuk0b PtQMPGRwhmOSlx5PDJHPhhPhgF7iu0ljtJ/NBvKrHeDs5Yx/L9uvRoQyT8UqtJs4o3lD vO4nNM2wuRrU+uIgmVaayHiPU/Yim8Ywd59EtDXptWEbFLXvIkG503+tn/x1zLsQbAEV YqU6JzbeyrpHd+cstG7RPWniXtOgjCNHA5ZVwtqHdz5yscgrPQ7N9MaEYyUcrY0ifjDa G5VTe0uoJNFXURaYSLy4ErquLtNLrfSjx5T7qSS1q0rnMH+pRavJKZZX6KbBJhs74031 ldtA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=mifF5X33; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id sd14-20020a1709076e0e00b0073dcb2ec4d2si12721962ejc.889.2022.11.08.07.51.31; Tue, 08 Nov 2022 07:51:55 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=mifF5X33; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234563AbiKHPuk (ORCPT + 99 others); Tue, 8 Nov 2022 10:50:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38328 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234537AbiKHPua (ORCPT ); Tue, 8 Nov 2022 10:50:30 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E0D7025E81; Tue, 8 Nov 2022 07:50:29 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 71C2F61652; Tue, 8 Nov 2022 15:50:29 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7F996C433D6; Tue, 8 Nov 2022 15:50:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667922628; bh=87/lyGR9IWeD+IoOj3R8OVwKVrMqxcqeTsI/Pz131p4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mifF5X336aIMdZFwcbjp/lOahDVYpjuR2Ee6gQnY7vfN2iBGGJDn2sserBeQGKl6O Fj1PU96oNreEWVw8LBcX09KHQysIc77sYucfB+nYF90Y0kppX+iufyIIr6l2IOzVln uOTGhrPVG+9FBB6Z7DSECAkDE7G4sEiNqfuOmib5Y7kd+zJ1jG6K3pAHhSz/kf+vne W9qh4ujgw0aDUg2N1yVBOEuLakE5M9wEn/5VKNyiHfnKqSA5FKzL9lgXFbUyKNmvBl Mnc/ohp1iBNa4fgKQhLhXw3lY50I+7CkiXy3rAWy1m0GX1p1NHEZhygzJbNr+v3D4/ f5UVosqaCj1CQ== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Florent Revest , Mark Rutland , Will Deacon Subject: [RFC PATCH 8/9] fprobe: Pass return address to the handlers Date: Wed, 9 Nov 2022 00:50:25 +0900 Message-Id: <166792262501.919356.16676046094403503882.stgit@devnote3> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog In-Reply-To: <166792255429.919356.14116090269057513181.stgit@devnote3> References: <166792255429.919356.14116090269057513181.stgit@devnote3> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1748943729779429034?= X-GMAIL-MSGID: =?utf-8?q?1748943729779429034?= From: Masami Hiramatsu (Google) Pass return address as 'ret_ip' to the fprobe entry and return handlers. Signed-off-by: Masami Hiramatsu (Google) --- include/linux/fprobe.h | 6 ++++-- include/linux/rethook.h | 2 +- kernel/kprobes.c | 1 + kernel/trace/bpf_trace.c | 6 ++++-- kernel/trace/fprobe.c | 6 +++--- kernel/trace/rethook.c | 3 ++- lib/test_fprobe.c | 10 +++++++--- samples/fprobe/fprobe_example.c | 6 ++++-- 8 files changed, 26 insertions(+), 14 deletions(-) diff --git a/include/linux/fprobe.h b/include/linux/fprobe.h index 47fefc7f363b..134f0f59ffa8 100644 --- a/include/linux/fprobe.h +++ b/include/linux/fprobe.h @@ -35,9 +35,11 @@ struct fprobe { int nr_maxactive; int (*entry_handler)(struct fprobe *fp, unsigned long entry_ip, - struct pt_regs *regs, void *entry_data); + unsigned long ret_ip, struct pt_regs *regs, + void *entry_data); void (*exit_handler)(struct fprobe *fp, unsigned long entry_ip, - struct pt_regs *regs, void *entry_data); + unsigned long ret_ip, struct pt_regs *regs, + void *entry_data); }; /* This fprobe is soft-disabled. */ diff --git a/include/linux/rethook.h b/include/linux/rethook.h index c8ac1e5afcd1..fdf26cd0e742 100644 --- a/include/linux/rethook.h +++ b/include/linux/rethook.h @@ -14,7 +14,7 @@ struct rethook_node; -typedef void (*rethook_handler_t) (struct rethook_node *, void *, struct pt_regs *); +typedef void (*rethook_handler_t) (struct rethook_node *, void *, unsigned long, struct pt_regs *); /** * struct rethook - The rethook management data structure. diff --git a/kernel/kprobes.c b/kernel/kprobes.c index cd9f5a66a690..61d9eb467cef 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -2124,6 +2124,7 @@ static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs) NOKPROBE_SYMBOL(pre_handler_kretprobe); static void kretprobe_rethook_handler(struct rethook_node *rh, void *data, + unsigned long ret_addr, struct pt_regs *regs) { struct kretprobe *rp = (struct kretprobe *)data; diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index dadcddb6a429..44ca58192c31 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -2625,7 +2625,8 @@ kprobe_multi_link_prog_run(struct bpf_kprobe_multi_link *link, static int kprobe_multi_link_handler(struct fprobe *fp, unsigned long fentry_ip, - struct pt_regs *regs, void *data) + unsigned long ret_ip, struct pt_regs *regs, + void *data) { struct bpf_kprobe_multi_link *link; @@ -2636,7 +2637,8 @@ kprobe_multi_link_handler(struct fprobe *fp, unsigned long fentry_ip, static void kprobe_multi_link_exit_handler(struct fprobe *fp, unsigned long fentry_ip, - struct pt_regs *regs, void *data) + unsigned long ret_ip, struct pt_regs *regs, + void *data) { struct bpf_kprobe_multi_link *link; diff --git a/kernel/trace/fprobe.c b/kernel/trace/fprobe.c index 9abb3905bc8e..973bc664fcc1 100644 --- a/kernel/trace/fprobe.c +++ b/kernel/trace/fprobe.c @@ -52,7 +52,7 @@ static void fprobe_handler(unsigned long ip, unsigned long parent_ip, } if (fp->entry_handler) - ret = fp->entry_handler(fp, ip, ftrace_get_regs(fregs), entry_data); + ret = fp->entry_handler(fp, ip, parent_ip, ftrace_get_regs(fregs), entry_data); /* If entry_handler returns !0, nmissed is not counted. */ if (rh) { @@ -81,7 +81,7 @@ static void fprobe_kprobe_handler(unsigned long ip, unsigned long parent_ip, } static void fprobe_exit_handler(struct rethook_node *rh, void *data, - struct pt_regs *regs) + unsigned long ret_ip, struct pt_regs *regs) { struct fprobe *fp = (struct fprobe *)data; struct fprobe_rethook_node *fpr; @@ -91,7 +91,7 @@ static void fprobe_exit_handler(struct rethook_node *rh, void *data, fpr = container_of(rh, struct fprobe_rethook_node, node); - fp->exit_handler(fp, fpr->entry_ip, regs, + fp->exit_handler(fp, fpr->entry_ip, ret_ip, regs, fp->entry_data_size ? (void *)fpr->data : NULL); } NOKPROBE_SYMBOL(fprobe_exit_handler); diff --git a/kernel/trace/rethook.c b/kernel/trace/rethook.c index c69d82273ce7..3f6702b27c85 100644 --- a/kernel/trace/rethook.c +++ b/kernel/trace/rethook.c @@ -299,7 +299,8 @@ unsigned long rethook_trampoline_handler(struct pt_regs *regs, break; handler = READ_ONCE(rhn->rethook->handler); if (handler) - handler(rhn, rhn->rethook->data, regs); + handler(rhn, rhn->rethook->data, + correct_ret_addr, regs); if (first == node) break; diff --git a/lib/test_fprobe.c b/lib/test_fprobe.c index 926d5104b291..addf7db4a191 100644 --- a/lib/test_fprobe.c +++ b/lib/test_fprobe.c @@ -39,7 +39,8 @@ static noinline u32 fprobe_selftest_nest_target(u32 value, u32 (*nest)(u32)) } static notrace int fp_entry_handler(struct fprobe *fp, unsigned long ip, - struct pt_regs *regs, void *data) + unsigned long ret_ip, + struct pt_regs *regs, void *data) { KUNIT_EXPECT_FALSE(current_test, preemptible()); /* This can be called on the fprobe_selftest_target and the fprobe_selftest_target2 */ @@ -57,6 +58,7 @@ static notrace int fp_entry_handler(struct fprobe *fp, unsigned long ip, } static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip, + unsigned long ret_ip, struct pt_regs *regs, void *data) { unsigned long ret = regs_return_value(regs); @@ -78,14 +80,16 @@ static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip, } static notrace int nest_entry_handler(struct fprobe *fp, unsigned long ip, - struct pt_regs *regs, void *data) + unsigned long ret_ip, + struct pt_regs *regs, void *data) { KUNIT_EXPECT_FALSE(current_test, preemptible()); return 0; } static notrace void nest_exit_handler(struct fprobe *fp, unsigned long ip, - struct pt_regs *regs, void *data) + unsigned long ret_ip, + struct pt_regs *regs, void *data) { KUNIT_EXPECT_FALSE(current_test, preemptible()); KUNIT_EXPECT_EQ(current_test, ip, target_nest_ip); diff --git a/samples/fprobe/fprobe_example.c b/samples/fprobe/fprobe_example.c index 4efc8feb6277..64e715e7ed11 100644 --- a/samples/fprobe/fprobe_example.c +++ b/samples/fprobe/fprobe_example.c @@ -49,6 +49,7 @@ static void show_backtrace(void) } static int sample_entry_handler(struct fprobe *fp, unsigned long ip, + unsigned long ret_ip, struct pt_regs *regs, void *data) { if (use_trace) @@ -65,10 +66,11 @@ static int sample_entry_handler(struct fprobe *fp, unsigned long ip, return 0; } -static void sample_exit_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs, +static void sample_exit_handler(struct fprobe *fp, unsigned long ip, + unsigned long ret_ip, struct pt_regs *regs, void *data) { - unsigned long rip = instruction_pointer(regs); + unsigned long rip = ret_ip; if (use_trace) /* From patchwork Tue Nov 8 15:50:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 17116 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2795325wru; Tue, 8 Nov 2022 08:01:20 -0800 (PST) X-Google-Smtp-Source: AMsMyM5cDfXv4pAvW/2R3InGKYFXd1kvb78F1Dy+0NCtf1sWKMHJU+y4QSSDqRyLAZkbCsVjRZz/ X-Received: by 2002:a63:e64f:0:b0:43c:9db1:8096 with SMTP id p15-20020a63e64f000000b0043c9db18096mr46751639pgj.567.1667923279897; Tue, 08 Nov 2022 08:01:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1667923279; cv=none; d=google.com; s=arc-20160816; b=xmP2IT4eIiuci+hJYvDdQ6NqPDnVrTNM1thkgvBiNuriXM9RaYz0YSh15xhyL60OOO 9Q5aSou4+74+a6pTEVFL7oQmGO/ZpVWCqaJOaRSd9qrfYOSkqmCT52lpBX4hi7CnY8Gl Jr+ZWaqjteEE7mlyF6xnfqb8Al4g2IclbZjUexP0biSsJttiQn4jzWpIh31kXQ/susxZ +7pukDb1dK1ftIETZnBZnoO/Ofrif+AyFxIzYdPXuG7RpAlmZqPqgIu5V+pecNxD/J2c dE150ubwxiQck9QnzOteGNcw6pvt8a9ni9bnuN0XTJO8ixZ74v03xpAjQuGDBJqVUOzG LaSQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=fmLJRu0xc4raq4H2GD6sw6tbZdZbisPVCbpAMQb3upI=; b=tQCHDnEIvBFi0jO3DEo/mQrZLEkIQ0vGugF2rLl3E1NhxwOs3qwPZdamzPyXQDDVaI LDYo6y76sKG6jPhbLyws4qDsxDscB3dyKlM8uJon5FHoCCDKik9MS/TayW7EEWg7zemt kXJoJzkAG94DlmSasOWJIo7L2sw6Zoi6U5rAeixtOv4YN1LKSb0HXY//skCazyf6Af9a 7PZBiwrxWWgd/0GWLSy/U4yZuMhtFdaErBhn9tpHhqoi09ObIkAdY2he7rxZ0HU5vWCT ndOP/tlArMoA1pmrw8UEuMVYzEHhtK+SN6eQJj1kiWIGnM6uH+In9g6QoTn251xKWaHM 8zuQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=JRSfvtyd; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id h62-20020a625341000000b00536fa6bbb11si13197385pfb.344.2022.11.08.08.01.05; Tue, 08 Nov 2022 08:01:19 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=JRSfvtyd; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234639AbiKHPuw (ORCPT + 99 others); Tue, 8 Nov 2022 10:50:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38902 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234606AbiKHPul (ORCPT ); Tue, 8 Nov 2022 10:50:41 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EE4C25C755; Tue, 8 Nov 2022 07:50:38 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 7DAEB6163B; Tue, 8 Nov 2022 15:50:38 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4BA03C433D6; Tue, 8 Nov 2022 15:50:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667922637; bh=yG/5Bgs9HCFm/B0PDbumewX/1pLYBe0kuJAMXGHG8Mk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JRSfvtydnf/Eu8vGmeuaDP7yDz0JbGVvYva2+7KpAyrE0Vchkl0NYSwJk07YrR0As UkeWiJV4eo0kinqF/6WzaimctDp/9lzbGyQHcycpua97k6Y75tvfP1xq5ilQMcQ40a DejySf+PDBGXgZSQxbxlgh95LQUqOtW8neSZjYWbX4ExZhj+iVAYeguakeKklNTpM6 KiRHr70xwoP13nKeWraHkPICrpkn7eTiH+T8KFRzrRagwb2Ba3Qgpf8Hcg9I7F0avf jnFnjt2A6ATEtBFHFQNaVKyLMfRCYYQn9o66+UzdyT293OW9UV3/YZJ8az7gFJgc3g hHUx0Q0Qeuw1w== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Florent Revest , Mark Rutland , Will Deacon Subject: [RFC PATCH 9/9] tracing/probes: Add fprobe-events Date: Wed, 9 Nov 2022 00:50:34 +0900 Message-Id: <166792263423.919356.14181339761424544980.stgit@devnote3> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog In-Reply-To: <166792255429.919356.14116090269057513181.stgit@devnote3> References: <166792255429.919356.14116090269057513181.stgit@devnote3> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1748944321315047492?= X-GMAIL-MSGID: =?utf-8?q?1748944321315047492?= From: Masami Hiramatsu (Google) Add fprobe events for tracing function entry and exit. The fprobe event is a new dynamic events which is only for the function (symbol) entry and exit. This event accepts non register fetch arguments so that user can trace the function arguments and return values. The fprobe events syntax is here; f[:[GRP/][EVENT]] FUNCTION [FETCHARGS] f[MAXACTIVE][:[GRP/][EVENT]] FUNCTION%return [FETCHARGS] E.g. # echo 'f vfs_read $arg1' >> dynamic_events # echo 'f vfs_read%return $retval' >> dynamic_events # cat dynamic_events f:fprobes/vfs_read_entry vfs_read arg1=$arg1 f:fprobes/vfs_read_exit vfs_read%return arg1=$retval # echo 1 > events/fprobes/enable # head -n 20 trace | tail # TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | sh-142 [005] ...1. 448.386420: vfs_read_entry: (vfs_read+0x4/0x340) arg1=0xffff888007f7c540 sh-142 [005] ..... 448.386436: vfs_read_exit: (ksys_read+0x75/0x100 <- vfs_read) arg1=0x1 sh-142 [005] ...1. 448.386451: vfs_read_entry: (vfs_read+0x4/0x340) arg1=0xffff888007f7c540 sh-142 [005] ..... 448.386458: vfs_read_exit: (ksys_read+0x75/0x100 <- vfs_read) arg1=0x1 sh-142 [005] ...1. 448.386469: vfs_read_entry: (vfs_read+0x4/0x340) arg1=0xffff888007f7c540 sh-142 [005] ..... 448.386476: vfs_read_exit: (ksys_read+0x75/0x100 <- vfs_read) arg1=0x1 sh-142 [005] ...1. 448.602073: vfs_read_entry: (vfs_read+0x4/0x340) arg1=0xffff888007f7c540 sh-142 [005] ..... 448.602089: vfs_read_exit: (ksys_read+0x75/0x100 <- vfs_read) arg1=0x1 Signed-off-by: Masami Hiramatsu (Google) --- include/linux/fprobe.h | 5 include/linux/trace_events.h | 3 kernel/trace/Kconfig | 14 + kernel/trace/Makefile | 1 kernel/trace/fprobe.c | 11 kernel/trace/trace.h | 11 kernel/trace/trace_fprobe.c | 1120 ++++++++++++++++++++++++++++++++++++++++++ kernel/trace/trace_probe.c | 4 kernel/trace/trace_probe.h | 4 9 files changed, 1168 insertions(+), 5 deletions(-) create mode 100644 kernel/trace/trace_fprobe.c diff --git a/include/linux/fprobe.h b/include/linux/fprobe.h index 134f0f59ffa8..3e03758151f4 100644 --- a/include/linux/fprobe.h +++ b/include/linux/fprobe.h @@ -66,6 +66,7 @@ int register_fprobe(struct fprobe *fp, const char *filter, const char *notfilter int register_fprobe_ips(struct fprobe *fp, unsigned long *addrs, int num); int register_fprobe_syms(struct fprobe *fp, const char **syms, int num); int unregister_fprobe(struct fprobe *fp); +bool fprobe_is_registered(struct fprobe *fp); #else static inline int register_fprobe(struct fprobe *fp, const char *filter, const char *notfilter) { @@ -83,6 +84,10 @@ static inline int unregister_fprobe(struct fprobe *fp) { return -EOPNOTSUPP; } +static inline bool fprobe_is_registered(struct fprobe *fp) +{ + return false; +} #endif /** diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 20749bd9db71..24c3f8ff92a5 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -317,6 +317,7 @@ enum { TRACE_EVENT_FL_KPROBE_BIT, TRACE_EVENT_FL_UPROBE_BIT, TRACE_EVENT_FL_EPROBE_BIT, + TRACE_EVENT_FL_FPROBE_BIT, TRACE_EVENT_FL_CUSTOM_BIT, }; @@ -331,6 +332,7 @@ enum { * KPROBE - Event is a kprobe * UPROBE - Event is a uprobe * EPROBE - Event is an event probe + * FPROBE - Event is an function probe * CUSTOM - Event is a custom event (to be attached to an exsiting tracepoint) * This is set when the custom event has not been attached * to a tracepoint yet, then it is cleared when it is. @@ -345,6 +347,7 @@ enum { TRACE_EVENT_FL_KPROBE = (1 << TRACE_EVENT_FL_KPROBE_BIT), TRACE_EVENT_FL_UPROBE = (1 << TRACE_EVENT_FL_UPROBE_BIT), TRACE_EVENT_FL_EPROBE = (1 << TRACE_EVENT_FL_EPROBE_BIT), + TRACE_EVENT_FL_FPROBE = (1 << TRACE_EVENT_FL_FPROBE_BIT), TRACE_EVENT_FL_CUSTOM = (1 << TRACE_EVENT_FL_CUSTOM_BIT), }; diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index e9e95c790b8e..0fa80be04f71 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -634,6 +634,20 @@ config BLK_DEV_IO_TRACE If unsure, say N. +config FPROBE_EVENTS + depends on FPROBE + depends on HAVE_REGS_AND_STACK_ACCESS_API + bool "Enable fprobe-based dynamic events" + select TRACING + select PROBE_EVENTS + select DYNAMIC_EVENTS + default y + help + This allows user to add tracing events on the function entry and + exit via ftrace interface. The syntax is same as the kprobe events + and the kprobe events on function entry and exit will be + transparently converted to this fprobe events. + config KPROBE_EVENTS depends on KPROBES depends on HAVE_REGS_AND_STACK_ACCESS_API diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile index c6651e16b557..64b61f67a403 100644 --- a/kernel/trace/Makefile +++ b/kernel/trace/Makefile @@ -104,6 +104,7 @@ obj-$(CONFIG_BOOTTIME_TRACING) += trace_boot.o obj-$(CONFIG_FTRACE_RECORD_RECURSION) += trace_recursion_record.o obj-$(CONFIG_FPROBE) += fprobe.o obj-$(CONFIG_RETHOOK) += rethook.o +obj-$(CONFIG_FPROBE_EVENTS) += trace_fprobe.o obj-$(CONFIG_TRACEPOINT_BENCHMARK) += trace_benchmark.o obj-$(CONFIG_RV) += rv/ diff --git a/kernel/trace/fprobe.c b/kernel/trace/fprobe.c index 973bc664fcc1..1cfd4edcd579 100644 --- a/kernel/trace/fprobe.c +++ b/kernel/trace/fprobe.c @@ -305,6 +305,14 @@ int register_fprobe_syms(struct fprobe *fp, const char **syms, int num) } EXPORT_SYMBOL_GPL(register_fprobe_syms); +bool fprobe_is_registered(struct fprobe *fp) +{ + if (!fp || (fp->ops.saved_func != fprobe_handler && + fp->ops.saved_func != fprobe_kprobe_handler)) + return false; + return true; +} + /** * unregister_fprobe() - Unregister fprobe from ftrace * @fp: A fprobe data structure to be unregistered. @@ -317,8 +325,7 @@ int unregister_fprobe(struct fprobe *fp) { int ret; - if (!fp || (fp->ops.saved_func != fprobe_handler && - fp->ops.saved_func != fprobe_kprobe_handler)) + if (!fprobe_is_registered(fp)) return -EINVAL; /* diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 54ee5711c729..f8d9be50ce4c 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -144,6 +144,17 @@ struct kretprobe_trace_entry_head { unsigned long ret_ip; }; +struct fentry_trace_entry_head { + struct trace_entry ent; + unsigned long ip; +}; + +struct fexit_trace_entry_head { + struct trace_entry ent; + unsigned long func; + unsigned long ret_ip; +}; + #define TRACE_BUF_SIZE 1024 struct trace_array; diff --git a/kernel/trace/trace_fprobe.c b/kernel/trace/trace_fprobe.c new file mode 100644 index 000000000000..a5911133e560 --- /dev/null +++ b/kernel/trace/trace_fprobe.c @@ -0,0 +1,1120 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Fprobe-based tracing events + * Copyright (C) 2022 Google LLC. + */ +#define pr_fmt(fmt) "trace_fprobe: " fmt + +#include +#include +#include +#include +#include + +#include "trace_dynevent.h" +#include "trace_probe.h" +#include "trace_probe_kernel.h" +#include "trace_probe_tmpl.h" + +#define FPROBE_EVENT_SYSTEM "fprobes" +#define RETHOOK_MAXACTIVE_MAX 4096 + +static int trace_fprobe_create(const char *raw_command); +static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev); +static int trace_fprobe_release(struct dyn_event *ev); +static bool trace_fprobe_is_busy(struct dyn_event *ev); +static bool trace_fprobe_match(const char *system, const char *event, + int argc, const char **argv, struct dyn_event *ev); + +static struct dyn_event_operations trace_fprobe_ops = { + .create = trace_fprobe_create, + .show = trace_fprobe_show, + .is_busy = trace_fprobe_is_busy, + .free = trace_fprobe_release, + .match = trace_fprobe_match, +}; + +/* + * Kprobe event core functions + */ +struct trace_fprobe { + struct dyn_event devent; + struct fprobe fp; + const char *symbol; + struct trace_probe tp; +}; + +static bool is_trace_fprobe(struct dyn_event *ev) +{ + return ev->ops == &trace_fprobe_ops; +} + +static struct trace_fprobe *to_trace_fprobe(struct dyn_event *ev) +{ + return container_of(ev, struct trace_fprobe, devent); +} + +/** + * for_each_trace_fprobe - iterate over the trace_fprobe list + * @pos: the struct trace_fprobe * for each entry + * @dpos: the struct dyn_event * to use as a loop cursor + */ +#define for_each_trace_fprobe(pos, dpos) \ + for_each_dyn_event(dpos) \ + if (is_trace_fprobe(dpos) && (pos = to_trace_fprobe(dpos))) + +static bool trace_fprobe_is_return(struct trace_fprobe *tf) +{ + return tf->fp.exit_handler != NULL; +} + +static const char *trace_fprobe_symbol(struct trace_fprobe *tf) +{ + return tf->symbol ? tf->symbol : "unknown"; +} + +static bool trace_fprobe_is_busy(struct dyn_event *ev) +{ + struct trace_fprobe *tf = to_trace_fprobe(ev); + + return trace_probe_is_enabled(&tf->tp); +} + +static bool trace_fprobe_match_command_head(struct trace_fprobe *tf, + int argc, const char **argv) +{ + char buf[MAX_ARGSTR_LEN + 1]; + + if (!argc) + return true; + + snprintf(buf, sizeof(buf), "%s", trace_fprobe_symbol(tf)); + if (strcmp(buf, argv[0])) + return false; + argc--; argv++; + + return trace_probe_match_command_args(&tf->tp, argc, argv); +} + +static bool trace_fprobe_match(const char *system, const char *event, + int argc, const char **argv, struct dyn_event *ev) +{ + struct trace_fprobe *tf = to_trace_fprobe(ev); + + return (event[0] == '\0' || + strcmp(trace_probe_name(&tf->tp), event) == 0) && + (!system || strcmp(trace_probe_group_name(&tf->tp), system) == 0) && + trace_fprobe_match_command_head(tf, argc, argv); +} + +static bool trace_fprobe_is_registered(struct trace_fprobe *tf) +{ + return fprobe_is_registered(&tf->fp); +} + +/* Return the length of string -- including null terminal byte */ +static nokprobe_inline int +fetch_store_strlen_user(unsigned long addr) +{ + return kern_fetch_store_strlen_user(addr); +} + +/* Return the length of string -- including null terminal byte */ +static nokprobe_inline int +fetch_store_strlen(unsigned long addr) +{ + return kern_fetch_store_strlen(addr); +} + +/* + * Fetch a null-terminated string from user. Caller MUST set *(u32 *)buf + * with max length and relative data location. + */ +static nokprobe_inline int +fetch_store_string_user(unsigned long addr, void *dest, void *base) +{ + return kern_fetch_store_string_user(addr, dest, base); +} + +/* + * Fetch a null-terminated string. Caller MUST set *(u32 *)buf with max + * length and relative data location. + */ +static nokprobe_inline int +fetch_store_string(unsigned long addr, void *dest, void *base) +{ + return kern_fetch_store_string(addr, dest, base); +} + +static nokprobe_inline int +probe_mem_read_user(void *dest, void *src, size_t size) +{ + const void __user *uaddr = (__force const void __user *)src; + + return copy_from_user_nofault(dest, uaddr, size); +} + +static nokprobe_inline int +probe_mem_read(void *dest, void *src, size_t size) +{ +#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE + if ((unsigned long)src < TASK_SIZE) + return probe_mem_read_user(dest, src, size); +#endif + return copy_from_kernel_nofault(dest, src, size); +} + +/* Note that we don't verify it, since the code does not come from user space */ +static int +process_fetch_insn(struct fetch_insn *code, void *rec, void *dest, + void *base) +{ + struct pt_regs *regs = rec; + unsigned long val; + +retry: + /* 1st stage: get value from context */ + switch (code->op) { + case FETCH_OP_REG: + val = regs_get_register(regs, code->param); + break; + case FETCH_OP_STACK: + val = regs_get_kernel_stack_nth(regs, code->param); + break; + case FETCH_OP_STACKP: + val = kernel_stack_pointer(regs); + break; + case FETCH_OP_RETVAL: + val = regs_return_value(regs); + break; + case FETCH_OP_IMM: + val = code->immediate; + break; + case FETCH_OP_COMM: + val = (unsigned long)current->comm; + break; + case FETCH_OP_DATA: + val = (unsigned long)code->data; + break; +#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API + case FETCH_OP_ARG: + val = regs_get_kernel_argument(regs, code->param); + break; +#endif + case FETCH_NOP_SYMBOL: /* Ignore a place holder */ + code++; + goto retry; + default: + return -EILSEQ; + } + code++; + + return process_fetch_insn_bottom(code, val, dest, base); +} +NOKPROBE_SYMBOL(process_fetch_insn) + +/* function entry handler */ +static nokprobe_inline void +__fentry_trace_func(struct trace_fprobe *tf, unsigned long entry_ip, + struct pt_regs *regs, + struct trace_event_file *trace_file) +{ + struct fentry_trace_entry_head *entry; + struct trace_event_call *call = trace_probe_event_call(&tf->tp); + struct trace_event_buffer fbuffer; + int dsize; + + WARN_ON(call != trace_file->event_call); + + if (trace_trigger_soft_disabled(trace_file)) + return; + + dsize = __get_data_size(&tf->tp, regs); + + entry = trace_event_buffer_reserve(&fbuffer, trace_file, + sizeof(*entry) + tf->tp.size + dsize); + if (!entry) + return; + + fbuffer.regs = regs; + entry = fbuffer.entry = ring_buffer_event_data(fbuffer.event); + entry->ip = entry_ip; + store_trace_args(&entry[1], &tf->tp, regs, sizeof(*entry), dsize); + + trace_event_buffer_commit(&fbuffer); +} + +static void +fentry_trace_func(struct trace_fprobe *tf, unsigned long entry_ip, + struct pt_regs *regs) +{ + struct event_file_link *link; + + trace_probe_for_each_link_rcu(link, &tf->tp) + __fentry_trace_func(tf, entry_ip, regs, link->file); +} +NOKPROBE_SYMBOL(fentry_trace_func); + +/* Kretprobe handler */ +static nokprobe_inline void +__fexit_trace_func(struct trace_fprobe *tf, unsigned long entry_ip, + unsigned long ret_ip, struct pt_regs *regs, + struct trace_event_file *trace_file) +{ + struct fexit_trace_entry_head *entry; + struct trace_event_buffer fbuffer; + struct trace_event_call *call = trace_probe_event_call(&tf->tp); + int dsize; + + WARN_ON(call != trace_file->event_call); + + if (trace_trigger_soft_disabled(trace_file)) + return; + + dsize = __get_data_size(&tf->tp, regs); + + entry = trace_event_buffer_reserve(&fbuffer, trace_file, + sizeof(*entry) + tf->tp.size + dsize); + if (!entry) + return; + + fbuffer.regs = regs; + entry = fbuffer.entry = ring_buffer_event_data(fbuffer.event); + entry->func = entry_ip; + entry->ret_ip = ret_ip; + store_trace_args(&entry[1], &tf->tp, regs, sizeof(*entry), dsize); + + trace_event_buffer_commit(&fbuffer); +} + +static void +fexit_trace_func(struct trace_fprobe *tf, unsigned long entry_ip, + unsigned long ret_ip, struct pt_regs *regs) +{ + struct event_file_link *link; + + trace_probe_for_each_link_rcu(link, &tf->tp) + __fexit_trace_func(tf, entry_ip, ret_ip, regs, link->file); +} +NOKPROBE_SYMBOL(fexit_trace_func); + +#ifdef CONFIG_PERF_EVENTS + +static int fentry_perf_func(struct trace_fprobe *tf, unsigned long entry_ip, + struct pt_regs *regs) +{ + struct trace_event_call *call = trace_probe_event_call(&tf->tp); + struct fentry_trace_entry_head *entry; + struct hlist_head *head; + int size, __size, dsize; + int rctx; + + if (bpf_prog_array_valid(call)) { + unsigned long orig_ip = instruction_pointer(regs); + int ret; + + ret = trace_call_bpf(call, regs); + + /* + * We need to check and see if we modified the pc of the + * pt_regs, and if so return 1 so that we don't do the + * single stepping. + */ + if (orig_ip != instruction_pointer(regs)) + return 1; + if (!ret) + return 0; + } + + head = this_cpu_ptr(call->perf_events); + if (hlist_empty(head)) + return 0; + + dsize = __get_data_size(&tf->tp, regs); + __size = sizeof(*entry) + tf->tp.size + dsize; + size = ALIGN(__size + sizeof(u32), sizeof(u64)); + size -= sizeof(u32); + + entry = perf_trace_buf_alloc(size, NULL, &rctx); + if (!entry) + return 0; + + entry->ip = entry_ip; + memset(&entry[1], 0, dsize); + store_trace_args(&entry[1], &tf->tp, regs, sizeof(*entry), dsize); + perf_trace_buf_submit(entry, size, rctx, call->event.type, 1, regs, + head, NULL); + return 0; +} +NOKPROBE_SYMBOL(fentry_perf_func); + +static void +fexit_perf_func(struct trace_fprobe *tf, unsigned long entry_ip, + unsigned long ret_ip, struct pt_regs *regs) +{ + struct trace_event_call *call = trace_probe_event_call(&tf->tp); + struct fexit_trace_entry_head *entry; + struct hlist_head *head; + int size, __size, dsize; + int rctx; + + if (bpf_prog_array_valid(call) && !trace_call_bpf(call, regs)) + return; + + head = this_cpu_ptr(call->perf_events); + if (hlist_empty(head)) + return; + + dsize = __get_data_size(&tf->tp, regs); + __size = sizeof(*entry) + tf->tp.size + dsize; + size = ALIGN(__size + sizeof(u32), sizeof(u64)); + size -= sizeof(u32); + + entry = perf_trace_buf_alloc(size, NULL, &rctx); + if (!entry) + return; + + entry->func = entry_ip; + entry->ret_ip = ret_ip; + store_trace_args(&entry[1], &tf->tp, regs, sizeof(*entry), dsize); + perf_trace_buf_submit(entry, size, rctx, call->event.type, 1, regs, + head, NULL); +} +NOKPROBE_SYMBOL(fexit_perf_func); +#endif /* CONFIG_PERF_EVENTS */ + +static int fentry_dispatcher(struct fprobe *fp, unsigned long entry_ip, + unsigned long ret_ip, struct pt_regs *regs, + void *entry_data) +{ + struct trace_fprobe *tf = container_of(fp, struct trace_fprobe, fp); + int ret = 0; + + if (trace_probe_test_flag(&tf->tp, TP_FLAG_TRACE)) + fentry_trace_func(tf, entry_ip, regs); +#ifdef CONFIG_PERF_EVENTS + if (trace_probe_test_flag(&tf->tp, TP_FLAG_PROFILE)) + ret = fentry_perf_func(tf, entry_ip, regs); +#endif + return ret; +} +NOKPROBE_SYMBOL(fentry_dispatcher); + +static void fexit_dispatcher(struct fprobe *fp, unsigned long entry_ip, + unsigned long ret_ip, struct pt_regs *regs, + void *entry_data) +{ + struct trace_fprobe *tf = container_of(fp, struct trace_fprobe, fp); + + if (trace_probe_test_flag(&tf->tp, TP_FLAG_TRACE)) + fexit_trace_func(tf, entry_ip, ret_ip, regs); +#ifdef CONFIG_PERF_EVENTS + if (trace_probe_test_flag(&tf->tp, TP_FLAG_PROFILE)) + fexit_perf_func(tf, entry_ip, ret_ip, regs); +#endif +} +NOKPROBE_SYMBOL(fexit_dispatcher); + +static void free_trace_fprobe(struct trace_fprobe *tf) +{ + if (tf) { + trace_probe_cleanup(&tf->tp); + kfree(tf->symbol); + kfree(tf); + } +} + +/* + * Allocate new trace_probe and initialize it (including fprobe). + */ +static struct trace_fprobe *alloc_trace_fprobe(const char *group, + const char *event, + const char *symbol, + int maxactive, + int nargs, bool is_return) +{ + struct trace_fprobe *tf; + int ret = -ENOMEM; + + tf = kzalloc(struct_size(tf, tp.args, nargs), GFP_KERNEL); + if (!tf) + return ERR_PTR(ret); + + tf->symbol = kstrdup(symbol, GFP_KERNEL); + if (!tf->symbol) + goto error; + + if (is_return) + tf->fp.exit_handler = fexit_dispatcher; + else + tf->fp.entry_handler = fentry_dispatcher; + + tf->fp.nr_maxactive = maxactive; + + ret = trace_probe_init(&tf->tp, event, group, false); + if (ret < 0) + goto error; + + dyn_event_init(&tf->devent, &trace_fprobe_ops); + return tf; +error: + free_trace_fprobe(tf); + return ERR_PTR(ret); +} + +static struct trace_fprobe *find_trace_fprobe(const char *event, + const char *group) +{ + struct dyn_event *pos; + struct trace_fprobe *tf; + + for_each_trace_fprobe(tf, pos) + if (strcmp(trace_probe_name(&tf->tp), event) == 0 && + strcmp(trace_probe_group_name(&tf->tp), group) == 0) + return tf; + return NULL; +} + +static inline int __enable_trace_fprobe(struct trace_fprobe *tf) +{ + if (trace_fprobe_is_registered(tf)) + enable_fprobe(&tf->fp); + + return 0; +} + +static void __disable_trace_fprobe(struct trace_probe *tp) +{ + struct trace_fprobe *tf; + + list_for_each_entry(tf, trace_probe_probe_list(tp), tp.list) { + if (!trace_fprobe_is_registered(tf)) + continue; + disable_fprobe(&tf->fp); + } +} + +/* + * Enable trace_probe + * if the file is NULL, enable "perf" handler, or enable "trace" handler. + */ +static int enable_trace_fprobe(struct trace_event_call *call, + struct trace_event_file *file) +{ + struct trace_probe *tp; + struct trace_fprobe *tf; + bool enabled; + int ret = 0; + + tp = trace_probe_primary_from_call(call); + if (WARN_ON_ONCE(!tp)) + return -ENODEV; + enabled = trace_probe_is_enabled(tp); + + /* This also changes "enabled" state */ + if (file) { + ret = trace_probe_add_file(tp, file); + if (ret) + return ret; + } else + trace_probe_set_flag(tp, TP_FLAG_PROFILE); + + if (!enabled) { + list_for_each_entry(tf, trace_probe_probe_list(tp), tp.list) { + /* TODO: check the fprobe is gone */ + __enable_trace_fprobe(tf); + } + } + + return 0; +} + +/* + * Disable trace_probe + * if the file is NULL, disable "perf" handler, or disable "trace" handler. + */ +static int disable_trace_fprobe(struct trace_event_call *call, + struct trace_event_file *file) +{ + struct trace_probe *tp; + + tp = trace_probe_primary_from_call(call); + if (WARN_ON_ONCE(!tp)) + return -ENODEV; + + if (file) { + if (!trace_probe_get_file_link(tp, file)) + return -ENOENT; + if (!trace_probe_has_single_file(tp)) + goto out; + trace_probe_clear_flag(tp, TP_FLAG_TRACE); + } else + trace_probe_clear_flag(tp, TP_FLAG_PROFILE); + + if (!trace_probe_is_enabled(tp)) + __disable_trace_fprobe(tp); + + out: + if (file) + /* + * Synchronization is done in below function. For perf event, + * file == NULL and perf_trace_event_unreg() calls + * tracepoint_synchronize_unregister() to ensure synchronize + * event. We don't need to care about it. + */ + trace_probe_remove_file(tp, file); + + return 0; +} + +/* Event entry printers */ +static enum print_line_t +print_fentry_event(struct trace_iterator *iter, int flags, + struct trace_event *event) +{ + struct fentry_trace_entry_head *field; + struct trace_seq *s = &iter->seq; + struct trace_probe *tp; + + field = (struct fentry_trace_entry_head *)iter->ent; + tp = trace_probe_primary_from_call( + container_of(event, struct trace_event_call, event)); + if (WARN_ON_ONCE(!tp)) + goto out; + + trace_seq_printf(s, "%s: (", trace_probe_name(tp)); + + if (!seq_print_ip_sym(s, field->ip, flags | TRACE_ITER_SYM_OFFSET)) + goto out; + + trace_seq_putc(s, ')'); + + if (print_probe_args(s, tp->args, tp->nr_args, + (u8 *)&field[1], field) < 0) + goto out; + + trace_seq_putc(s, '\n'); + out: + return trace_handle_return(s); +} + +static enum print_line_t +print_fexit_event(struct trace_iterator *iter, int flags, + struct trace_event *event) +{ + struct fexit_trace_entry_head *field; + struct trace_seq *s = &iter->seq; + struct trace_probe *tp; + + field = (struct fexit_trace_entry_head *)iter->ent; + tp = trace_probe_primary_from_call( + container_of(event, struct trace_event_call, event)); + if (WARN_ON_ONCE(!tp)) + goto out; + + trace_seq_printf(s, "%s: (", trace_probe_name(tp)); + + if (!seq_print_ip_sym(s, field->ret_ip, flags | TRACE_ITER_SYM_OFFSET)) + goto out; + + trace_seq_puts(s, " <- "); + + if (!seq_print_ip_sym(s, field->func, flags & ~TRACE_ITER_SYM_OFFSET)) + goto out; + + trace_seq_putc(s, ')'); + + if (print_probe_args(s, tp->args, tp->nr_args, + (u8 *)&field[1], field) < 0) + goto out; + + trace_seq_putc(s, '\n'); + + out: + return trace_handle_return(s); +} + +static int fentry_event_define_fields(struct trace_event_call *event_call) +{ + int ret; + struct fentry_trace_entry_head field; + struct trace_probe *tp; + + tp = trace_probe_primary_from_call(event_call); + if (WARN_ON_ONCE(!tp)) + return -ENOENT; + + DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); + + return traceprobe_define_arg_fields(event_call, sizeof(field), tp); +} + +static int fexit_event_define_fields(struct trace_event_call *event_call) +{ + int ret; + struct fexit_trace_entry_head field; + struct trace_probe *tp; + + tp = trace_probe_primary_from_call(event_call); + if (WARN_ON_ONCE(!tp)) + return -ENOENT; + + DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0); + DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0); + + return traceprobe_define_arg_fields(event_call, sizeof(field), tp); +} + +static struct trace_event_functions fentry_funcs = { + .trace = print_fentry_event +}; + +static struct trace_event_functions fexit_funcs = { + .trace = print_fexit_event +}; + +static struct trace_event_fields fentry_fields_array[] = { + { .type = TRACE_FUNCTION_TYPE, + .define_fields = fentry_event_define_fields }, + {} +}; + +static struct trace_event_fields fexit_fields_array[] = { + { .type = TRACE_FUNCTION_TYPE, + .define_fields = fexit_event_define_fields }, + {} +}; + +static int fprobe_register(struct trace_event_call *event, + enum trace_reg type, void *data); + +static inline void init_trace_event_call(struct trace_fprobe *tf) +{ + struct trace_event_call *call = trace_probe_event_call(&tf->tp); + + if (trace_fprobe_is_return(tf)) { + call->event.funcs = &fexit_funcs; + call->class->fields_array = fexit_fields_array; + } else { + call->event.funcs = &fentry_funcs; + call->class->fields_array = fentry_fields_array; + } + + call->flags = TRACE_EVENT_FL_FPROBE; + call->class->reg = fprobe_register; +} + +static int register_fprobe_event(struct trace_fprobe *tf) +{ + init_trace_event_call(tf); + + return trace_probe_register_event_call(&tf->tp); +} + +static int unregister_fprobe_event(struct trace_fprobe *tf) +{ + return trace_probe_unregister_event_call(&tf->tp); +} + +/* Internal register function - just handle fprobe and flags */ +static int __register_trace_fprobe(struct trace_fprobe *tf) +{ + int i, ret; + + /* Should we need new LOCKDOWN flag for fprobe? */ + ret = security_locked_down(LOCKDOWN_KPROBES); + if (ret) + return ret; + + if (trace_fprobe_is_registered(tf)) + return -EINVAL; + + for (i = 0; i < tf->tp.nr_args; i++) { + ret = traceprobe_update_arg(&tf->tp.args[i]); + if (ret) + return ret; + } + + /* Set/clear disabled flag according to tp->flag */ + if (trace_probe_is_enabled(&tf->tp)) + tf->fp.flags &= ~FPROBE_FL_DISABLED; + else + tf->fp.flags |= FPROBE_FL_DISABLED; + + /* TODO: handle filter, nofilter or symbol list */ + return register_fprobe(&tf->fp, tf->symbol, NULL); +} + +/* Internal unregister function - just handle fprobe and flags */ +static void __unregister_trace_fprobe(struct trace_fprobe *tf) +{ + if (trace_fprobe_is_registered(tf)) { + unregister_fprobe(&tf->fp); + memset(&tf->fp, 0, sizeof(tf->fp)); + } +} + +/* TODO: make this trace_*probe common function */ +/* Unregister a trace_probe and probe_event */ +static int unregister_trace_fprobe(struct trace_fprobe *tf) +{ + /* If other probes are on the event, just unregister fprobe */ + if (trace_probe_has_sibling(&tf->tp)) + goto unreg; + + /* Enabled event can not be unregistered */ + if (trace_probe_is_enabled(&tf->tp)) + return -EBUSY; + + /* If there's a reference to the dynamic event */ + if (trace_event_dyn_busy(trace_probe_event_call(&tf->tp))) + return -EBUSY; + + /* Will fail if probe is being used by ftrace or perf */ + if (unregister_fprobe_event(tf)) + return -EBUSY; + +unreg: + __unregister_trace_fprobe(tf); + dyn_event_remove(&tf->devent); + trace_probe_unlink(&tf->tp); + + return 0; +} + +static bool trace_fprobe_has_same_fprobe(struct trace_fprobe *orig, + struct trace_fprobe *comp) +{ + struct trace_probe_event *tpe = orig->tp.event; + int i; + + list_for_each_entry(orig, &tpe->probes, tp.list) { + if (strcmp(trace_fprobe_symbol(orig), + trace_fprobe_symbol(comp))) + continue; + + /* + * trace_probe_compare_arg_type() ensured that nr_args and + * each argument name and type are same. Let's compare comm. + */ + for (i = 0; i < orig->tp.nr_args; i++) { + if (strcmp(orig->tp.args[i].comm, + comp->tp.args[i].comm)) + break; + } + + if (i == orig->tp.nr_args) + return true; + } + + return false; +} + +static int append_trace_fprobe(struct trace_fprobe *tf, struct trace_fprobe *to) +{ + int ret; + + if (trace_fprobe_is_return(tf) != trace_fprobe_is_return(to)) { + trace_probe_log_set_index(0); + trace_probe_log_err(0, DIFF_PROBE_TYPE); + ret = -EEXIST; + } + ret = trace_probe_compare_arg_type(&tf->tp, &to->tp); + if (ret) { + /* Note that argument starts index = 2 */ + trace_probe_log_set_index(ret + 1); + trace_probe_log_err(0, DIFF_ARG_TYPE); + return -EEXIST; + } + if (trace_fprobe_has_same_fprobe(to, tf)) { + trace_probe_log_set_index(0); + trace_probe_log_err(0, SAME_PROBE); + return -EEXIST; + } + + /* Append to existing event */ + ret = trace_probe_append(&tf->tp, &to->tp); + if (ret) + return ret; + + ret = __register_trace_fprobe(tf); + if (ret) + trace_probe_unlink(&tf->tp); + else + dyn_event_add(&tf->devent, trace_probe_event_call(&tf->tp)); + + return ret; +} + +/* Register a trace_probe and probe_event */ +static int register_trace_fprobe(struct trace_fprobe *tf) +{ + struct trace_fprobe *old_tf; + int ret; + + mutex_lock(&event_mutex); + + old_tf = find_trace_fprobe(trace_probe_name(&tf->tp), + trace_probe_group_name(&tf->tp)); + if (old_tf) { + ret = append_trace_fprobe(tf, old_tf); + goto end; + } + + /* Register new event */ + ret = register_fprobe_event(tf); + if (ret) { + if (ret == -EEXIST) { + trace_probe_log_set_index(0); + trace_probe_log_err(0, EVENT_EXIST); + } else + pr_warn("Failed to register probe event(%d)\n", ret); + goto end; + } + + /* Register fprobe */ + ret = __register_trace_fprobe(tf); + if (ret < 0) + unregister_fprobe_event(tf); + else + dyn_event_add(&tf->devent, trace_probe_event_call(&tf->tp)); + +end: + mutex_unlock(&event_mutex); + return ret; +} + +static int __trace_fprobe_create(int argc, const char *argv[]) +{ + /* + * Argument syntax: + * - Add fentry probe: + * f[:[GRP/][EVENT]] [MOD:]KSYM [FETCHARGS] + * - Add fexit probe: + * f[N][:[GRP/][EVENT]] [MOD:]KSYM%return [FETCHARGS] + * + * Fetch args: + * $retval : fetch return value + * $stack : fetch stack address + * $stackN : fetch Nth entry of stack (N:0-) + * $argN : fetch Nth argument (N:1-) + * $comm : fetch current task comm + * @ADDR : fetch memory at ADDR (ADDR should be in kernel) + * @SYM[+|-offs] : fetch memory at SYM +|- offs (SYM is a data symbol) + * Dereferencing memory fetch: + * +|-offs(ARG) : fetch memory at ARG +|- offs address. + * Alias name of args: + * NAME=FETCHARG : set NAME as alias of FETCHARG. + * Type of args: + * FETCHARG:TYPE : use TYPE instead of unsigned long. + */ + struct trace_fprobe *tf = NULL; + int i, len, ret = 0; + bool is_return = false; + char *symbol = NULL, *tmp = NULL; + const char *event = NULL, *group = FPROBE_EVENT_SYSTEM; + int maxactive = 0; + char buf[MAX_EVENT_NAME_LEN]; + char gbuf[MAX_EVENT_NAME_LEN]; + unsigned int flags = TPARG_FL_KERNEL; + + if (argv[0][0] != 'f' || argc < 2) + return -ECANCELED; + + trace_probe_log_init("trace_fprobe", argc, argv); + + event = strchr(&argv[0][1], ':'); + if (event) + event++; + + if (isdigit(argv[0][1])) { + if (event) + len = event - &argv[0][1] - 1; + else + len = strlen(&argv[0][1]); + if (len > MAX_EVENT_NAME_LEN - 1) { + trace_probe_log_err(1, BAD_MAXACT); + goto parse_error; + } + memcpy(buf, &argv[0][1], len); + buf[len] = '\0'; + ret = kstrtouint(buf, 0, &maxactive); + if (ret || !maxactive) { + trace_probe_log_err(1, BAD_MAXACT); + goto parse_error; + } + /* fprobe rethook instances are iterated over via a list. The + * maximum should stay reasonable. + */ + if (maxactive > RETHOOK_MAXACTIVE_MAX) { + trace_probe_log_err(1, MAXACT_TOO_BIG); + goto parse_error; + } + } + + trace_probe_log_set_index(1); + + /* a symbol specified */ + symbol = kstrdup(argv[1], GFP_KERNEL); + if (!symbol) + return -ENOMEM; + + tmp = strchr(symbol, '%'); + if (tmp) { + if (!strcmp(tmp, "%return")) { + *tmp = '\0'; + is_return = true; + } else { + trace_probe_log_err(tmp - symbol, BAD_ADDR_SUFFIX); + goto parse_error; + } + } + + flags |= TPARG_FL_FENTRY; + if (is_return) + flags |= TPARG_FL_RETURN; + + trace_probe_log_set_index(0); + if (event) { + ret = traceprobe_parse_event_name(&event, &group, gbuf, + event - argv[0]); + if (ret) + goto parse_error; + } + + if (!event) { + /* Make a new event name */ + snprintf(buf, MAX_EVENT_NAME_LEN, "%s_%s", symbol, + is_return ? "exit" : "entry"); + sanitize_event_name(buf); + event = buf; + } + + /* setup a probe */ + tf = alloc_trace_fprobe(group, event, symbol, maxactive, + argc - 2, is_return); + if (IS_ERR(tf)) { + ret = PTR_ERR(tf); + /* This must return -ENOMEM, else there is a bug */ + WARN_ON_ONCE(ret != -ENOMEM); + goto out; /* We know tf is not allocated */ + } + argc -= 2; argv += 2; + + /* parse arguments */ + for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { + trace_probe_log_set_index(i + 2); + ret = traceprobe_parse_probe_arg(&tf->tp, i, argv[i], flags); + if (ret) + goto error; /* This can be -ENOMEM */ + } + + ret = traceprobe_set_print_fmt(&tf->tp, + is_return ? PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL); + if (ret < 0) + goto error; + + ret = register_trace_fprobe(tf); + if (ret) { + trace_probe_log_set_index(1); + if (ret == -EILSEQ) + trace_probe_log_err(0, BAD_INSN_BNDRY); + else if (ret == -ENOENT) + trace_probe_log_err(0, BAD_PROBE_ADDR); + else if (ret != -ENOMEM && ret != -EEXIST) + trace_probe_log_err(0, FAIL_REG_PROBE); + goto error; + } + +out: + trace_probe_log_clear(); + kfree(symbol); + return ret; + +parse_error: + ret = -EINVAL; +error: + free_trace_fprobe(tf); + goto out; +} + +static int trace_fprobe_create(const char *raw_command) +{ + return trace_probe_create(raw_command, __trace_fprobe_create); +} + +static int trace_fprobe_release(struct dyn_event *ev) +{ + struct trace_fprobe *tf = to_trace_fprobe(ev); + int ret = unregister_trace_fprobe(tf); + + if (!ret) + free_trace_fprobe(tf); + return ret; +} + +static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev) +{ + struct trace_fprobe *tf = to_trace_fprobe(ev); + int i; + + seq_putc(m, 'f'); + if (trace_fprobe_is_return(tf) && tf->fp.nr_maxactive) + seq_printf(m, "%d", tf->fp.nr_maxactive); + seq_printf(m, ":%s/%s", trace_probe_group_name(&tf->tp), + trace_probe_name(&tf->tp)); + + seq_printf(m, " %s%s", trace_fprobe_symbol(tf), + trace_fprobe_is_return(tf) ? "%return" : ""); + + for (i = 0; i < tf->tp.nr_args; i++) + seq_printf(m, " %s=%s", tf->tp.args[i].name, tf->tp.args[i].comm); + seq_putc(m, '\n'); + + return 0; +} + +/* + * called by perf_trace_init() or __ftrace_set_clr_event() under event_mutex. + */ +static int fprobe_register(struct trace_event_call *event, + enum trace_reg type, void *data) +{ + struct trace_event_file *file = data; + + switch (type) { + case TRACE_REG_REGISTER: + return enable_trace_fprobe(event, file); + case TRACE_REG_UNREGISTER: + return disable_trace_fprobe(event, file); + +#ifdef CONFIG_PERF_EVENTS + case TRACE_REG_PERF_REGISTER: + return enable_trace_fprobe(event, NULL); + case TRACE_REG_PERF_UNREGISTER: + return disable_trace_fprobe(event, NULL); + case TRACE_REG_PERF_OPEN: + case TRACE_REG_PERF_CLOSE: + case TRACE_REG_PERF_ADD: + case TRACE_REG_PERF_DEL: + return 0; +#endif + } + return 0; +} + +/* + * Register dynevent at core_initcall. This allows kernel to setup fprobe + * events in postcore_initcall without tracefs. + */ +static __init int init_fprobe_trace_early(void) +{ + int ret; + + ret = dyn_event_register(&trace_fprobe_ops); + if (ret) + return ret; + + return 0; +} +core_initcall(init_fprobe_trace_early); diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index 36dff277de46..df7fb60b40b6 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c @@ -384,8 +384,8 @@ parse_probe_arg(char *arg, const struct fetch_type *type, break; case '%': /* named register */ - if (flags & TPARG_FL_TPOINT) { - /* eprobes do not handle registers */ + if (flags & (TPARG_FL_TPOINT || TPARG_FL_FPROBE)) { + /* eprobe and fprobe do not handle registers */ trace_probe_log_err(offs, BAD_VAR); break; } diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h index de38f1c03776..b316b1254583 100644 --- a/kernel/trace/trace_probe.h +++ b/kernel/trace/trace_probe.h @@ -353,7 +353,9 @@ int trace_probe_create(const char *raw_command, int (*createfn)(int, const char #define TPARG_FL_KERNEL BIT(1) #define TPARG_FL_FENTRY BIT(2) #define TPARG_FL_TPOINT BIT(3) -#define TPARG_FL_MASK GENMASK(3, 0) +#define TPARG_FL_USER BIT(4) +#define TPARG_FL_FPROBE BIT(5) +#define TPARG_FL_MASK GENMASK(5, 0) extern int traceprobe_parse_probe_arg(struct trace_probe *tp, int i, const char *argv, unsigned int flags);