From patchwork Thu Nov 9 00:41:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josh Poimboeuf X-Patchwork-Id: 163190 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b129:0:b0:403:3b70:6f57 with SMTP id q9csp138595vqs; Wed, 8 Nov 2023 16:44:44 -0800 (PST) X-Google-Smtp-Source: AGHT+IHxrBCvN3DUASLYRFiQpF4SThc6fNS0HCl8x7Ccr2WSN+Mupt2S6iVTk0oQl8tgVpaN3Ztg X-Received: by 2002:a17:902:e54b:b0:1cc:4625:74ed with SMTP id n11-20020a170902e54b00b001cc462574edmr4310594plf.53.1699490683890; Wed, 08 Nov 2023 16:44:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1699490683; cv=none; d=google.com; s=arc-20160816; b=dN4061/Gr7NBNrxl3T+IkKSMG3K2DuOYAvg0v9F/pPHKg51d8aKp8XtRQUI3lVmcM9 gB8oUs0UhQ7jp9XfVmC4+XPbntAAtF6459/ohZe5yGaSY8ZH9NTSO2C/ceMhKBJRebRs xWNflJ0WoniLHjITIzprnEbqTHcFFG5fnyo3PLWN0NeTFUyOSGEUyEtLDdfPCGQeLu5X C6MI4WB/OsxS+bt5i9fL89RQ+4PE5pXYJBZ7dx2ymrZiUblK805qzGQwzZH2HC8zI2ar gVolJpHXho5Th9AlKNAUQz7BsgPYq3oW2Kdiq+Y0/g1naEZs5HbcfCkzIT16+716FI7i a2nA== 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 :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=xZwicV/9KWxe6EyENJh4aVjyAd7V5y7yNg+rVax3IYU=; fh=3ahOA1+93SqEqAeT96I/cgRVlate7pzd5ZZzl/6KbbU=; b=zjWs4rg4r62yBmar+JIwRqDwNB4BqezkEHEccMNDQQOAH4/3F6CmchGLYMaMJhLFL9 T7gC4/RHQ5JsNnkc/VWfe9jEFWyQlaWXMiKoJx9P5FtPzcdM//FYLNc75EJDY22tcIS5 OhspFgEKjsB472x0Gjps/qmyzI2NjtJgg/TLfV5e/cra4mww55cdzJC4fJITFQ68OU+9 zCUrbD5VDWxAqDfEhqoU5Ev0/Cx0D+rSpsszOihgyP5b80EJCdJBGWpmM+LKcnAu8APq hPOMgyEJCnECgDmk5PUWUvrPTpcG/cfHzfzoERpgn9k5CemtcvgZ8Zjx86oaPCWgieX0 5UyQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=og2t3FQy; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 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 fry.vger.email (fry.vger.email. [2620:137:e000::3:8]) by mx.google.com with ESMTPS id 21-20020a170902c15500b001cc2ba37be8si3306825plj.258.2023.11.08.16.44.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Nov 2023 16:44:43 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) client-ip=2620:137:e000::3:8; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=og2t3FQy; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 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 (depot.vger.email [IPv6:2620:137:e000::3:0]) by fry.vger.email (Postfix) with ESMTP id 45C5D82E1E38; Wed, 8 Nov 2023 16:44:37 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at fry.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232630AbjKIAoL (ORCPT + 32 others); Wed, 8 Nov 2023 19:44:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48900 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232113AbjKIAnp (ORCPT ); Wed, 8 Nov 2023 19:43:45 -0500 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4EDC51992; Wed, 8 Nov 2023 16:43:43 -0800 (PST) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5D534C433BA; Thu, 9 Nov 2023 00:43:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1699490623; bh=v76o2vA/VG9otrtJQHKg2j3xEjD5Gu2nvX2ekprmSw0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=og2t3FQyVJK/vz8cFtmD/kFi17HXxKWytVXbx7ruZxtkXOtaU17/nq2+veBi+qCH5 7TJ/nCsW5q1wpKGCkm649MYUnu8x8x+SemvUGkos4s1bnb05fTvZr6QCajYf1Oa8jT 209Yn9rDlUkpi6CdhrYqWbEV/FrGywanlTEBEg1UAHNdYwJSWWQXdV/bopDt861AOQ FZQFPWxZULZ++CdBZdyBxqdZRo30tgAWWl8b0OmvNL9M38HlHzTarYYm6DFbkaxW9C 8zXU+Qv/DXmqmoYRO/K26NFM3DISCHg4CgvwchqqToCMo1wH52xHMTNa4AqVMgoqQO wFm6TIIpuKgqw== From: Josh Poimboeuf To: Peter Zijlstra , Steven Rostedt , Ingo Molnar , Arnaldo Carvalho de Melo Cc: linux-kernel@vger.kernel.org, x86@kernel.org, Indu Bhagat , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Ian Rogers , Adrian Hunter , linux-perf-users@vger.kernel.org, Mark Brown , linux-toolchains@vger.kernel.org Subject: [PATCH RFC 06/10] unwind: Introduce generic user space unwinding interfaces Date: Wed, 8 Nov 2023 16:41:11 -0800 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (fry.vger.email [0.0.0.0]); Wed, 08 Nov 2023 16:44:37 -0800 (PST) X-Spam-Status: No, score=-1.2 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on fry.vger.email X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1782045143355125306 X-GMAIL-MSGID: 1782045143355125306 Introduce generic user space unwinder interfaces which will provide a unified way for architectures to unwind different user space stack frame types. Signed-off-by: Josh Poimboeuf --- arch/Kconfig | 3 ++ include/linux/user_unwind.h | 32 +++++++++++++++ kernel/Makefile | 1 + kernel/unwind/Makefile | 1 + kernel/unwind/user.c | 77 +++++++++++++++++++++++++++++++++++++ 5 files changed, 114 insertions(+) create mode 100644 include/linux/user_unwind.h create mode 100644 kernel/unwind/Makefile create mode 100644 kernel/unwind/user.c diff --git a/arch/Kconfig b/arch/Kconfig index 690c82212224..c4a08485835e 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -428,6 +428,9 @@ config HAVE_HARDLOCKUP_DETECTOR_ARCH config HAVE_PERF_CALLCHAIN_DEFERRED bool +config HAVE_USER_UNWIND + bool + config HAVE_PERF_REGS bool help diff --git a/include/linux/user_unwind.h b/include/linux/user_unwind.h new file mode 100644 index 000000000000..2812b88c95fd --- /dev/null +++ b/include/linux/user_unwind.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_USER_UNWIND_H +#define _LINUX_USER_UNWIND_H + +#include +#include + +enum user_unwind_type { + USER_UNWIND_TYPE_AUTO, + USER_UNWIND_TYPE_FP, +}; + +struct user_unwind_frame { + s32 cfa_off; + s32 ra_off; + s32 fp_off; + bool use_fp; +}; + +struct user_unwind_state { + unsigned long ip, sp, fp; + enum user_unwind_type type; + bool done; +}; + +extern int user_unwind_start(struct user_unwind_state *state, enum user_unwind_type); +extern int user_unwind_next(struct user_unwind_state *state); + +#define for_each_user_frame(state, type) \ + for (user_unwind_start(&state, type); !state.done; user_unwind_next(&state)) + +#endif /* _LINUX_USER_UNWIND_H */ diff --git a/kernel/Makefile b/kernel/Makefile index 3947122d618b..bddf58b3b496 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -50,6 +50,7 @@ obj-y += rcu/ obj-y += livepatch/ obj-y += dma/ obj-y += entry/ +obj-y += unwind/ obj-$(CONFIG_MODULES) += module/ obj-$(CONFIG_KCMP) += kcmp.o diff --git a/kernel/unwind/Makefile b/kernel/unwind/Makefile new file mode 100644 index 000000000000..eb466d6a3295 --- /dev/null +++ b/kernel/unwind/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_HAVE_USER_UNWIND) += user.o diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c new file mode 100644 index 000000000000..8f9432306482 --- /dev/null +++ b/kernel/unwind/user.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include +#include + +static struct user_unwind_frame fp_frame = { + ARCH_INIT_USER_FP_FRAME +}; + +int user_unwind_next(struct user_unwind_state *state) +{ + struct user_unwind_frame _frame; + struct user_unwind_frame *frame = &_frame; + unsigned long cfa, fp, ra; + int ret = -EINVAL; + + if (state->done) + return -EINVAL; + + switch (state->type) { + case USER_UNWIND_TYPE_FP: + frame = &fp_frame; + break; + default: + BUG(); + } + + cfa = (frame->use_fp ? state->fp : state->sp) + frame->cfa_off; + + if (frame->ra_off && get_user(ra, (unsigned long *)(cfa + frame->ra_off))) + goto the_end; + + if (frame->fp_off && get_user(fp, (unsigned long *)(cfa + frame->fp_off))) + goto the_end; + + state->sp = cfa; + state->ip = ra; + if (frame->fp_off) + state->fp = fp; + + return 0; + +the_end: + state->done = true; + return ret; +} + +int user_unwind_start(struct user_unwind_state *state, + enum user_unwind_type type) +{ + struct pt_regs *regs = task_pt_regs(current); + + might_sleep(); + + memset(state, 0, sizeof(*state)); + + if (!current->mm) { + state->done = true; + return -EINVAL; + } + + if (type == USER_UNWIND_TYPE_AUTO) + state->type = USER_UNWIND_TYPE_FP; + else + state->type = type; + + state->sp = user_stack_pointer(regs); + state->ip = instruction_pointer(regs); + state->fp = frame_pointer(regs); + + return user_unwind_next(state); +}