[RFC,16/34] hurd: Add sys/ucontext.h and sigcontext.h for x86_64

Message ID 20230319151017.531737-17-bugaevc@gmail.com (mailing list archive)
State Committed, archived
Headers
Series The rest of the x86_64-gnu port |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent

Commit Message

Sergey Bugaev March 19, 2023, 3:09 p.m. UTC
  This is based on the Linux port's version, but laid out to match Mach's
struct i386_thread_state, much like the i386 version does.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
---

I'm not very sure about the FP stuff, nor about any of this, really. Please
do review.

 sysdeps/mach/hurd/x86_64/bits/sigcontext.h | 131 +++++++++++++++++
 sysdeps/mach/hurd/x86_64/sys/ucontext.h    | 157 +++++++++++++++++++++
 sysdeps/mach/hurd/x86_64/ucontext_i.sym    |  38 +++++
 3 files changed, 326 insertions(+)
 create mode 100644 sysdeps/mach/hurd/x86_64/bits/sigcontext.h
 create mode 100644 sysdeps/mach/hurd/x86_64/sys/ucontext.h
 create mode 100644 sysdeps/mach/hurd/x86_64/ucontext_i.sym
  

Comments

Samuel Thibault April 10, 2023, 6:39 p.m. UTC | #1
Hello,

Applied, thanks!

Note that I have pushed sysdeps/mach/hurd/x86_64/sys/ucontext.h to
sysdeps/x86_64/sys/ucontext.h since it's not mach-specific, and Linux
has its own for x86.

Samuel

