From nobody Tue Apr 7 12:20:32 2026 Received: from mail-yx1-f45.google.com (mail-yx1-f45.google.com [74.125.224.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DED122D0606 for ; Fri, 3 Apr 2026 15:07:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.224.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775228857; cv=none; b=B42LG2h4hGTMabw2R+21ZwEV21FzH2/9/Q3zBPfrCDzNgWny7sDJ52Jve3FhtH1WSE1jZLV6UwePSvGvB2bh1A2saxcbIxRJL44iK4kYP3ksC+q+eUXomV5Sor6OCif/YX81WBinQW+GJ+KFCIf8KGlS50D9Kx0tj2QsUZF+GgY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775228857; c=relaxed/simple; bh=JqzjxrASCrbeWA8VfiletB36YH/9qyaQjLjjEHhVSwA=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=BR6yC3RhH59R41c3M2YL446ZJ6KsDb3HdqwMtYjBgewsImsDIb8+iccK26hjDR3/MbYTnb0G7lm2xsSjsFEhC2J+FUmrhBWEfqCCtzeOJ9Nc0sVTfBxebwQEiH4iiF2sEc2uQGZC8Q3jdDh66SprvugDU5bJPIHXj+gTLg3/S54= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=YfgckIif; arc=none smtp.client-ip=74.125.224.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="YfgckIif" Received: by mail-yx1-f45.google.com with SMTP id 956f58d0204a3-65032e9cf01so2000004d50.3 for ; Fri, 03 Apr 2026 08:07:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775228855; x=1775833655; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=JsQjO3PERcPZEm6Bz+nItD8XASPby72+cIh66p2HJv8=; b=YfgckIif0oJWs9ZnYandhXjt7qXGe5BPaQZ/GcN6J+b27S+649oEO9LHJH2nCwj3Cb xpNoPobB4ASCz14xND2kLo95kU6CDHQJz5D9Z1LByxNbhEcOocWpd7UCIqzsoS9xWrSB zyyDry9MDx196IXeiubcVCrCT7WX9vIvw8g0roU43LhLc3SGRNnr/7VDxHWo7iolgLfp xd0/g/1AyzjcwQbmpZyTGdiC5S6Z4jqTZzCbuCnkRbVQA7IFYG3aa2oTJ2XREXFOVlLg HwS/yGgEI5FtK4dSP69KpOC9pDgWYuWYqD5Z0PhD98mdfofw54SvtafqqjpVUdXjCv4D uTHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775228855; x=1775833655; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=JsQjO3PERcPZEm6Bz+nItD8XASPby72+cIh66p2HJv8=; b=M/qOGINjqt/0kHED70chHFzWryp+NsnFoVZx5V5EXdgwJgvUwotNBZItQZBF47MdmQ RcmlesBRPirz0PKz1AgvNjZqULI7ShnY+4UvlvayOzJigOmn524lxPqAXYqHSOfoBVvm fgiedFa959CbJcG+FM+UG1A+dwaQ2ZHQzGAxav8G/9ObT6aDAl6B+iWQRrrpc+T2km8V EkX+RdPpeQKkqvxqG10rNBUBLoDAxdHFrbM0PkLIvTqiQ2mQRVoQ0OyvLiwk97CdiO/d gyWVSN9XkA9eA330n1hpgpOw3Hb/YZ6gJzRHcngVpnw28/6OA7DthISJuqqWHmBS4s+P ggFQ== X-Forwarded-Encrypted: i=1; AJvYcCVZavCkw6xmXAQV3GgCObZ3mZj8q4FyUK9uJYgTKG7m5PB+xl4SZ2huNqahF62w/CVjFxV5N49ee7RLfFY=@vger.kernel.org X-Gm-Message-State: AOJu0Ywcb2SiHPD5WjBLGxI1eVwpCerOHFj3hhl9ANAP8rp0gV+WXqkk g2uy97CmS+Euowve/bIaQYceDiiDUqz1omF4ICWja54f6vzvQNFmtPB2 X-Gm-Gg: AeBDieuuEawnYvNHhjqUTPObuWzS4wMHF8jXGletaz8xV7KSwK2MkMaCLutAC2UBsbX k1X55OfAlF7TUbLrhUdnGweDFJUT/e1V24hVLe1eSZVZhkJ5Pe+Zeo1zfkM9C0lsvx1D70iHGfu wIATiVdX6NVecv+UWnhUrrOd85soYYPOuE6BeVJ1lMiC4roU7c9JZQmUsfPw3k5IDJ5UiNJVBLB nr2qEUZm5aF2yNItzfl1vPsNZquyX5UwnucmDedf2KRMfPq6EPHkWrKMYMsXA1Gu3k/P+vfXMGD zo+2mbqCoVmfxcDK/2Zdj1oDkQDz8H7v8kr6OOqfyAvFhlQgHaF6kT6xxTKTidXxC7VF04T/did QusZjXaqmsKVDYiP6p4shyasG7OSk+wLPYHi2iREyMRE7bhs0SiXYoVBb78RDZPK0L7A3hBgC8Y LNJQ26lEkogY6jdBmuGG4= X-Received: by 2002:a05:690e:1481:b0:650:3459:5d48 with SMTP id 956f58d0204a3-6504868e0f8mr2852008d50.12.1775228854902; Fri, 03 Apr 2026 08:07:34 -0700 (PDT) Received: from localhost ([76.195.202.134]) by smtp.gmail.com with UTF8SMTPSA id 956f58d0204a3-6503a828f3csm2554853d50.3.2026.04.03.08.07.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Apr 2026 08:07:34 -0700 (PDT) From: Matt Turner To: Magnus Lindholm Cc: linux-alpha@vger.kernel.org, linux-kernel@vger.kernel.org, Matt Turner Subject: [PATCH] alpha: Add PTRACE_GETREGSET/PTRACE_SETREGSET support Date: Fri, 3 Apr 2026 11:06:58 -0400 Message-ID: <20260403150730.490272-1-mattst88@gmail.com> X-Mailer: git-send-email 2.52.0 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" Enable HAVE_ARCH_TRACEHOOK and implement task_user_regset_view() to provide regset-based register access on Alpha. This adds support for PTRACE_GETREGSET and PTRACE_SETREGSET, which are handled by the generic ptrace_request() path. Two regsets are defined: - REGSET_GENERAL (NT_PRSTATUS): 33 registers (32 GPRs + unique), matching the existing elf_gregset_t layout used by dump_elf_thread() - REGSET_FPU (NT_PRFPREG): 32 floating-point registers from thread_info->fp[] Also implement the full set of syscall accessor functions in asm/syscall.h and user_stack_pointer() in asm/ptrace.h, which are required by the generic PTRACE_GET_SYSCALL_INFO code that HAVE_ARCH_TRACEHOOK enables. Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Matt Turner --- This is an implementation of PTRACE_{G,S}ETREGSET using the standard infrastructure. arch/alpha/Kconfig | 1 + arch/alpha/include/asm/ptrace.h | 12 +++ arch/alpha/include/asm/syscall.h | 67 ++++++++++++++- arch/alpha/kernel/ptrace.c | 137 +++++++++++++++++++++++++++++++ 4 files changed, 215 insertions(+), 2 deletions(-) diff --git ./arch/alpha/Kconfig ./arch/alpha/Kconfig index 6c7dbf0adad6..3e61dfaa2ba9 100644 --- ./arch/alpha/Kconfig +++ ./arch/alpha/Kconfig @@ -14,6 +14,7 @@ config ALPHA select FORCE_PCI select PCI_DOMAINS if PCI select PCI_SYSCALL if PCI + select HAVE_ARCH_TRACEHOOK select HAVE_ASM_MODVERSIONS select HAVE_PAGE_SIZE_8KB select HAVE_PCSPKR_PLATFORM diff --git ./arch/alpha/include/asm/ptrace.h ./arch/alpha/include/asm/ptrac= e.h index 3557ce64ed21..af97a8d3ed5b 100644 --- ./arch/alpha/include/asm/ptrace.h +++ ./arch/alpha/include/asm/ptrace.h @@ -4,6 +4,7 @@ =20 #include =20 +#include =20 #define arch_has_single_step() (1) #define user_mode(regs) (((regs)->ps & 8) !=3D 0) @@ -24,4 +25,15 @@ static inline unsigned long regs_return_value(struct pt_= regs *regs) return regs->r0; } =20 +/* + * The user stack pointer is not stored in pt_regs. It lives in the + * PCB, which sits at the base of the kernel stack (i.e. in thread_info). + */ +static inline unsigned long user_stack_pointer(struct pt_regs *regs) +{ + struct thread_info *ti =3D + (struct thread_info *)((char *)(regs + 1) - 2 * PAGE_SIZE); + return ti->pcb.usp; +} + #endif diff --git ./arch/alpha/include/asm/syscall.h ./arch/alpha/include/asm/sysc= all.h index f21babaeed85..dab35748ef74 100644 --- ./arch/alpha/include/asm/syscall.h +++ ./arch/alpha/include/asm/syscall.h @@ -3,10 +3,31 @@ #define _ASM_ALPHA_SYSCALL_H =20 #include +#include +#include =20 -static inline int syscall_get_arch(struct task_struct *task) +static inline int syscall_get_nr(struct task_struct *task, + struct pt_regs *regs) { - return AUDIT_ARCH_ALPHA; + return regs->r0; +} + +static inline void syscall_set_nr(struct task_struct *task, + struct pt_regs *regs, int nr) +{ + regs->r0 =3D nr; +} + +static inline void syscall_rollback(struct task_struct *task, + struct pt_regs *regs) +{ + /* Alpha does not save the original syscall number separately. */ +} + +static inline long syscall_get_error(struct task_struct *task, + struct pt_regs *regs) +{ + return regs->r19 ? regs->r0 : 0; } =20 static inline long syscall_get_return_value(struct task_struct *task, @@ -15,4 +36,46 @@ static inline long syscall_get_return_value(struct task_= struct *task, return regs->r0; } =20 +static inline void syscall_set_return_value(struct task_struct *task, + struct pt_regs *regs, + int error, long val) +{ + if (error) { + regs->r0 =3D error; + regs->r19 =3D 1; /* a3: signal error */ + } else { + regs->r0 =3D val; + regs->r19 =3D 0; /* a3: no error */ + } +} + +static inline void syscall_get_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned long *args) +{ + args[0] =3D regs->r16; /* a0 */ + args[1] =3D regs->r17; /* a1 */ + args[2] =3D regs->r18; /* a2 */ + args[3] =3D regs->r19; /* a3 */ + args[4] =3D regs->r20; /* a4 */ + args[5] =3D regs->r21; /* a5 */ +} + +static inline void syscall_set_arguments(struct task_struct *task, + struct pt_regs *regs, + const unsigned long *args) +{ + regs->r16 =3D args[0]; /* a0 */ + regs->r17 =3D args[1]; /* a1 */ + regs->r18 =3D args[2]; /* a2 */ + regs->r19 =3D args[3]; /* a3 */ + regs->r20 =3D args[4]; /* a4 */ + regs->r21 =3D args[5]; /* a5 */ +} + +static inline int syscall_get_arch(struct task_struct *task) +{ + return AUDIT_ARCH_ALPHA; +} + #endif /* _ASM_ALPHA_SYSCALL_H */ diff --git ./arch/alpha/kernel/ptrace.c ./arch/alpha/kernel/ptrace.c index fde4c68e7a0b..f1a10c4112e7 100644 --- ./arch/alpha/kernel/ptrace.c +++ ./arch/alpha/kernel/ptrace.c @@ -12,10 +12,12 @@ #include #include #include +#include #include #include #include #include +#include =20 #include #include @@ -274,6 +276,141 @@ void ptrace_disable(struct task_struct *child) user_disable_single_step(child); } =20 +/* + * Get the general registers from a task. + * Follows the elf_gregset_t layout: 32 GPRs + unique (replacing PS). + */ +static int genregs_get(struct task_struct *target, + const struct user_regset *regset, + struct membuf to) +{ + elf_gregset_t gregs; + + dump_elf_thread(gregs, task_pt_regs(target), + task_thread_info(target)); + return membuf_write(&to, &gregs, sizeof(gregs)); +} + +/* + * Set the general registers for a task. + */ +static int genregs_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + elf_gregset_t gregs; + struct pt_regs *regs =3D task_pt_regs(target); + struct switch_stack *sw =3D ((struct switch_stack *)regs) - 1; + struct thread_info *ti =3D task_thread_info(target); + int ret; + + /* Start with the current register values. */ + dump_elf_thread(gregs, regs, ti); + + ret =3D user_regset_copyin(&pos, &count, &kbuf, &ubuf, + &gregs, 0, sizeof(gregs)); + if (ret) + return ret; + + /* Apply the register values back. */ + regs->r0 =3D gregs[0]; + regs->r1 =3D gregs[1]; + regs->r2 =3D gregs[2]; + regs->r3 =3D gregs[3]; + regs->r4 =3D gregs[4]; + regs->r5 =3D gregs[5]; + regs->r6 =3D gregs[6]; + regs->r7 =3D gregs[7]; + regs->r8 =3D gregs[8]; + sw->r9 =3D gregs[9]; + sw->r10 =3D gregs[10]; + sw->r11 =3D gregs[11]; + sw->r12 =3D gregs[12]; + sw->r13 =3D gregs[13]; + sw->r14 =3D gregs[14]; + sw->r15 =3D gregs[15]; + regs->r16 =3D gregs[16]; + regs->r17 =3D gregs[17]; + regs->r18 =3D gregs[18]; + regs->r19 =3D gregs[19]; + regs->r20 =3D gregs[20]; + regs->r21 =3D gregs[21]; + regs->r22 =3D gregs[22]; + regs->r23 =3D gregs[23]; + regs->r24 =3D gregs[24]; + regs->r25 =3D gregs[25]; + regs->r26 =3D gregs[26]; + regs->r27 =3D gregs[27]; + regs->r28 =3D gregs[28]; + regs->gp =3D gregs[29]; + ti->pcb.usp =3D gregs[30]; + regs->pc =3D gregs[31]; + ti->pcb.unique =3D gregs[32]; + + return 0; +} + +/* + * Get the floating-point registers from a task. + */ +static int fpregs_get(struct task_struct *target, + const struct user_regset *regset, + struct membuf to) +{ + return membuf_write(&to, task_thread_info(target)->fp, + ELF_NFPREG * sizeof(elf_fpreg_t)); +} + +/* + * Set the floating-point registers for a task. + */ +static int fpregs_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + return user_regset_copyin(&pos, &count, &kbuf, &ubuf, + task_thread_info(target)->fp, + 0, ELF_NFPREG * sizeof(elf_fpreg_t)); +} + +enum alpha_regset { + REGSET_GENERAL, + REGSET_FPU, +}; + +static const struct user_regset alpha_regsets[] =3D { + [REGSET_GENERAL] =3D { + USER_REGSET_NOTE_TYPE(PRSTATUS), + .n =3D ELF_NGREG, + .size =3D sizeof(elf_greg_t), + .align =3D sizeof(elf_greg_t), + .regset_get =3D genregs_get, + .set =3D genregs_set, + }, + [REGSET_FPU] =3D { + USER_REGSET_NOTE_TYPE(PRFPREG), + .n =3D ELF_NFPREG, + .size =3D sizeof(elf_fpreg_t), + .align =3D sizeof(elf_fpreg_t), + .regset_get =3D fpregs_get, + .set =3D fpregs_set, + }, +}; + +static const struct user_regset_view user_alpha_view =3D { + .name =3D "alpha", + .e_machine =3D ELF_ARCH, + .regsets =3D alpha_regsets, + .n =3D ARRAY_SIZE(alpha_regsets), +}; + +const struct user_regset_view *task_user_regset_view(struct task_struct *t= ask) +{ + return &user_alpha_view; +} + long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { --=20 2.52.0