The branch main has been updated by pouria:

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

commit b84d31ee74535a0026ff83f2a34c07b7557f9785
Author:     Ricardo Branco <[email protected]>
AuthorDate: 2026-04-26 14:43:59 +0000
Commit:     Pouria Mousavizadeh Tehrani <[email protected]>
CommitDate: 2026-06-02 07:25:34 +0000

    linux: Add linux_pt_fpregset and bsd_to_linux_fpregset() for amd64
    
    Add struct linux_pt_fpregset, the amd64 Linux NT_PRFPREG payload,
    corresponding to user_i387_struct in Linux. The struct describes
    the 512-byte FXSAVE area as exposed by PTRACE_GETREGSET.
    
    Add bsd_to_linux_fpregset() to translate from FreeBSD's struct fpreg
    to struct linux_pt_fpregset. Fields are extracted from the fpr_env[]
    array which stores the FXSAVE environment packed as four 64-bit words.
    The FP and XMM register banks are bulk-copied as opaque byte arrays.
    
    Signed-off-by:  Ricardo Branco <[email protected]>
    Reviewed by:    kib
    Pull-Request:   https://github.com/freebsd/freebsd-src/pull/2165
---
 sys/amd64/linux/linux.h         | 18 ++++++++++++++++++
 sys/amd64/linux/linux_machdep.c | 20 ++++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/sys/amd64/linux/linux.h b/sys/amd64/linux/linux.h
index fb7aaa2d731c..8e025b73dbd8 100644
--- a/sys/amd64/linux/linux.h
+++ b/sys/amd64/linux/linux.h
@@ -237,14 +237,32 @@ struct linux_pt_regset {
        l_ulong gs;
 };
 
+/* This corresponds to 'user_i387_struct' in Linux. */
+struct linux_pt_fpregset {
+       l_ushort cwd;
+       l_ushort swd;
+       l_ushort twd;
+       l_ushort fop;
+       uint64_t rip;
+       uint64_t rdp;
+       uint32_t mxcsr;
+       uint32_t mxcsr_mask;
+       uint32_t st_space[32];
+       uint32_t xmm_space[64];
+       uint32_t padding[24];
+};
+
 #ifdef _KERNEL
 struct reg;
+struct fpreg;
 struct syscall_info;
 
 void   bsd_to_linux_regset(const struct reg *b_reg,
            struct linux_pt_regset *l_regset);
 void   linux_to_bsd_regset(struct reg *b_reg,
            const struct linux_pt_regset *l_regset);
+void   bsd_to_linux_fpregset(const struct fpreg *b_fpreg,
+           struct linux_pt_fpregset *l_fpregset);
 void   linux_ptrace_get_syscall_info_machdep(const struct reg *reg,
            struct syscall_info *si);
 int    linux_ptrace_getregs_machdep(struct thread *td, pid_t pid,
diff --git a/sys/amd64/linux/linux_machdep.c b/sys/amd64/linux/linux_machdep.c
index 7ec1ec56bb95..e05f824cbea1 100644
--- a/sys/amd64/linux/linux_machdep.c
+++ b/sys/amd64/linux/linux_machdep.c
@@ -281,6 +281,26 @@ linux_to_bsd_regset(struct reg *b_reg, const struct 
linux_pt_regset *l_regset)
        b_reg->r_gs = l_regset->gs;
 }
 
+void
+bsd_to_linux_fpregset(const struct fpreg *b_fpreg,
+    struct linux_pt_fpregset *l_fpregset)
+{
+       l_fpregset->cwd = b_fpreg->fpr_env[0];
+       l_fpregset->swd = b_fpreg->fpr_env[0] >> 16;
+       l_fpregset->twd = b_fpreg->fpr_env[0] >> 32;
+       l_fpregset->fop = b_fpreg->fpr_env[0] >> 48;
+       l_fpregset->rip = b_fpreg->fpr_env[1];
+       l_fpregset->rdp = b_fpreg->fpr_env[2];
+       l_fpregset->mxcsr = b_fpreg->fpr_env[3];
+       l_fpregset->mxcsr_mask = b_fpreg->fpr_env[3] >> 32;
+
+       memcpy(l_fpregset->st_space, b_fpreg->fpr_acc,
+           sizeof(l_fpregset->st_space));
+       memcpy(l_fpregset->xmm_space, b_fpreg->fpr_xacc,
+           sizeof(l_fpregset->xmm_space));
+       memset(l_fpregset->padding, 0, sizeof(l_fpregset->padding));
+}
+
 void
 linux_ptrace_get_syscall_info_machdep(const struct reg *reg,
     struct syscall_info *si)

Reply via email to