git: d801e93ec202 - stable/13 - Use a regset for NT_ARM_VFP.

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Fri, 13 May 2022 17:42:49 UTC
The branch stable/13 has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=d801e93ec202c1fc34efef0414383d031771194d

commit d801e93ec202c1fc34efef0414383d031771194d
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2022-03-23 20:33:06 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2022-05-13 00:02:44 +0000

    Use a regset for NT_ARM_VFP.
    
    This includes adding support for NT_ARM_VFP for 32-bit binaries
    running under aarch64 kernels both for ptrace(), and coredumps via the
    kernel and gcore.
    
    Reviewed by:    andrew, markj
    Sponsored by:   University of Cambridge, Google, Inc.
    Differential Revision:  https://reviews.freebsd.org/D34448
    
    (cherry picked from commit add00c381e5c9938133061c401dcba764009cafc)
---
 sys/arm/arm/elf_machdep.c           | 14 ++------------
 sys/arm/arm/ptrace_machdep.c        | 33 +++++++++++++++++++++++++++++++++
 sys/arm64/arm64/elf32_machdep.c     |  1 -
 sys/arm64/arm64/freebsd32_machdep.c |  9 +++------
 sys/arm64/arm64/ptrace_machdep.c    | 34 ++++++++++++++++++++++++++++++++++
 sys/arm64/include/vfp.h             |  5 +++++
 usr.bin/gcore/elfcore.c             |  7 ++-----
 7 files changed, 79 insertions(+), 24 deletions(-)

diff --git a/sys/arm/arm/elf_machdep.c b/sys/arm/arm/elf_machdep.c
index d993ba57c7d0..735c00766f9b 100644
--- a/sys/arm/arm/elf_machdep.c
+++ b/sys/arm/arm/elf_machdep.c
@@ -145,19 +145,9 @@ elf32_arm_abi_supported(struct image_params *imgp, int32_t *osrel __unused,
 }
 
 void
-elf32_dump_thread(struct thread *td, void *dst, size_t *off)
+elf32_dump_thread(struct thread *td __unused, void *dst __unused,
+    size_t *off __unused)
 {
-#ifdef VFP
-	mcontext_vfp_t vfp;
-
-	if (dst != NULL) {
-		get_vfpcontext(td, &vfp);
-		*off = elf32_populate_note(NT_ARM_VFP, &vfp, dst, sizeof(vfp),
-		    NULL);
-	} else
-		*off = elf32_populate_note(NT_ARM_VFP, NULL, NULL, sizeof(vfp),
-		    NULL);
-#endif
 }
 
 bool
diff --git a/sys/arm/arm/ptrace_machdep.c b/sys/arm/arm/ptrace_machdep.c
index 563f962dc473..d8acc58d0fd0 100644
--- a/sys/arm/arm/ptrace_machdep.c
+++ b/sys/arm/arm/ptrace_machdep.c
@@ -28,12 +28,45 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/types.h>
+#include <sys/elf.h>
 #include <sys/proc.h>
 #include <sys/ptrace.h>
+#include <sys/reg.h>
 #ifdef VFP
 #include <machine/vfp.h>
 #endif
 
+#ifdef VFP
+static bool
+get_arm_vfp(struct regset *rs, struct thread *td, void *buf, size_t *sizep)
+{
+	if (buf != NULL) {
+		KASSERT(*sizep == sizeof(mcontext_vfp_t),
+		    ("%s: invalid size", __func__));
+		get_vfpcontext(td, buf);
+	}
+	*sizep = sizeof(mcontext_vfp_t);
+	return (true);
+}
+
+static bool
+set_arm_vfp(struct regset *rs, struct thread *td, void *buf,
+    size_t size)
+{
+	KASSERT(size == sizeof(mcontext_vfp_t), ("%s: invalid size", __func__));
+	set_vfpcontext(td, buf);
+	return (true);
+}
+
+static struct regset regset_arm_vfp = {
+	.note = NT_ARM_VFP,
+	.size = sizeof(mcontext_vfp_t),
+	.get = get_arm_vfp,
+	.set = set_arm_vfp,
+};
+ELF_REGSET(regset_arm_vfp);
+#endif
+
 int
 cpu_ptrace(struct thread *td, int req, void *addr, int data)
 {
diff --git a/sys/arm64/arm64/elf32_machdep.c b/sys/arm64/arm64/elf32_machdep.c
index 4322c07d6e82..4123c45e1e36 100644
--- a/sys/arm64/arm64/elf32_machdep.c
+++ b/sys/arm64/arm64/elf32_machdep.c
@@ -285,5 +285,4 @@ freebsd32_setregs(struct thread *td, struct image_params *imgp,
 void
 elf32_dump_thread(struct thread *td, void *dst, size_t *off)
 {
-	/* XXX: VFP */
 }
diff --git a/sys/arm64/arm64/freebsd32_machdep.c b/sys/arm64/arm64/freebsd32_machdep.c
index f9b847d8b658..7338e2b410f9 100644
--- a/sys/arm64/arm64/freebsd32_machdep.c
+++ b/sys/arm64/arm64/freebsd32_machdep.c
@@ -57,10 +57,6 @@ extern void freebsd32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
  */
 #define UC32_COPY_SIZE  offsetof(ucontext32_t, uc_link)
 
-#ifdef VFP
-static void get_fpcontext32(struct thread *td, mcontext32_vfp_t *);
-#endif
-
 /*
  * Stubs for machine dependent 32-bits system calls.
  */
@@ -123,7 +119,7 @@ freebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap)
 }
 
 #ifdef VFP
