From patchwork Sat Feb 18 20:37:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergey Bugaev X-Patchwork-Id: 65224 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 07D543888C7C for ; Sat, 18 Feb 2023 20:39:30 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 07D543888C7C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1676752770; bh=87A600v7GDrduEQWMkCtpkQOQF9mlg4+ESrinobReN0=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=UiZeQuEjB84bXgmj791Kn7KfwnT3TCDlDJpAXAon8Vky5ZEQOkt1TyPhgN48ZIIOk pbEs+CbxDGQ9KZyqhDh10Si0m2caIQnxwl3eKQeEmR5AKaSZpMaBacqen3YHN5Mlsf yn5WkxnJc54x7rvgERxrRBlujzjV4eN2iqOoMzvk= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-lf1-x129.google.com (mail-lf1-x129.google.com [IPv6:2a00:1450:4864:20::129]) by sourceware.org (Postfix) with ESMTPS id 46F1F385841A for ; Sat, 18 Feb 2023 20:37:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 46F1F385841A Received: by mail-lf1-x129.google.com with SMTP id k20so574868lfv.10 for ; Sat, 18 Feb 2023 12:37:46 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=87A600v7GDrduEQWMkCtpkQOQF9mlg4+ESrinobReN0=; b=U8vZ4vda0OtRVMoX5T5Qf5Mj/L0Qluy2YwDw0Us1K1JU232jI1wKhFaObDj5eDeGmv jYj+nF7LWPFm+QOYpCmyh+ZBR2tx0Rf3u+3VdrEGp4mma4WYrlLfFIybDEfSZEkxsQBt GLqoe1Kb5IsDOoEgRp5Aq2nLdFmNe5npF3KHw941um0hYFBr5+3HKUz4MXmJfVkOzwlj dcRzivBTyaalQ4GY9pxw0XQHOVovTesxcmTQ1S0MlEMikJL8J8VOG2MVPo1s3/feCP3C 9fuvR/T838oYMAUOdN0BoyBzCXw0Re56b/BTQOCgpmIAhHtlla1M0mpS0W2Dxs3HP5CF qusg== X-Gm-Message-State: AO0yUKUuhTOxn2GJODB2AM/wEgVotBK0DERB7gRfdsZQb2G4dqSHDpS5 gbLyNJ2DqI6DQmZNDxTREYqLLx4f+zFs0A== X-Google-Smtp-Source: AK7set+0pvq0bja0lg7nev0OfkZCot6Ojug4VtpAdRi3rwG1gDBk8Uc5EqUZgpt8Vt+cZIdY+PJVyg== X-Received: by 2002:a19:ad04:0:b0:4d8:56f2:6054 with SMTP id t4-20020a19ad04000000b004d856f26054mr778134lfc.41.1676752664599; Sat, 18 Feb 2023 12:37:44 -0800 (PST) Received: from surface-pro-6.. ([2a00:1370:818c:4a57:e4a7:ca9:e8d7:4ead]) by smtp.gmail.com with ESMTPSA id u15-20020a05651c130f00b002934febffe4sm1004049lja.128.2023.02.18.12.37.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Feb 2023 12:37:44 -0800 (PST) To: bug-hurd@gnu.org, libc-alpha@sourceware.org Cc: =?utf-8?q?Fl=C3=A1vio_Cruz?= , Sergey Bugaev Subject: [RFC PATCH 9/9] hurd, htl: Add some more x86_64-specific code Date: Sat, 18 Feb 2023 23:37:17 +0300 Message-Id: <20230218203717.373211-10-bugaevc@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230218203717.373211-1-bugaevc@gmail.com> References: <20230218203717.373211-1-bugaevc@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-11.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Sergey Bugaev via Libc-alpha From: Sergey Bugaev Reply-To: Sergey Bugaev Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" Signed-off-by: Sergey Bugaev --- sysdeps/mach/hurd/x86/init-first.c | 14 +- sysdeps/mach/hurd/x86_64/tls.h | 257 ++++++++++++++++++++ sysdeps/mach/x86_64/thread_state.h | 51 ++++ sysdeps/x86_64/htl/bits/pthreadtypes-arch.h | 36 +++ sysdeps/x86_64/htl/pt-machdep.h | 28 +++ 5 files changed, 385 insertions(+), 1 deletion(-) create mode 100644 sysdeps/mach/hurd/x86_64/tls.h create mode 100644 sysdeps/mach/x86_64/thread_state.h create mode 100644 sysdeps/x86_64/htl/bits/pthreadtypes-arch.h create mode 100644 sysdeps/x86_64/htl/pt-machdep.h diff --git a/sysdeps/mach/hurd/x86/init-first.c b/sysdeps/mach/hurd/x86/init-first.c index 75ac1ff2..d4e6a4d6 100644 --- a/sysdeps/mach/hurd/x86/init-first.c +++ b/sysdeps/mach/hurd/x86/init-first.c @@ -43,8 +43,14 @@ extern char **__libc_argv attribute_hidden; extern char **_dl_argv; #ifndef SHARED -unsigned short __init1_desc; static tcbhead_t __init1_tcbhead; +# ifndef __x86_64__ +unsigned short __init1_desc; +# endif +#endif + +#ifdef __x86_64__ +unsigned char __libc_tls_initialized; #endif /* Things that want to be run before _hurd_init or much anything else. @@ -248,7 +254,13 @@ first_init (void) /* In the static case, we need to set up TLS early so that the stack protection guard can be read at gs:0x14 by the gcc-generated snippets. */ _hurd_tls_init (&__init1_tcbhead); + + /* Make sure __LIBC_NO_TLS () keeps evaluating to 1. */ +# ifdef __x86_64__ + __libc_tls_initialized = 0; +# else asm ("movw %%gs,%w0" : "=m" (__init1_desc)); +# endif #endif RUN_RELHOOK (_hurd_preinit_hook, ()); diff --git a/sysdeps/mach/hurd/x86_64/tls.h b/sysdeps/mach/hurd/x86_64/tls.h new file mode 100644 index 00000000..644dcb1a --- /dev/null +++ b/sysdeps/mach/hurd/x86_64/tls.h @@ -0,0 +1,257 @@ +/* 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 + . */ + +#ifndef _X86_64_TLS_H +#define _X86_64_TLS_H + + +/* Some things really need not be machine-dependent. */ +#include + + +#ifndef __ASSEMBLER__ +# include +# include +# include +# include + +/* 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"); + +extern unsigned char __libc_tls_initialized; +# define __LIBC_NO_TLS() __builtin_expect (!__libc_tls_initialized, 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) _hurd_tls_init ((tcbhead_t *) (descr)) + +# 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) */ + +/* Return the TCB address of a thread given its state. + Note: this is expensive. */ +static inline tcbhead_t * __attribute__ ((unused)) +THREAD_TCB (thread_t thread, + const void *all_state __attribute__ ((unused))) +{ + error_t err; + /* Fetch the target thread's state. */ + struct i386_fsgs_base_state state; + mach_msg_type_number_t state_count = i386_FSGS_BASE_STATE_COUNT; + err = __thread_get_state (thread, i386_FSGS_BASE_STATE, + (thread_state_t) &state, + &state_count); + assert_perror (err); + assert (state_count == i386_FSGS_BASE_STATE_COUNT); + return (tcbhead_t *) state.fs_base; +} + +/* 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) + +/* Set up TLS in the new thread of a fork child, copying from the original. */ +static inline kern_return_t __attribute__ ((unused)) +_hurd_tls_fork (thread_t child, thread_t orig, + void *machine_state __attribute__ ((unused))) +{ + error_t err; + struct i386_fsgs_base_state state; + mach_msg_type_number_t state_count = i386_FSGS_BASE_STATE_COUNT; + err = __thread_get_state (orig, i386_FSGS_BASE_STATE, + (thread_state_t) &state, + &state_count); + if (err) + return err; + assert (state_count == i386_FSGS_BASE_STATE_COUNT); + + return __thread_set_state (child, i386_FSGS_BASE_STATE, + (thread_state_t) &state, + state_count); +} + +static inline kern_return_t __attribute__ ((unused)) +_hurd_tls_new (thread_t child, tcbhead_t *tcb) +{ + struct i386_fsgs_base_state state; + + tcb->tcb = tcb; + tcb->self = child; + + /* Install the TCB address into FS base. */ + state.fs_base = (uintptr_t) tcb; + state.gs_base = 0; + return __thread_set_state (child, i386_FSGS_BASE_STATE, + (thread_state_t) &state, + i386_FSGS_BASE_STATE_COUNT); +} + +static inline bool __attribute__ ((unused)) +_hurd_tls_init (tcbhead_t *tcb) +{ + error_t err; + thread_t self = __mach_thread_self (); + + /* We always at least start the sigthread anyway. */ + tcb->multiple_threads = 1; + + err = _hurd_tls_new (self, tcb); + __mach_port_deallocate (__mach_task_self (), self); + __libc_tls_initialized = 1; + return err == 0; +} + + +/* 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 */ diff --git a/sysdeps/mach/x86_64/thread_state.h b/sysdeps/mach/x86_64/thread_state.h new file mode 100644 index 00000000..d8c8889f --- /dev/null +++ b/sysdeps/mach/x86_64/thread_state.h @@ -0,0 +1,51 @@ +/* Mach thread state definitions for machine-independent code. 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 + . */ + +#ifndef _MACH_X86_64_THREAD_STATE_H +#define _MACH_X86_64_THREAD_STATE_H 1 + +#include + +#define MACHINE_NEW_THREAD_STATE_FLAVOR i386_THREAD_STATE +#define MACHINE_THREAD_STATE_FLAVOR i386_THREAD_STATE +#define MACHINE_THREAD_STATE_COUNT i386_THREAD_STATE_COUNT + +#define machine_thread_state i386_thread_state + +#define PC rip +#define SP ursp +#define SYSRETURN rax + +#define MACHINE_THREAD_STATE_FIX_NEW(ts) do { \ + asm ("mov %%cs, %w0" : "=q" ((ts)->cs)); \ + asm ("mov %%ds, %w0" : "=q" ((ts)->ds)); \ + asm ("mov %%es, %w0" : "=q" ((ts)->es)); \ + asm ("mov %%fs, %w0" : "=q" ((ts)->fs)); \ + asm ("mov %%gs, %w0" : "=q" ((ts)->gs)); \ +} while(0) + +struct machine_thread_all_state + { + int set; /* Mask of bits (1 << FLAVOR). */ + struct i386_thread_state basic; + struct i386_float_state fpu; + }; + +#include + +#endif /* mach/x86_64/thread_state.h */ diff --git a/sysdeps/x86_64/htl/bits/pthreadtypes-arch.h b/sysdeps/x86_64/htl/bits/pthreadtypes-arch.h new file mode 100644 index 00000000..1d402cc6 --- /dev/null +++ b/sysdeps/x86_64/htl/bits/pthreadtypes-arch.h @@ -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 + . */ + +#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 +#define __ONCE_ALIGNMENT + +#endif /* bits/pthreadtypes.h */ diff --git a/sysdeps/x86_64/htl/pt-machdep.h b/sysdeps/x86_64/htl/pt-machdep.h new file mode 100644 index 00000000..2e2846fa --- /dev/null +++ b/sysdeps/x86_64/htl/pt-machdep.h @@ -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 + . */ + +#ifndef _PT_MACHDEP_H +#define _PT_MACHDEP_H 1 + +struct pthread_mcontext +{ + void *pc; + void *sp; +}; + +#endif /* pt-machdep.h */