From nobody Thu Sep 24 15:11:00 2026 Received: from mx.itxnorge.no (itx-kvm-14.itxnorge.no [91.189.121.228]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E611D54CF74; Tue, 22 Sep 2026 13:57:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.189.121.228 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790085444; cv=none; b=pr9ZWJ6VJigUJMytL17WtKhcTPr0e8iWST68N4aCwmoAqWGK6/1bC/9EVrZWMg1W4t791qmtzVFc5+q3yD3whRJWRj2AShPTEg5bEgIA1+cik5kLQn/PDAtounv4N1SkMYOWVtfshd4zWgL5lGSV+J0SvMlJrl1GyJ41movEH7o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790085444; c=relaxed/simple; bh=3C+io7Yq19YmBExI43YBPe/62sja9K3kdCDyE7hhx4Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ehd0xAwrmDxe7LJPKoTR6RpMVDBWaQknttcJeHLuy/NKa2Kl37bJFYTmqUFHH2f66jtLO1m+IZkbeLz/heAR9leL4szAypLkhqCaoH+oWnBmmdcEJXsyauNuk0Fgv2IA/GcXHCL80i1qbc7yB+cNy5i9IOcPO4qkLkNkiBKZ59w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=itx.no; spf=pass smtp.mailfrom=itx.no; dkim=pass (1024-bit key) header.d=itx.no header.i=@itx.no header.b=oLX8Bi+w; arc=none smtp.client-ip=91.189.121.228 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=itx.no Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=itx.no Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=itx.no header.i=@itx.no header.b="oLX8Bi+w" From: Stian Halseth DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=itx.no; s=mx.itx.no; t=1790085435; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=nwfjX7nuhFS4t6Nv0nmF2X/fHblO6tMBdc3Wj6hQel8=; b=oLX8Bi+weS6iRFK9GdWKgG10zw1/6l96sWhbqYitByPNKgFOKflfGyeKtxpPrKlyQXFsNw daLwmS/hG44ehoODz7lZ57mtC4RyTuSIZJVn+22dZXvKAVmcigI/zkL9ptH1l8Ev0PKidE bZpca8nZciXXOozR49HEy8Xxuqd5vZU= To: Peter Zijlstra , Ingo Molnar , Andreas Larsson , "David S. Miller" Cc: Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , James Clark , linux-perf-users@vger.kernel.org, sparclinux@vger.kernel.org, linux-kernel@vger.kernel.org, Stian Halseth Subject: [RFC PATCH 1/2] perf/core: Let an arch prepare the user stack before it is dumped Date: Tue, 22 Sep 2026 15:56:52 +0200 Message-ID: <20260922135653.1622301-2-stian@itx.no> In-Reply-To: <20260922135653.1622301-1-stian@itx.no> References: <20260922135653.1622301-1-stian@itx.no> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" PERF_SAMPLE_STACK_USER copies the user stack as it is in memory, which assumes the whole call chain is there. On sparc the sampled window's %l and %i registers, including the frame pointer and return address an unwinder starts from, may still be in the register file: they only reach the stack when a window spills. perf_callchain_user() already handles this for the callchain by calling flushw_user() first; the user stack dump has no equivalent arch entry point. Add perf_arch_prepare_ustack(), a no-op by default, called from perf_prepare_sample() before the dump size is computed, so an arch can write back whatever part of the user's stack state it still holds in registers. Doing this in the arch PMU interrupt handler would not do: software events such as cpu-clock reach perf_event_overflow() without passing through it. Signed-off-by: Stian Halseth --- include/linux/perf_event.h | 7 +++++++ kernel/events/core.c | 2 ++ 2 files changed, 9 insertions(+) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 5842552294c1..758b98b75346 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1815,6 +1815,13 @@ extern unsigned long perf_instruction_pointer(struct= perf_event *event, #ifndef perf_arch_bpf_user_pt_regs # define perf_arch_bpf_user_pt_regs(regs) regs #endif +/* + * Called before the user stack of the current task is dumped, for an arch + * that still holds part of the user's stack state in registers. + */ +#ifndef perf_arch_prepare_ustack +static inline void perf_arch_prepare_ustack(void) { } +#endif =20 #ifndef perf_arch_guest_misc_flags static inline unsigned long perf_arch_guest_misc_flags(struct pt_regs *reg= s) diff --git a/kernel/events/core.c b/kernel/events/core.c index db7b76d6b68a..90fb35c7d279 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -8718,6 +8718,8 @@ void perf_prepare_sample(struct perf_sample_data *dat= a, u16 header_size =3D perf_sample_data_size(data, event); u16 size =3D sizeof(u64); =20 + if (data->regs_user.regs) + perf_arch_prepare_ustack(); stack_size =3D perf_sample_ustack_size(stack_size, header_size, data->regs_user.regs); =20 --=20 2.55.0 From nobody Thu Sep 24 15:11:00 2026 Received: from mx.itxnorge.no (itx-kvm-14.itxnorge.no [91.189.121.228]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DE9A554936E; Tue, 22 Sep 2026 13:57:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.189.121.228 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790085446; cv=none; b=Lp/6IKzzAGEpy8tWYRdwSvcJjn/oVqYsRSy4BFObECwd5skxCfQI/XXD6iCwfBdMT00RAdP3rNJotq/q+WGBDXlwrdoaMRnmavLZdnuWJQ/zo+IyNSK2v1iThJDyBg8tmRcAJQiMN7HeWS4O3wVhKXs0gUiKIt6R1a08JphThCA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790085446; c=relaxed/simple; bh=pN/M8AdJGfApBsIjohsqKZc+u7W0H3nuc7qL18S2QCw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=riPJyKIZ3GYq2iRwYp4x5s88/15ogywCdrtvke2BpEUbgUVGZXDQMhWefljFSvd78F7zJvTu+ioN0hw4UcmKQV7C8IM7t95RJdLyr79V/vxzBYJjVEPlUECxMGxVIBnp2ktRhmYEubwIi2D5V/61wcnZbv82ouAsxWGPYT7HV+4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=itx.no; spf=pass smtp.mailfrom=itx.no; dkim=pass (1024-bit key) header.d=itx.no header.i=@itx.no header.b=DE+bxE3Y; arc=none smtp.client-ip=91.189.121.228 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=itx.no Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=itx.no Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=itx.no header.i=@itx.no header.b="DE+bxE3Y" From: Stian Halseth DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=itx.no; s=mx.itx.no; t=1790085436; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4PsXtLsCdtkC02MuBzxmxbitWNwPTeetSeVoh7aihcE=; b=DE+bxE3Y8ObbpBY+xv0grmMMkKqIR6J2HRqDDie1LUj09UydY6Lpy0BbBjLjuxvB4FkzGC PSb7mznBGG+EmmdgetOTpCkXXrt4r6BKp106wl6EGmWF7IRn2O+BPEEKutkilpRJ07pTtD VO9EdZ59gZTo9yT7Kg09cUCzuEYzmlo= To: Peter Zijlstra , Ingo Molnar , Andreas Larsson , "David S. Miller" Cc: Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , James Clark , linux-perf-users@vger.kernel.org, sparclinux@vger.kernel.org, linux-kernel@vger.kernel.org, Stian Halseth Subject: [RFC PATCH 2/2] sparc64: Support PERF_SAMPLE_REGS_USER and PERF_SAMPLE_STACK_USER Date: Tue, 22 Sep 2026 15:56:53 +0200 Message-ID: <20260922135653.1622301-3-stian@itx.no> In-Reply-To: <20260922135653.1622301-1-stian@itx.no> References: <20260922135653.1622301-1-stian@itx.no> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Select HAVE_PERF_REGS and HAVE_PERF_USER_STACK_DUMP and add the perf_regs implementation. The exposed registers mirror struct pt_regs: %g0-%g7, %o0-%o7 (named from the user's point of view; pt_regs calls them UREG_I*), %tstate, PC, NPC and %y. %o6 is reported as held in the register, i.e. with the 2047 stack bias for a 64-bit task, the same as ptrace and user_stack_pointer(). Values of a 32-bit task are truncated to 32 bits as genregs32_get() does, since the hardware does not zero-extend them. perf_arch_prepare_ustack() flushes the user register windows so the sampled window's %l and %i registers are in the dumped stack, where a DWARF unwinder needs them: the CFI of a function after `save` defines the CFA in terms of %i6. This makes perf record --call-graph dwarf and eu-stackprof usable on sparc64. Signed-off-by: Stian Halseth --- arch/sparc/Kconfig | 2 + arch/sparc/include/asm/perf_event.h | 3 ++ arch/sparc/include/uapi/asm/perf_regs.h | 33 +++++++++++++ arch/sparc/kernel/Makefile | 2 +- arch/sparc/kernel/perf_regs.c | 65 +++++++++++++++++++++++++ 5 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 arch/sparc/include/uapi/asm/perf_regs.h create mode 100644 arch/sparc/kernel/perf_regs.c diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index ab77d3f2536e..9d7f575f359d 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -93,6 +93,8 @@ config SPARC64 select RTC_DRV_SUN4V select RTC_DRV_STARFIRE select HAVE_PERF_EVENTS + select HAVE_PERF_REGS + select HAVE_PERF_USER_STACK_DUMP select PERF_USE_VMALLOC select ARCH_HAVE_NMI_SAFE_CMPXCHG select HAVE_C_RECORDMCOUNT diff --git a/arch/sparc/include/asm/perf_event.h b/arch/sparc/include/asm/p= erf_event.h index c2aec0c7f4f5..03f1ab1618b9 100644 --- a/arch/sparc/include/asm/perf_event.h +++ b/arch/sparc/include/asm/perf_event.h @@ -25,6 +25,9 @@ do { \ (regs)->u_regs[UREG_I6] =3D _fp; \ (regs)->u_regs[UREG_I7] =3D _i7; \ } while (0) + +void perf_arch_prepare_ustack(void); +#define perf_arch_prepare_ustack perf_arch_prepare_ustack #endif =20 #endif diff --git a/arch/sparc/include/uapi/asm/perf_regs.h b/arch/sparc/include/u= api/asm/perf_regs.h new file mode 100644 index 000000000000..17f14335d6c0 --- /dev/null +++ b/arch/sparc/include/uapi/asm/perf_regs.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_ASM_SPARC_PERF_REGS_H +#define _UAPI_ASM_SPARC_PERF_REGS_H + +/* + * Mirrors struct pt_regs. O6 is %sp as held in the register, i.e. biased + * by 2047 for a 64-bit task. + */ +enum perf_event_sparc_regs { + PERF_REG_SPARC_G0, + PERF_REG_SPARC_G1, + PERF_REG_SPARC_G2, + PERF_REG_SPARC_G3, + PERF_REG_SPARC_G4, + PERF_REG_SPARC_G5, + PERF_REG_SPARC_G6, + PERF_REG_SPARC_G7, + PERF_REG_SPARC_O0, + PERF_REG_SPARC_O1, + PERF_REG_SPARC_O2, + PERF_REG_SPARC_O3, + PERF_REG_SPARC_O4, + PERF_REG_SPARC_O5, + PERF_REG_SPARC_O6, + PERF_REG_SPARC_O7, + PERF_REG_SPARC_TSTATE, + PERF_REG_SPARC_PC, + PERF_REG_SPARC_NPC, + PERF_REG_SPARC_Y, + PERF_REG_SPARC_MAX +}; + +#endif /* _UAPI_ASM_SPARC_PERF_REGS_H */ diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 497b5714fa8f..a3dd92247c3b 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -113,7 +113,7 @@ obj-$(CONFIG_AUDIT) +=3D audit.o audit--$(CONFIG_AUDIT) :=3D compat_audit.o obj-$(CONFIG_COMPAT) +=3D $(audit--y) =20 -pc--$(CONFIG_PERF_EVENTS) :=3D perf_event.o +pc--$(CONFIG_PERF_EVENTS) :=3D perf_event.o perf_regs.o obj-$(CONFIG_SPARC64) +=3D $(pc--y) =20 obj-$(CONFIG_UPROBES) +=3D uprobes.o diff --git a/arch/sparc/kernel/perf_regs.c b/arch/sparc/kernel/perf_regs.c new file mode 100644 index 000000000000..644a0a11cb90 --- /dev/null +++ b/arch/sparc/kernel/perf_regs.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include + +u64 perf_reg_value(struct pt_regs *regs, int idx) +{ + u64 val; + + switch (idx) { + case PERF_REG_SPARC_G0 ... PERF_REG_SPARC_O7: + val =3D regs->u_regs[idx]; + break; + case PERF_REG_SPARC_TSTATE: + return regs->tstate; + case PERF_REG_SPARC_PC: + val =3D regs->tpc; + break; + case PERF_REG_SPARC_NPC: + val =3D regs->tnpc; + break; + case PERF_REG_SPARC_Y: + return regs->y; + default: + WARN_ON_ONCE(1); + return 0; + } + + if (test_thread_flag(TIF_32BIT)) + val =3D (u32)val; + + return val; +} + +#define REG_RESERVED (~((1ULL << PERF_REG_SPARC_MAX) - 1)) + +int perf_reg_validate(u64 mask) +{ + if (!mask || mask & REG_RESERVED) + return -EINVAL; + + return 0; +} + +u64 perf_reg_abi(struct task_struct *task) +{ + if (test_tsk_thread_flag(task, TIF_32BIT)) + return PERF_SAMPLE_REGS_ABI_32; + + return PERF_SAMPLE_REGS_ABI_64; +} + +void perf_get_regs_user(struct perf_regs *regs_user, + struct pt_regs *regs) +{ + regs_user->regs =3D task_pt_regs(current); + regs_user->abi =3D perf_reg_abi(current); +} + +void perf_arch_prepare_ustack(void) +{ + flushw_user(); +} --=20 2.55.0