From nobody Wed Sep 17 22:23:52 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9B9E6C4332F for ; Thu, 15 Dec 2022 04:03:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229655AbiLOEDD (ORCPT ); Wed, 14 Dec 2022 23:03:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54608 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229484AbiLOECR (ORCPT ); Wed, 14 Dec 2022 23:02:17 -0500 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B2A071EAD5 for ; Wed, 14 Dec 2022 20:02:15 -0800 (PST) Received: from loongson.cn (unknown [111.9.175.10]) by gateway (Coremail) with SMTP id _____8AxaepGnJpj4LkFAA--.9760S3; Thu, 15 Dec 2022 12:02:14 +0800 (CST) Received: from localhost.localdomain (unknown [111.9.175.10]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxtOVDnJpjVBkAAA--.887S3; Thu, 15 Dec 2022 12:02:14 +0800 (CST) From: Jinyang He To: Huacai Chen , WANG Xuerui , Qing Zhang Cc: loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, Steven Rostedt , Masami Hiramatsu , Mark Rutland Subject: [PATCH 1/6] LoongArch: Get frame info in unwind_start when regs is not supported Date: Thu, 15 Dec 2022 12:01:36 +0800 Message-Id: <20221215040141.18610-2-hejinyang@loongson.cn> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20221215040141.18610-1-hejinyang@loongson.cn> References: <20221215040141.18610-1-hejinyang@loongson.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAf8BxtOVDnJpjVBkAAA--.887S3 X-CM-SenderInfo: pkhmx0p1dqwqxorr0wxvrqhubq/ X-Coremail-Antispam: 1Uk129KBjvJXoWxCr1rKFykXr47urWrCrWktFb_yoW5ZFy5p3 sxCrsxWr45uF9Fqr9rtw1kZr95Grn7uw12gF9rt34rC3W7XFyxurnYv34DZFs8t3yvgw10 qFn5KrW5Ka1UJaUanT9S1TB71UUUUjUqnTZGkaVYY2UrUUUUj1kv1TuYvTs0mT0YCTnIWj qI5I8CrVACY4xI64kE6c02F40Ex7xfYxn0WfASr-VFAUDa7-sFnT9fnUUIcSsGvfJTRUUU bSxYFVCjjxCrM7AC8VAFwI0_Jr0_Gr1l1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s 1l1IIY67AEw4v_Jrv_JF1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xv wVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwA2z4 x0Y4vEx4A2jsIE14v26r4UJVWxJr1l84ACjcxK6I8E87Iv6xkF7I0E14v26r4UJVWxJr1l n4kS14v26r1Y6r17M2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6xkI12xvs2x26I8E6x ACxx1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r1q6rW5McIj6I8E 87Iv67AKxVW8JVWxJwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lc7CjxV Aaw2AFwI0_JF0_Jw1l42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1l4IxY O2xFxVAFwI0_Jrv_JF1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGV WUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_ JFI_Gr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4j6F4UMIIF0xvE42xK8VAvwI8IcIk0rV WUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42IY6I8E87Iv6xkF7I0E14v26r4j6r4U JbIYCTnIWIevJa73UjIFyTuYvjxUxhiSDUUUU Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" At unwind_start, it is better to try to get its frame info even we not support regs rather than get them outside. So that we can simply use unwind_{start, next_frame, done} outside. Signed-off-by: Jinyang He --- arch/loongarch/kernel/process.c | 12 +++--------- arch/loongarch/kernel/unwind_guess.c | 6 ++++++ arch/loongarch/kernel/unwind_prologue.c | 16 +++++++++++++--- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/arch/loongarch/kernel/process.c b/arch/loongarch/kernel/proces= s.c index 502b8b950057..6ef45174ad35 100644 --- a/arch/loongarch/kernel/process.c +++ b/arch/loongarch/kernel/process.c @@ -197,20 +197,14 @@ int copy_thread(struct task_struct *p, const struct k= ernel_clone_args *args) =20 unsigned long __get_wchan(struct task_struct *task) { - unsigned long pc; + unsigned long pc =3D 0; struct unwind_state state; =20 if (!try_get_task_stack(task)) return 0; =20 - unwind_start(&state, task, NULL); - state.sp =3D thread_saved_fp(task); - get_stack_info(state.sp, state.task, &state.stack_info); - state.pc =3D thread_saved_ra(task); -#ifdef CONFIG_UNWINDER_PROLOGUE - state.type =3D UNWINDER_PROLOGUE; -#endif - for (; !unwind_done(&state); unwind_next_frame(&state)) { + for (unwind_start(&state, task, NULL); !unwind_done(&state); + unwind_next_frame(&state)) { pc =3D unwind_get_return_address(&state); if (!pc) break; diff --git a/arch/loongarch/kernel/unwind_guess.c b/arch/loongarch/kernel/u= nwind_guess.c index e2d2e4f3001f..e03864511582 100644 --- a/arch/loongarch/kernel/unwind_guess.c +++ b/arch/loongarch/kernel/unwind_guess.c @@ -26,6 +26,12 @@ void unwind_start(struct unwind_state *state, struct tas= k_struct *task, if (regs) { state->sp =3D regs->regs[3]; state->pc =3D regs->csr_era; + } else if (task =3D=3D current) { + state->sp =3D (unsigned long)__builtin_frame_address(0); + state->pc =3D (unsigned long)__builtin_return_address(0); + } else { + state->sp =3D thread_saved_fp(task); + state->pc =3D thread_saved_ra(task); } =20 state->task =3D task; diff --git a/arch/loongarch/kernel/unwind_prologue.c b/arch/loongarch/kerne= l/unwind_prologue.c index 0f8d1451ebb8..9d51ea37782e 100644 --- a/arch/loongarch/kernel/unwind_prologue.c +++ b/arch/loongarch/kernel/unwind_prologue.c @@ -141,12 +141,22 @@ void unwind_start(struct unwind_state *state, struct = task_struct *task, struct pt_regs *regs) { memset(state, 0, sizeof(*state)); + state->type =3D UNWINDER_PROLOGUE; =20 - if (regs && __kernel_text_address(regs->csr_era)) { - state->pc =3D regs->csr_era; + if (regs) { state->sp =3D regs->regs[3]; + state->pc =3D regs->csr_era; state->ra =3D regs->regs[1]; - state->type =3D UNWINDER_PROLOGUE; + if (!__kernel_text_address(state->pc)) + state->type =3D UNWINDER_GUESS; + } else if (task =3D=3D current) { + state->sp =3D (unsigned long)__builtin_frame_address(0); + state->pc =3D (unsigned long)__builtin_return_address(0); + state->ra =3D 0; + } else { + state->sp =3D thread_saved_fp(task); + state->pc =3D thread_saved_ra(task); + state->ra =3D 0; } =20 state->task =3D task; --=20 2.34.3 From nobody Wed Sep 17 22:23:52 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1D947C4332F for ; Thu, 15 Dec 2022 04:03:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229560AbiLOEDI (ORCPT ); Wed, 14 Dec 2022 23:03:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54612 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229631AbiLOECR (ORCPT ); Wed, 14 Dec 2022 23:02:17 -0500 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 0C9B61F60C for ; Wed, 14 Dec 2022 20:02:15 -0800 (PST) Received: from loongson.cn (unknown [111.9.175.10]) by gateway (Coremail) with SMTP id _____8AxRPBHnJpj5rkFAA--.13185S3; Thu, 15 Dec 2022 12:02:15 +0800 (CST) Received: from localhost.localdomain (unknown [111.9.175.10]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxtOVDnJpjVBkAAA--.887S4; Thu, 15 Dec 2022 12:02:14 +0800 (CST) From: Jinyang He To: Huacai Chen , WANG Xuerui , Qing Zhang Cc: loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, Steven Rostedt , Masami Hiramatsu , Mark Rutland Subject: [PATCH 2/6] LoongArch: Use correct sp value to get graph addr in unwinder guess Date: Thu, 15 Dec 2022 12:01:37 +0800 Message-Id: <20221215040141.18610-3-hejinyang@loongson.cn> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20221215040141.18610-1-hejinyang@loongson.cn> References: <20221215040141.18610-1-hejinyang@loongson.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAf8BxtOVDnJpjVBkAAA--.887S4 X-CM-SenderInfo: pkhmx0p1dqwqxorr0wxvrqhubq/ X-Coremail-Antispam: 1Uk129KBjvJXoW3Gw1fAFWUCF43CF43XFWfuFg_yoWxJr4kpF 9xCas3GrWxWryqgrnrXr1jvrn5Crn2kw12gFyDJ34FkFnrXry3Grn0v34qvFs8J3y8Wr48 XFn5GrW5KanrG3JanT9S1TB71UUUUjUqnTZGkaVYY2UrUUUUj1kv1TuYvTs0mT0YCTnIWj qI5I8CrVACY4xI64kE6c02F40Ex7xfYxn0WfASr-VFAUDa7-sFnT9fnUUIcSsGvfJTRUUU bSxYFVCjjxCrM7AC8VAFwI0_Jr0_Gr1l1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s 1l1IIY67AEw4v_Jrv_JF1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xv wVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwA2z4 x0Y4vEx4A2jsIE14v26r4UJVWxJr1l84ACjcxK6I8E87Iv6xkF7I0E14v26r4UJVWxJr1l n4kS14v26r1Y6r17M2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6xkI12xvs2x26I8E6x ACxx1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r1q6rW5McIj6I8E 87Iv67AKxVW8JVWxJwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lc7CjxV Aaw2AFwI0_JF0_Jw1l42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1l4IxY O2xFxVAFwI0_Jrv_JF1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGV WUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_ Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4j6F4UMIIF0xvE42xK8VAvwI8IcIk0rV WUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26r4j6r4U JbIYCTnIWIevJa73UjIFyTuYvjxUxhiSDUUUU Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The stack frame when function_graph enable like follows, --------- <- function sp_on_entry | | | FAKE_RA <- sp_on_entry - sizeof(pt_regs) + PT_R1 | --------- <- sp_on_entry - sizeof(pt_regs) So if we want to get the &FAKE_RA we should get sp_on_entry first. In unwinder_prologue case, we can get the sp_on_entry as state->sp, because we try to calculate each CFA and the ra saved address. But in unwinder_guess case, we cannot get it because we do not try to calculate the CFA. Although LoongArch have not fixed frame, the $ra is saved at CFA - 8 in most cases, we can try guess, too. As we store the pc in state, we not need to dereference state->sp, too. Signed-off-by: Jinyang He --- arch/loongarch/include/asm/ftrace.h | 2 -- arch/loongarch/include/asm/unwind.h | 9 +++++++++ arch/loongarch/kernel/unwind_guess.c | 12 ++++-------- arch/loongarch/kernel/unwind_prologue.c | 22 ++++++---------------- 4 files changed, 19 insertions(+), 26 deletions(-) diff --git a/arch/loongarch/include/asm/ftrace.h b/arch/loongarch/include/a= sm/ftrace.h index 90f9d3399b2a..3418d32d4fc7 100644 --- a/arch/loongarch/include/asm/ftrace.h +++ b/arch/loongarch/include/asm/ftrace.h @@ -10,8 +10,6 @@ #define FTRACE_REGS_PLT_IDX 1 #define NR_FTRACE_PLTS 2 =20 -#define GRAPH_FAKE_OFFSET (sizeof(struct pt_regs) - offsetof(struct pt_reg= s, regs[1])) - #ifdef CONFIG_FUNCTION_TRACER =20 #define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */ diff --git a/arch/loongarch/include/asm/unwind.h b/arch/loongarch/include/a= sm/unwind.h index f2b52b9ea93d..6ece48f0ff77 100644 --- a/arch/loongarch/include/asm/unwind.h +++ b/arch/loongarch/include/asm/unwind.h @@ -7,8 +7,10 @@ #ifndef _ASM_UNWIND_H #define _ASM_UNWIND_H =20 +#include #include =20 +#include #include =20 enum unwinder_type { @@ -40,4 +42,11 @@ static inline bool unwind_error(struct unwind_state *sta= te) return state->error; } =20 +#define GRAPH_FAKE_OFFSET (sizeof(struct pt_regs) - offsetof(struct pt_reg= s, regs[1])) +static inline unsigned long unwind_graph_addr(struct unwind_state *state, + unsigned long pc, unsigned long cfa) +{ + return ftrace_graph_ret_addr(state->task, &state->graph_idx, + pc, (unsigned long *)(cfa - GRAPH_FAKE_OFFSET)); +} #endif /* _ASM_UNWIND_H */ diff --git a/arch/loongarch/kernel/unwind_guess.c b/arch/loongarch/kernel/u= nwind_guess.c index e03864511582..8ce32c37c587 100644 --- a/arch/loongarch/kernel/unwind_guess.c +++ b/arch/loongarch/kernel/unwind_guess.c @@ -11,10 +11,7 @@ unsigned long unwind_get_return_address(struct unwind_st= ate *state) { if (unwind_done(state)) return 0; - else if (state->first) - return state->pc; - - return *(unsigned long *)(state->sp); + return state->pc; } EXPORT_SYMBOL_GPL(unwind_get_return_address); =20 @@ -36,7 +33,7 @@ void unwind_start(struct unwind_state *state, struct task= _struct *task, =20 state->task =3D task; state->first =3D true; - + state->pc =3D unwind_graph_addr(state, state->pc, state->sp); get_stack_info(state->sp, state->task, &state->stack_info); =20 if (!unwind_done(state) && !__kernel_text_address(state->pc)) @@ -60,9 +57,8 @@ bool unwind_next_frame(struct unwind_state *state) state->sp < info->end; state->sp +=3D sizeof(unsigned long)) { addr =3D *(unsigned long *)(state->sp); - state->pc =3D ftrace_graph_ret_addr(state->task, &state->graph_idx, - addr, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET)); - if (__kernel_text_address(addr)) + state->pc =3D unwind_graph_addr(state, addr, state->sp + 8); + if (__kernel_text_address(state->pc)) return true; } =20 diff --git a/arch/loongarch/kernel/unwind_prologue.c b/arch/loongarch/kerne= l/unwind_prologue.c index 9d51ea37782e..35cab7f77c6b 100644 --- a/arch/loongarch/kernel/unwind_prologue.c +++ b/arch/loongarch/kernel/unwind_prologue.c @@ -21,16 +21,9 @@ static inline void unwind_state_fixup(struct unwind_stat= e *state) =20 unsigned long unwind_get_return_address(struct unwind_state *state) { - if (unwind_done(state)) return 0; - else if (state->type) - return state->pc; - else if (state->first) - return state->pc; - - return *(unsigned long *)(state->sp); - + return state->pc; } EXPORT_SYMBOL_GPL(unwind_get_return_address); =20 @@ -43,9 +36,8 @@ static bool unwind_by_guess(struct unwind_state *state) state->sp < info->end; state->sp +=3D sizeof(unsigned long)) { addr =3D *(unsigned long *)(state->sp); - state->pc =3D ftrace_graph_ret_addr(state->task, &state->graph_idx, - addr, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET)); - if (__kernel_text_address(addr)) + state->pc =3D unwind_graph_addr(state, addr, state->sp + 8); + if (__kernel_text_address(state->pc)) return true; } =20 @@ -161,7 +153,7 @@ void unwind_start(struct unwind_state *state, struct ta= sk_struct *task, =20 state->task =3D task; state->first =3D true; - + state->pc =3D unwind_graph_addr(state, state->pc, state->sp); get_stack_info(state->sp, state->task, &state->stack_info); =20 if (!unwind_done(state) && !__kernel_text_address(state->pc)) @@ -188,8 +180,7 @@ bool unwind_next_frame(struct unwind_state *state) =20 case UNWINDER_PROLOGUE: if (unwind_by_prologue(state)) { - state->pc =3D ftrace_graph_ret_addr(state->task, &state->graph_idx, - state->pc, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET)); + state->pc =3D unwind_graph_addr(state, state->pc, state->sp); return true; } =20 @@ -204,8 +195,7 @@ bool unwind_next_frame(struct unwind_state *state) state->first =3D true; state->ra =3D regs->regs[1]; state->sp =3D regs->regs[3]; - state->pc =3D ftrace_graph_ret_addr(state->task, &state->graph_idx, - pc, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET)); + state->pc =3D pc; get_stack_info(state->sp, state->task, info); =20 return true; --=20 2.34.3 From nobody Wed Sep 17 22:23:52 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D1C24C4332F for ; Thu, 15 Dec 2022 04:03:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229658AbiLOEDV (ORCPT ); Wed, 14 Dec 2022 23:03:21 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54610 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229708AbiLOECR (ORCPT ); Wed, 14 Dec 2022 23:02:17 -0500 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id BAD721FF94 for ; Wed, 14 Dec 2022 20:02:16 -0800 (PST) Received: from loongson.cn (unknown [111.9.175.10]) by gateway (Coremail) with SMTP id _____8Bx1vBHnJpj7LkFAA--.12962S3; Thu, 15 Dec 2022 12:02:15 +0800 (CST) Received: from localhost.localdomain (unknown [111.9.175.10]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxtOVDnJpjVBkAAA--.887S5; Thu, 15 Dec 2022 12:02:15 +0800 (CST) From: Jinyang He To: Huacai Chen , WANG Xuerui , Qing Zhang Cc: loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, Steven Rostedt , Masami Hiramatsu , Mark Rutland Subject: [PATCH 3/6] LoongArch: Adjust PC value when unwind next frame in prologue unwinder Date: Thu, 15 Dec 2022 12:01:38 +0800 Message-Id: <20221215040141.18610-4-hejinyang@loongson.cn> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20221215040141.18610-1-hejinyang@loongson.cn> References: <20221215040141.18610-1-hejinyang@loongson.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAf8BxtOVDnJpjVBkAAA--.887S5 X-CM-SenderInfo: pkhmx0p1dqwqxorr0wxvrqhubq/ X-Coremail-Antispam: 1Uk129KBjvJXoW7ZryUAFyftFyrGr4kGrykZrb_yoW8JFy8p3 93AFZ5Gr4jqr13G39rtr4Dur95CrykGr42gFWDtry8u3Z0qFn7urnI9ryqvanYq34kJr10 qw1Fg3ya9F4UJwUanT9S1TB71UUUUjUqnTZGkaVYY2UrUUUUj1kv1TuYvTs0mT0YCTnIWj qI5I8CrVACY4xI64kE6c02F40Ex7xfYxn0WfASr-VFAUDa7-sFnT9fnUUIcSsGvfJTRUUU bSxYFVCjjxCrM7AC8VAFwI0_Jr0_Gr1l1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s 1l1IIY67AEw4v_Jrv_JF1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xv wVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwA2z4 x0Y4vEx4A2jsIE14v26r4UJVWxJr1l84ACjcxK6I8E87Iv6xkF7I0E14v26r4UJVWxJr1l n4kS14v26r1Y6r17M2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6xkI12xvs2x26I8E6x ACxx1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r1q6rW5McIj6I8E 87Iv67AKxVW8JVWxJwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lc7CjxV Aaw2AFwI0_JF0_Jw1l42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1l4IxY O2xFxVAFwI0_Jrv_JF1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGV WUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_ Xr0_Ar1lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4j6F4UMIIF0xvE42xK8VAvwI8IcIk0rV WUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26r4j6r4U JbIYCTnIWIevJa73UjIFyTuYvjxUxhiSDUUUU Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" When state->first is not set, the PC is a return address in the previous frame. We need to adjust it value in case overflow to the next symbol. Signed-off-by: Jinyang He --- arch/loongarch/kernel/unwind_prologue.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/loongarch/kernel/unwind_prologue.c b/arch/loongarch/kerne= l/unwind_prologue.c index 35cab7f77c6b..d464c533c64f 100644 --- a/arch/loongarch/kernel/unwind_prologue.c +++ b/arch/loongarch/kernel/unwind_prologue.c @@ -48,7 +48,7 @@ static bool unwind_by_prologue(struct unwind_state *state) { long frame_ra =3D -1; unsigned long frame_size =3D 0; - unsigned long size, offset, pc =3D state->pc; + unsigned long size, offset, pc; struct pt_regs *regs; struct stack_info *info =3D &state->stack_info; union loongarch_instruction *ip, *ip_end; @@ -70,6 +70,10 @@ static bool unwind_by_prologue(struct unwind_state *stat= e) return true; } =20 + /* When first is not set, the PC is a return address in the previous fram= e. + * We need to adjust it value in case overflow to the next symbol. + */ + pc =3D state->pc - (state->first ? 0 : LOONGARCH_INSN_SIZE); if (!kallsyms_lookup_size_offset(pc, &size, &offset)) return false; =20 --=20 2.34.3 From nobody Wed Sep 17 22:23:52 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 94F74C4332F for ; Thu, 15 Dec 2022 04:03:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229738AbiLOEDa (ORCPT ); Wed, 14 Dec 2022 23:03:30 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54234 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229681AbiLOECT (ORCPT ); Wed, 14 Dec 2022 23:02:19 -0500 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id DCFA82019A for ; Wed, 14 Dec 2022 20:02:17 -0800 (PST) Received: from loongson.cn (unknown [111.9.175.10]) by gateway (Coremail) with SMTP id _____8DxuupInJpj8rkFAA--.13377S3; Thu, 15 Dec 2022 12:02:16 +0800 (CST) Received: from localhost.localdomain (unknown [111.9.175.10]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxtOVDnJpjVBkAAA--.887S6; Thu, 15 Dec 2022 12:02:16 +0800 (CST) From: Jinyang He To: Huacai Chen , WANG Xuerui , Qing Zhang Cc: loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, Steven Rostedt , Masami Hiramatsu , Mark Rutland Subject: [PATCH 4/6] LoongArch: Strip guess_unwinder out from prologue_unwinder Date: Thu, 15 Dec 2022 12:01:39 +0800 Message-Id: <20221215040141.18610-5-hejinyang@loongson.cn> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20221215040141.18610-1-hejinyang@loongson.cn> References: <20221215040141.18610-1-hejinyang@loongson.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAf8BxtOVDnJpjVBkAAA--.887S6 X-CM-SenderInfo: pkhmx0p1dqwqxorr0wxvrqhubq/ X-Coremail-Antispam: 1Uk129KBjvAXoW3KryfCrW3uF4DWrW5XF45GFg_yoW8Jw1fCo WftF4agr48X3y5t3yjyryUtFyYgr4jka1UAw43trn8Wr42y343ur4jqasxXFyIqw1rKrWU Gr42gF4rXan7Arn3n29KB7ZKAUJUUUU7529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf J3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU0xBIdaVrnRJU UUBIb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2IYs7xG6rWj6s 0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_Xr0_Ar1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr0_Cr1l84 ACjcxK6I8E87Iv67AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVCY1x0267AKxVW8Jr0_Cr1U M2kKe7AKxVWUXVWUAwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07AIYIkI8VC2zV CFFI0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWUtVWrXwAv7VC2 z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JMxkF7I 0En4kS14v26r126r1DMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMxCI bckI1I0E14v26r1Y6r17MI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_Jr I_JrWlx4CE17CEb7AF67AKxVWUtVW8ZwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v2 6ryj6F1UMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwCI42IY6xAIw20EY4v20xvaj4 0_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8 JrUvcSsGvfC2KfnxnUUI43ZEXa7IU0epB3UUUUU== Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The prolugue unwinder rely on symbol info. When PC is not in kernel text address, it cannot find relative symbol info and it will be broken. The guess unwinder will be used in this case. And the guess unwinder codes in prolugue unwinder is redundant. Strip it out and set the unwinder info in unwind_state. Signed-off-by: Jinyang He --- arch/loongarch/include/asm/unwind.h | 22 ++++ arch/loongarch/kernel/Makefile | 3 +- arch/loongarch/kernel/unwind.c | 52 +++++++++ arch/loongarch/kernel/unwind_guess.c | 41 ++----- arch/loongarch/kernel/unwind_prologue.c | 135 +++++++++--------------- 5 files changed, 135 insertions(+), 118 deletions(-) create mode 100644 arch/loongarch/kernel/unwind.c diff --git a/arch/loongarch/include/asm/unwind.h b/arch/loongarch/include/a= sm/unwind.h index 6ece48f0ff77..a16aff1d086a 100644 --- a/arch/loongarch/include/asm/unwind.h +++ b/arch/loongarch/include/asm/unwind.h @@ -18,6 +18,8 @@ enum unwinder_type { UNWINDER_PROLOGUE, }; =20 +struct unwinder_ops; + struct unwind_state { char type; /* UNWINDER_XXX */ struct stack_info stack_info; @@ -25,8 +27,22 @@ struct unwind_state { bool first, error, is_ftrace; int graph_idx; unsigned long sp, pc, ra; + const struct unwinder_ops *ops; +}; + +struct unwinder_ops { + void (*unwind_start)(struct unwind_state *state, + struct task_struct *task, struct pt_regs *regs); + bool (*unwind_next_frame)(struct unwind_state *state); + unsigned long (*unwind_get_return_address)(struct unwind_state *state); }; =20 +extern const struct unwinder_ops *default_unwinder; +extern const struct unwinder_ops unwinder_guess; +#ifdef CONFIG_UNWINDER_PROLOGUE +extern const struct unwinder_ops unwinder_prologue; +#endif + void unwind_start(struct unwind_state *state, struct task_struct *task, struct pt_regs *regs); bool unwind_next_frame(struct unwind_state *state); @@ -49,4 +65,10 @@ static inline unsigned long unwind_graph_addr(struct unw= ind_state *state, return ftrace_graph_ret_addr(state->task, &state->graph_idx, pc, (unsigned long *)(cfa - GRAPH_FAKE_OFFSET)); } + +static inline void unwind_register_unwinder(struct unwind_state *state, + const struct unwinder_ops *unwinder) +{ + state->ops =3D unwinder; +} #endif /* _ASM_UNWIND_H */ diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile index 7ca65195f7f8..cb6029ea3ea9 100644 --- a/arch/loongarch/kernel/Makefile +++ b/arch/loongarch/kernel/Makefile @@ -8,7 +8,7 @@ extra-y :=3D vmlinux.lds obj-y +=3D head.o cpu-probe.o cacheinfo.o env.o setup.o entry.o genex.o \ traps.o irq.o idle.o process.o dma.o mem.o io.o reset.o switch.o \ elf.o syscall.o signal.o time.o topology.o inst.o ptrace.o vdso.o \ - alternative.o unaligned.o + alternative.o unaligned.o unwind.o unwind_guess.o =20 obj-$(CONFIG_ACPI) +=3D acpi.o obj-$(CONFIG_EFI) +=3D efi.o @@ -42,7 +42,6 @@ obj-$(CONFIG_MAGIC_SYSRQ) +=3D sysrq.o obj-$(CONFIG_KEXEC) +=3D machine_kexec.o relocate_kernel.o obj-$(CONFIG_CRASH_DUMP) +=3D crash_dump.o =20 -obj-$(CONFIG_UNWINDER_GUESS) +=3D unwind_guess.o obj-$(CONFIG_UNWINDER_PROLOGUE) +=3D unwind_prologue.o =20 obj-$(CONFIG_PERF_EVENTS) +=3D perf_event.o perf_regs.o diff --git a/arch/loongarch/kernel/unwind.c b/arch/loongarch/kernel/unwind.c new file mode 100644 index 000000000000..568c6fe707d1 --- /dev/null +++ b/arch/loongarch/kernel/unwind.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 Loongson Technology Corporation Limited + */ +#include + +#if defined(CONFIG_UNWINDER_GUESS) +const struct unwinder_ops *default_unwinder =3D &unwinder_guess; +#elif defined(CONFIG_UNWINDER_PROLOGUE) +const struct unwinder_ops *default_unwinder =3D &unwinder_prologue; +#endif + +unsigned long unwind_get_return_address(struct unwind_state *state) +{ + if (!state->ops || unwind_done(state)) + return 0; + return state->ops->unwind_get_return_address(state); +} +EXPORT_SYMBOL_GPL(unwind_get_return_address); + +void unwind_start(struct unwind_state *state, struct task_struct *task, + struct pt_regs *regs) +{ + memset(state, 0, sizeof(*state)); + unwind_register_unwinder(state, default_unwinder); + if (regs) { + state->sp =3D regs->regs[3]; + state->pc =3D regs->csr_era; + state->ra =3D regs->regs[1]; + } else if (task =3D=3D current) { + state->sp =3D (unsigned long)__builtin_frame_address(0); + state->pc =3D (unsigned long)__builtin_return_address(0); + state->ra =3D 0; + } else { + state->sp =3D thread_saved_fp(task); + state->pc =3D thread_saved_ra(task); + state->ra =3D 0; + } + state->task =3D task; + get_stack_info(state->sp, state->task, &state->stack_info); + state->pc =3D unwind_graph_addr(state, state->pc, state->sp); + state->ops->unwind_start(state, task, regs); +} +EXPORT_SYMBOL_GPL(unwind_start); + +bool unwind_next_frame(struct unwind_state *state) +{ + if (!state->ops || unwind_done(state)) + return false; + return state->ops->unwind_next_frame(state); +} +EXPORT_SYMBOL_GPL(unwind_next_frame); diff --git a/arch/loongarch/kernel/unwind_guess.c b/arch/loongarch/kernel/u= nwind_guess.c index 8ce32c37c587..b7ca2b88ac63 100644 --- a/arch/loongarch/kernel/unwind_guess.c +++ b/arch/loongarch/kernel/unwind_guess.c @@ -7,51 +7,23 @@ =20 #include =20 -unsigned long unwind_get_return_address(struct unwind_state *state) +static unsigned long get_return_address(struct unwind_state *state) { - if (unwind_done(state)) - return 0; return state->pc; } -EXPORT_SYMBOL_GPL(unwind_get_return_address); =20 -void unwind_start(struct unwind_state *state, struct task_struct *task, +static void start(struct unwind_state *state, struct task_struct *task, struct pt_regs *regs) { - memset(state, 0, sizeof(*state)); - - if (regs) { - state->sp =3D regs->regs[3]; - state->pc =3D regs->csr_era; - } else if (task =3D=3D current) { - state->sp =3D (unsigned long)__builtin_frame_address(0); - state->pc =3D (unsigned long)__builtin_return_address(0); - } else { - state->sp =3D thread_saved_fp(task); - state->pc =3D thread_saved_ra(task); - } - - state->task =3D task; - state->first =3D true; - state->pc =3D unwind_graph_addr(state, state->pc, state->sp); - get_stack_info(state->sp, state->task, &state->stack_info); - if (!unwind_done(state) && !__kernel_text_address(state->pc)) unwind_next_frame(state); } -EXPORT_SYMBOL_GPL(unwind_start); =20 -bool unwind_next_frame(struct unwind_state *state) +static bool next_frame(struct unwind_state *state) { struct stack_info *info =3D &state->stack_info; unsigned long addr; =20 - if (unwind_done(state)) - return false; - - if (state->first) - state->first =3D false; - do { for (state->sp +=3D sizeof(unsigned long); state->sp < info->end; @@ -68,4 +40,9 @@ bool unwind_next_frame(struct unwind_state *state) =20 return false; } -EXPORT_SYMBOL_GPL(unwind_next_frame); + +const struct unwinder_ops unwinder_guess =3D { + .unwind_start =3D start, + .unwind_next_frame =3D next_frame, + .unwind_get_return_address =3D get_return_address, +}; diff --git a/arch/loongarch/kernel/unwind_prologue.c b/arch/loongarch/kerne= l/unwind_prologue.c index d464c533c64f..9677e13c4b4c 100644 --- a/arch/loongarch/kernel/unwind_prologue.c +++ b/arch/loongarch/kernel/unwind_prologue.c @@ -9,6 +9,8 @@ #include #include =20 +static const struct unwinder_ops *guard_unwinder =3D &unwinder_guess; + static inline void unwind_state_fixup(struct unwind_state *state) { #ifdef CONFIG_DYNAMIC_FTRACE @@ -19,31 +21,19 @@ static inline void unwind_state_fixup(struct unwind_sta= te *state) #endif } =20 -unsigned long unwind_get_return_address(struct unwind_state *state) +static unsigned long get_return_address(struct unwind_state *state) { - if (unwind_done(state)) - return 0; return state->pc; } -EXPORT_SYMBOL_GPL(unwind_get_return_address); - -static bool unwind_by_guess(struct unwind_state *state) -{ - struct stack_info *info =3D &state->stack_info; - unsigned long addr; - - for (state->sp +=3D sizeof(unsigned long); - state->sp < info->end; - state->sp +=3D sizeof(unsigned long)) { - addr =3D *(unsigned long *)(state->sp); - state->pc =3D unwind_graph_addr(state, addr, state->sp + 8); - if (__kernel_text_address(state->pc)) - return true; - } - - return false; -} =20 +/* + * LoongArch function prologue like follows, + * [others instructions not use stack var] + * addi.d sp, sp, -imm + * st.d xx, sp, offset <- save callee saved regs and + * st.d yy, sp, offset save ra if function is nest. + * [others instructions] + */ static bool unwind_by_prologue(struct unwind_state *state) { long frame_ra =3D -1; @@ -89,6 +79,10 @@ static bool unwind_by_prologue(struct unwind_state *stat= e) ip++; } =20 + /* + * Not find stack alloc action, PC may be in a leaf function. Only the + * first being true is reasonable, otherwise indicate analysis is broken. + */ if (!frame_size) { if (state->first) goto first; @@ -106,6 +100,7 @@ static bool unwind_by_prologue(struct unwind_state *sta= te) ip++; } =20 + /* Not find save $ra action, PC may be in a leaf function, too. */ if (frame_ra < 0) { if (state->first) { state->sp =3D state->sp + frame_size; @@ -114,96 +109,63 @@ static bool unwind_by_prologue(struct unwind_state *s= tate) return false; } =20 - if (state->first) - state->first =3D false; - state->pc =3D *(unsigned long *)(state->sp + frame_ra); state->sp =3D state->sp + frame_size; goto out; =20 first: - state->first =3D false; - if (state->pc =3D=3D state->ra) - return false; - state->pc =3D state->ra; =20 out: + state->first =3D false; unwind_state_fixup(state); return !!__kernel_text_address(state->pc); } =20 -void unwind_start(struct unwind_state *state, struct task_struct *task, +static void start(struct unwind_state *state, struct task_struct *task, struct pt_regs *regs) { - memset(state, 0, sizeof(*state)); - state->type =3D UNWINDER_PROLOGUE; - - if (regs) { - state->sp =3D regs->regs[3]; - state->pc =3D regs->csr_era; - state->ra =3D regs->regs[1]; - if (!__kernel_text_address(state->pc)) - state->type =3D UNWINDER_GUESS; - } else if (task =3D=3D current) { - state->sp =3D (unsigned long)__builtin_frame_address(0); - state->pc =3D (unsigned long)__builtin_return_address(0); - state->ra =3D 0; - } else { - state->sp =3D thread_saved_fp(task); - state->pc =3D thread_saved_ra(task); - state->ra =3D 0; - } - - state->task =3D task; state->first =3D true; - state->pc =3D unwind_graph_addr(state, state->pc, state->sp); - get_stack_info(state->sp, state->task, &state->stack_info); =20 - if (!unwind_done(state) && !__kernel_text_address(state->pc)) - unwind_next_frame(state); + /* + * The current PC is not kernel text address, we cannot find its + * relative symbol. Thus, prologue analysis will be broken. Luckly, + * we can use the guard unwinder. + */ + if (!__kernel_text_address(state->pc)) { + unwind_register_unwinder(state, guard_unwinder); + if (!unwind_done(state)) + unwind_next_frame(state); + } } -EXPORT_SYMBOL_GPL(unwind_start); =20 -bool unwind_next_frame(struct unwind_state *state) +static bool next_frame(struct unwind_state *state) { struct stack_info *info =3D &state->stack_info; struct pt_regs *regs; unsigned long pc; =20 - if (unwind_done(state)) - return false; - do { - switch (state->type) { - case UNWINDER_GUESS: - state->first =3D false; - if (unwind_by_guess(state)) - return true; - break; - - case UNWINDER_PROLOGUE: - if (unwind_by_prologue(state)) { - state->pc =3D unwind_graph_addr(state, state->pc, state->sp); - return true; - } + if (unwind_by_prologue(state)) { + state->pc =3D unwind_graph_addr(state, state->pc, state->sp); + return true; + } =20 - if (info->type =3D=3D STACK_TYPE_IRQ && - info->end =3D=3D state->sp) { - regs =3D (struct pt_regs *)info->next_sp; - pc =3D regs->csr_era; + if (info->type =3D=3D STACK_TYPE_IRQ && + info->end =3D=3D state->sp) { + regs =3D (struct pt_regs *)info->next_sp; + pc =3D regs->csr_era; =20 - if (user_mode(regs) || !__kernel_text_address(pc)) - return false; + if (user_mode(regs) || !__kernel_text_address(pc)) + return false; =20 - state->first =3D true; - state->ra =3D regs->regs[1]; - state->sp =3D regs->regs[3]; - state->pc =3D pc; - get_stack_info(state->sp, state->task, info); + state->first =3D true; + state->ra =3D regs->regs[1]; + state->sp =3D regs->regs[3]; + state->pc =3D pc; + get_stack_info(state->sp, state->task, info); =20 - return true; - } + return true; } =20 state->sp =3D info->next_sp; @@ -212,4 +174,9 @@ bool unwind_next_frame(struct unwind_state *state) =20 return false; } -EXPORT_SYMBOL_GPL(unwind_next_frame); + +const struct unwinder_ops unwinder_prologue =3D { + .unwind_start =3D start, + .unwind_next_frame =3D next_frame, + .unwind_get_return_address =3D get_return_address, +}; --=20 2.34.3 From nobody Wed Sep 17 22:23:52 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BC049C4332F for ; Thu, 15 Dec 2022 04:03:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229732AbiLOED0 (ORCPT ); Wed, 14 Dec 2022 23:03:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54470 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229680AbiLOECT (ORCPT ); Wed, 14 Dec 2022 23:02:19 -0500 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 108322036F for ; Wed, 14 Dec 2022 20:02:17 -0800 (PST) Received: from loongson.cn (unknown [111.9.175.10]) by gateway (Coremail) with SMTP id _____8Cxl_FJnJpj+LkFAA--.12715S3; Thu, 15 Dec 2022 12:02:17 +0800 (CST) Received: from localhost.localdomain (unknown [111.9.175.10]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxtOVDnJpjVBkAAA--.887S7; Thu, 15 Dec 2022 12:02:16 +0800 (CST) From: Jinyang He To: Huacai Chen , WANG Xuerui , Qing Zhang Cc: loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, Steven Rostedt , Masami Hiramatsu , Mark Rutland Subject: [PATCH 5/6] LoongArch: Add raw_show_trace to enable guess unwinder default Date: Thu, 15 Dec 2022 12:01:40 +0800 Message-Id: <20221215040141.18610-6-hejinyang@loongson.cn> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20221215040141.18610-1-hejinyang@loongson.cn> References: <20221215040141.18610-1-hejinyang@loongson.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAf8BxtOVDnJpjVBkAAA--.887S7 X-CM-SenderInfo: pkhmx0p1dqwqxorr0wxvrqhubq/ X-Coremail-Antispam: 1Uk129KBjvJXoW7AF13WF43Jw4kXF43XFWrKrg_yoW8JF4Dpa ykCF9Ygr4fWFW2g347Xr1DuF98JF95Zw13uFZxAw1rCFsxK3W7Jr1Fv34Yva9Yyry8JryI qFsYkryj9ayjy3JanT9S1TB71UUUUjUqnTZGkaVYY2UrUUUUj1kv1TuYvTs0mT0YCTnIWj qI5I8CrVACY4xI64kE6c02F40Ex7xfYxn0WfASr-VFAUDa7-sFnT9fnUUIcSsGvfJTRUUU bSxYFVCjjxCrM7AC8VAFwI0_Jr0_Gr1l1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s 1l1IIY67AEw4v_Jrv_JF1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xv wVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwA2z4 x0Y4vEx4A2jsIE14v26r4UJVWxJr1l84ACjcxK6I8E87Iv6xkF7I0E14v26r4UJVWxJr1l n4kS14v26r1Y6r17M2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6xkI12xvs2x26I8E6x ACxx1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26rWY6Fy7McIj6I8E 87Iv67AKxVW8JVWxJwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lc7CjxV Aaw2AFwI0_JF0_Jw1l42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1l4IxY O2xFxVAFwI0_Jrv_JF1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGV WUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_ Xr0_Ar1lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4j6F4UMIIF0xvE42xK8VAvwI8IcIk0rV WUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26r4j6r4U JbIYCTnIWIevJa73UjIFyTuYvjxU36RRDUUUU Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Inspired by MIPS, add cmdline parameter named 'raw_show_trace' to enable guess unwinder in prologue unwinder unwind_start() default. In some cases the guess is more efficient than prologue. Signed-off-by: Jinyang He --- arch/loongarch/kernel/unwind_prologue.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/loongarch/kernel/unwind_prologue.c b/arch/loongarch/kerne= l/unwind_prologue.c index 9677e13c4b4c..441641227c10 100644 --- a/arch/loongarch/kernel/unwind_prologue.c +++ b/arch/loongarch/kernel/unwind_prologue.c @@ -122,11 +122,22 @@ static bool unwind_by_prologue(struct unwind_state *s= tate) return !!__kernel_text_address(state->pc); } =20 +static int raw_show_trace; +static int __init set_raw_show_trace(char *str) +{ + raw_show_trace =3D 1; + return 1; +} +__setup("raw_show_trace", set_raw_show_trace); + static void start(struct unwind_state *state, struct task_struct *task, struct pt_regs *regs) { state->first =3D true; =20 + if (raw_show_trace) + unwind_register_unwinder(state, guard_unwinder); + /* * The current PC is not kernel text address, we cannot find its * relative symbol. Thus, prologue analysis will be broken. Luckly, --=20 2.34.3 From nobody Wed Sep 17 22:23:52 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9B6E7C4332F for ; Thu, 15 Dec 2022 04:03:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229749AbiLOEDf (ORCPT ); Wed, 14 Dec 2022 23:03:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54202 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229683AbiLOEC0 (ORCPT ); Wed, 14 Dec 2022 23:02:26 -0500 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 1CB1FF0C for ; Wed, 14 Dec 2022 20:02:24 -0800 (PST) Received: from loongson.cn (unknown [111.9.175.10]) by gateway (Coremail) with SMTP id _____8BxnutPnJpjDLoFAA--.13437S3; Thu, 15 Dec 2022 12:02:23 +0800 (CST) Received: from localhost.localdomain (unknown [111.9.175.10]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxtOVDnJpjVBkAAA--.887S8; Thu, 15 Dec 2022 12:02:23 +0800 (CST) From: Jinyang He To: Huacai Chen , WANG Xuerui , Qing Zhang Cc: loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, Steven Rostedt , Masami Hiramatsu , Mark Rutland Subject: [PATCH 6/6] LoongArch: Add generic ex-handler unwind in prologue unwinder Date: Thu, 15 Dec 2022 12:01:41 +0800 Message-Id: <20221215040141.18610-7-hejinyang@loongson.cn> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20221215040141.18610-1-hejinyang@loongson.cn> References: <20221215040141.18610-1-hejinyang@loongson.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAf8BxtOVDnJpjVBkAAA--.887S8 X-CM-SenderInfo: pkhmx0p1dqwqxorr0wxvrqhubq/ X-Coremail-Antispam: 1Uk129KBjvJXoW3XF15XF48Wr4DXFWDuF4Uurg_yoWxAw17pF 9akrn5Gr4rKr9Fqry7Jryq9r98Aw4kCw17KF9rKas5CF1Iqry3WrnYy34qvF1DJ3y8WFyI qFs3Xrya9a1UJa7anT9S1TB71UUUUjUqnTZGkaVYY2UrUUUUj1kv1TuYvTs0mT0YCTnIWj qI5I8CrVACY4xI64kE6c02F40Ex7xfYxn0WfASr-VFAUDa7-sFnT9fnUUIcSsGvfJTRUUU bSkYFVCjjxCrM7AC8VAFwI0_Jr0_Gr1l1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s 1l1IIY67AEw4v_JrI_Jryl8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xv wVC0I7IYx2IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVWxJVW8Jr1l84 ACjcxK6I8E87Iv67AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVCY1x0267AKxVW8Jr0_Cr1U M2kKe7AKxVWUXVWUAwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07AIYIkI8VC2zV CFFI0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWrXVW3AwAv7VC2 z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JMxkF7I 0En4kS14v26r126r1DMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMxCI bckI1I0E14v26r1Y6r17MI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_Jr I_JrWlx4CE17CEb7AF67AKxVWUtVW8ZwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v2 6ryj6F1UMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwCI42IY6xAIw20EY4v20xvaj4 0_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8 JrUvcSsGvfC2KfnxnUUI43ZEXa7IUn0385UUUUU== Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" When exception is triggered, code flow go handle_\exception in some cases. One of stackframe in this case as follows, high -> +-------+ | REGS | <- a pt_regs | | | | <- ex trigger | REGS | <- ex pt_regs <-+ | | | | | | low -> +-------+ ->unwind-+ When unwinder unwind to handler_\exception it cannot go on prologue analysis. It is asynchronous code flow, we should get the next frame PC from regs->csr_era but not from regs->regs[1]. And we copy the handler codes to eentry in the early time and copy the handler codes to NUMA-relative memory named pcpu_handlers if NUMA is enabled. Thus, unwinder cannot unwind normally. Therefore, try to give some hint in handler_\exception and fixup it in unwind_next_frame. Reported-by: Qing Zhang Signed-off-by: Jinyang He --- arch/loongarch/include/asm/unwind.h | 2 +- arch/loongarch/kernel/genex.S | 3 + arch/loongarch/kernel/unwind_prologue.c | 100 +++++++++++++++++++++--- arch/loongarch/mm/tlb.c | 2 +- 4 files changed, 92 insertions(+), 15 deletions(-) diff --git a/arch/loongarch/include/asm/unwind.h b/arch/loongarch/include/a= sm/unwind.h index a16aff1d086a..c02cb3b39fe2 100644 --- a/arch/loongarch/include/asm/unwind.h +++ b/arch/loongarch/include/asm/unwind.h @@ -24,7 +24,7 @@ struct unwind_state { char type; /* UNWINDER_XXX */ struct stack_info stack_info; struct task_struct *task; - bool first, error, is_ftrace; + bool first, error, reset; int graph_idx; unsigned long sp, pc, ra; const struct unwinder_ops *ops; diff --git a/arch/loongarch/kernel/genex.S b/arch/loongarch/kernel/genex.S index 75e5be807a0d..7e5c293ed89f 100644 --- a/arch/loongarch/kernel/genex.S +++ b/arch/loongarch/kernel/genex.S @@ -67,14 +67,17 @@ SYM_FUNC_END(except_vec_cex) .macro BUILD_HANDLER exception handler prep .align 5 SYM_FUNC_START(handle_\exception) + 666: BACKUP_T0T1 SAVE_ALL build_prep_\prep move a0, sp la.abs t0, do_\handler jirl ra, t0, 0 + 668: RESTORE_ALL_AND_RET SYM_FUNC_END(handle_\exception) + SYM_DATA(unwind_hint_\exception, .word 668b - 666b) .endm =20 BUILD_HANDLER ade ade badv diff --git a/arch/loongarch/kernel/unwind_prologue.c b/arch/loongarch/kerne= l/unwind_prologue.c index 441641227c10..c34bb035ac56 100644 --- a/arch/loongarch/kernel/unwind_prologue.c +++ b/arch/loongarch/kernel/unwind_prologue.c @@ -2,23 +2,102 @@ /* * Copyright (C) 2022 Loongson Technology Corporation Limited */ +#include #include #include =20 #include +#include #include +#include #include =20 static const struct unwinder_ops *guard_unwinder =3D &unwinder_guess; =20 -static inline void unwind_state_fixup(struct unwind_state *state) +extern const int unwind_hint_ade; +extern const int unwind_hint_ale; +extern const int unwind_hint_bp; +extern const int unwind_hint_fpe; +extern const int unwind_hint_fpu; +extern const int unwind_hint_lsx; +extern const int unwind_hint_lasx; +extern const int unwind_hint_lbt; +extern const int unwind_hint_ri; +extern const int unwind_hint_watch; +extern unsigned long eentry; +#ifdef CONFIG_NUMA +extern unsigned long pcpu_handlers[NR_CPUS]; +#endif + +static inline bool scan_handler(unsigned long entry_offset) { -#ifdef CONFIG_DYNAMIC_FTRACE - static unsigned long ftrace =3D (unsigned long)ftrace_call + 4; + int idx, offset; =20 - if (state->pc =3D=3D ftrace) - state->is_ftrace =3D true; + if (entry_offset >=3D EXCCODE_INT_START * VECSIZE) + return false; + + idx =3D entry_offset / VECSIZE; + offset =3D entry_offset % VECSIZE; + switch (idx) { + case EXCCODE_ADE: + return offset =3D=3D unwind_hint_ade; + case EXCCODE_ALE: + return offset =3D=3D unwind_hint_ale; + case EXCCODE_BP: + return offset =3D=3D unwind_hint_bp; + case EXCCODE_FPE: + return offset =3D=3D unwind_hint_fpe; + case EXCCODE_FPDIS: + return offset =3D=3D unwind_hint_fpu; + case EXCCODE_LSXDIS: + return offset =3D=3D unwind_hint_lsx; + case EXCCODE_LASXDIS: + return offset =3D=3D unwind_hint_lasx; + case EXCCODE_BTDIS: + return offset =3D=3D unwind_hint_lbt; + case EXCCODE_INE: + return offset =3D=3D unwind_hint_ri; + case EXCCODE_WATCH: + return offset =3D=3D unwind_hint_watch; + default: + return false; + } +} + +static inline bool fix_exceptions(unsigned long pc) +{ +#ifdef CONFIG_NUMA + int cpu; + + for_each_possible_cpu(cpu) { + if (!pcpu_handlers[cpu]) + continue; + if (scan_handler(pc - pcpu_handlers[cpu])) + return true; + } #endif + return scan_handler(pc - eentry); +} + +/* + * As we meet ftrace_regs_entry, reset first flag like first doing + * tracing. Prologue analysis will stop soon because PC is at entry. + */ +static inline bool fix_ftrace(unsigned long pc) +{ +#ifdef CONFIG_DYNAMIC_FTRACE + return pc =3D=3D (unsigned long)ftrace_call + LOONGARCH_INSN_SIZE; +#else + return false; +#endif +} + +static inline bool unwind_state_fixup(struct unwind_state *state) +{ + if (!fix_exceptions(state->pc) && !fix_ftrace(state->pc)) + return false; + state->reset =3D true; + return true; } =20 static unsigned long get_return_address(struct unwind_state *state) @@ -46,14 +125,10 @@ static bool unwind_by_prologue(struct unwind_state *st= ate) if (state->sp >=3D info->end || state->sp < info->begin) return false; =20 - if (state->is_ftrace) { - /* - * As we meet ftrace_regs_entry, reset first flag like first doing - * tracing. Prologue analysis will stop soon because PC is at entry. - */ + if (state->reset) { regs =3D (struct pt_regs *)state->sp; state->first =3D true; - state->is_ftrace =3D false; + state->reset =3D false; state->pc =3D regs->csr_era; state->ra =3D regs->regs[1]; state->sp =3D regs->regs[3]; @@ -118,8 +193,7 @@ static bool unwind_by_prologue(struct unwind_state *sta= te) =20 out: state->first =3D false; - unwind_state_fixup(state); - return !!__kernel_text_address(state->pc); + return unwind_state_fixup(state) || __kernel_text_address(state->pc); } =20 static int raw_show_trace; diff --git a/arch/loongarch/mm/tlb.c b/arch/loongarch/mm/tlb.c index da3681f131c8..8bad6b0cff59 100644 --- a/arch/loongarch/mm/tlb.c +++ b/arch/loongarch/mm/tlb.c @@ -251,7 +251,7 @@ static void output_pgtable_bits_defines(void) } =20 #ifdef CONFIG_NUMA -static unsigned long pcpu_handlers[NR_CPUS]; +unsigned long pcpu_handlers[NR_CPUS]; #endif extern long exception_handlers[VECSIZE * 128 / sizeof(long)]; =20 --=20 2.34.3