Sergey Bugaev, le dim. 19 mars 2023 18:09:59 +0300, a ecrit:
> This is based on the Linux port's version, but laid out to match Mach's
> struct i386_thread_state, much like the i386 version does.
> 
> Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
> ---
> 
> I'm not very sure about the FP stuff, nor about any of this, really. Please
> do review.
> 
>  sysdeps/mach/hurd/x86_64/bits/sigcontext.h | 131 +++++++++++++++++
>  sysdeps/mach/hurd/x86_64/sys/ucontext.h    | 157 +++++++++++++++++++++
>  sysdeps/mach/hurd/x86_64/ucontext_i.sym    |  38 +++++
>  3 files changed, 326 insertions(+)
>  create mode 100644 sysdeps/mach/hurd/x86_64/bits/sigcontext.h
>  create mode 100644 sysdeps/mach/hurd/x86_64/sys/ucontext.h
>  create mode 100644 sysdeps/mach/hurd/x86_64/ucontext_i.sym
> 
> diff --git a/sysdeps/mach/hurd/x86_64/bits/sigcontext.h b/sysdeps/mach/hurd/x86_64/bits/sigcontext.h
> new file mode 100644
> index 00000000..3a3b34bc
> --- /dev/null
> +++ b/sysdeps/mach/hurd/x86_64/bits/sigcontext.h
> @@ -0,0 +1,131 @@
> +/* Machine-dependent signal context structure for GNU Hurd.  x86_64 version.
> +   Copyright (C) 1991-2023 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _BITS_SIGCONTEXT_H
> +#define _BITS_SIGCONTEXT_H 1
> +
> +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H
> +# error "Never use <bits/sigcontext.h> directly; include <signal.h> instead."
> +#endif
> +
> +/* Signal handlers are actually called:
> +   void handler (int sig, int code, struct sigcontext *scp);  */
> +
> +#include <bits/types/__sigset_t.h>
> +#include <mach/machine/fp_reg.h>
> +
> +/* State of this thread when the signal was taken.  */
> +struct sigcontext
> +  {
> +    /* These first members are machine-independent.  */
> +
> +    int sc_onstack;		/* Nonzero if running on sigstack.  */
> +    __sigset_t sc_mask;		/* Blocked signals to restore.  */
> +
> +    /* MiG reply port this thread is using.  */
> +    unsigned int sc_reply_port;
> +
> +    /* Port this thread is doing an interruptible RPC on.  */
> +    unsigned int sc_intr_port;
> +
> +    /* Error code associated with this signal (interpreted as `error_t').  */
> +    int sc_error;
> +
> +    /* All following members are machine-dependent.  The rest of this
> +       structure is written to be laid out identically to:
> +       {
> +	 struct i386_thread_state basic;
> +	 struct i386_float_state fpu;
> +       }
> +       trampoline.c knows this, so it must be changed if this changes.  */
> +
> +#define sc_i386_thread_state sc_gs /* Beginning of correspondence.  */
> +    /* Segment registers.  */
> +    int sc_gs;
> +    int sc_fs;
> +    int sc_es;
> +    int sc_ds;
> +
> +    long sc_r8;
> +    long sc_r9;
> +    long sc_r10;
> +    long sc_r11;
> +    long sc_r12;
> +    long sc_r13;
> +    long sc_r14;
> +    long sc_r15;
> +    long sc_rdi;
> +    long sc_rsi;
> +    long sc_rbp;
> +    long sc_rsp;		/* Not used; sc_ursp is used instead.  */
> +    long sc_rbx;
> +    long sc_rdx;
> +    long sc_rcx;
> +    long sc_rax;
> +    long sc_rip;		/* Instruction pointer.  */
> +
> +    int sc_cs;			/* Code segment register.  */
> +
> +    long sc_rfl;		/* Processor flags.  */
> +
> +    long sc_ursp;		/* This stack pointer is used.  */
> +    int sc_ss;			/* Stack segment register.  */
> +
> +    /* Following mimics struct i386_float_state.  Structures and symbolic
> +       values can be found in <mach/i386/fp_reg.h>.  */
> +#define sc_i386_float_state sc_fpkind
> +    int sc_fpkind;		/* FP_NO, FP_387, etc.  */
> +    int sc_fpused;		/* If zero, ignore rest of float state.  */
> +    struct i386_fp_save sc_fpsave;
> +    struct i386_fp_regs sc_fpregs;
> +    int sc_fpexcsr;		/* FPSR including exception bits.  */
> +  };
> +
> +/* Traditional BSD names for some members.  */
> +#define sc_sp	sc_ursp		/* Stack pointer.  */
> +#define sc_fp	sc_rbp		/* Frame pointer.  */
> +#define sc_pc	sc_rip		/* Process counter.  */
> +#define sc_ps	sc_rfl
> +
> +
> +/* The deprecated sigcode values below are passed as an extra, non-portable
> +   argument to regular signal handlers.  You should use SA_SIGINFO handlers
> +   instead, which use the standard POSIX signal codes.  */
> +
> +/* Codes for SIGFPE.  */
> +#define FPE_INTOVF_TRAP		0x1 /* integer overflow */
> +#define FPE_INTDIV_FAULT	0x2 /* integer divide by zero */
> +#define FPE_FLTOVF_FAULT	0x3 /* floating overflow */
> +#define FPE_FLTDIV_FAULT	0x4 /* floating divide by zero */
> +#define FPE_FLTUND_FAULT	0x5 /* floating underflow */
> +#define FPE_SUBRNG_FAULT	0x7 /* BOUNDS instruction failed */
> +#define FPE_FLTDNR_FAULT	0x8 /* denormalized operand */
> +#define FPE_FLTINX_FAULT	0x9 /* floating loss of precision */
> +#define FPE_EMERR_FAULT		0xa /* mysterious emulation error 33 */
> +#define FPE_EMBND_FAULT		0xb /* emulation BOUNDS instruction failed */
> +
> +/* Codes for SIGILL.  */
> +#define ILL_INVOPR_FAULT	0x1 /* invalid operation */
> +#define ILL_STACK_FAULT		0x2 /* fault on microkernel stack access */
> +#define ILL_FPEOPR_FAULT	0x3 /* invalid floating operation */
> +
> +/* Codes for SIGTRAP.  */
> +#define DBG_SINGLE_TRAP		0x1 /* single step */
> +#define DBG_BRKPNT_FAULT	0x2 /* breakpoint instruction */
> +
> +#endif /* bits/sigcontext.h */
> diff --git a/sysdeps/mach/hurd/x86_64/sys/ucontext.h b/sysdeps/mach/hurd/x86_64/sys/ucontext.h
> new file mode 100644
> index 00000000..d73a8937
> --- /dev/null
> +++ b/sysdeps/mach/hurd/x86_64/sys/ucontext.h
> @@ -0,0 +1,157 @@
> +/* Copyright (C) 2001-2023 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _SYS_UCONTEXT_H
> +#define _SYS_UCONTEXT_H	1
> +
> +#include <features.h>
> +
> +#include <bits/types.h>
> +#include <bits/types/sigset_t.h>
> +#include <bits/types/stack_t.h>
> +
> +
> +#ifdef __USE_MISC
> +# define __ctx(fld) fld
> +#else
> +# define __ctx(fld) __ ## fld
> +#endif
> +
> +/* Type for general register.  */
> +__extension__ typedef long long int greg_t;
> +
> +/* Number of general registers.  */
> +#define __NGREG	23
> +#ifdef __USE_MISC
> +# define NGREG	__NGREG
> +#endif
> +
> +/* Container for all general registers.  */
> +typedef greg_t gregset_t[__NGREG];
> +
> +#ifdef __USE_GNU
> +/* Number of each register in the `gregset_t' array.  */
> +enum
> +{
> +  REG_GSFS = 0,		/* Actually int gs, fs.  */
> +# define REG_GSFS	REG_GSFS
> +  REG_ESDS,		/* Actually int es, ds.  */
> +# define REG_ESDS	REG_ESDS
> +  REG_R8,
> +# define REG_R8		REG_R8
> +  REG_R9,
> +# define REG_R9		REG_R9
> +  REG_R10,
> +# define REG_R10	REG_R10
> +  REG_R11,
> +# define REG_R11	REG_R11
> +  REG_R12,
> +# define REG_R12	REG_R12
> +  REG_R13,
> +# define REG_R13	REG_R13
> +  REG_R14,
> +# define REG_R14	REG_R14
> +  REG_R15,
> +# define REG_R15	REG_R15
> +  REG_RDI,
> +# define REG_RDI	REG_RDI
> +  REG_RSI,
> +# define REG_RSI	REG_RSI
> +  REG_RBP,
> +# define REG_RBP	REG_RBP
> +  REG_RSP,
> +# define REG_RSP	REG_RSP
> +  REG_RBX,
> +# define REG_RBX	REG_RBX
> +  REG_RDX,
> +# define REG_RDX	REG_RDX
> +  REG_RCX,
> +# define REG_RCX	REG_RCX
> +  REG_RAX,
> +# define REG_RAX	REG_RAX
> +  REG_RIP,
> +# define REG_RIP	REG_RIP
> +  REG_CS,		/* Actually int cs, pad.  */
> +# define REG_CS		REG_CS
> +  REG_RFL,
> +# define REG_RFL	REG_RFL
> +  REG_ERR,
> +# define REG_ERR	REG_ERR
> +  REG_TRAPNO,
> +# define REG_TRAPNO	REG_TRAPNO
> +  REG_OLDMASK,
> +# define REG_OLDMASK	REG_OLDMASK
> +  REG_CR2
> +# define REG_CR2	REG_CR2
> +};
> +#endif
> +
> +struct _libc_fpxreg
> +{
> +  unsigned short int __ctx(significand)[4];
> +  unsigned short int __ctx(exponent);
> +  unsigned short int __glibc_reserved1[3];
> +};
> +
> +struct _libc_xmmreg
> +{
> +  __uint32_t	__ctx(element)[4];
> +};
> +
> +struct _libc_fpstate
> +{
> +  /* 64-bit FXSAVE format.  */
> +  __uint16_t		__ctx(cwd);
> +  __uint16_t		__ctx(swd);
> +  __uint16_t		__ctx(ftw);
> +  __uint16_t		__ctx(fop);
> +  __uint64_t		__ctx(rip);
> +  __uint64_t		__ctx(rdp);
> +  __uint32_t		__ctx(mxcsr);
> +  __uint32_t		__ctx(mxcr_mask);
> +  struct _libc_fpxreg	_st[8];
> +  struct _libc_xmmreg	_xmm[16];
> +  __uint32_t		__glibc_reserved1[24];
> +};
> +
> +/* Structure to describe FPU registers.  */
> +typedef struct _libc_fpstate *fpregset_t;
> +
> +/* Context to describe whole processor state.  */
> +typedef struct
> +  {
> +    gregset_t __ctx(gregs);
> +    /* Note that fpregs is a pointer.  */
> +    fpregset_t __ctx(fpregs);
> +    __extension__ unsigned long long __reserved1 [8];
> +} mcontext_t;
> +
> +/* Userlevel context.  */
> +typedef struct ucontext_t
> +  {
> +    unsigned long int __ctx(uc_flags);
> +    struct ucontext_t *uc_link;
> +    stack_t uc_stack;
> +    mcontext_t uc_mcontext;
> +    sigset_t uc_sigmask;
> +    struct _libc_fpstate __fpregs_mem;
> +    __extension__ unsigned long long int __ssp[4];
> +  } ucontext_t;
> +
> +#undef __ctx
> +
> +#endif /* sys/ucontext.h */
> diff --git a/sysdeps/mach/hurd/x86_64/ucontext_i.sym b/sysdeps/mach/hurd/x86_64/ucontext_i.sym
> new file mode 100644
> index 00000000..7e536956
> --- /dev/null
> +++ b/sysdeps/mach/hurd/x86_64/ucontext_i.sym
> @@ -0,0 +1,38 @@
> +#include <stddef.h>
> +#include <signal.h>
> +#include <sys/ucontext.h>
> +
> +--
> +
> +SIG_BLOCK
> +SIG_SETMASK
> +
> +_NSIG8		(_NSIG / 8)
> +
> +#define ucontext(member)	offsetof (ucontext_t, member)
> +#define mcontext(member)	ucontext (uc_mcontext.member)
> +#define mreg(reg)		mcontext (gregs[REG_##reg])
> +
> +oRBP		mreg (RBP)
> +oRSP		mreg (RSP)
> +oRBX		mreg (RBX)
> +oR8		mreg (R8)
> +oR9		mreg (R9)
> +oR10		mreg (R10)
> +oR11		mreg (R11)
> +oR12		mreg (R12)
> +oR13		mreg (R13)
> +oR14		mreg (R14)
> +oR15		mreg (R15)
> +oRDI		mreg (RDI)
> +oRSI		mreg (RSI)
> +oRDX		mreg (RDX)
> +oRAX		mreg (RAX)
> +oRCX		mreg (RCX)
> +oRIP		mreg (RIP)
> +oRFL		mreg (RFL)
> +oFPREGS		mcontext (fpregs)
> +oSIGMASK	ucontext (uc_sigmask)
> +oFPREGSMEM	ucontext (__fpregs_mem)
> +oMXCSR		ucontext (__fpregs_mem.mxcsr)
> +oSSP		ucontext (__ssp)
> -- 
> 2.39.2
>
  
