[RFC,11/12] hurd, htl: Add some x86_64-specific code
Checks
Commit Message
tls.h in particular is very unfinished.
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
---
sysdeps/mach/hurd/x86_64/static-start.S | 27 +++
sysdeps/mach/hurd/x86_64/tls.h | 182 ++++++++++++++++++++
sysdeps/mach/hurd/x86_64/tlsdesc.sym | 22 +++
sysdeps/x86_64/htl/bits/pthreadtypes-arch.h | 36 ++++
sysdeps/x86_64/htl/machine-sp.h | 29 ++++
sysdeps/x86_64/htl/pt-machdep.h | 28 +++
6 files changed, 324 insertions(+)
create mode 100644 sysdeps/mach/hurd/x86_64/static-start.S
create mode 100644 sysdeps/mach/hurd/x86_64/tls.h
create mode 100644 sysdeps/mach/hurd/x86_64/tlsdesc.sym
create mode 100644 sysdeps/x86_64/htl/bits/pthreadtypes-arch.h
create mode 100644 sysdeps/x86_64/htl/machine-sp.h
create mode 100644 sysdeps/x86_64/htl/pt-machdep.h
Comments
Sergey Bugaev, le dim. 12 févr. 2023 14:10:42 +0300, a ecrit:
> It seems that GCC expects TLS on x86_64 to be done relative to %fs, not %gs, so
> that's what I attempted to do in tls.h. The main thing missing there is the
> ability to actually set (and read) the %fs base address of a thread. It is my
> understanding (but note that I have no idea what I'm talking about) that on
> x86_64 the segment descriptors (as in GDT/LDT) are not used for this,
segmentation has somewhat disappeared in x86_64, yes.
> and instead the address can be set by writing to a MSR. Linux exposes
> the arch_prctl (ARCH_[GS]ET_[FG]S) syscall for this; so maybe GNU Mach
> could also have an explicit routine for this, perhaps like this:
>
> routine i386_set_fgs_base (
> target_thread: thread_t;
> which: int;
> value: rpc_vm_address_t);
Indeed.
> We should not need a getter routine, because one can simply inspect the target
> thread's state (unless, again, I misunderstand things horribly).
For 16bit fs/gs values we could read them from userland yes. But for
fs/gs base, the FSGSBASE instruction is not available on all 64bit
processors. And ATM in THREAD_TCB we want to be able to get the base of
another thread.
> diff --git a/sysdeps/mach/hurd/x86_64/static-start.S b/sysdeps/mach/hurd/x86_64/static-start.S
> new file mode 100644
> index 00000000..982d3d52
> --- /dev/null
> +++ b/sysdeps/mach/hurd/x86_64/static-start.S
> @@ -0,0 +1,27 @@
> +/* Type of the TCB. */
> +typedef struct
> +{
> + void *tcb; /* Points to this structure. */
> + dtv_t *dtv; /* Vector of pointers to TLS data. */
> + thread_t self; /* This thread's control port. */
> + int __glibc_padding1;
> + int multiple_threads;
> + int gscope_flag;
> + uintptr_t sysinfo;
> + uintptr_t stack_guard;
> + uintptr_t pointer_guard;
> + long __glibc_padding2[2];
> + int private_futex;
? Isn't that rather feature_1 ?
> + int __glibc_padding3;
> + /* Reservation of some values for the TM ABI. */
> + void *__private_tm[4];
> + /* GCC split stack support. */
> + void *__private_ss;
> + /* The lowest address of shadow stack. */
> + unsigned long long int ssp_base;
> +
> + /* Keep these fields last, so offsets of fields above can continue being
> + compatible with the x86_64 NPTL version. */
> + mach_port_t reply_port; /* This thread's reply port. */
> + struct hurd_sigstate *_hurd_sigstate;
> +
> + /* Used by the exception handling implementation in the dynamic loader. */
> + struct rtld_catch *rtld_catch;
> +} tcbhead_t;
> +
> +/* GCC generates %fs:0x28 to access the stack guard. */
> +_Static_assert (offsetof (tcbhead_t, stack_guard) == 0x28,
> + "stack guard offset");
> +/* libgcc uses %fs:0x70 to access the split stack pointer. */
> +_Static_assert (offsetof (tcbhead_t, __private_ss) == 0x70,
> + "split stack pointer offset");
Indeed. Could you perhaps also add them to the i386 tls.h?
> +/* FIXME */
> +# define __LIBC_NO_TLS() 0
We'll want an efficient way to know whether we have configured TLS
indeed. At worse we can make it a global variable.
> +/* The TCB can have any size and the memory following the address the
> + thread pointer points to is unspecified. Allocate the TCB there. */
> +# define TLS_TCB_AT_TP 1
> +# define TLS_DTV_AT_TP 0
> +
Also copy the comment above TCB_ALIGNMENT.
> +/* Install new dtv for current thread. */
> +# define INSTALL_NEW_DTV(dtvp) THREAD_SETMEM (THREAD_SELF, dtv, dtvp)
> +/* Return the address of the dtv for the current thread. */
> +# define THREAD_DTV() THREAD_GETMEM (THREAD_SELF, dtv)
While at it, try to make the i386 version use that too?
Samuel
On Sun, Feb 12, 2023 at 7:11 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
>
> Sergey Bugaev, le dim. 12 févr. 2023 14:10:42 +0300, a ecrit:
> > We should not need a getter routine, because one can simply inspect the target
> > thread's state (unless, again, I misunderstand things horribly).
>
> For 16bit fs/gs values we could read them from userland yes. But for
> fs/gs base, the FSGSBASE instruction is not available on all 64bit
> processors. And ATM in THREAD_TCB we want to be able to get the base of
> another thread.
What I've meant is:
__thread_get_state (whatever_thread, &state);
uintptr_t its_fs_base = state->fs_base;
You can't really do the same to *write* [fg]s_base, because doing
thread_set_state on your own thread is bound to end badly.
> > diff --git a/sysdeps/mach/hurd/x86_64/static-start.S b/sysdeps/mach/hurd/x86_64/static-start.S
> > new file mode 100644
> > index 00000000..982d3d52
> > --- /dev/null
> > +++ b/sysdeps/mach/hurd/x86_64/static-start.S
> > @@ -0,0 +1,27 @@
> > +/* Type of the TCB. */
> > +typedef struct
> > +{
> > + void *tcb; /* Points to this structure. */
> > + dtv_t *dtv; /* Vector of pointers to TLS data. */
> > + thread_t self; /* This thread's control port. */
> > + int __glibc_padding1;
> > + int multiple_threads;
> > + int gscope_flag;
> > + uintptr_t sysinfo;
> > + uintptr_t stack_guard;
> > + uintptr_t pointer_guard;
> > + long __glibc_padding2[2];
> > + int private_futex;
>
> ? Isn't that rather feature_1 ?
sysdeps/mach/hurd/i386/tls.h has 'int private_futex;', which is where
I stole this from. A quick grep confirms that it's never used, so we
might rename both to feature_1, or maybe another instance of
__glibc_padding.
> > +/* GCC generates %fs:0x28 to access the stack guard. */
> > +_Static_assert (offsetof (tcbhead_t, stack_guard) == 0x28,
> > + "stack guard offset");
> > +/* libgcc uses %fs:0x70 to access the split stack pointer. */
> > +_Static_assert (offsetof (tcbhead_t, __private_ss) == 0x70,
> > + "split stack pointer offset");
>
> Indeed. Could you perhaps also add them to the i386 tls.h?
> > +/* Install new dtv for current thread. */
> > +# define INSTALL_NEW_DTV(dtvp) THREAD_SETMEM (THREAD_SELF, dtv, dtvp)
> > +/* Return the address of the dtv for the current thread. */
> > +# define THREAD_DTV() THREAD_GETMEM (THREAD_SELF, dtv)
>
> While at it, try to make the i386 version use that too?
Yeah, I have not ported the improvements back to the 32-bit version;
maybe I should. Another cool one is doing fs/gs-relative access using
GCC's __seg_fs/__seg_gs when supported.
Sergey
Sergey Bugaev, le dim. 12 févr. 2023 19:25:11 +0300, a ecrit:
> On Sun, Feb 12, 2023 at 7:11 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
> > Sergey Bugaev, le dim. 12 févr. 2023 14:10:42 +0300, a ecrit:
> > > We should not need a getter routine, because one can simply inspect the target
> > > thread's state (unless, again, I misunderstand things horribly).
> >
> > For 16bit fs/gs values we could read them from userland yes. But for
> > fs/gs base, the FSGSBASE instruction is not available on all 64bit
> > processors. And ATM in THREAD_TCB we want to be able to get the base of
> > another thread.
>
> What I've meant is:
>
> __thread_get_state (whatever_thread, &state);
> uintptr_t its_fs_base = state->fs_base;
>
> You can't really do the same to *write* [fg]s_base, because doing
> thread_set_state on your own thread is bound to end badly.
? Well, sure, just like setting fs/gs through thread state was not done
for i386.
I don't see where you're aiming. Getting fs/gs from __thread_get_state
won't actually give you the base, you'll just read something like 0.
> > > diff --git a/sysdeps/mach/hurd/x86_64/static-start.S b/sysdeps/mach/hurd/x86_64/static-start.S
> > > new file mode 100644
> > > index 00000000..982d3d52
> > > --- /dev/null
> > > +++ b/sysdeps/mach/hurd/x86_64/static-start.S
> > > @@ -0,0 +1,27 @@
> > > +/* Type of the TCB. */
> > > +typedef struct
> > > +{
> > > + void *tcb; /* Points to this structure. */
> > > + dtv_t *dtv; /* Vector of pointers to TLS data. */
> > > + thread_t self; /* This thread's control port. */
> > > + int __glibc_padding1;
> > > + int multiple_threads;
> > > + int gscope_flag;
> > > + uintptr_t sysinfo;
> > > + uintptr_t stack_guard;
> > > + uintptr_t pointer_guard;
> > > + long __glibc_padding2[2];
> > > + int private_futex;
> >
> > ? Isn't that rather feature_1 ?
>
> sysdeps/mach/hurd/i386/tls.h has 'int private_futex;', which is where
> I stole this from. A quick grep confirms that it's never used,
Yes, this was just to align on the nptl tls.h. But apparently that got
renamed and hurd's tls wasn't updated.
> so we might rename both to feature_1, or maybe another instance of
> __glibc_padding.
Better stay coherent with the nptl version.
> > > +/* GCC generates %fs:0x28 to access the stack guard. */
> > > +_Static_assert (offsetof (tcbhead_t, stack_guard) == 0x28,
> > > + "stack guard offset");
> > > +/* libgcc uses %fs:0x70 to access the split stack pointer. */
> > > +_Static_assert (offsetof (tcbhead_t, __private_ss) == 0x70,
> > > + "split stack pointer offset");
> >
> > Indeed. Could you perhaps also add them to the i386 tls.h?
>
> > > +/* Install new dtv for current thread. */
> > > +# define INSTALL_NEW_DTV(dtvp) THREAD_SETMEM (THREAD_SELF, dtv, dtvp)
> > > +/* Return the address of the dtv for the current thread. */
> > > +# define THREAD_DTV() THREAD_GETMEM (THREAD_SELF, dtv)
> >
> > While at it, try to make the i386 version use that too?
>
> Yeah, I have not ported the improvements back to the 32-bit version;
> maybe I should.
Better always keep things as coherent as possible. Otherwise another you
will later wonder why in the hell we have differences between the two
versions.
> Another cool one is doing fs/gs-relative access using
> GCC's __seg_fs/__seg_gs when supported.
Yes, that's nice indeed!
Samuel
* Samuel Thibault via Libc-alpha:
> Sergey Bugaev, le dim. 12 févr. 2023 19:25:11 +0300, a ecrit:
>> On Sun, Feb 12, 2023 at 7:11 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
>> > Sergey Bugaev, le dim. 12 févr. 2023 14:10:42 +0300, a ecrit:
>> > > We should not need a getter routine, because one can simply inspect the target
>> > > thread's state (unless, again, I misunderstand things horribly).
>> >
>> > For 16bit fs/gs values we could read them from userland yes. But for
>> > fs/gs base, the FSGSBASE instruction is not available on all 64bit
>> > processors. And ATM in THREAD_TCB we want to be able to get the base of
>> > another thread.
>>
>> What I've meant is:
>>
>> __thread_get_state (whatever_thread, &state);
>> uintptr_t its_fs_base = state->fs_base;
>>
>> You can't really do the same to *write* [fg]s_base, because doing
>> thread_set_state on your own thread is bound to end badly.
>
> ? Well, sure, just like setting fs/gs through thread state was not done
> for i386.
>
> I don't see where you're aiming. Getting fs/gs from __thread_get_state
> won't actually give you the base, you'll just read something like 0.
The convention is that the FSBASE address is at %fs:0. The x86-64 TLS
ABI assumes this, so that it's possible to compute the global (not
thread-specific) address of a TLS variable.
Florian Weimer, le dim. 12 févr. 2023 17:40:58 +0100, a ecrit:
> * Samuel Thibault via Libc-alpha:
>
> > Sergey Bugaev, le dim. 12 févr. 2023 19:25:11 +0300, a ecrit:
> >> On Sun, Feb 12, 2023 at 7:11 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
> >> > Sergey Bugaev, le dim. 12 févr. 2023 14:10:42 +0300, a ecrit:
> >> > > We should not need a getter routine, because one can simply inspect the target
> >> > > thread's state (unless, again, I misunderstand things horribly).
> >> >
> >> > For 16bit fs/gs values we could read them from userland yes. But for
> >> > fs/gs base, the FSGSBASE instruction is not available on all 64bit
> >> > processors. And ATM in THREAD_TCB we want to be able to get the base of
> >> > another thread.
> >>
> >> What I've meant is:
> >>
> >> __thread_get_state (whatever_thread, &state);
> >> uintptr_t its_fs_base = state->fs_base;
> >>
> >> You can't really do the same to *write* [fg]s_base, because doing
> >> thread_set_state on your own thread is bound to end badly.
> >
> > ? Well, sure, just like setting fs/gs through thread state was not done
> > for i386.
> >
> > I don't see where you're aiming. Getting fs/gs from __thread_get_state
> > won't actually give you the base, you'll just read something like 0.
>
> The convention is that the FSBASE address is at %fs:0.
Yes, but that works only for reading your own base, not the base of
another thread.
Samuel
On Sun, Feb 12, 2023 at 7:36 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
>
> Sergey Bugaev, le dim. 12 févr. 2023 19:25:11 +0300, a ecrit:
> > On Sun, Feb 12, 2023 at 7:11 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
> > > Sergey Bugaev, le dim. 12 févr. 2023 14:10:42 +0300, a ecrit:
> > > > We should not need a getter routine, because one can simply inspect the target
> > > > thread's state (unless, again, I misunderstand things horribly).
> > >
> > > For 16bit fs/gs values we could read them from userland yes. But for
> > > fs/gs base, the FSGSBASE instruction is not available on all 64bit
> > > processors. And ATM in THREAD_TCB we want to be able to get the base of
> > > another thread.
> >
> > What I've meant is:
> >
> > __thread_get_state (whatever_thread, &state);
> > uintptr_t its_fs_base = state->fs_base;
> >
> > You can't really do the same to *write* [fg]s_base, because doing
> > thread_set_state on your own thread is bound to end badly.
>
> ? Well, sure, just like setting fs/gs through thread state was not done
> for i386.
>
> I don't see where you're aiming. Getting fs/gs from __thread_get_state
> won't actually give you the base, you'll just read something like 0.
It is my understanding that the actual values of fs/gs (i.e. the index
of a descriptor) are not useful on x86_64. But fs_base and gs_base are
now things that you have to store in the thread state and save/restore
on every context switch. fs_base and gs_base are like registers in
their own right (well, MSRs are registers). Thus, it should be easy to
read them from the state structure exposed by the kernel.
But again, I really have very little understanding of this, so maybe
I'm talking nonsense.
Sergey
Sergey Bugaev, le dim. 12 févr. 2023 19:51:33 +0300, a ecrit:
> On Sun, Feb 12, 2023 at 7:36 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
> >
> > Sergey Bugaev, le dim. 12 févr. 2023 19:25:11 +0300, a ecrit:
> > > On Sun, Feb 12, 2023 at 7:11 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
> > > > Sergey Bugaev, le dim. 12 févr. 2023 14:10:42 +0300, a ecrit:
> > > > > We should not need a getter routine, because one can simply inspect the target
> > > > > thread's state (unless, again, I misunderstand things horribly).
> > > >
> > > > For 16bit fs/gs values we could read them from userland yes. But for
> > > > fs/gs base, the FSGSBASE instruction is not available on all 64bit
> > > > processors. And ATM in THREAD_TCB we want to be able to get the base of
> > > > another thread.
> > >
> > > What I've meant is:
> > >
> > > __thread_get_state (whatever_thread, &state);
> > > uintptr_t its_fs_base = state->fs_base;
> > >
> > > You can't really do the same to *write* [fg]s_base, because doing
> > > thread_set_state on your own thread is bound to end badly.
> >
> > ? Well, sure, just like setting fs/gs through thread state was not done
> > for i386.
> >
> > I don't see where you're aiming. Getting fs/gs from __thread_get_state
> > won't actually give you the base, you'll just read something like 0.
>
> It is my understanding that the actual values of fs/gs (i.e. the index
> of a descriptor) are not useful on x86_64. But fs_base and gs_base are
> now things that you have to store in the thread state and save/restore
> on every context switch. fs_base and gs_base are like registers in
> their own right (well, MSRs are registers). Thus, it should be easy to
> read them from the state structure exposed by the kernel.
Ah, so you mean adding the fs/gs bases to the thread_state content.
I'd rather make it a separate state content, like we have a separate
i386_DEBUG_STATE content.
(And thus no need for a new RPC).
Samuel
* Samuel Thibault:
> Florian Weimer, le dim. 12 févr. 2023 17:40:58 +0100, a ecrit:
>> * Samuel Thibault via Libc-alpha:
>>
>> > Sergey Bugaev, le dim. 12 févr. 2023 19:25:11 +0300, a ecrit:
>> >> On Sun, Feb 12, 2023 at 7:11 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
>> >> > Sergey Bugaev, le dim. 12 févr. 2023 14:10:42 +0300, a ecrit:
>> >> > > We should not need a getter routine, because one can simply inspect the target
>> >> > > thread's state (unless, again, I misunderstand things horribly).
>> >> >
>> >> > For 16bit fs/gs values we could read them from userland yes. But for
>> >> > fs/gs base, the FSGSBASE instruction is not available on all 64bit
>> >> > processors. And ATM in THREAD_TCB we want to be able to get the base of
>> >> > another thread.
>> >>
>> >> What I've meant is:
>> >>
>> >> __thread_get_state (whatever_thread, &state);
>> >> uintptr_t its_fs_base = state->fs_base;
>> >>
>> >> You can't really do the same to *write* [fg]s_base, because doing
>> >> thread_set_state on your own thread is bound to end badly.
>> >
>> > ? Well, sure, just like setting fs/gs through thread state was not done
>> > for i386.
>> >
>> > I don't see where you're aiming. Getting fs/gs from __thread_get_state
>> > won't actually give you the base, you'll just read something like 0.
>>
>> The convention is that the FSBASE address is at %fs:0.
>
> Yes, but that works only for reading your own base, not the base of
> another thread.
Well, yes, but how do you identify the other thread? Usually by the
address of its TCB.
Florian Weimer, le dim. 12 févr. 2023 20:29:43 +0100, a ecrit:
> * Samuel Thibault:
>
> > Florian Weimer, le dim. 12 févr. 2023 17:40:58 +0100, a ecrit:
> >> * Samuel Thibault via Libc-alpha:
> >>
> >> > Sergey Bugaev, le dim. 12 févr. 2023 19:25:11 +0300, a ecrit:
> >> >> On Sun, Feb 12, 2023 at 7:11 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
> >> >> > Sergey Bugaev, le dim. 12 févr. 2023 14:10:42 +0300, a ecrit:
> >> >> > > We should not need a getter routine, because one can simply inspect the target
> >> >> > > thread's state (unless, again, I misunderstand things horribly).
> >> >> >
> >> >> > For 16bit fs/gs values we could read them from userland yes. But for
> >> >> > fs/gs base, the FSGSBASE instruction is not available on all 64bit
> >> >> > processors. And ATM in THREAD_TCB we want to be able to get the base of
> >> >> > another thread.
> >> >>
> >> >> What I've meant is:
> >> >>
> >> >> __thread_get_state (whatever_thread, &state);
> >> >> uintptr_t its_fs_base = state->fs_base;
> >> >>
> >> >> You can't really do the same to *write* [fg]s_base, because doing
> >> >> thread_set_state on your own thread is bound to end badly.
> >> >
> >> > ? Well, sure, just like setting fs/gs through thread state was not done
> >> > for i386.
> >> >
> >> > I don't see where you're aiming. Getting fs/gs from __thread_get_state
> >> > won't actually give you the base, you'll just read something like 0.
> >>
> >> The convention is that the FSBASE address is at %fs:0.
> >
> > Yes, but that works only for reading your own base, not the base of
> > another thread.
>
> Well, yes, but how do you identify the other thread? Usually by the
> address of its TCB.
Yes, but that's not (yet) the case in htl.
Samuel
new file mode 100644
@@ -0,0 +1,27 @@
+/* Startup code for statically linked Hurd/x86_64 binaries.
+ Copyright (C) 1998-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/>. */
+
+ .text
+ .globl _start
+_start:
+ call _hurd_stack_setup
+ xorq %rdx, %rdx
+ jmp _start1
+
+#define _start _start1
+#include <sysdeps/x86_64/start.S>
new file mode 100644
@@ -0,0 +1,182 @@
+/* Definitions for thread-local data handling. Hurd/x86_64 version.
+ Copyright (C) 2003-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 _X86_64_TLS_H
+#define _X86_64_TLS_H
+
+
+/* Some things really need not be machine-dependent. */
+#include <sysdeps/mach/hurd/tls.h>
+
+
+#ifndef __ASSEMBLER__
+# include <dl-dtv.h>
+
+/* Type of the TCB. */
+typedef struct
+{
+ void *tcb; /* Points to this structure. */
+ dtv_t *dtv; /* Vector of pointers to TLS data. */
+ thread_t self; /* This thread's control port. */
+ int __glibc_padding1;
+ int multiple_threads;
+ int gscope_flag;
+ uintptr_t sysinfo;
+ uintptr_t stack_guard;
+ uintptr_t pointer_guard;
+ long __glibc_padding2[2];
+ int private_futex;
+ int __glibc_padding3;
+ /* Reservation of some values for the TM ABI. */
+ void *__private_tm[4];
+ /* GCC split stack support. */
+ void *__private_ss;
+ /* The lowest address of shadow stack. */
+ unsigned long long int ssp_base;
+
+ /* Keep these fields last, so offsets of fields above can continue being
+ compatible with the x86_64 NPTL version. */
+ mach_port_t reply_port; /* This thread's reply port. */
+ struct hurd_sigstate *_hurd_sigstate;
+
+ /* Used by the exception handling implementation in the dynamic loader. */
+ struct rtld_catch *rtld_catch;
+} tcbhead_t;
+
+/* GCC generates %fs:0x28 to access the stack guard. */
+_Static_assert (offsetof (tcbhead_t, stack_guard) == 0x28,
+ "stack guard offset");
+/* libgcc uses %fs:0x70 to access the split stack pointer. */
+_Static_assert (offsetof (tcbhead_t, __private_ss) == 0x70,
+ "split stack pointer offset");
+
+/* FIXME */
+# define __LIBC_NO_TLS() 0
+
+/* The TCB can have any size and the memory following the address the
+ thread pointer points to is unspecified. Allocate the TCB there. */
+# define TLS_TCB_AT_TP 1
+# define TLS_DTV_AT_TP 0
+
+# define TCB_ALIGNMENT 64
+
+# define TLS_INIT_TP(descr) 0
+
+# if __GNUC_PREREQ (6, 0)
+
+# define THREAD_SELF \
+ (*(tcbhead_t * __seg_fs *) offsetof (tcbhead_t, tcb))
+# define THREAD_GETMEM(descr, member) \
+ (*(__typeof (descr->member) __seg_fs *) offsetof (tcbhead_t, member))
+# define THREAD_SETMEM(descr, member, value) \
+ (*(__typeof (descr->member) __seg_fs *) offsetof (tcbhead_t, member) = value)
+
+# else
+
+# define THREAD_SELF \
+ ({ tcbhead_t *__tcb; \
+ asm ("movq %%fs:%c1,%0" : "=r" (__tcb) \
+ : "i" (offsetof (tcbhead_t, tcb))); \
+ __tcb; })
+
+/* Read member of the thread descriptor directly. */
+# define THREAD_GETMEM(descr, member) \
+ ({ __typeof (descr->member) __value; \
+ _Static_assert (sizeof (__value) == 1 \
+ || sizeof (__value) == 4 \
+ || sizeof (__value) == 8, \
+ "size of per-thread data"); \
+ if (sizeof (__value) == 1) \
+ asm volatile ("movb %%fs:%P2,%b0" \
+ : "=q" (__value) \
+ : "0" (0), "i" (offsetof (tcbhead_t, member))); \
+ else if (sizeof (__value) == 4) \
+ asm volatile ("movl %%fs:%P1,%0" \
+ : "=r" (__value) \
+ : "i" (offsetof (tcbhead_t, member))); \
+ else /* 8 */ \
+ asm volatile ("movq %%fs:%P1,%0" \
+ : "=r" (__value) \
+ : "i" (offsetof (tcbhead_t, member))); \
+ __value; })
+
+/* Write member of the thread descriptor directly. */
+# define THREAD_SETMEM(descr, member, value) \
+ ({ \
+ _Static_assert (sizeof (descr->member) == 1 \
+ || sizeof (descr->member) == 4 \
+ || sizeof (descr->member) == 8, \
+ "size of per-thread data"); \
+ if (sizeof (descr->member) == 1) \
+ asm volatile ("movb %b0,%%fs:%P1" : \
+ : "iq" (value), \
+ "i" (offsetof (tcbhead_t, member))); \
+ else if (sizeof (descr->member) == 4) \
+ asm volatile ("movl %0,%%fs:%P1" : \
+ : "ir" (value), \
+ "i" (offsetof (tcbhead_t, member))); \
+ else /* 8 */ \
+ asm volatile ("movq %0,%%fs:%P1" : \
+ : "ir" (value), \
+ "i" (offsetof (tcbhead_t, member))); \
+ })
+# endif /* __GNUC_PREREQ (6, 0) */
+
+/* Set the stack guard field in TCB head. */
+# define THREAD_SET_STACK_GUARD(value) \
+ THREAD_SETMEM (THREAD_SELF, stack_guard, value)
+# define THREAD_COPY_STACK_GUARD(descr) \
+ ((descr)->stack_guard \
+ = THREAD_GETMEM (THREAD_SELF, stack_guard))
+
+/* Set the pointer guard field in the TCB head. */
+# define THREAD_SET_POINTER_GUARD(value) \
+ THREAD_SETMEM (THREAD_SELF, pointer_guard, value)
+# define THREAD_COPY_POINTER_GUARD(descr) \
+ ((descr)->pointer_guard \
+ = THREAD_GETMEM (THREAD_SELF, pointer_guard))
+
+/* Install new dtv for current thread. */
+# define INSTALL_NEW_DTV(dtvp) THREAD_SETMEM (THREAD_SELF, dtv, dtvp)
+
+/* Return the address of the dtv for the current thread. */
+# define THREAD_DTV() THREAD_GETMEM (THREAD_SELF, dtv)
+
+/* Global scope switch support. */
+# define THREAD_GSCOPE_FLAG_UNUSED 0
+# define THREAD_GSCOPE_FLAG_USED 1
+# define THREAD_GSCOPE_FLAG_WAIT 2
+
+# define THREAD_GSCOPE_SET_FLAG() \
+ THREAD_SETMEM (THREAD_SELF, gscope_flag, THREAD_GSCOPE_FLAG_USED)
+
+# define THREAD_GSCOPE_RESET_FLAG() \
+ ({ \
+ int __flag; \
+ asm volatile ("xchgl %0, %%fs:%P1" \
+ : "=r" (__flag) \
+ : "i" (offsetof (tcbhead_t, gscope_flag)), \
+ "0" (THREAD_GSCOPE_FLAG_UNUSED)); \
+ if (__flag == THREAD_GSCOPE_FLAG_WAIT) \
+ lll_wake (THREAD_SELF->gscope_flag, LLL_PRIVATE); \
+ })
+
+
+
+#endif /* __ASSEMBLER__ */
+#endif /* x86_64/tls.h */
new file mode 100644
@@ -0,0 +1,22 @@
+#include <stddef.h>
+#include <sysdep.h>
+#include <tls.h>
+#include <link.h>
+#include <dl-tlsdesc.h>
+
+--
+
+-- We have to override sysdeps/x86_64/tlsdesc.sym to adapt to our libpthread.
+
+-- Abuse tls.h macros to derive offsets relative to the thread register.
+
+DTV_OFFSET offsetof(tcbhead_t, dtv)
+
+TLSDESC_ARG offsetof(struct tlsdesc, arg)
+
+TLSDESC_GEN_COUNT offsetof(struct tlsdesc_dynamic_arg, gen_count)
+TLSDESC_MODID offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_module)
+TLSDESC_MODOFF offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_offset)
+
+TI_MODULE_OFFSET offsetof(tls_index, ti_module)
+TI_OFFSET_OFFSET offsetof(tls_index, ti_offset)
new file mode 100644
@@ -0,0 +1,36 @@
+/* Machine-specific pthread type layouts. Hurd x86_64 version.
+ Copyright (C) 2002-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_PTHREADTYPES_ARCH_H
+#define _BITS_PTHREADTYPES_ARCH_H 1
+
+#define __SIZEOF_PTHREAD_MUTEX_T 32
+#define __SIZEOF_PTHREAD_ATTR_T 48
+#define __SIZEOF_PTHREAD_RWLOCK_T 48
+#define __SIZEOF_PTHREAD_BARRIER_T 40
+#define __SIZEOF_PTHREAD_MUTEXATTR_T 16
+#define __SIZEOF_PTHREAD_COND_T 40
+#define __SIZEOF_PTHREAD_CONDATTR_T 8
+#define __SIZEOF_PTHREAD_RWLOCKATTR_T 4
+#define __SIZEOF_PTHREAD_BARRIERATTR_T 4
+#define __SIZEOF_PTHREAD_ONCE_T 8
+
+#define __LOCK_ALIGNMENT __attribute__ ((__aligned__(4)))
+#define __ONCE_ALIGNMENT
+
+#endif /* bits/pthreadtypes.h */
new file mode 100644
@@ -0,0 +1,29 @@
+/* Machine-specific function to return the stack pointer. x86_64 version.
+ Copyright (C) 1994-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 _MACHINE_SP_H
+#define _MACHINE_SP_H
+
+/* Return the current stack pointer. */
+
+#define __thread_stack_pointer() ({ \
+ register uintptr_t __sp__ asm("rsp"); \
+ __sp__; \
+})
+
+#endif /* machine-sp.h */
new file mode 100644
@@ -0,0 +1,28 @@
+/* Machine dependent pthreads internal defenitions. x86_64 version.
+ Copyright (C) 2000-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 _PT_MACHDEP_H
+#define _PT_MACHDEP_H 1
+
+struct pthread_mcontext
+{
+ void *pc;
+ void *sp;
+};
+
+#endif /* pt-machdep.h */