-static void
+void
 get_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
 {
 	struct pcb *pcb;
@@ -155,7 +151,7 @@ get_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
 	}
 }
 
-static void
+void
 set_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
 {
 	struct pcb *pcb;
@@ -172,6 +168,7 @@ set_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
 	critical_exit();
 }
 #endif
+
 static void
 get_mcontext32(struct thread *td, mcontext32_t *mcp, int flags)
 {
diff --git a/sys/arm64/arm64/ptrace_machdep.c b/sys/arm64/arm64/ptrace_machdep.c
index 144ff29aff47..abf1991a51a6 100644
--- a/sys/arm64/arm64/ptrace_machdep.c
+++ b/sys/arm64/arm64/ptrace_machdep.c
@@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/elf.h>
 #include <sys/exec.h>
 #include <sys/imgact.h>
 #include <sys/kernel.h>
@@ -38,6 +39,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/ptrace.h>
+#include <sys/reg.h>
 #include <sys/rwlock.h>
 #include <sys/signalvar.h>
 #include <sys/syscallsubr.h>
@@ -47,6 +49,38 @@ __FBSDID("$FreeBSD$");
 
 #include <machine/armreg.h>
 
+#if defined(VFP) && defined(COMPAT_FREEBSD32)
+static bool
+get_arm_vfp(struct regset *rs, struct thread *td, void *buf, size_t *sizep)
+{
+	if (buf != NULL) {
+		KASSERT(*sizep == sizeof(mcontext32_vfp_t),
+		    ("%s: invalid size", __func__));
+		get_fpcontext32(td, buf);
+	}
+	*sizep = sizeof(mcontext32_vfp_t);
+	return (true);
+}
+
+static bool
+set_arm_vfp(struct regset *rs, struct thread *td, void *buf,
+    size_t size)
+{
+	KASSERT(size == sizeof(mcontext32_vfp_t), ("%s: invalid size",
+	    __func__));
+	set_fpcontext32(td, buf);
+	return (true);
+}
+
+static struct regset regset_arm_vfp = {
+	.note = NT_ARM_VFP,
+	.size = sizeof(mcontext32_vfp_t),
+	.get = get_arm_vfp,
+	.set = set_arm_vfp,
+};
+ELF32_REGSET(regset_arm_vfp);
+#endif
+
 int
 ptrace_set_pc(struct thread *td, u_long addr)
 {
diff --git a/sys/arm64/include/vfp.h b/sys/arm64/include/vfp.h
index 9808b3a8d831..650eb6938f5e 100644
--- a/sys/arm64/include/vfp.h
+++ b/sys/arm64/include/vfp.h
@@ -93,6 +93,11 @@ int is_fpu_kern_thread(u_int);
 #define VFP_FPSR_FROM_FPSCR(vpscr) ((vpscr) &~ 0x7c00000)
 #define VFP_FPCR_FROM_FPSCR(vpsrc) ((vpsrc) & 0x7c00000)
 
+#ifdef COMPAT_FREEBSD32
+void get_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp);
+void set_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp);
+#endif
+
 #endif
 
 #endif
diff --git a/usr.bin/gcore/elfcore.c b/usr.bin/gcore/elfcore.c
index b93ef7ed92d6..42d90aaaf155 100644
--- a/usr.bin/gcore/elfcore.c
+++ b/usr.bin/gcore/elfcore.c
@@ -110,9 +110,6 @@ static void elf_detach(void);	/* atexit() handler. */
 static void *elf_note_prpsinfo(void *, size_t *);
 static void *elf_note_thrmisc(void *, size_t *);
 static void *elf_note_ptlwpinfo(void *, size_t *);
-#if defined(__arm__)
-static void *elf_note_arm_vfp(void *, size_t *);
-#endif
 #if defined(__i386__) || defined(__amd64__)
 static void *elf_note_x86_xstate(void *, size_t *);
 #endif
@@ -375,8 +372,8 @@ elf_putnotes(pid_t pid, struct sbuf *sb, size_t *sizep)
 		elf_putregnote(NT_FPREGSET, tids[i], sb);
 		elf_putnote(NT_THRMISC, elf_note_thrmisc, tids + i, sb);
 		elf_putnote(NT_PTLWPINFO, elf_note_ptlwpinfo, tids + i, sb);
-#if defined(__arm__)
-		elf_putnote(NT_ARM_VFP, elf_note_arm_vfp, tids + i, sb);
+#if (defined(ELFCORE_COMPAT_32) && defined(__aarch64__)) || defined(__arm__)
+		elf_putregnote(NT_ARM_VFP, tids[i], sb);
 #endif
 #if defined(__i386__) || defined(__amd64__)
 		elf_putnote(NT_X86_XSTATE, elf_note_x86_xstate, tids + i, sb);