Samuel Thibault April 10, 2023, 6:58 p.m. UTC | #2
Sergey Bugaev, le dim. 19 mars 2023 18:09:59 +0300, a ecrit:
> +#ifdef __USE_GNU
> +/* Number of each register in the `gregset_t' array.  */
> +enum
> +{
> +  REG_GSFS = 0,		/* Actually int gs, fs.  */
> +# define REG_GSFS	REG_GSFS
> +  REG_ESDS,		/* Actually int es, ds.  */
> +# define REG_ESDS	REG_ESDS

On second thought, why REG_ESDS? They are basically useless on amd64

Linux packs all segment registers in REG_CSGSFS, probably better to
stuff them the same way? (all three really are 16bit only, even if the
thread_state is padding them to 32bits).

Samuel
  
Sergey Bugaev April 10, 2023, 7:07 p.m. UTC | #3
On Mon, Apr 10, 2023, 21:39 Samuel Thibault <samuel.thibault@gnu.org> wrote:
>
> Hello,
>
> Applied, thanks!

Yay! Thank you for finding the time to review some more patches!
Here's to hoping that the rest will follow.

> Note that I have pushed sysdeps/mach/hurd/x86_64/sys/ucontext.h to
> sysdeps/x86_64/sys/ucontext.h since it's not mach-specific, and Linux
> has its own for x86.

It's not technically Mach specific, but it's arranged the same way as
Mach's struct i386_thread_state, and code in hurdsig.c relies on this.
If, say, Flavio would have arranged registers differently in gnumach
commit feba9b7b1d88e505feb6579e41dc45e48c264e6f — say, put rdi & rsi
before the r{8..15} gang, like it's done in the 32-bit version — then
ucontext definitions would also have to be different. So while it
could work for any port (provided it doesn't care about the ordering),
putting it into the generic tree underemphasizes why it has to be
arranged this specifically.

But it's up to you, of course.

Sergey
  
Sergey Bugaev April 10, 2023, 7:13 p.m. UTC | #4
On Mon, Apr 10, 2023 at 9:58 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
>
> Sergey Bugaev, le dim. 19 mars 2023 18:09:59 +0300, a ecrit:
> > +#ifdef __USE_GNU
> > +/* Number of each register in the `gregset_t' array.  */
> > +enum
> > +{
> > +  REG_GSFS = 0,              /* Actually int gs, fs.  */
> > +# define REG_GSFS    REG_GSFS
> > +  REG_ESDS,          /* Actually int es, ds.  */
> > +# define REG_ESDS    REG_ESDS
>
> On second thought, why REG_ESDS? They are basically useless on amd64
>
> Linux packs all segment registers in REG_CSGSFS, probably better to
> stuff them the same way? (all three really are 16bit only, even if the
> thread_state is padding them to 32bits).

Exactly because that's how they are laid out in struct
i386_thread_state, if you count in 8-byte chunks.

Look at how these REG_* definitions are used in fill_ucontext () in
trampoline.c (that's the one, not hursig.c like my previous message
said).

Sergey
  
Samuel Thibault April 10, 2023, 7:21 p.m. UTC | #5
Sergey Bugaev, le lun. 10 avril 2023 22:07:33 +0300, a ecrit:
> On Mon, Apr 10, 2023, 21:39 Samuel Thibault <samuel.thibault@gnu.org> wrote:
> > Note that I have pushed sysdeps/mach/hurd/x86_64/sys/ucontext.h to
> > sysdeps/x86_64/sys/ucontext.h since it's not mach-specific, and Linux
> > has its own for x86.
> 
> It's not technically Mach specific, but it's arranged the same way as
> Mach's struct i386_thread_state,

It doesn't need to be.

> and code in hurdsig.c relies on this.

Yes, but that can surely be changed to fix the mapping?

Samuel
  
Samuel Thibault April 10, 2023, 7:21 p.m. UTC | #6
Sergey Bugaev, le lun. 10 avril 2023 22:13:06 +0300, a ecrit:
> On Mon, Apr 10, 2023 at 9:58 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
> >
> > Sergey Bugaev, le dim. 19 mars 2023 18:09:59 +0300, a ecrit:
> > > +#ifdef __USE_GNU
> > > +/* Number of each register in the `gregset_t' array.  */
> > > +enum
> > > +{
> > > +  REG_GSFS = 0,              /* Actually int gs, fs.  */
> > > +# define REG_GSFS    REG_GSFS
> > > +  REG_ESDS,          /* Actually int es, ds.  */
> > > +# define REG_ESDS    REG_ESDS
> >
> > On second thought, why REG_ESDS? They are basically useless on amd64
> >
> > Linux packs all segment registers in REG_CSGSFS, probably better to
> > stuff them the same way? (all three really are 16bit only, even if the
> > thread_state is padding them to 32bits).
> 
> Exactly because that's how they are laid out in struct
> i386_thread_state, if you count in 8-byte chunks.

But we don't have to map to that.

Samuel
  
Sergey Bugaev April 10, 2023, 9:50 p.m. UTC | #7
On Mon, Apr 10, 2023 at 10:22 PM Samuel Thibault
<samuel.thibault@gnu.org> wrote:
>
> Sergey Bugaev, le lun. 10 avril 2023 22:13:06 +0300, a ecrit:
> > On Mon, Apr 10, 2023 at 9:58 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
> > >
> > > Sergey Bugaev, le dim. 19 mars 2023 18:09:59 +0300, a ecrit:
> > > > +#ifdef __USE_GNU
> > > > +/* Number of each register in the `gregset_t' array.  */
> > > > +enum
> > > > +{
> > > > +  REG_GSFS = 0,              /* Actually int gs, fs.  */
> > > > +# define REG_GSFS    REG_GSFS
> > > > +  REG_ESDS,          /* Actually int es, ds.  */
> > > > +# define REG_ESDS    REG_ESDS
> > >
> > > On second thought, why REG_ESDS? They are basically useless on amd64
> > >
> > > Linux packs all segment registers in REG_CSGSFS, probably better to
> > > stuff them the same way? (all three really are 16bit only, even if the
> > > thread_state is padding them to 32bits).
> >
> > Exactly because that's how they are laid out in struct
> > i386_thread_state, if you count in 8-byte chunks.
>
> But we don't have to map to that.

Well yes, I was trying to make the x86_64 version do the same thing as
i386 does, hence arranging registers in sigcontext, ucontext, and
thread state in the same way, so they can be memcpied, like on i386.
But we could also lay this out differently and just write some more
code to fill the ucontext.

Sergey
  
Samuel Thibault April 10, 2023, 10:23 p.m. UTC | #8
Sergey Bugaev, le mar. 11 avril 2023 00:50:25 +0300, a ecrit:
> On Mon, Apr 10, 2023 at 10:22 PM Samuel Thibault
> <samuel.thibault@gnu.org> wrote:
> >
> > Sergey Bugaev, le lun. 10 avril 2023 22:13:06 +0300, a ecrit:
> > > On Mon, Apr 10, 2023 at 9:58 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
> > > >
> > > > Sergey Bugaev, le dim. 19 mars 2023 18:09:59 +0300, a ecrit:
> > > > > +#ifdef __USE_GNU
> > > > > +/* Number of each register in the `gregset_t' array.  */
> > > > > +enum
> > > > > +{
> > > > > +  REG_GSFS = 0,              /* Actually int gs, fs.  */
> > > > > +# define REG_GSFS    REG_GSFS
> > > > > +  REG_ESDS,          /* Actually int es, ds.  */
> > > > > +# define REG_ESDS    REG_ESDS
> > > >
> > > > On second thought, why REG_ESDS? They are basically useless on amd64
> > > >
> > > > Linux packs all segment registers in REG_CSGSFS, probably better to
> > > > stuff them the same way? (all three really are 16bit only, even if the
> > > > thread_state is padding them to 32bits).
> > >
> > > Exactly because that's how they are laid out in struct
> > > i386_thread_state, if you count in 8-byte chunks.
> >
> > But we don't have to map to that.
> 
> Well yes, I was trying to make the x86_64 version do the same thing as
> i386 does, hence arranging registers in sigcontext, ucontext, and
> thread state in the same way, so they can be memcpied, like on i386.

Ah, but on i386 it's only coincidence that it's the same layout, just
because that's the pusha layourt :)

> But we could also lay this out differently and just write some more
> code to fill the ucontext.

I'd say better stick to some sane layout that makes it simpler for most
uses. We don't have to stick to the Linux layout either.

Samuel
  

Patch

diff --git a/sysdeps/mach/hurd/x86_64/bits/sigcontext.h b/sysdeps/mach/hurd/x86_64/bits/sigcontext.h
new file mode 100644
index 00000000..3a3b34bc
--- /dev/null
+++ b/sysdeps/mach/hurd/x86_64/bits/sigcontext.h
@@ -0,0 +1,131 @@ 
+/* Machine-dependent signal context structure for GNU Hurd.  x86_64 version.
+   Copyright (C) 1991-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _BITS_SIGCONTEXT_H
+#define _BITS_SIGCONTEXT_H 1
+
+#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H
+# error "Never use <bits/sigcontext.h> directly; include <signal.h> instead."
+#endif
+
+/* Signal handlers are actually called:
+   void handler (int sig, int code, struct sigcontext *scp);  */
+
+#include <bits/types/__sigset_t.h>
+#include <mach/machine/fp_reg.h>
+
+/* State of this thread when the signal was taken.  */
+struct sigcontext
+  {
+    /* These first members are machine-independent.  */
+
+    int sc_onstack;		/* Nonzero if running on sigstack.  */
+    __sigset_t sc_mask;		/* Blocked signals to restore.  */
+
+    /* MiG reply port this thread is using.  */
+    unsigned int sc_reply_port;
+
+    /* Port this thread is doing an interruptible RPC on.  */
+    unsigned int sc_intr_port;
+
+    /* Error code associated with this signal (interpreted as `error_t').  */
+    int sc_error;
+
+    /* All following members are machine-dependent.  The rest of this
+       structure is written to be laid out identically to:
+       {
+	 struct i386_thread_state basic;
+	 struct i386_float_state fpu;
+       }
+       trampoline.c knows this, so it must be changed if this changes.  */
+
+#define sc_i386_thread_state sc_gs /* Beginning of correspondence.  */
+    /* Segment registers.  */
+    int sc_gs;
+    int sc_fs;
+    int sc_es;
+    int sc_ds;
+
+    long sc_r8;
+    long sc_r9;
+    long sc_r10;
+    long sc_r11;
+    long sc_r12;
+    long sc_r13;
+    long sc_r14;
+    long sc_r15;
+    long sc_rdi;
+    long sc_rsi;
+    long sc_rbp;
+    long sc_rsp;		/* Not used; sc_ursp is used instead.  */
+    long sc_rbx;
+    long sc_rdx;
+    long sc_rcx;
+    long sc_rax;
+    long sc_rip;		/* Instruction pointer.  */
+
+    int sc_cs;			/* Code segment register.  */
+
+    long sc_rfl;		/* Processor flags.  */
+
+    long sc_ursp;		/* This stack pointer is used.  */
+    int sc_ss;			/* Stack segment register.  */
+
+    /* Following mimics struct i386_float_state.  Structures and symbolic
+       values can be found in <mach/i386/fp_reg.h>.  */
+#define sc_i386_float_state sc_fpkind
+    int sc_fpkind;		/* FP_NO, FP_387, etc.  */
+    int sc_fpused;		/* If zero, ignore rest of float state.  */
+    struct i386_fp_save sc_fpsave;
+    struct i386_fp_regs sc_fpregs;
+    int sc_fpexcsr;		/* FPSR including exception bits.  */
+  };
+
+/* Traditional BSD names for some members.  */
+#define sc_sp	sc_ursp		/* Stack pointer.  */
+#define sc_fp	sc_rbp		/* Frame pointer.  */
+#define sc_pc	sc_rip		/* Process counter.  */
+#define sc_ps	sc_rfl
+
+
+/* The deprecated sigcode values below are passed as an extra, non-portable
+   argument to regular signal handlers.  You should use SA_SIGINFO handlers
+   instead, which use the standard POSIX signal codes.  */
+
+/* Codes for SIGFPE.  */
+#define FPE_INTOVF_TRAP		0x1 /* integer overflow */
+#define FPE_INTDIV_FAULT	0x2 /* integer divide by zero */
+#define FPE_FLTOVF_FAULT	0x3 /* floating overflow */
+#define FPE_FLTDIV_FAULT	0x4 /* floating divide by zero */
+#define FPE_FLTUND_FAULT	0x5 /* floating underflow */
+#define FPE_SUBRNG_FAULT	0x7 /* BOUNDS instruction failed */
+#define FPE_FLTDNR_FAULT	0x8 /* denormalized operand */
+#define FPE_FLTINX_FAULT	0x9 /* floating loss of precision */
+#define FPE_EMERR_FAULT		0xa /* mysterious emulation error 33 */
+#define FPE_EMBND_FAULT		0xb /* emulation BOUNDS instruction failed */
+
+/* Codes for SIGILL.  */
+#define ILL_INVOPR_FAULT	0x1 /* invalid operation */
+#define ILL_STACK_FAULT		0x2 /* fault on microkernel stack access */
+#define ILL_FPEOPR_FAULT	0x3 /* invalid floating operation */
+
+/* Codes for SIGTRAP.  */
+#define DBG_SINGLE_TRAP		0x1 /* single step */
+#define DBG_BRKPNT_FAULT	0x2 /* breakpoint instruction */
+
+#endif /* bits/sigcontext.h */
diff --git a/sysdeps/mach/hurd/x86_64/sys/ucontext.h b/sysdeps/mach/hurd/x86_64/sys/ucontext.h
new file mode 100644
index 00000000..d73a8937
--- /dev/null
+++ b/sysdeps/mach/hurd/x86_64/sys/ucontext.h
@@ -0,0 +1,157 @@ 
+/* Copyright (C) 2001-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_UCONTEXT_H
+#define _SYS_UCONTEXT_H	1
+
+#include <features.h>
+
+#include <bits/types.h>
+#include <bits/types/sigset_t.h>
+#include <bits/types/stack_t.h>
+
+
+#ifdef __USE_MISC
+# define __ctx(fld) fld
+#else
+# define __ctx(fld) __ ## fld
+#endif
+
+/* Type for general register.  */
+__extension__ typedef long long int greg_t;
+
+/* Number of general registers.  */
+#define __NGREG	23
+#ifdef __USE_MISC
+# define NGREG	__NGREG
+#endif
+
+/* Container for all general registers.  */
+typedef greg_t gregset_t[__NGREG];
+
+#ifdef __USE_GNU
+/* Number of each register in the `gregset_t' array.  */
+enum
+{
+  REG_GSFS = 0,		/* Actually int gs, fs.  */
+# define REG_GSFS	REG_GSFS
+  REG_ESDS,		/* Actually int es, ds.  */
+# define REG_ESDS	REG_ESDS
+  REG_R8,
+# define REG_R8		REG_R8
+  REG_R9,
+# define REG_R9		REG_R9
+  REG_R10,
+# define REG_R10	REG_R10
+  REG_R11,
+# define REG_R11	REG_R11
+  REG_R12,
+# define REG_R12	REG_R12
+  REG_R13,
+# define REG_R13	REG_R13
+  REG_R14,
+# define REG_R14	REG_R14
+  REG_R15,
+# define REG_R15	REG_R15
+  REG_RDI,
+# define REG_RDI	REG_RDI
+  REG_RSI,
+# define REG_RSI	REG_RSI
+  REG_RBP,
+# define REG_RBP	REG_RBP
+  REG_RSP,
+# define REG_RSP	REG_RSP
+  REG_RBX,
+# define REG_RBX	REG_RBX
+  REG_RDX,
+# define REG_RDX	REG_RDX
+  REG_RCX,
+# define REG_RCX	REG_RCX
+  REG_RAX,
+# define REG_RAX	REG_RAX
+  REG_RIP,
+# define REG_RIP	REG_RIP
+  REG_CS,		/* Actually int cs, pad.  */
+# define REG_CS		REG_CS
+  REG_RFL,
+# define REG_RFL	REG_RFL
+  REG_ERR,
+# define REG_ERR	REG_ERR
+  REG_TRAPNO,
+# define REG_TRAPNO	REG_TRAPNO
+  REG_OLDMASK,
+# define REG_OLDMASK	REG_OLDMASK
+  REG_CR2
+# define REG_CR2	REG_CR2
+};
+#endif
+
+struct _libc_fpxreg
+{
+  unsigned short int __ctx(significand)[4];
+  unsigned short int __ctx(exponent);
+  unsigned short int __glibc_reserved1[3];
+};
+
+struct _libc_xmmreg
+{
+  __uint32_t	__ctx(element)[4];
+};
+
+struct _libc_fpstate
+{
+  /* 64-bit FXSAVE format.  */
+  __uint16_t		__ctx(cwd);
+  __uint16_t		__ctx(swd);
+  __uint16_t		__ctx(ftw);
+  __uint16_t		__ctx(fop);
+  __uint64_t		__ctx(rip);
+  __uint64_t		__ctx(rdp);
+  __uint32_t		__ctx(mxcsr);
+  __uint32_t		__ctx(mxcr_mask);
+  struct _libc_fpxreg	_st[8];
+  struct _libc_xmmreg	_xmm[16];
+  __uint32_t		__glibc_reserved1[24];
+};
+
+/* Structure to describe FPU registers.  */
+typedef struct _libc_fpstate *fpregset_t;
+
+/* Context to describe whole processor state.  */
+typedef struct
+  {
+    gregset_t __ctx(gregs);
+    /* Note that fpregs is a pointer.  */
+    fpregset_t __ctx(fpregs);
+    __extension__ unsigned long long __reserved1 [8];
+} mcontext_t;
+
+/* Userlevel context.  */
+typedef struct ucontext_t
+  {
+    unsigned long int __ctx(uc_flags);
+    struct ucontext_t *uc_link;
+    stack_t uc_stack;
+    mcontext_t uc_mcontext;
+    sigset_t uc_sigmask;
+    struct _libc_fpstate __fpregs_mem;
+    __extension__ unsigned long long int __ssp[4];
+  } ucontext_t;
+
+#undef __ctx
+
+#endif /* sys/ucontext.h */
diff --git a/sysdeps/mach/hurd/x86_64/ucontext_i.sym b/sysdeps/mach/hurd/x86_64/ucontext_i.sym
new file mode 100644
index 00000000..7e536956
--- /dev/null
+++ b/sysdeps/mach/hurd/x86_64/ucontext_i.sym
@@ -0,0 +1,38 @@ 
+#include <stddef.h>
+#include <signal.h>
+#include <sys/ucontext.h>
+
+--
+
+SIG_BLOCK
+SIG_SETMASK
+
+_NSIG8		(_NSIG / 8)
+
+#define ucontext(member)	offsetof (ucontext_t, member)
+#define mcontext(member)	ucontext (uc_mcontext.member)
+#define mreg(reg)		mcontext (gregs[REG_##reg])
+
+oRBP		mreg (RBP)
+oRSP		mreg (RSP)
+oRBX		mreg (RBX)
+oR8		mreg (R8)
+oR9		mreg (R9)
+oR10		mreg (R10)
+oR11		mreg (R11)
+oR12		mreg (R12)
+oR13		mreg (R13)
+oR14		mreg (R14)
+oR15		mreg (R15)
+oRDI		mreg (RDI)
+oRSI		mreg (RSI)
+oRDX		mreg (RDX)
+oRAX		mreg (RAX)
+oRCX		mreg (RCX)
+oRIP		mreg (RIP)
+oRFL		mreg (RFL)
+oFPREGS		mcontext (fpregs)
+oSIGMASK	ucontext (uc_sigmask)
+oFPREGSMEM	ucontext (__fpregs_mem)
+oMXCSR		ucontext (__fpregs_mem.mxcsr)
+oSSP		ucontext (__ssp)