From mboxrd@z Thu Jan 1 00:00:00 1970 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 61A0CC5518F for ; Tue, 4 Aug 2026 10:37:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-ID:Date:Subject:Cc :To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=AJgTkyNtH5eLOERiyZWg7AzDXIL0tzQf3wmmB0syonY=; b=KXsW/7w+N0Amli Kq45xssxZlQn8lvAgZkYl1wUDc4jgEOzuUZRqq6ncX3FtjlM62pTuu/h3q1lMtb37esTQQ79YtWtB bEAwQaQ2nEVVxldShHvWZjEFno2nXOv7Vc2XCpIMWKOMr5DbItzcVg3D3GgcbDT6Z3uN1IALc12C8 YlZkyPZ975gXAHPiJYc3ccXeQX1rgjidYH6sCqTnRAd8NSlXgxiK6lgn52GCTvOR1/CnouJlUcFu4 tEj+ZcBMptHFzp2VD4ZQZ8T8buTTrzgl+eZrro6mZckWdaoPZMtUXY6bBOzFuZ8yxRhLkD/Fbrz9y UKdSciWwbaCBvLvcmCoA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wrCVt-00000001YR5-0LZy; Tue, 04 Aug 2026 10:36:49 +0000 Received: from out30-97.freemail.mail.aliyun.com ([115.124.30.97]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1wrCVp-00000001YQ4-06w3 for linux-riscv@lists.infradead.org; Tue, 04 Aug 2026 10:36:48 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.alibaba.com; s=default; t=1785839797; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=9qthyqQX/Ih/uUwRYMYrPDP5NZjEf9dKmI4Qn+fFJ20=; b=tM+/C75IuBZJDcN9Atleof6PlYNhQOBN1C69esxVO9hCczfhQ+8Rjs/CYUjxEYEDSYwVTTvndORxJL77dg4Jl2Na59nCFn1WqhNj9Q4FO0kMl0BigkUVzT+riDlGHcbsyxhHIUC54Ml1UZEir0E2/yHLgpXgxKwiLUOgQU7y77M= X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R791e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=maildocker-contentspam033037009110;MF=wanghan@linux.alibaba.com;NM=1;PH=DS;RN=34;SR=0;TI=SMTPD_---0X8NlqWZ_1785839792; Received: from wanghan-Workstation..(mailfrom:wanghan@linux.alibaba.com fp:SMTPD_---0X8NlqWZ_1785839792 cluster:ay36) by smtp.aliyun-inc.com; Tue, 04 Aug 2026 18:36:34 +0800 From: Wang Han To: Paul Walmsley , Palmer Dabbelt , Albert Ou Cc: Alexandre Ghiti , linux-riscv@lists.infradead.org, Oleg Nesterov , Steven Rostedt , Masami Hiramatsu , Mark Rutland , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , James Clark , Josh Poimboeuf , Jiri Kosina , Miroslav Benes , Petr Mladek , Joe Lawrence , Shuah Khan , oliver.yang@linux.alibaba.com, xueshuai@linux.alibaba.com, zhuo.song@linux.alibaba.com, jkchen@linux.alibaba.com, Marcos Paulo de Souza , linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, live-patching@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v5 0/7] riscv: Add reliable stack unwinding for livepatch Date: Tue, 4 Aug 2026 18:36:19 +0800 Message-ID: <20260804103626.2803112-1-wanghan@linux.alibaba.com> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260804_033645_903515_044C2A05 X-CRM114-Status: GOOD ( 18.39 ) X-BeenThere: linux-riscv@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org Hi, This is v5 of the RISC-V reliable stack unwinding series for livepatch. The series adds explicit frame-record metadata, preserves the frame pointer through dynamic ftrace, and replaces the open-coded stack walker with a conservative frame-pointer based unwinder. It then enables the RISC-V livepatch capability and adds the syscall-wrapper selftest prefix. Changes since v4: * Use sizeof(struct frame_record) for STACKFRAME_RECORD_SIZE, as requested by Shuai Xue. * Guard IRQ stack accessors and IRQ stack entries with CONFIG_IRQ_STACKS, addressing the link-time issue reported by Shuai Xue and Sashiko. * Add the corresponding Reviewed-by tag from Shuai Xue to 1/7. * Rebase onto the latest riscv/for-next; no other functional changes. The review replies have been sent in the v4 RESEND thread. Base: riscv/for-next ff492e321c47 ("Revert \"riscv: hwprobe: Fix stale vDSO data for late-initialized keys at boot\"") Previous versions: v4 RESEND: https://lore.kernel.org/r/20260629072713.3273743-1-wanghan@linux.alibaba.com v3: https://lore.kernel.org/r/cover.194d76e3a15b.v3.riscv-livepatch.wanghan@linux.alibaba.com v2: https://lore.kernel.org/r/20260528082310.1994388-1-wanghan@linux.alibaba.com v1: https://lore.kernel.org/r/20260527123530.2593918-1-wanghan@linux.alibaba.com Validation: * Built Linux 7.2.0-rc6 with riscv64-unknown-linux-gnu-gcc 15.2.0 and binutils 2.46. * Standard livepatch configuration built successfully, including Image, vmlinux, modules, compile_commands.json and GDB scripts. * CONFIG_IRQ_STACKS=n variant linked successfully with GCC. * QEMU 8.2.2, 1 CPU: livepatch selftests PASS: 7, SKIP: 1, FAIL: 0; ftrace function graph 3 passed, 0 failed, 3 unsupported. * QEMU 8.2.2, 4 CPUs: livepatch selftests PASS: 7, SKIP: 1, FAIL: 0; ftrace function graph 3 passed, 0 failed, 3 unsupported. * No BUG, WARNING, Oops, panic, unreliable stack or Call Trace found by the validation log scans. Expected negative livepatch errors are part of the selftests. Wang Han (7): riscv: stacktrace: Add frame record metadata riscv: stacktrace: disable KASAN and KCOV instrumentation for stacktrace.o riscv: ftrace: always preserve s0 in dynamic ftrace register frame riscv: stacktrace: introduce stack-bound tracking helpers riscv: stacktrace: switch to frame-pointer based unwinder riscv: Kconfig: enable HAVE_RELIABLE_STACKTRACE and HAVE_LIVEPATCH selftests/livepatch: Add RISC-V syscall wrapper prefix arch/riscv/Kconfig | 4 + arch/riscv/include/asm/ptrace.h | 9 + arch/riscv/include/asm/stacktrace.h | 67 ++- arch/riscv/include/asm/stacktrace/common.h | 159 +++++ arch/riscv/include/asm/stacktrace/frame.h | 53 ++ arch/riscv/kernel/Makefile | 6 + arch/riscv/kernel/asm-offsets.c | 6 + arch/riscv/kernel/entry.S | 39 +- arch/riscv/kernel/ftrace.c | 6 +- arch/riscv/kernel/head.S | 23 + arch/riscv/kernel/mcount-dyn.S | 4 - arch/riscv/kernel/perf_callchain.c | 2 +- arch/riscv/kernel/process.c | 33 +- arch/riscv/kernel/stacktrace.c | 561 +++++++++++++++--- .../livepatch/test_modules/test_klp_syscall.c | 2 + 15 files changed, 868 insertions(+), 106 deletions(-) create mode 100644 arch/riscv/include/asm/stacktrace/common.h create mode 100644 arch/riscv/include/asm/stacktrace/frame.h Range-diff against v4: 1: 8cef363cfed7 ! 1: cbb1dc004d0f riscv: stacktrace: Add frame record metadata @@ Commit message the secondary CPU path sets up s0 before smp_callin() so idle-task unwinding does not inherit an undefined caller frame; * copy_thread creates matching final metadata records for new kernel - and user tasks, and keeps s0 available for the frame-pointer chain; - * call_on_irq_stack still reserves an aligned stack slot, but links the - saved {fp, ra} with the raw frame-record size so s0 points at the - RISC-V frame record rather than past the alignment padding. + and user tasks, and keeps s0 available for the frame-pointer chain. - The call_on_irq_stack adjustment fixes a latent RV32 issue. On RV64, - sizeof(struct stackframe) is equal to the stack alignment, so the old - s0 value happened to point just above the saved {fp, ra}. On RV32, the - raw frame record is 8 bytes while the reserved stack slot is 16-byte - aligned, so the old s0 value pointed into the padding. Using the raw - record size makes s0 point above the saved frame record on both RV32 - and RV64 while still reserving the aligned slot. + Keep the embedded metadata-record field offsets distinct from the + s0-relative STACKFRAME_* offsets used by call_on_irq_stack(), because + the latter describe a frame record relative to s0 rather than to the + record base. These changes keep s0 reserved for the frame-pointer chain at task and - stack-switch boundaries. + exception boundaries. + Reviewed-by: Shuai Xue Signed-off-by: Wang Han ## arch/riscv/include/asm/ptrace.h ## @@ arch/riscv/kernel/asm-offsets.c: void asm_offsets(void) OFFSET(HIBERN_PBE_ADDR, pbe, address); @@ arch/riscv/kernel/asm-offsets.c: void asm_offsets(void) - OFFSET(SBI_HART_BOOT_STACK_PTR_OFFSET, sbi_hart_boot_data, stack_ptr); - DEFINE(STACKFRAME_SIZE_ON_STACK, ALIGN(sizeof(struct stackframe), STACK_ALIGN)); -+ DEFINE(STACKFRAME_RECORD_SIZE, sizeof(struct stackframe)); - OFFSET(STACKFRAME_FP, stackframe, fp); - OFFSET(STACKFRAME_RA, stackframe, ra); + DEFINE(STACKFRAME_FP, offsetof(struct stackframe, fp) - sizeof(struct stackframe)); + DEFINE(STACKFRAME_RA, offsetof(struct stackframe, ra) - sizeof(struct stackframe)); ++ DEFINE(STACKFRAME_RECORD_SIZE, sizeof(struct frame_record)); ++ OFFSET(FRAME_RECORD_FP, frame_record, fp); ++ OFFSET(FRAME_RECORD_RA, frame_record, ra); #ifdef CONFIG_FUNCTION_TRACER + DEFINE(FTRACE_OPS_FUNC, offsetof(struct ftrace_ops, func)); + #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS ## arch/riscv/kernel/entry.S ## @@ @@ arch/riscv/kernel/entry.S: SYM_CODE_START(handle_exception) + * Create a metadata frame record. The unwinder will use this to + * identify and unwind exception boundaries. + */ -+ REG_S zero, (S_STACKFRAME + STACKFRAME_FP)(sp) /* stackframe.record.fp = 0 */ -+ REG_S zero, (S_STACKFRAME + STACKFRAME_RA)(sp) /* stackframe.record.ra = 0 */ ++ REG_S zero, (S_STACKFRAME + FRAME_RECORD_FP)(sp) /* stackframe.record.fp = 0 */ ++ REG_S zero, (S_STACKFRAME + FRAME_RECORD_RA)(sp) /* stackframe.record.ra = 0 */ +#ifdef CONFIG_RISCV_M_MODE + li t0, SR_MPP + and t0, s1, t0 @@ arch/riscv/kernel/entry.S: SYM_CODE_START_LOCAL(handle_kernel_stack_overflow) + * pt_regs boundary and the unwinder can resume from the pre-overflow + * frame pointer saved in PT_S0. + */ -+ REG_S zero, (S_STACKFRAME + STACKFRAME_FP)(sp) -+ REG_S zero, (S_STACKFRAME + STACKFRAME_RA)(sp) ++ REG_S zero, (S_STACKFRAME + FRAME_RECORD_FP)(sp) ++ REG_S zero, (S_STACKFRAME + FRAME_RECORD_RA)(sp) + li t0, FRAME_META_TYPE_PT_REGS + REG_S t0, S_STACKFRAME_TYPE(sp) + addi s0, sp, S_STACKFRAME + STACKFRAME_RECORD_SIZE @@ arch/riscv/kernel/entry.S: ASM_NOKPROBE(handle_kernel_stack_overflow) move a2, sp /* pt_regs */ call ret_from_fork_kernel j ret_from_exception -@@ arch/riscv/kernel/entry.S: SYM_FUNC_START(call_on_irq_stack) - addi sp, sp, -STACKFRAME_SIZE_ON_STACK - REG_S ra, STACKFRAME_RA(sp) - REG_S s0, STACKFRAME_FP(sp) -- addi s0, sp, STACKFRAME_SIZE_ON_STACK -+ addi s0, sp, STACKFRAME_RECORD_SIZE - - /* Switch to the per-CPU shadow call stack */ - scs_save_current -@@ arch/riscv/kernel/entry.S: SYM_FUNC_START(call_on_irq_stack) - scs_load_current - - /* Switch back to the thread stack and restore ra and s0 */ -- addi sp, s0, -STACKFRAME_SIZE_ON_STACK -+ addi sp, s0, -STACKFRAME_RECORD_SIZE - REG_L ra, STACKFRAME_RA(sp) - REG_L s0, STACKFRAME_FP(sp) - addi sp, sp, STACKFRAME_SIZE_ON_STACK ## arch/riscv/kernel/head.S ## @@ @@ arch/riscv/kernel/head.S: SYM_CODE_START(_start_kernel) + * fp/s0 points above the metadata record (RISC-V + * convention). + */ -+ REG_S zero, (S_STACKFRAME + STACKFRAME_FP)(sp) -+ REG_S zero, (S_STACKFRAME + STACKFRAME_RA)(sp) ++ REG_S zero, (S_STACKFRAME + FRAME_RECORD_FP)(sp) ++ REG_S zero, (S_STACKFRAME + FRAME_RECORD_RA)(sp) + li t0, FRAME_META_TYPE_FINAL + REG_S t0, S_STACKFRAME_TYPE(sp) + addi s0, sp, S_STACKFRAME + STACKFRAME_RECORD_SIZE 2: 237864b66d78 = 2: c63daa8759a6 riscv: stacktrace: disable KASAN and KCOV instrumentation for stacktrace.o 3: e6035966a35a = 3: 352269306907 riscv: ftrace: always preserve s0 in dynamic ftrace register frame 4: d132087ea01e ! 4: 2cc86f5728c1 riscv: stacktrace: introduce stack-bound tracking helpers @@ arch/riscv/include/asm/stacktrace.h: extern void notrace walk_stackframe(struct +/* + * IRQ stack accessors + */ ++#ifdef CONFIG_IRQ_STACKS +static inline struct stack_info stackinfo_get_irq(void) +{ + unsigned long low = (unsigned long)raw_cpu_read(irq_stack_ptr); @@ arch/riscv/include/asm/stacktrace.h: extern void notrace walk_stackframe(struct + + return stackinfo_on_stack(&info, sp, size); +} ++#endif /* CONFIG_IRQ_STACKS */ + +/* + * Task stack accessors 5: 02adea3ece82 ! 5: 57c5e7d08cf8 riscv: stacktrace: switch to frame-pointer based unwinder @@ arch/riscv/kernel/stacktrace.c: unsigned long __get_wchan(struct task_struct *ta + struct task_struct *tsk = task ?: current; + struct stack_info stacks[] = { + stackinfo_get_task(tsk), ++#ifdef CONFIG_IRQ_STACKS + STACKINFO_CPU(tsk, irq), ++#endif +#ifdef CONFIG_VMAP_STACK + STACKINFO_CPU(tsk, overflow), +#endif 6: c7d7dbe7a8a1 = 6: 9b3379fe9320 riscv: Kconfig: enable HAVE_RELIABLE_STACKTRACE and HAVE_LIVEPATCH 7: ae94a234b34a < -: ------------ selftests/livepatch: Add RISC-V syscall wrapper prefix -: ------------ > 7: 07dddd25aae1 selftests/livepatch: Add RISC-V syscall wrapper prefix base-commit: ff492e321c477f0c8899ac2b875635a84e928d78 -- 2.43.0 _______________________________________________ linux-riscv mailing list linux-riscv@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-riscv