* [PATCH v3 1/5] alpha: fix stale user_stack_pointer()
2026-10-18 14:22 [PATCH v3 0/5] alpha: perf register sampling and user stack dumps Matt Turner
@ 2026-10-18 14:22 ` Matt Turner
2026-10-18 14:22 ` [PATCH v3 2/5] alpha: stop storing the user stack pointer in pt_regs Matt Turner
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Matt Turner @ 2026-10-18 14:22 UTC (permalink / raw)
To: Richard Henderson, Magnus Lindholm
Cc: linux-alpha, linux-kernel, linux-doc, linux-perf-users,
Ian Rogers, Matt Turner
PALcode keeps the user stack pointer in the PCB, not the trap frame, so
pt_regs->usp is only valid where entry code stores it: entSys,
do_entArith() and do_entIF(). Interrupts, page faults and unaligned
traps leave it stale, and ptrace and /proc/<pid>/syscall read it
through user_stack_pointer().
A user-mode pt_regs is at the top of its task's stack, so find the
thread_info from it and use rdusp() for current or pcb.usp otherwise,
as KSTK_ESP() and the regset code already do.
Fixes: 8a2857bc2b30 ("alpha: enable regset-based ptrace and core dumps")
Assisted-by: Claude:claude-opus-5-5
Reviewed-by: Magnus Lindholm <linmag7@gmail.com>
Tested-by: Magnus Lindholm <linmag7@gmail.com>
Acked-by: Ian Rogers <irogers@google.com>
Signed-off-by: Matt Turner <mattst88@gmail.com>
---
arch/alpha/include/asm/ptrace.h | 7 +------
arch/alpha/kernel/ptrace.c | 12 ++++++++++++
2 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/arch/alpha/include/asm/ptrace.h b/arch/alpha/include/asm/ptrace.h
index 430e8dc27ff7..45d1229344b6 100644
--- a/arch/alpha/include/asm/ptrace.h
+++ b/arch/alpha/include/asm/ptrace.h
@@ -26,12 +26,7 @@ static inline unsigned long regs_return_value(struct pt_regs *regs)
return regs->r0;
}
-/* Helpers for working with the user stack pointer */
-static inline unsigned long user_stack_pointer(struct pt_regs *regs)
-{
- /* Valid for user-mode regs */
- return regs->usp;
-}
+unsigned long user_stack_pointer(struct pt_regs *regs);
static __always_inline bool regs_irqs_disabled(struct pt_regs *regs)
{
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index e1d8c2f69688..dba7e9905cfa 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -440,6 +440,18 @@ ptrace_cancel_bpt(struct task_struct * child)
return (nsaved != 0);
}
+/*
+ * PALcode keeps the user stack pointer in the PCB, not the trap frame.
+ * A user-mode pt_regs sits at the top of its task's stack, so the
+ * thread_info is at the base.
+ */
+unsigned long user_stack_pointer(struct pt_regs *regs)
+{
+ struct thread_info *ti = (void *)((unsigned long)regs & -THREAD_SIZE);
+
+ return ti == current_thread_info() ? rdusp() : ti->pcb.usp;
+}
+
void user_enable_single_step(struct task_struct *child)
{
/* Mark single stepping. */
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v3 2/5] alpha: stop storing the user stack pointer in pt_regs
2026-10-18 14:22 [PATCH v3 0/5] alpha: perf register sampling and user stack dumps Matt Turner
2026-10-18 14:22 ` [PATCH v3 1/5] alpha: fix stale user_stack_pointer() Matt Turner
@ 2026-10-18 14:22 ` Matt Turner
2026-10-18 14:22 ` [PATCH v3 3/5] alpha: use user_stack_pointer() in KSTK_ESP() and dump_elf_thread() Matt Turner
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Matt Turner @ 2026-10-18 14:22 UTC (permalink / raw)
To: Richard Henderson, Magnus Lindholm
Cc: linux-alpha, linux-kernel, linux-doc, linux-perf-users,
Ian Rogers, Matt Turner
Nothing reads pt_regs->usp now that user_stack_pointer() uses the PCB.
Drop the stores, which saves a PAL_rdusp call on every syscall, and
give the field back its old name.
Assisted-by: Claude:claude-opus-5-5
Reviewed-by: Magnus Lindholm <linmag7@gmail.com>
Tested-by: Magnus Lindholm <linmag7@gmail.com>
Acked-by: Ian Rogers <irogers@google.com>
Signed-off-by: Matt Turner <mattst88@gmail.com>
---
arch/alpha/include/uapi/asm/ptrace.h | 2 +-
arch/alpha/kernel/asm-offsets.c | 1 -
arch/alpha/kernel/entry.S | 5 -----
arch/alpha/kernel/traps.c | 8 --------
4 files changed, 1 insertion(+), 15 deletions(-)
diff --git a/arch/alpha/include/uapi/asm/ptrace.h b/arch/alpha/include/uapi/asm/ptrace.h
index 9d86b2a1526e..72ed913a910f 100644
--- a/arch/alpha/include/uapi/asm/ptrace.h
+++ b/arch/alpha/include/uapi/asm/ptrace.h
@@ -43,7 +43,7 @@ struct pt_regs {
unsigned long trap_a1;
unsigned long trap_a2;
/* This makes the stack 16-byte aligned as GCC expects */
- unsigned long usp;
+ unsigned long __pad0;
/* These are saved by PAL-code: */
unsigned long ps;
unsigned long pc;
diff --git a/arch/alpha/kernel/asm-offsets.c b/arch/alpha/kernel/asm-offsets.c
index c89792c86044..22ed3c975b1c 100644
--- a/arch/alpha/kernel/asm-offsets.c
+++ b/arch/alpha/kernel/asm-offsets.c
@@ -30,7 +30,6 @@ static void __used foo(void)
DEFINE(HAE_CACHE, offsetof(struct alpha_machine_vector, hae_cache));
DEFINE(HAE_REG, offsetof(struct alpha_machine_vector, hae_register));
- DEFINE(PT_REGS_USP, offsetof(struct pt_regs, usp));
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
DEFINE(TI_SYSCALL_WORK, offsetof(struct thread_info, syscall_work));
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index bfa116d455fb..790389a15c3c 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -476,11 +476,6 @@ entSys:
ldq $1, 0($sp) /* syscall nr from saved r0 */
stq $1, 8($sp) /* regs->r1 = shadow syscall nr */
- mov $0, $8
- call_pal PAL_rdusp
- stq $0, PT_REGS_USP($sp)
- mov $8, $0
-
lda $8, 0x3fff
bic $sp, $8, $8
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index cfaef96c4ce8..5882c65b7ef1 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -30,12 +30,6 @@
#include "proto.h"
-static __always_inline void alpha_snapshot_usp(struct pt_regs *regs)
-{
- if (user_mode(regs))
- regs->usp = rdusp();
-}
-
void
dik_show_regs(struct pt_regs *regs, unsigned long *r9_15)
{
@@ -186,7 +180,6 @@ do_entArith(unsigned long summary, unsigned long write_mask,
{
long si_code = FPE_FLTINV;
- alpha_snapshot_usp(regs);
if (summary & 1) {
/* Software-completion summary bit is set, so try to
emulate the instruction. If the processor supports
@@ -208,7 +201,6 @@ do_entIF(unsigned long type, struct pt_regs *regs)
{
int signo, code;
- alpha_snapshot_usp(regs);
if (type == 3) { /* FEN fault */
/* Irritating users can call PAL_clrfen to disable the
FPU for the process. The kernel will then trap in
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v3 3/5] alpha: use user_stack_pointer() in KSTK_ESP() and dump_elf_thread()
2026-10-18 14:22 [PATCH v3 0/5] alpha: perf register sampling and user stack dumps Matt Turner
2026-10-18 14:22 ` [PATCH v3 1/5] alpha: fix stale user_stack_pointer() Matt Turner
2026-10-18 14:22 ` [PATCH v3 2/5] alpha: stop storing the user stack pointer in pt_regs Matt Turner
@ 2026-10-18 14:22 ` Matt Turner
2026-10-18 14:22 ` [PATCH v3 4/5] alpha: add HAVE_PERF_REGS and HAVE_PERF_USER_STACK_DUMP support Matt Turner
2026-10-18 14:22 ` [PATCH v3 5/5] alpha: fill in pc for software event samples Matt Turner
4 siblings, 0 replies; 8+ messages in thread
From: Matt Turner @ 2026-10-18 14:22 UTC (permalink / raw)
To: Richard Henderson, Magnus Lindholm
Cc: linux-alpha, linux-kernel, linux-doc, linux-perf-users,
Ian Rogers, Matt Turner
Both open-code the same PCB lookup.
Assisted-by: Claude:claude-opus-5-5
Tested-by: Magnus Lindholm <linmag7@gmail.com>
Reviewed-by: Magnus Lindholm <linmag7@gmail.com>
Acked-by: Ian Rogers <irogers@google.com>
Signed-off-by: Matt Turner <mattst88@gmail.com>
---
arch/alpha/include/asm/processor.h | 3 +--
arch/alpha/kernel/process.c | 2 +-
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/arch/alpha/include/asm/processor.h b/arch/alpha/include/asm/processor.h
index c461a26d47b3..73251cd671e0 100644
--- a/arch/alpha/include/asm/processor.h
+++ b/arch/alpha/include/asm/processor.h
@@ -43,8 +43,7 @@ unsigned long __get_wchan(struct task_struct *p);
#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc)
-#define KSTK_ESP(tsk) \
- ((tsk) == current ? rdusp() : task_thread_info(tsk)->pcb.usp)
+#define KSTK_ESP(tsk) user_stack_pointer(task_pt_regs(tsk))
#define cpu_relax() barrier()
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 06522451f018..7861c9e767b7 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -318,7 +318,7 @@ dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt, struct thread_info *ti)
dest[27] = pt->r27;
dest[28] = pt->r28;
dest[29] = pt->gp;
- dest[30] = ti == current_thread_info() ? rdusp() : ti->pcb.usp;
+ dest[30] = user_stack_pointer(pt);
dest[31] = pt->pc;
/* Once upon a time this was the PS value. Which is stupid
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 4/5] alpha: add HAVE_PERF_REGS and HAVE_PERF_USER_STACK_DUMP support
2026-10-18 14:22 [PATCH v3 0/5] alpha: perf register sampling and user stack dumps Matt Turner
` (2 preceding siblings ...)
2026-10-18 14:22 ` [PATCH v3 3/5] alpha: use user_stack_pointer() in KSTK_ESP() and dump_elf_thread() Matt Turner
@ 2026-10-18 14:22 ` Matt Turner
2026-10-26 0:44 ` Jan-Benedict Glaw
2026-10-18 14:22 ` [PATCH v3 5/5] alpha: fill in pc for software event samples Matt Turner
4 siblings, 1 reply; 8+ messages in thread
From: Matt Turner @ 2026-10-18 14:22 UTC (permalink / raw)
To: Richard Henderson, Magnus Lindholm
Cc: linux-alpha, linux-kernel, linux-doc, linux-perf-users,
Ian Rogers, Matt Turner
Let perf sample registers and dump the user stack, which is what the
perf tool needs for --call-graph dwarf.
The register indices follow the hardware numbering, so r0-r30 map
directly to DWARF register numbers, with pc after them. r9-r15
are callee-saved and live in switch_stack rather than pt_regs, so they
cannot be sampled. Without r15 an unwinder cannot recover the CFA of a
first frame that uses $15 as its frame pointer.
sp is not in pt_regs either: for user frames it comes from
user_stack_pointer(), and for kernel frames (PERF_SAMPLE_REGS_INTR) it
is the end of the trap frame, as in stacktrace.c.
Software events such as context switches and tracepoints hand perf a
per-CPU pt_regs filled in by perf_fetch_caller_regs() instead of a
trap frame. It is not on the stack and has no room for sp, so report
sp as 0 there rather than the address of the per-CPU buffer.
Assisted-by: Claude:claude-opus-5-5
Acked-by: Ian Rogers <irogers@google.com>
Tested-by: Magnus Lindholm <linmag7@gmail.com>
Reviewed-by: Magnus Lindholm <linmag7@gmail.com>
Signed-off-by: Matt Turner <mattst88@gmail.com>
---
.../features/perf/perf-regs/arch-support.txt | 2 +-
.../features/perf/perf-stackdump/arch-support.txt | 2 +-
arch/alpha/Kconfig | 2 +
arch/alpha/include/uapi/asm/perf_regs.h | 45 +++++++++++++++
arch/alpha/kernel/Makefile | 1 +
arch/alpha/kernel/perf_regs.c | 64 ++++++++++++++++++++++
6 files changed, 114 insertions(+), 2 deletions(-)
diff --git a/Documentation/features/perf/perf-regs/arch-support.txt b/Documentation/features/perf/perf-regs/arch-support.txt
index 4c9a5a012075..7d736d678fd4 100644
--- a/Documentation/features/perf/perf-regs/arch-support.txt
+++ b/Documentation/features/perf/perf-regs/arch-support.txt
@@ -6,7 +6,7 @@
-----------------------
| arch |status|
-----------------------
- | alpha: | TODO |
+ | alpha: | ok |
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
diff --git a/Documentation/features/perf/perf-stackdump/arch-support.txt b/Documentation/features/perf/perf-stackdump/arch-support.txt
index dd362b5cb638..17b84ea7769d 100644
--- a/Documentation/features/perf/perf-stackdump/arch-support.txt
+++ b/Documentation/features/perf/perf-stackdump/arch-support.txt
@@ -6,7 +6,7 @@
-----------------------
| arch |status|
-----------------------
- | alpha: | TODO |
+ | alpha: | ok |
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index b2c359b947f6..8fafbfabd1e5 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -41,6 +41,8 @@ config ALPHA
select HAVE_PAGE_SIZE_8KB
select HAVE_PCSPKR_PLATFORM
select HAVE_PERF_EVENTS
+ select HAVE_PERF_REGS
+ select HAVE_PERF_USER_STACK_DUMP
select NEED_DMA_MAP_STATE
select NEED_SG_DMA_LENGTH
select GENERIC_IRQ_PROBE
diff --git a/arch/alpha/include/uapi/asm/perf_regs.h b/arch/alpha/include/uapi/asm/perf_regs.h
new file mode 100644
index 000000000000..b6d2dcf6e184
--- /dev/null
+++ b/arch/alpha/include/uapi/asm/perf_regs.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _ASM_ALPHA_PERF_REGS_H
+#define _ASM_ALPHA_PERF_REGS_H
+
+/*
+ * Indices 0-30 match the hardware (and DWARF) register numbers.
+ * r9-r15 are not saved in pt_regs and cannot be sampled.
+ */
+enum perf_event_alpha_regs {
+ PERF_REG_ALPHA_R0,
+ PERF_REG_ALPHA_R1,
+ PERF_REG_ALPHA_R2,
+ PERF_REG_ALPHA_R3,
+ PERF_REG_ALPHA_R4,
+ PERF_REG_ALPHA_R5,
+ PERF_REG_ALPHA_R6,
+ PERF_REG_ALPHA_R7,
+ PERF_REG_ALPHA_R8,
+ PERF_REG_ALPHA_R9,
+ PERF_REG_ALPHA_R10,
+ PERF_REG_ALPHA_R11,
+ PERF_REG_ALPHA_R12,
+ PERF_REG_ALPHA_R13,
+ PERF_REG_ALPHA_R14,
+ PERF_REG_ALPHA_R15,
+ PERF_REG_ALPHA_R16,
+ PERF_REG_ALPHA_R17,
+ PERF_REG_ALPHA_R18,
+ PERF_REG_ALPHA_R19,
+ PERF_REG_ALPHA_R20,
+ PERF_REG_ALPHA_R21,
+ PERF_REG_ALPHA_R22,
+ PERF_REG_ALPHA_R23,
+ PERF_REG_ALPHA_R24,
+ PERF_REG_ALPHA_R25,
+ PERF_REG_ALPHA_R26,
+ PERF_REG_ALPHA_R27,
+ PERF_REG_ALPHA_R28,
+ PERF_REG_ALPHA_GP,
+ PERF_REG_ALPHA_SP,
+ PERF_REG_ALPHA_PC,
+ PERF_REG_ALPHA_MAX,
+};
+
+#endif /* _ASM_ALPHA_PERF_REGS_H */
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index 4ea5c189e60e..0c04b89676ed 100644
--- a/arch/alpha/kernel/Makefile
+++ b/arch/alpha/kernel/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_PCI) += pci.o pci_iommu.o pci-sysfs.o
obj-$(CONFIG_SRM_ENV) += srm_env.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_PERF_EVENTS) += perf_event.o
+obj-$(CONFIG_HAVE_PERF_REGS) += perf_regs.o
obj-$(CONFIG_RTC_DRV_ALPHA) += rtc.o
obj-$(CONFIG_AUDIT) += audit.o
diff --git a/arch/alpha/kernel/perf_regs.c b/arch/alpha/kernel/perf_regs.c
new file mode 100644
index 000000000000..33ea2e831ba0
--- /dev/null
+++ b/arch/alpha/kernel/perf_regs.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bits.h>
+#include <linux/perf_event.h>
+#include <linux/sched/task_stack.h>
+#include <asm/perf_regs.h>
+
+#define REG(idx, field) \
+ [PERF_REG_ALPHA_##idx] = offsetof(struct pt_regs, field)
+
+#define REG_RESERVED (~GENMASK_ULL(PERF_REG_ALPHA_MAX - 1, 0) | \
+ GENMASK_ULL(PERF_REG_ALPHA_R15, PERF_REG_ALPHA_R9))
+
+static const unsigned int pt_regs_offset[PERF_REG_ALPHA_MAX] = {
+ REG(R0, r0), REG(R1, r1), REG(R2, r2), REG(R3, r3),
+ REG(R4, r4), REG(R5, r5), REG(R6, r6), REG(R7, r7),
+ REG(R8, r8), REG(R16, r16), REG(R17, r17), REG(R18, r18),
+ REG(R19, r19), REG(R20, r20), REG(R21, r21), REG(R22, r22),
+ REG(R23, r23), REG(R24, r24), REG(R25, r25), REG(R26, r26),
+ REG(R27, r27), REG(R28, r28), REG(GP, gp), REG(PC, pc),
+};
+
+u64 perf_reg_value(struct pt_regs *regs, int idx)
+{
+ if (idx == PERF_REG_ALPHA_SP) {
+ if (user_mode(regs))
+ return user_stack_pointer(regs);
+ /*
+ * Software events built by perf_fetch_caller_regs() use a
+ * per-CPU pt_regs rather than a trap frame, and pt_regs has
+ * nowhere to record sp, so report none.
+ */
+ if (!object_is_on_stack(regs))
+ return 0;
+ /* Same kernel sp approximation as stacktrace.c. */
+ return (unsigned long)(regs + 1);
+ }
+
+ if (WARN_ON_ONCE((u32)idx >= PERF_REG_ALPHA_MAX ||
+ BIT_ULL(idx) & REG_RESERVED))
+ return 0;
+
+ return *(unsigned long *)((void *)regs + pt_regs_offset[idx]);
+}
+
+int perf_reg_validate(u64 mask)
+{
+ if (!mask || mask & REG_RESERVED)
+ return -EINVAL;
+
+ return 0;
+}
+
+u64 perf_reg_abi(struct task_struct *task)
+{
+ return PERF_SAMPLE_REGS_ABI_64;
+}
+
+void perf_get_regs_user(struct perf_regs *regs_user,
+ struct pt_regs *regs)
+{
+ regs_user->regs = task_pt_regs(current);
+ regs_user->abi = perf_reg_abi(current);
+}
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH v3 4/5] alpha: add HAVE_PERF_REGS and HAVE_PERF_USER_STACK_DUMP support
2026-10-18 14:22 ` [PATCH v3 4/5] alpha: add HAVE_PERF_REGS and HAVE_PERF_USER_STACK_DUMP support Matt Turner
@ 2026-10-26 0:44 ` Jan-Benedict Glaw
0 siblings, 0 replies; 8+ messages in thread
From: Jan-Benedict Glaw @ 2026-10-26 0:44 UTC (permalink / raw)
To: Matt Turner
Cc: Richard Henderson, Magnus Lindholm, linux-alpha, linux-kernel,
linux-doc, linux-perf-users, Ian Rogers
[-- Attachment #1: Type: text/plain, Size: 3708 bytes --]
Hi,
On Sun, 2026-10-18 10:22:04 -0400, Matt Turner <mattst88@gmail.com> wrote:
> Let perf sample registers and dump the user stack, which is what the
> perf tool needs for --call-graph dwarf.
After this patch series, it conflicts with previous upstream changes:
[…]
> diff --git a/arch/alpha/kernel/perf_regs.c b/arch/alpha/kernel/perf_regs.c
> new file mode 100644
> index 000000000000..33ea2e831ba0
> --- /dev/null
> +++ b/arch/alpha/kernel/perf_regs.c
> @@ -0,0 +1,64 @@
[…]
> +int perf_reg_validate(u64 mask)
> +{
> + if (!mask || mask & REG_RESERVED)
> + return -EINVAL;
> +
> + return 0;
> +}
[…]
# CC arch/alpha/kernel/perf_regs.o
alpha-linux-gcc -Wp,-MMD,arch/alpha/kernel/.perf_regs.o.d -nostdinc -I./arch/alpha/include -I./arch/alpha/include/generated -I./include -I./include -I./arch/alpha/include/uapi -I./arch/alpha/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/compiler-version.h -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -fshort-wchar -funsigned-char -fno-common -fno-PIE -fno-strict-aliasing -std=gnu11 -fms-extensions -pipe -mno-fp-regs -ffixed-8 -fno-jump-tables -mcpu=ev56 -mtune=ev6 -Wa,-mev6 -fno-delete-null-pointer-checks -O2 -fno-allow-store-data-races -fno-stack-protector -fno-omit-frame-pointer -fno-optimize-sibling-calls -ftrivial-auto-var-init=zero -fzero-init-padding-bits=all -fno-stack-clash-protection -fdiagnostics-show-context=2 -fstrict-flex-arrays=3 -fno-strict-overflow -fno-stack-check -fconserve-stack -fno-builtin-wcslen -Wall -Wextra -Wundef -Werror=implicit-function-declaration -Werror=implicit-int -Werror=return-type -Werror=strict-prototypes -Wno-format-security -Wno-trigraphs -Wno-frame-address -Wno-address-of-packed-member -Wmissing-declarations -Wmissing-prototypes -Wframe-larger-than=2048 -Wno-main -Wno-type-limits -Wno-dangling-pointer -Wvla-larger-than=1 -Wno-pointer-sign -Wcast-function-type -Wno-unterminated-string-initialization -Wno-array-bounds -Wno-stringop-overflow -Wno-alloc-size-larger-than -Wimplicit-fallthrough=5 -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -Wenum-conversion -Wunused -Wno-unused-but-set-variable -Wno-unused-const-variable -Wno-packed-not-aligned -Wno-format-overflow -Wno-format-truncation -Wno-stringop-truncation -Wno-override-init -Wno-missing-field-initializers -Wno-shift-negative-value -Wno-maybe-uninitialized -Wno-sign-compare -Wno-unused-parameter -g -Wno-sign-compare -DKBUILD_MODFILE='"arch/alpha/kernel/perf_regs"' -DKBUILD_BASENAME='"perf_regs"' -DKBUILD_MODNAME='"perf_regs"' -D__KBUILD_MODNAME=perf_regs -c -o arch/alpha/kernel/perf_regs.o arch/alpha/kernel/perf_regs.c
arch/alpha/kernel/perf_regs.c:46:5: error: conflicting types for 'perf_reg_validate'; have 'int(u64)' {aka 'int(long long unsigned int)'}
46 | int perf_reg_validate(u64 mask)
| ^~~~~~~~~~~~~~~~~
In file included from ./include/linux/perf_event.h:50,
from arch/alpha/kernel/perf_regs.c:4:
./include/linux/perf_regs.h:13:5: note: previous declaration of 'perf_reg_validate' with type 'int(u64, bool)' {aka 'int(long long unsigned int, _Bool)'}
13 | int perf_reg_validate(u64 mask, bool simd_enabled);
| ^~~~~~~~~~~~~~~~~
make[4]: *** [scripts/Makefile.build:290: arch/alpha/kernel/perf_regs.o] Error 1
make[3]: *** [scripts/Makefile.build:551: arch/alpha/kernel] Error 2
make[2]: *** [scripts/Makefile.build:551: arch/alpha] Error 2
make[1]: *** [/home/jenkins/workspace/linux-alpha-alpha-defconfig___3/linux/Makefile:2229: .] Error 2
make: *** [Makefile:248: __sub-make] Error 2
MfG, JBG
--
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 5/5] alpha: fill in pc for software event samples
2026-10-18 14:22 [PATCH v3 0/5] alpha: perf register sampling and user stack dumps Matt Turner
` (3 preceding siblings ...)
2026-10-18 14:22 ` [PATCH v3 4/5] alpha: add HAVE_PERF_REGS and HAVE_PERF_USER_STACK_DUMP support Matt Turner
@ 2026-10-18 14:22 ` Matt Turner
2026-10-18 17:50 ` Magnus Lindholm
4 siblings, 1 reply; 8+ messages in thread
From: Matt Turner @ 2026-10-18 14:22 UTC (permalink / raw)
To: Richard Henderson, Magnus Lindholm
Cc: linux-alpha, linux-kernel, linux-doc, linux-perf-users,
Ian Rogers, Matt Turner
Context switch and tracepoint events have no trap frame, so perf builds
one with perf_fetch_caller_regs(). Alpha does not define
perf_arch_fetch_caller_regs(), which leaves that pt_regs zeroed, and
these samples report pc as 0.
Record the caller's address as pc. The zero ps already marks the frame
as kernel mode, and pt_regs has nowhere to keep sp, so pc is all that
can be filled in.
perf_fetch_caller_regs() gets that address from CALLER_ADDR0, which
alpha defines as 0 when CONFIG_FRAME_POINTER is disabled. Finding the
level zero return address does not need a frame pointer, so make
alpha_ftrace_return_address0() available in both configurations. Only
ftrace_return_address(n) still depends on frame pointers.
Reported-by: Magnus Lindholm <linmag7@gmail.com>
Suggested-by: Magnus Lindholm <linmag7@gmail.com>
Closes: https://lore.kernel.org/all/CA%2B%3DFv5S8-Zk8-LUpZnWiBfTGSQXthepmRc_-a9O%2BpEPmVW0mRA@mail.gmail.com/
Assisted-by: Claude:claude-opus-5-5
Reviewed-by: Magnus Lindholm <linmag7@gmail.com>
Acked-by: Ian Rogers <irogers@google.com>
Signed-off-by: Matt Turner <mattst88@gmail.com>
---
arch/alpha/include/asm/ftrace.h | 5 ++---
arch/alpha/include/asm/perf_event.h | 7 +++++++
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/arch/alpha/include/asm/ftrace.h b/arch/alpha/include/asm/ftrace.h
index 7ec44134c804..5b75a294a7c9 100644
--- a/arch/alpha/include/asm/ftrace.h
+++ b/arch/alpha/include/asm/ftrace.h
@@ -2,8 +2,6 @@
#ifndef _ASM_ALPHA_FTRACE_H
#define _ASM_ALPHA_FTRACE_H
-#ifdef CONFIG_FRAME_POINTER
-
static void *alpha_ftrace_return_address0(void)
noinline notrace;
static void *alpha_ftrace_return_address0(void)
@@ -13,6 +11,8 @@ static void *alpha_ftrace_return_address0(void)
#define ftrace_return_address0 alpha_ftrace_return_address0()
+#ifdef CONFIG_FRAME_POINTER
+
/*
* __builtin_return_address() requires a constant integer argument.
* Keep this as a macro so the value is seen at the callsite.
@@ -21,7 +21,6 @@ static void *alpha_ftrace_return_address0(void)
#else /* !CONFIG_FRAME_POINTER */
-#define ftrace_return_address0 0UL
#define ftrace_return_address(n) ((void)(n), 0UL)
#endif /* CONFIG_FRAME_POINTER */
diff --git a/arch/alpha/include/asm/perf_event.h b/arch/alpha/include/asm/perf_event.h
index 5996e7a6757e..72536566014a 100644
--- a/arch/alpha/include/asm/perf_event.h
+++ b/arch/alpha/include/asm/perf_event.h
@@ -1,4 +1,11 @@
#ifndef __ASM_ALPHA_PERF_EVENT_H
#define __ASM_ALPHA_PERF_EVENT_H
+/*
+ * Software events have no trap frame, so perf_fetch_caller_regs() fills
+ * in a zeroed pt_regs. A zero ps already means kernel mode; only pc is
+ * missing.
+ */
+#define perf_arch_fetch_caller_regs(regs, __ip) ((regs)->pc = (__ip))
+
#endif /* __ASM_ALPHA_PERF_EVENT_H */
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH v3 5/5] alpha: fill in pc for software event samples
2026-10-18 14:22 ` [PATCH v3 5/5] alpha: fill in pc for software event samples Matt Turner
@ 2026-10-18 17:50 ` Magnus Lindholm
0 siblings, 0 replies; 8+ messages in thread
From: Magnus Lindholm @ 2026-10-18 17:50 UTC (permalink / raw)
To: Matt Turner
Cc: Richard Henderson, linux-alpha, linux-kernel, linux-doc,
linux-perf-users, Ian Rogers
Hi Matt,
On Sun, Oct 18, 2026 at 4:22 PM Matt Turner <mattst88@gmail.com> wrote:
>
> Context switch and tracepoint events have no trap frame, so perf builds
> one with perf_fetch_caller_regs(). Alpha does not define
> perf_arch_fetch_caller_regs(), which leaves that pt_regs zeroed, and
> these samples report pc as 0.
>
> Record the caller's address as pc. The zero ps already marks the frame
> as kernel mode, and pt_regs has nowhere to keep sp, so pc is all that
> can be filled in.
>
> perf_fetch_caller_regs() gets that address from CALLER_ADDR0, which
> alpha defines as 0 when CONFIG_FRAME_POINTER is disabled. Finding the
> level zero return address does not need a frame pointer, so make
> alpha_ftrace_return_address0() available in both configurations. Only
> ftrace_return_address(n) still depends on frame pointers.
>
> Reported-by: Magnus Lindholm <linmag7@gmail.com>
> Suggested-by: Magnus Lindholm <linmag7@gmail.com>
> Closes: https://lore.kernel.org/all/CA%2B%3DFv5S8-Zk8-LUpZnWiBfTGSQXthepmRc_-a9O%2BpEPmVW0mRA@mail.gmail.com/
> Assisted-by: Claude:claude-opus-5-5
> Reviewed-by: Magnus Lindholm <linmag7@gmail.com>
> Acked-by: Ian Rogers <irogers@google.com>
> Signed-off-by: Matt Turner <mattst88@gmail.com>
> ---
> arch/alpha/include/asm/ftrace.h | 5 ++---
> arch/alpha/include/asm/perf_event.h | 7 +++++++
> 2 files changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/arch/alpha/include/asm/ftrace.h b/arch/alpha/include/asm/ftrace.h
> index 7ec44134c804..5b75a294a7c9 100644
> --- a/arch/alpha/include/asm/ftrace.h
> +++ b/arch/alpha/include/asm/ftrace.h
> @@ -2,8 +2,6 @@
> #ifndef _ASM_ALPHA_FTRACE_H
> #define _ASM_ALPHA_FTRACE_H
>
> -#ifdef CONFIG_FRAME_POINTER
> -
> static void *alpha_ftrace_return_address0(void)
> noinline notrace;
> static void *alpha_ftrace_return_address0(void)
> @@ -13,6 +11,8 @@ static void *alpha_ftrace_return_address0(void)
>
> #define ftrace_return_address0 alpha_ftrace_return_address0()
>
> +#ifdef CONFIG_FRAME_POINTER
> +
> /*
> * __builtin_return_address() requires a constant integer argument.
> * Keep this as a macro so the value is seen at the callsite.
> @@ -21,7 +21,6 @@ static void *alpha_ftrace_return_address0(void)
>
> #else /* !CONFIG_FRAME_POINTER */
>
> -#define ftrace_return_address0 0UL
> #define ftrace_return_address(n) ((void)(n), 0UL)
>
> #endif /* CONFIG_FRAME_POINTER */
> diff --git a/arch/alpha/include/asm/perf_event.h b/arch/alpha/include/asm/perf_event.h
> index 5996e7a6757e..72536566014a 100644
> --- a/arch/alpha/include/asm/perf_event.h
> +++ b/arch/alpha/include/asm/perf_event.h
> @@ -1,4 +1,11 @@
> #ifndef __ASM_ALPHA_PERF_EVENT_H
> #define __ASM_ALPHA_PERF_EVENT_H
>
> +/*
> + * Software events have no trap frame, so perf_fetch_caller_regs() fills
> + * in a zeroed pt_regs. A zero ps already means kernel mode; only pc is
> + * missing.
> + */
> +#define perf_arch_fetch_caller_regs(regs, __ip) ((regs)->pc = (__ip))
> +
> #endif /* __ASM_ALPHA_PERF_EVENT_H */
>
> --
> 2.55.0
>
Tested on my AlphaServer ES40 with CONFIG_FRAME_POINTER disabled.
Context-switch and sched_switch samples report valid PCs, with
synthetic SP correctly remaining zero.
Tested-by: Magnus Lindholm <linmag7@gmail.com>
Thanks,
Magnus
^ permalink raw reply [flat|nested] 8+ messages in thread